--- /dev/null
+#include "Camera.hxx"
+
+Camera::Camera()
+ : m_resX(-1),
+ m_resY(-1)
+{
+}
+
+Camera::Camera(int resX, int resY)
+ : m_resX(resX),
+ m_resY(resY)
+{
+}
+
+Camera::~Camera()
+{
+}
+
+int
+Camera::resX() const
+{
+ return m_resX;
+}
+
+int
+Camera::resY() const
+{
+ return m_resY;
+}
--- /dev/null
+#ifndef CAMERA_HXX
+#define CAMERA_HXX
+
+#include "Ray.hxx"
+
+class Camera
+{
+public:
+ Camera(int resX, int resY);
+ virtual ~Camera();
+ virtual bool InitRay(float x, float y, Ray &ray) = 0;
+
+ int resX() const;
+ int resY() const;
+protected:
+ Camera();
+
+ int m_resX, m_resY;
+};
+#endif
--- /dev/null
+#include <cassert>
+#include <fstream>
+#include <iostream>
+
+#include "Image.hxx"
+
+Image::Image(int resX, int resY)
+:
+ m_resX(resX),
+ m_resY(resY)
+{
+ assert (resX > 0 && resY > 0);
+ std::cerr << "(Image): ResX = " << m_resX << ", resY = " << m_resY << std::endl;
+ m_pixel = new Vec3f[m_resX*m_resY];
+}
+
+Image::~Image()
+{
+ delete [] m_pixel;
+}
+
+Image::Image()
+{
+}
+
+Image::Image(const Image& o)
+{
+ operator=(o);
+}
+
+Image&
+Image::operator=(const Image& o)
+{
+ return *this;
+}
+
+Vec3f&
+Image::operator()(int x, int y)
+{
+ assert(x >= 0 && x < m_resX);
+ assert(y >= 0 && y < m_resY);
+
+ return m_pixel[y*m_resX+x];
+}
+
+void Image::WritePPM(const std::string& fileName)
+{
+ std::cerr << "(Image): Writing to file " << fileName << std::endl;
+ std::ofstream file(fileName.c_str());
+
+ if(!file.is_open())
+ {
+ std::cerr << "(Image): Could not open file " << fileName << std::endl;
+ return;
+ }
+
+ file << "P3" << std::endl;
+ file << m_resX << " " << m_resY << " " << 255 << std::endl;
+ for (int y=m_resY-1;y>=0;y--)
+ {
+ for (int x=0;x<m_resX;x++)
+ {
+ file
+ << (int)(255.99999999 * (*this)(x,y)[0]) << " "
+ << (int)(255.99999999 * (*this)(x,y)[1]) << " "
+ << (int)(255.99999999 * (*this)(x,y)[2]) << " "
+ << "\t";
+ }
+ file << std::endl;
+ file << std::flush;
+ }
+ file.close();
+ }
--- /dev/null
+#ifndef IMAGE_HXX
+#define IMAGE_HXX
+
+#include <string>
+
+#include "Vec3f.hxx"
+
+class Image
+{
+public:
+ Image(int resX,int resY);
+ ~Image();
+
+ //! pixel access operator read/write
+ Vec3f& operator()(int x, int y);
+
+ void WritePPM(const std::string& fileName);/*in Image.cxx*/
+
+private:
+ Image();
+ Image(const Image& );
+ Image& operator=(const Image& );
+
+ int m_resX, m_resY;
+ Vec3f* m_pixel;
+};
+
+#endif
--- /dev/null
+.SUFFIXES: .cxx .a
+
+all: MicroTrace
+
+CC = g++
+CFLAGS = -O3 -Wall
+
+OBJ = MicroTrace.o\
+ Vec3f.o\
+ Camera.o\
+ PerspectiveCamera.o\
+ Image.o\
+ Ray.o
+
+%.o: %.cxx *.hxx
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.a:
+ ar r $@ $<
+
+
+
+MicroTrace: $(OBJ)
+
+clean:
+ rm *.o *.a MicroTrace
--- /dev/null
+#include <string>
+
+#include "Vec3f.hxx"
+//#include "Sphere.hxx"
+//#include "Triangle.hxx"
+//#include "InfinitePlane.hxx"
+
+#include "Image.hxx"
+#include "PerspectiveCamera.hxx"
+
+void RenderFrame(Camera &camera,
+ const std::string& fileName)
+{
+ /* scene objects */
+
+ /*
+ Sphere s1(Vec3f(-2,1.7,0),2);
+ Sphere s2(Vec3f(1,-1,1),2.2);
+ Sphere s3(Vec3f(3,0.8,-2),2);*/
+ //InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0));
+
+ /*
+ Triangle t1(Vec3f(-2,3.7,0),Vec3f(1,2,1),Vec3f(3,2.8,-2));
+ Triangle t2(Vec3f(3,2,3),Vec3f(3,2,-3),Vec3f(-3,2,-3));
+ */
+ Image img(camera.resX(),camera.resY()); // image array
+ Ray ray; // primary ray
+
+ for(int y=0;y<camera.resY();y++)
+ for (int x=0;x<camera.resX();x++)
+ {
+
+ /* Initialize your ray here */
+
+ camera.InitRay(x+0.5,y+0.5,ray); // initialize ray
+
+ Vec3f col = Vec3f(0,0,0); // background color
+
+ /*
+ if (s1.Intersect(ray))
+ col = Vec3f(1,0,0);
+ if (s2.Intersect(ray))
+ col = Vec3f(0,1,0);
+ if (s3.Intersect(ray))
+ col = Vec3f(0,0,1);
+ if (p1.Intersect(ray))
+ col = Vec3f(1,1,0);
+ if (t1.Intersect(ray))
+ col = Vec3f(0,1,1);
+ if (t2.Intersect(ray))
+ col = Vec3f(1,1,1);
+
+ img(x,y) = col; // store pixel color
+ */
+ }
+ img.WritePPM(fileName); // write final image
+}
+
+#define RESX 640 // image x-resolution
+#define RESY 480 // image y-resolution
+
+int main(int, char**)
+{
+ /* render three images with different camera settings */
+
+ PerspectiveCamera c1(Vec3f(0,0,10),Vec3f(0,0,-1),Vec3f(0,1,0),60,RESX,RESY);
+ RenderFrame(c1,"perspective1.ppm");
+
+ PerspectiveCamera c2(Vec3f(-8,3,8),Vec3f(1,-.1,-1),Vec3f(0,1,0),45,RESX,RESY);
+ RenderFrame(c2,"perspective2.ppm");
+
+ PerspectiveCamera c3(Vec3f(-8,3,8),Vec3f(1,-.1,-1),Vec3f(1,1,0),45,RESX,RESY);
+ RenderFrame(c3,"perspective3.ppm");
+}
--- /dev/null
+#include "PerspectiveCamera.hxx"
+
+PerspectiveCamera::PerspectiveCamera()
+ : Camera()
+{
+}
+
+PerspectiveCamera::PerspectiveCamera(const Vec3f& pos,
+ const Vec3f& dir,
+ const Vec3f& up,
+ float angle,
+ int resX,
+ int resY)
+ : Camera(resX,resY),
+ m_pos(pos),
+ m_dir(dir),
+ m_up(up),
+ m_angle(angle)
+{
+ // preprocess the values and fill the rest of the member variables here
+}
+
+PerspectiveCamera::~PerspectiveCamera()
+{
+}
+
+PerspectiveCamera::PerspectiveCamera(const PerspectiveCamera& )
+{
+
+}
+
+PerspectiveCamera&
+PerspectiveCamera::operator=(const PerspectiveCamera& )
+{
+ return *this;
+}
+
+bool
+PerspectiveCamera::InitRay(float x, //!< pixel x-coordinate
+ float y, //!< pixel y-coordinate
+ Ray& ray //!< should be filled by this function
+ )
+{
+ // define direction,position and maximum hit distance of Ray here
+ return false;
+}
--- /dev/null
+#ifndef PERSPECTIVECAMERA_HXX
+#define PERSPECTIVECAMERA_HXX
+
+#include "Camera.hxx"
+
+class PerspectiveCamera : public Camera
+{
+public:
+ PerspectiveCamera(const Vec3f& pos,
+ const Vec3f& dir,
+ const Vec3f& up,
+ float angle,
+ int resX,
+ int resY
+ );
+ ~PerspectiveCamera();
+
+ virtual bool InitRay(float x, float y, Ray &ray);
+
+private:
+ //! hidden constructors to prevent misuse. If you need those at some point, just make them public and implement them properly!
+ PerspectiveCamera();
+ PerspectiveCamera(const PerspectiveCamera& c);
+ PerspectiveCamera& operator=(const PerspectiveCamera& c);
+
+ //! input values
+ Vec3f m_pos, m_dir, m_up;
+ float m_angle;
+
+ //! preprocessed values
+ float m_focus;
+ Vec3f m_xAxis, m_yAxis, m_zAxis;
+ float m_aspect;
+};
+#endif
--- /dev/null
+#ifndef PRIMITIVE_HXX
+#define PRIMITIVE_HXX
+
+#include "Ray.hxx"
+
+class Primitive
+{
+public:
+ virtual bool Intersect(Ray &ray) = 0;
+};
+
+#endif
--- /dev/null
+#include "Ray.hxx"
+
+Ray::Ray()
+{
+}
+
+Ray::Ray(const Vec3f& org,
+ const Vec3f& dir)
+{
+}
+
+Ray::~Ray()
+{
+}
+
+Ray::Ray(const Ray& r)
+{
+}
+
+Ray&
+Ray::operator=(const Ray& r)
+{
+ return *this;
+}
+
+const Vec3f&
+Ray::origin() const
+{
+ return Vec3f();
+}
+
+const Vec3f&
+Ray::direction() const
+{
+ return Vec3f();
+}
+
+float
+Ray::t() const
+{
+ return 0.0f;
+}
--- /dev/null
+#ifndef RAY_HXX
+#define RAY_HXX
+
+#include "Vec3f.hxx"
+
+class Ray
+{
+public:
+ Ray();
+ Ray(const Vec3f& org, const Vec3f& dir);
+ ~Ray();
+ Ray(const Ray& r);
+ Ray& operator=(const Ray& r);
+
+ const Vec3f& origin() const;
+ const Vec3f& direction() const;
+ float t() const;
+private:
+ Vec3f m_org; //!< ray origin
+ Vec3f m_dir; //!< ray direction
+ float m_t; //!< current/maximum hit distance
+};
+
+inline std::ostream &operator<<(std::ostream &o,const Ray &ray)
+{ o << "Ray [" << ray.origin() << "+t*" << ray.direction() << "]"; return o; }
+
+#endif
--- /dev/null
+#include "Triangle.hxx"
+
+Triangle::Triangle(const Vec3f& a,
+ const Vec3f& b,
+ const Vec3f& c)
+ : m_a(a),
+ m_b(b),
+ m_c(c)
+{
+}
+
+Triangle::~Triangle()
+{
+}
+
+bool
+Triangle::Intersect(Ray& ray)
+{
+ const Vec3f edge1 = m_b-m_a;
+ const Vec3f edge2 = m_c-m_a;
+
+ const Vec3f pvec = ray.direction().cross(edge2);
+
+ const float det = edge1.dot(pvec);
+ if (fabs(det) < Epsilon) return false;
+
+ const float inv_det = 1.0f / det;
+
+ const Vec3f tvec = ray.origin()-m_a;
+ float lambda = tvec.dot( pvec );
+ lambda *= inv_det;
+
+ if (lambda < 0.0f || lambda > 1.0f)
+ return false;
+
+ const Vec3f qvec = tvec.cross(edge1);
+ float mue = ray.direction().dot(qvec);
+ mue *= inv_det;
+
+ if (mue < 0.0f || mue+lambda > 1.0f)
+ return false;
+
+ float f = edge2.dot(qvec);
+ f *= inv_det;
+ if (ray.t() <= f || f < 1e-4 )
+ return false;
+
+ ray.setT(f);
+
+ return true;
+}
--- /dev/null
+#ifndef TRIANGLE_HXX
+#define TRIANGLE_HXX
+
+#include "Primitive.hxx"
+
+class Triangle : public Primitive
+{
+public:
+ Triangle(const Vec3f& a, const Vec3f& b, const Vec3f& c);
+ virtual ~Triangle();
+
+ virtual bool Intersect(Ray& ray);
+private:
+ Vec3f m_a, m_b, m_c;
+};
+#endif
--- /dev/null
+#include <cassert>
+
+#include "Vec3f.hxx"
+
+Vec3f::Vec3f()
+{
+
+}
+
+Vec3f::Vec3f(float x, float y, float z)
+{
+
+}
+
+Vec3f::~Vec3f()
+{
+}
+
+Vec3f::Vec3f(const Vec3f& o)
+{
+
+}
+
+Vec3f&
+Vec3f::operator=(const Vec3f& o)
+{
+
+ return *this;
+}
+
+float
+Vec3f::operator|(const Vec3f& o)
+{
+
+ return 0.0f;
+}
+
+float
+Vec3f::dot(const Vec3f& o)
+{
+
+ return 0.0f;
+}
+
+Vec3f
+Vec3f::operator%(const Vec3f& o)
+{
+
+ return Vec3f();
+}
+
+Vec3f
+Vec3f::cross(const Vec3f& o)
+{
+
+ return Vec3f();
+}
+
+void
+Vec3f::normalize()
+{
+
+}
+
+float
+Vec3f::norm() const
+{
+ return 0.0f;
+}
+
+Vec3f
+Vec3f::operator*(const float t) const
+{
+ return Vec3f();
+}
+
+Vec3f&
+Vec3f::operator*=(const float t)
+{
+ return *this;
+}
+
+Vec3f
+Vec3f::operator/(const float t) const
+{
+ return Vec3f();
+}
+
+Vec3f&
+Vec3f::operator/=(const float t)
+{
+ return *this;
+}
+
+// example implementation of a standard operator
+Vec3f
+Vec3f::operator+(const Vec3f& o) const
+{
+ Vec3f v(*this);
+
+ return v += o;
+}
+
+// example implementation of an in-place operator
+Vec3f&
+Vec3f::operator+=(const Vec3f& o)
+{
+ for(unsigned int i = 0; i < 3; ++i)
+ {
+ m_values[i] += o.m_values[i];
+ }
+
+ return *this;
+}
+
+Vec3f
+Vec3f::operator-(const Vec3f& o) const
+{
+ return Vec3f();
+}
+
+Vec3f&
+Vec3f::operator-=(const Vec3f& o)
+{
+ return *this;
+}
+
+Vec3f
+Vec3f::operator*(const Vec3f& o) const
+{
+ return Vec3f();
+}
+
+Vec3f&
+Vec3f::operator*=(const Vec3f& o)
+{
+ return *this;
+}
+
+Vec3f
+Vec3f::operator/(const Vec3f& o) const
+{
+ return Vec3f();
+}
+
+Vec3f&
+Vec3f::operator/=(const Vec3f& o)
+{
+ return *this;
+}
+
+float
+Vec3f::operator[](unsigned int i) const
+{
+ return 0.0f;
+}
+
+float&
+Vec3f::operator[](unsigned int i)
+{
+ assert(i < 3);
+ return m_values[i];
+}
--- /dev/null
+#ifndef VEC3F_HXX
+#define VEC3F_HXX
+
+#include <cmath>
+#include <iostream>
+
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#define max(a,b) MAX(a,b)
+#define min(a,b) MIN(a,b)
+
+#define Epsilon 1E-4
+#define Infinity HUGE_VAL
+
+//! Standard operators and useful methods for 3d vectors
+//! Fill in the missing parts in Vec3f.cxx
+class Vec3f
+{
+public:
+ Vec3f();
+ Vec3f(float x, float y, float z);
+
+ ~Vec3f();
+
+ Vec3f(const Vec3f& o);
+ Vec3f& operator=(const Vec3f& o);
+
+ //! dot product
+ float operator|(const Vec3f& o);
+ float dot(const Vec3f& o);
+
+ //! cross product
+ Vec3f operator%(const Vec3f& o);
+ Vec3f cross(const Vec3f& o);
+
+ //! normalize vector
+ void normalize();
+ //! length of a vector
+ float norm() const;
+
+ //! (self-)multiply with scalar
+ Vec3f operator*(const float t) const;
+ Vec3f& operator*=(const float t);
+
+ //! (self-)division by scalar
+ Vec3f operator/(const float t) const;
+ Vec3f& operator/=(const float t);
+
+ //! vector (self-)addition
+ Vec3f operator+(const Vec3f& o) const;
+ Vec3f& operator+=(const Vec3f& o);
+
+ //! vector (self-)subtraction
+ Vec3f operator-(const Vec3f& o) const;
+ Vec3f& operator-=(const Vec3f& o);
+
+ //! component-wise multiplication of two vectors
+ Vec3f operator*(const Vec3f& o) const;
+ Vec3f& operator*=(const Vec3f& o);
+
+ //! component-wise division of two vectors
+ Vec3f operator/(const Vec3f& o) const;
+ Vec3f& operator/=(const Vec3f& o);
+
+ //! element access functions ( read-only and read-write )
+ float operator[](unsigned int i) const;
+ float& operator[](unsigned int i);
+
+private:
+ float m_values[3];
+};
+
+inline std::ostream& operator<<(std::ostream& o, const Vec3f& v)
+{
+ o << "(" << v[0] << "," << v[1] << "," << v[2] << ")";
+ return o;
+}
+
+#endif
+
+