public:
Camera(int resX, int resY);
virtual ~Camera();
- virtual bool InitRay(float x, float y, Ray &ray) = 0;
+ virtual bool InitRay(float x, float y, Ray &ray) const = 0;
int resX() const;
int resY() const;
--- /dev/null
+#include "EyeLightShader.hxx"
+
+EyeLightShader::EyeLightShader(Scene* scene,
+ const Vec3f& color)
+ : Shader(scene),
+ m_color(color)
+{
+}
+
+EyeLightShader::~EyeLightShader()
+{
+}
+
+EyeLightShader::EyeLightShader()
+ : Shader(0),
+ m_color(Vec3f())
+{
+}
+
+Vec3f
+EyeLightShader::Shade(Ray& ray)
+{
+ return Vec3f();
+}
--- /dev/null
+#ifndef EYELIGHTSHADER_HXX
+#define EYELIGHTSHADER_HXX
+
+#include "Shader.hxx"
+
+class EyeLightShader : public Shader
+{
+public:
+ EyeLightShader(Scene* scene, const Vec3f& color = Vec3f(0.5,0.5,0.5));
+ virtual ~EyeLightShader();
+
+ virtual Vec3f Shade(Ray& ray);
+
+protected:
+ Vec3f m_color;
+
+private:
+ EyeLightShader();
+};
+#endif
--- /dev/null
+#include "FlatShader.hxx"
+
+FlatShader::FlatShader(Scene* scene,
+ const Vec3f& color)
+ : Shader(scene),
+ m_color(color)
+{
+}
+
+FlatShader::~FlatShader()
+{
+}
+
+FlatShader::FlatShader()
+ : Shader(0),
+ m_color(Vec3f())
+{
+}
+
+Vec3f
+FlatShader::Shade(Ray& ray)
+{
+ return Vec3f();
+}
--- /dev/null
+#ifndef FLATSHADER_HXX
+#define FLATSHADER_HXX
+
+#include "Shader.hxx"
+
+class FlatShader : public Shader
+{
+public:
+ FlatShader(Scene* scene, const Vec3f& color = Vec3f(0.5,0.5,0.5));
+ virtual ~FlatShader();
+
+ virtual Vec3f Shade(Ray& ray);
+
+private:
+ FlatShader();
+
+ Vec3f m_color;
+};
+#endif
--- /dev/null
+#include "InfinitePlane.hxx"
+
+InfinitePlane::InfinitePlane(const Vec3f& a, const Vec3f& n, Shader* shader)
+ : Primitive(shader),
+ m_a(a),
+ m_n(n)
+{
+
+}
+
+InfinitePlane::~InfinitePlane()
+{
+}
+
+bool
+InfinitePlane::Intersect(Ray& ray)
+{
+ Vec3f diff = m_a - ray.origin();
+ float t = diff.dot(m_n) / ray.direction().dot(m_n);
+ if (t < 1e-5 || t > ray.t())
+ return false;
+ ray.setT(t);
+ return true;
+}
+
+Vec3f
+InfinitePlane::GetNormal(Ray& ray)
+{
+ return Vec3f();
+}
--- /dev/null
+#ifndef INFINITE_PLANE_HXX
+#define INFINITE_PLANE_HXX
+
+#include "Primitive.hxx"
+
+class InfinitePlane : public Primitive
+{
+public:
+ InfinitePlane(const Vec3f& a, const Vec3f & n, Shader* shader);
+ virtual ~InfinitePlane();
+
+ virtual bool Intersect(Ray& ray);
+ virtual Vec3f GetNormal(Ray& ray);
+private:
+ Vec3f m_a, m_n;
+};
+#endif
all: MicroTrace
CC = g++
-CFLAGS = -O3 -Wall -g -O0
+CFLAGS = -O3 -Wall
+
OBJ = MicroTrace.o\
Vec3f.o\
Camera.o\
PerspectiveCamera.o\
+ Ray.o\
Image.o\
- Ray.o
+ InfinitePlane.o\
+ Sphere.o\
+ Triangle.o\
+ Shader.o\
+ FlatShader.o\
+ EyeLightShader.o\
+ ReflectiveEyeLightShader.o\
+ Scene.o\
+ Primitive.o
%.o: %.cxx *.hxx
$(CC) $(CFLAGS) -c $< -o $@
+%.a:
+ ar r $@ $<
+
+
+
MicroTrace: $(OBJ)
clean:
- rm *.o MicroTrace
+ rm *~ *.o *.a MicroTrace
#include <string>
-#include <iostream>
#include "Vec3f.hxx"
-//#include "Sphere.hxx"
-//#include "Triangle.hxx"
-//#include "InfinitePlane.hxx"
+#include "Sphere.hxx"
+#include "Triangle.hxx"
+#include "InfinitePlane.hxx"
#include "Image.hxx"
#include "PerspectiveCamera.hxx"
+#include "FlatShader.hxx"
+#include "EyeLightShader.hxx"
+#include "ReflectiveEyeLightShader.hxx"
+#include "Scene.hxx"
+
+void RenderFrameFlat(const std::string& fileName)
+{
+ /* Scene definition */
+
+ Scene scene;
+
+ /* Flat shaders */
+ FlatShader shd1(&scene, Vec3f(1,0,0)); // red surface
+ FlatShader shd2(&scene, Vec3f(0,1,0)); // green surface
+ FlatShader shd3(&scene, Vec3f(0,0,1)); // blue surface
+ FlatShader shd4(&scene, Vec3f(1,1,0)); // yellow surface
+ FlatShader shd5(&scene, Vec3f(0,1,1)); // cyan surface
+ FlatShader shd6(&scene, Vec3f(1,1,1)); // white surface
-void RenderFrame(Camera &camera, const std::string& fileName) {
/* scene objects */
+ Sphere s1(Vec3f(-2,1.7,0), 2, &shd1);
+ Sphere s2(Vec3f(1,-1,1), 2.2, &shd2);
+ Sphere s3(Vec3f(3,0.8,-2), 2, &shd3);
+ InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0), &shd4);
+
+
+ Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5);
+
+ /* add to scene */
+ scene.Add(&s1);
+ scene.Add(&s2);
+ scene.Add(&s3);
+ scene.Add(&p1);
+ scene.Add(&t1);
+
+
+ Image img(scene.camera()->resX(),scene.camera()->resY()); // image array
+ Ray ray; // primary ray
+
+ for(int y = 0; y < scene.camera()->resY(); y++)
+ {
+ for (int x = 0; x < scene.camera()->resX(); x++)
+ {
+
+ /* Initialize your ray here */
+
+ scene.camera()->InitRay(x+0.5,y+0.5,ray); // initialize ray
+
+ Vec3f col = scene.RayTrace(ray);
+
+ img(x,y) = col; // store pixel color
+ //std::cerr << "Main: Image color = " << img(x,y) << std::endl;
+ }
+ }
+ img.WritePPM(fileName); // write final image
+}
+
+
+void RenderFrameEyeLight(const std::string& fileName)
+{
+ /* Scene definition */
- /*
- 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
- */
+ Scene scene;
+
+ /* Flat shaders */
+ EyeLightShader shd1(&scene, Vec3f(1,0,0)); // red surface
+ EyeLightShader shd2(&scene, Vec3f(0,1,0)); // green surface
+ EyeLightShader shd3(&scene, Vec3f(0,0,1)); // blue surface
+ EyeLightShader shd4(&scene, Vec3f(1,1,0)); // yellow surface
+ EyeLightShader shd5(&scene, Vec3f(0,1,1)); // cyan surface
+ EyeLightShader shd6(&scene, Vec3f(1,1,1)); // white surface
+
+ /* scene objects */
+ Sphere s1(Vec3f(-2,1.7,0), 2, &shd1);
+ Sphere s2(Vec3f(1,-1,1), 2.2, &shd2);
+ Sphere s3(Vec3f(3,0.8,-2), 2, &shd3);
+ InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0), &shd4);
+
+
+ Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5);
+
+ /* add to scene */
+ scene.Add(&s1);
+ scene.Add(&s2);
+ scene.Add(&s3);
+ scene.Add(&p1);
+ scene.Add(&t1);
+
+ Image img(scene.camera()->resX(),scene.camera()->resY()); // image array
+ Ray ray; // primary ray
+
+ for(int y = 0; y < scene.camera()->resY(); y++)
+ {
+ for (int x = 0; x < scene.camera()->resX(); x++)
+ {
+
+ /* Initialize your ray here */
+
+ scene.camera()->InitRay(x+0.5,y+0.5,ray); // initialize ray
+
+ Vec3f col = scene.RayTrace(ray);
+
+ img(x,y) = col; // store pixel color
+ //std::cerr << "Main: Image color = " << img(x,y) << std::endl;
+ }
}
img.WritePPM(fileName); // write final image
}
+void RenderFrameReflectiveEyeLight(const std::string& fileName)
+{
+ /* Scene definition */
+
+ Scene scene;
+
+ /* Flat shaders */
+ ReflectiveEyeLightShader shd1(&scene, 1.0, Vec3f(1,0,0)); // red surface
+ ReflectiveEyeLightShader shd2(&scene, 1.0, Vec3f(0.0,1.0,0.0)); // green surface
+ ReflectiveEyeLightShader shd3(&scene, 1.0, Vec3f(0,0,1)); // blue surface
+ ReflectiveEyeLightShader shd4(&scene, 0.8, Vec3f(1,1,0)); // yellow surface
+ ReflectiveEyeLightShader shd5(&scene, 1.0, Vec3f(0,1,1)); // cyan surface
+ ReflectiveEyeLightShader shd6(&scene, 0.0, Vec3f(1,1,1)); // white surface
+
+ /* scene objects */
+ Sphere s1(Vec3f(-2,1.7,0), 2, &shd1);
+ Sphere s2(Vec3f(0.4,-1,1), 2.0, &shd2);
+ Sphere s3(Vec3f(3,0.8,-2), 2, &shd3);
+ InfinitePlane p1(Vec3f(0,-1,0),Vec3f(0,1,0), &shd4);
+
+
+ Triangle t1(Vec3f(-2,3,1),Vec3f(1,2,1),Vec3f(3,2.8,3), &shd5);
+
+ /* add to scene */
+ scene.Add(&s1);
+ scene.Add(&s2);
+ scene.Add(&s3);
+ scene.Add(&p1);
+ scene.Add(&t1);
+
+
+ Image img(scene.camera()->resX(),scene.camera()->resY()); // image array
+ Ray ray; // primary ray
+
+ for(int y = 0; y < scene.camera()->resY(); y++)
+ {
+ for (int x = 0; x < scene.camera()->resX(); x++)
+ {
+
+ /* Initialize your ray here */
+
+ scene.camera()->InitRay(x+0.5,y+0.5,ray); // initialize ray
+
+ Vec3f col = scene.RayTrace(ray);
+
+ img(x,y) = col; // store pixel color
+ //std::cerr << "Main: Image color = " << img(x,y) << std::endl;
+ }
+ }
+ img.WritePPM(fileName); // write final image
+}
+
+
+
#define RESX 640 // image x-resolution
#define RESY 480 // image y-resolution
-using namespace std;
-
-int main(int, char**) {
- // test vector implementation
-
- Vec3f bar(1, 4, 5), foo(3, 2, 1);
- cout << "Using example vector bar=" << bar << ", foo=" << foo << endl;
- cout << "bar | foo = " << (bar | foo) << ", should be 16" << endl;
- cout << "bar | bar = " << (bar | bar) << ", should be 42" << endl;
- cout << "foo | foo = " << (foo | foo) << ", should be 14" << endl;
- cout << "bar % foo = " << (bar % foo) << ", should be (-6,14,-10)" << endl;
- cout << "bar % bar = " << (bar % bar) << ", should be (0,0,0)" << endl;
- cout << "foo % foo = " << (foo % foo) << ", should be (0,0,0)" << endl;
- cout << "bar.norm() = " << bar.norm() << ", should be 6.48" << endl;
- cout << "foo.norm() = " << foo.norm() << ", should be 3.74" << endl;
- cout << "bar*5 = " << (bar * 5) << ", should be (5,20,25)" << endl;
- cout << "bar/5 = " << (bar / 5) << ", should be (0.2,0.8,1)" << endl;
- cout << "bar + foo = " << (bar + foo) << ", should be (4,6,6)" << endl;
- cout << "bar - foo = " << (bar - foo) << ", should be (-2,2,4)" << endl;
- cout << "foo - bar = " << (foo - bar) << ", should be (2,-2,-4)" << endl;
- cout << "bar * foo = " << (bar * foo) << ", should be (3,8,5)" << endl;
- cout << "bar / foo = " << (bar / foo) << ", should be (0.33,2,5)" << endl;
- cout << "foo / bar = " << (foo / bar) << ", should be (3,0.5,0.2)" << endl;
-
- cout << "bar *= 4: " << (bar *= 4) << ", should be (4,16,20)" << endl;
- cout << "bar /= 2: " << (bar /= 2) << ", should be (2,8,10)" << endl;
- cout << "bar += foo: " << (bar += foo) << ", should be (5,10,11)" << endl;
- cout << "bar -= Vec3f(5,6,3): " << (bar -= Vec3f(5, 6, 3))
- << ", should be (0,4,8)" << endl;
-
- cout << "bar[0] = " << bar[0] << ", should be 0" << endl;
- cout << "bar[1] = " << bar[1] << ", should be 4" << endl;
- cout << "bar[2] = " << bar[2] << ", should be 8" << endl;
- cout << "foo[0] = " << foo[0] << ", should be 3" << endl;
- cout << "foo[1] = " << foo[1] << ", should be 2" << endl;
- cout << "foo[2] = " << foo[2] << ", should be 1" << endl;
-
- bar.normalize();
- cout << "bar.normalize(): " << bar << ", should be (0,0.44,0.89)" << endl;
- foo.normalize();
- cout << "foo.normalize(): " << foo << ", should be (0.80,0.53,0.26)" << endl;
- bar = foo;
- cout << "bar := foo: bar = " << bar << ", should be (0.80,0.53,0.26)" << endl;
-
- /* 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");*/
+
+int main(int, char**)
+{
+ RenderFrameFlat("flatshaded.ppm");
+ RenderFrameEyeLight("eyelight.ppm");
+ RenderFrameReflectiveEyeLight("reflective.ppm");
}
+#include <limits>
+#include <iostream>
+
#include "PerspectiveCamera.hxx"
PerspectiveCamera::PerspectiveCamera()
m_angle(angle)
{
// preprocess the values and fill the rest of the member variables here
+
+ // compute local coordinate system
+ m_zAxis = dir;
+ m_xAxis = dir.cross(up);
+ m_yAxis = m_xAxis.cross(m_zAxis);
+
+ m_xAxis.normalize();
+ m_yAxis.normalize();
+ m_zAxis.normalize();
+
+ m_aspect = resX/static_cast<float>(resY);
+
+ // derive focal length from opening angle
+ float angle_in_rad = angle * M_PI / 180.0f;
+ m_focus = 1.0 / tan(angle_in_rad * 0.5);
}
PerspectiveCamera::~PerspectiveCamera()
PerspectiveCamera::InitRay(float x, //!< pixel x-coordinate
float y, //!< pixel y-coordinate
Ray& ray //!< should be filled by this function
- )
+ ) const
{
// define direction,position and maximum hit distance of Ray here
- return false;
+ Vec3f dir = m_xAxis * ( 2.0f * ((x/static_cast<float>(m_resX) - 0.5 ) * m_aspect ) )
+ + m_yAxis * ( 2.0f * (y/static_cast<float>(m_resY) - 0.5 ) )
+ + ( m_zAxis * m_focus );
+ dir.normalize();
+
+ ray.setDir(dir);
+ ray.setOrigin(m_pos);
+ float t = std::numeric_limits<float>::max();
+ ray.setT(t);
+
+ return true;
}
);
~PerspectiveCamera();
- virtual bool InitRay(float x, float y, Ray &ray);
+ virtual bool InitRay(float x, float y, Ray &ray) const;
private:
//! hidden constructors to prevent misuse. If you need those at some point, just make them public and implement them properly!
--- /dev/null
+#include "Primitive.hxx"
+
+Primitive::Primitive(Shader* shader)
+ : m_shader(shader)
+{
+}
+
+Primitive::~Primitive()
+{
+}
+
+bool
+Primitive::Occluded(Ray& ray)
+{
+ return Intersect(ray);
+}
+
+Shader*
+Primitive::shader()
+{
+ return m_shader;
+}
#define PRIMITIVE_HXX
#include "Ray.hxx"
+#include "Shader.hxx"
class Primitive
{
public:
+ Primitive(Shader* shader = 0);
+ virtual ~Primitive();
+
virtual bool Intersect(Ray &ray) = 0;
+ virtual bool Occluded(Ray& ray);
+ virtual Vec3f GetNormal(Ray& ray) = 0;
+
+ Shader* shader();
+protected:
+ Shader* m_shader;
};
#endif
+#include <limits>
+
#include "Ray.hxx"
Ray::Ray()
+ : m_org(Vec3f()),
+ m_dir(Vec3f()),
+ m_hit(0)
{
+ m_t = std::numeric_limits<float>::max();
}
Ray::Ray(const Vec3f& org,
const Vec3f& dir)
+ : m_org(org),
+ m_dir(dir),
+ m_hit(0)
{
+ m_t = std::numeric_limits<float>::max();
}
Ray::~Ray()
Ray::Ray(const Ray& r)
{
+ m_org = r.m_org;
+ m_dir = r.m_dir;
+ m_t = r.m_t;
+ m_hit = r.m_hit;
}
Ray&
Ray::operator=(const Ray& r)
{
+ if(this != &r)
+ {
+ m_org = r.m_org;
+ m_dir = r.m_dir;
+ m_t = r.m_t;
+ m_hit = r.m_hit;
+ }
return *this;
}
const Vec3f&
Ray::origin() const
{
- return Vec3f();
+ return m_org;
}
const Vec3f&
Ray::direction() const
{
- return Vec3f();
+ return m_dir;
}
float
Ray::t() const
{
- return 0.0f;
+ return m_t;
+}
+
+void
+Ray::setOrigin(const Vec3f& o)
+{
+ m_org = o;
+}
+
+void
+Ray::setDir(const Vec3f& d)
+{
+ m_dir = d;
+}
+
+void
+Ray::setT(float t)
+{
+ m_t = t;
+}
+
+Primitive*
+Ray::hit()
+{
+ return m_hit;
+}
+
+unsigned int
+Ray::recursionDepth() const
+{
+ return m_level;
+}
+
+void
+Ray::setRecursionDepth(unsigned int i)
+{
+ m_level = i;
}
#include "Vec3f.hxx"
+class Primitive;
+
class Ray
{
public:
const Vec3f& origin() const;
const Vec3f& direction() const;
float t() const;
+ Primitive* hit();
+ unsigned int recursionDepth() const;
+
+ void setOrigin(const Vec3f& o);
+ void setDir(const Vec3f& d);
+ void setT(float t);
+ void setRecursionDepth(unsigned int i);
+
private:
Vec3f m_org; //!< ray origin
Vec3f m_dir; //!< ray direction
float m_t; //!< current/maximum hit distance
+
+ unsigned int m_level; //!< level of recursion
+
+ Primitive* m_hit;
};
inline std::ostream &operator<<(std::ostream &o,const Ray &ray)
--- /dev/null
+#include "ReflectiveEyeLightShader.hxx"
+
+ReflectiveEyeLightShader::ReflectiveEyeLightShader(Scene* scene,
+ float reflectivity,
+ const Vec3f& color)
+ : EyeLightShader(scene,color),
+ m_reflectivity(reflectivity)
+{
+}
+
+ReflectiveEyeLightShader::~ReflectiveEyeLightShader()
+{
+}
+
+ReflectiveEyeLightShader::ReflectiveEyeLightShader()
+ : EyeLightShader(0),
+ m_reflectivity(0)
+{
+}
+
+Vec3f
+ReflectiveEyeLightShader::Shade(Ray& ray)
+{
+ return Vec3f();
+}
--- /dev/null
+#ifndef REFLECTIVEEYELIGHTSHADER_HXX
+#define REFLECTIVEEYELIGHTSHADER_HXX
+
+#include "EyeLightShader.hxx"
+
+class ReflectiveEyeLightShader : public EyeLightShader
+{
+public:
+ ReflectiveEyeLightShader(Scene* scene, float reflectivity, const Vec3f& color = Vec3f(0.5,0.5,0.5));
+ virtual ~ReflectiveEyeLightShader();
+
+ virtual Vec3f Shade(Ray& ray);
+
+protected:
+ float m_reflectivity;
+
+private:
+ ReflectiveEyeLightShader();
+};
+#endif
--- /dev/null
+#include "Scene.hxx"
+#include "PerspectiveCamera.hxx"
+
+Scene::Scene()
+ : m_camera(new PerspectiveCamera(Vec3f(0,0,8),
+ Vec3f(0,0,-1),
+ Vec3f(0,1,0),
+ 50,
+ 640,
+ 480)
+ ),
+ m_bgColor(Vec3f(0,0,0))
+{
+}
+
+Scene::~Scene()
+{
+ delete m_camera;
+}
+
+Scene::Scene(const Scene& s)
+{
+ operator=(s);
+}
+
+Scene&
+Scene::operator=(const Scene& s)
+{
+ return *this;
+}
+
+void
+Scene::Add(Primitive* p)
+{
+}
+
+
+bool
+Scene::Intersect(Ray& ray)
+{
+ return false;
+}
+
+bool
+Scene::Occluded(Ray& ray)
+{
+ return false;
+}
+
+Vec3f
+Scene::RayTrace(Ray& ray)
+{
+ return Vec3f();
+}
+
+const Camera*
+Scene::camera() const
+{
+ return m_camera;
+}
--- /dev/null
+#ifndef SCENE_HXX
+#define SCENE_HXX
+
+#include <vector>
+
+#include "Ray.hxx"
+#include "Camera.hxx"
+#include "Primitive.hxx"
+
+class Scene
+{
+public:
+ Scene();
+ virtual ~Scene();
+
+ // add another primitive to the scene
+ void Add(Primitive* p);
+
+ // intersect the ray with all objects in the scene
+ virtual bool Intersect(Ray& ray);
+ // find occluder
+ virtual bool Occluded(Ray& ray);
+
+ // trace the given ray and shade it, returnt the color of the shaded ray
+ Vec3f RayTrace(Ray& ray);
+
+ const Camera* camera() const;
+private:
+ Scene(const Scene& );
+ Scene& operator=(const Scene& );
+
+ Camera* m_camera;
+ // background color
+ Vec3f m_bgColor;
+
+ // primitives
+ std::vector<Primitive*> m_primitives;
+};
+#endif
--- /dev/null
+#include "Shader.hxx"
+
+Shader::Shader(Scene* scene)
+ : m_scene(scene)
+{
+}
+
+Shader::~Shader()
+{
+}
+
+Shader::Shader()
+{
+}
+
+Shader::Shader(const Shader& s)
+{
+ operator=(s);
+}
+
+Shader&
+Shader::operator=(const Shader& )
+{
+ return *this;
+}
--- /dev/null
+#ifndef SHADER_HXX
+#define SHADER_HXX
+
+#include "Vec3f.hxx"
+#include "Ray.hxx"
+
+// forward declaration
+class Scene;
+
+class Shader
+{
+public:
+ Shader(Scene* scene);
+ virtual ~Shader();
+
+ virtual Vec3f Shade(Ray& ray) = 0;
+protected:
+ Scene* m_scene;
+
+private:
+ Shader();
+ Shader(const Shader& );
+ Shader& operator=(const Shader& );
+};
+#endif
--- /dev/null
+#include "Sphere.hxx"
+
+Sphere::Sphere(const Vec3f& center, float radius, Shader* shader)
+ : Primitive(shader),
+ m_center(center),
+ m_radius(radius)
+{
+}
+
+Sphere::~Sphere()
+{
+}
+
+bool
+Sphere::Intersect(Ray& ray)
+{
+ float A = ray.direction().dot(ray.direction());
+ float C = (ray.origin()-m_center).dot(ray.origin()-m_center) - m_radius*m_radius;
+ float B = 2 * ray.direction().dot(ray.origin()-m_center);
+
+ if( B*B-4*A*C < 0 )
+ return false;
+
+ float root = sqrtf(B*B-4*A*C);
+ float t = (-B-root)/(2.0f*A);
+ if(t > ray.t())
+ return false;
+
+ if( t < 1e-6 )
+ {
+ t = (-B+root)/(2.0f*A);
+ if( t < 1e-6 || t > ray.t())
+ return false;
+ }
+ ray.setT(t);
+ return true;
+}
+
+Vec3f
+Sphere::GetNormal(Ray& ray)
+{
+ return Vec3f();
+}
--- /dev/null
+#ifndef SPHERE_HXX
+#define SPHERE_HXX
+
+#include "Primitive.hxx"
+
+
+class Sphere : public Primitive
+{
+public:
+ Sphere(const Vec3f& center, float radius, Shader* shader);
+ virtual ~Sphere();
+
+ virtual bool Intersect(Ray& ray);
+ virtual Vec3f GetNormal(Ray& ray);
+private:
+ Vec3f m_center;
+ float m_radius;
+};
+#endif
Triangle::Triangle(const Vec3f& a,
const Vec3f& b,
- const Vec3f& c)
- : m_a(a),
+ const Vec3f& c,
+ Shader* shader)
+ : Primitive(shader),
+ m_a(a),
m_b(b),
m_c(c)
{
return true;
}
+
+Vec3f
+Triangle::GetNormal(Ray& ray)
+{
+ return Vec3f();
+}
class Triangle : public Primitive
{
public:
- Triangle(const Vec3f& a, const Vec3f& b, const Vec3f& c);
+ Triangle(const Vec3f& a, const Vec3f& b, const Vec3f& c, Shader* shader);
virtual ~Triangle();
virtual bool Intersect(Ray& ray);
+ virtual Vec3f GetNormal(Ray& ray);
private:
Vec3f m_a, m_b, m_c;
};
#include "Vec3f.hxx"
-Vec3f::Vec3f() {
+Vec3f::Vec3f()
+{
+ for(int i = 0; i < 3; ++i)
+ {
+ m_values[i] = 0.0f;
+ }
}
-Vec3f::Vec3f(float x, float y, float z) {
+Vec3f::Vec3f(float x, float y, float z)
+{
m_values[0] = x;
m_values[1] = y;
m_values[2] = z;
}
-Vec3f::~Vec3f() {
+Vec3f::~Vec3f()
+{
}
-Vec3f::Vec3f(const Vec3f& o) {
- for(size_t i = 0; i < DIM; i++) {
- m_values[i] = o.m_values[i];
- }
+Vec3f::Vec3f(const Vec3f& o)
+{
+ for(int i = 0; i < 3; ++i)
+ {
+ m_values[i] = o.m_values[i];
+ }
}
-Vec3f& Vec3f::operator=(const Vec3f& o) {
- for(size_t i = 0; i < DIM; i++) {
- m_values[i] = o.m_values[i];
- }
+Vec3f&
+Vec3f::operator=(const Vec3f& o)
+{
+ if(this != &o)
+ {
+ for(int i = 0; i < 3; ++i)
+ {
+ m_values[i] = o.m_values[i];
+ }
+ }
return *this;
}
-float Vec3f::operator|(const Vec3f& o) {
-
- return dot(o);
-}
-
-float Vec3f::dot(const Vec3f& o) {
- float prod = 0;
- for(size_t i = 0; i < DIM; i++) {
- prod += m_values[i] * o.m_values[i];
- }
- return prod;
-}
-
-Vec3f Vec3f::operator%(const Vec3f& o) {
- return cross(o);
-}
-
-Vec3f Vec3f::cross(const Vec3f& o) {
- return Vec3f(m_values[1] * o.m_values[2] - m_values[2] * o.m_values[1],
- m_values[2] * o.m_values[0] - m_values[0] * o.m_values[2], m_values[0]
- * o.m_values[1] - m_values[1] * o.m_values[0]);
-}
-
-void Vec3f::normalize() {
- *this /= norm();
-}
-
-float Vec3f::norm() const {
- return sqrt(m_values[0] * m_values[0] + m_values[1] * m_values[1]
- + m_values[2] * m_values[2]);
-}
-
-Vec3f Vec3f::operator*(const float t) const {
+float
+Vec3f::operator|(const Vec3f& o) const
+{
+ return this->dot(o);
+}
+
+float
+Vec3f::dot(const Vec3f& o) const
+{
+ float dot = 0.0f;
+ for(int i = 0; i < 3; ++i)
+ {
+ dot += m_values[i]*o.m_values[i];
+ }
+ return dot;
+}
+
+Vec3f
+Vec3f::operator%(const Vec3f& o) const
+{
+ return this->cross(o);
+}
+
+Vec3f
+Vec3f::cross(const Vec3f& o) const
+{
+ float x = m_values[1]*o.m_values[2] - m_values[2]*o.m_values[1];
+ float y = m_values[2]*o.m_values[0] - m_values[0]*o.m_values[2];
+ float z = m_values[0]*o.m_values[1] - m_values[1]*o.m_values[0];
+
+ return Vec3f(x,y,z);
+}
+
+void
+Vec3f::normalize()
+{
+ float norm = this->norm();
+ *this *= 1.0f/norm;
+}
+
+float
+Vec3f::norm() const
+{
+ float n = this->dot(*this);
+ return sqrtf(n);
+}
+
+Vec3f
+Vec3f::operator*(const float t) const
+{
Vec3f v(*this);
return v *= t;
}
-Vec3f& Vec3f::operator*=(const float t) {
- for(unsigned int i = 0; i < 3; ++i) {
- m_values[i] *= t;
- }
+Vec3f&
+Vec3f::operator*=(const float t)
+{
+ for(int i = 0; i < 3; ++i)
+ {
+ m_values[i] *= t;
+ }
return *this;
}
-Vec3f Vec3f::operator/(const float t) const {
+Vec3f
+Vec3f::operator/(const float t) const
+{
Vec3f v(*this);
return v /= t;
}
-Vec3f& Vec3f::operator/=(const float t) {
- for(unsigned int i = 0; i < 3; ++i) {
- m_values[i] /= t;
- }
+Vec3f&
+Vec3f::operator/=(const float t)
+{
+ for(int i = 0; i < 3; ++i)
+ {
+ m_values[i] /= t;
+ }
return *this;
}
// example implementation of a standard operator
-Vec3f Vec3f::operator+(const Vec3f& o) const {
+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];
- }
+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 {
+
+Vec3f
+Vec3f::operator-(const Vec3f& o) const
+{
Vec3f v(*this);
+
return v -= o;
}
-Vec3f& Vec3f::operator-=(const Vec3f& o) {
- for(unsigned int i = 0; i < 3; ++i) {
- m_values[i] -= o.m_values[i];
- }
+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 {
+
+Vec3f
+Vec3f::operator*(const Vec3f& o) const
+{
Vec3f v(*this);
+
return v *= o;
}
-Vec3f& Vec3f::operator*=(const Vec3f& o) {
- for(unsigned int i = 0; i < 3; ++i) {
- m_values[i] *= o.m_values[i];
- }
+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 {
+Vec3f
+Vec3f::operator/(const Vec3f& o) const
+{
Vec3f v(*this);
+
return v /= o;
}
-Vec3f& Vec3f::operator/=(const Vec3f& o) {
- for(unsigned int i = 0; i < 3; ++i) {
- m_values[i] /= o.m_values[i];
- }
+Vec3f&
+Vec3f::operator/=(const Vec3f& o)
+{
+ for(unsigned int i = 0; i < 3; ++i)
+ {
+ m_values[i] /= o.m_values[i];
+ }
return *this;
}
-float Vec3f::operator[](unsigned int i) const {
- assert(i < DIM);
+float
+Vec3f::operator[](unsigned int i) const
+{
+ assert( i < 3 );
return m_values[i];
}
-float& Vec3f::operator[](unsigned int i) {
- assert(i < DIM);
+float&
+Vec3f::operator[](unsigned int i)
+{
+ assert(i < 3);
return m_values[i];
}
#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
-// dimension
-#define DIM 3
-
//! Standard operators and useful methods for 3d vectors
//! Fill in the missing parts in Vec3f.cxx
-class Vec3f {
+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);
-/*
- inline std::string& operator std::string() {
- std::string s = "(" + v[0] << "," << v[1] << "," << v[2] << ")");
- return std::string(
- }
-*/
+ 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) const;
+ float dot(const Vec3f& o) const;
+
+ //! cross product
+ Vec3f operator%(const Vec3f& o) const;
+ Vec3f cross(const Vec3f& o) const;
+
+ //! 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];
+ float m_values[3];
};
-inline std::ostream& operator<<(std::ostream& o, const Vec3f& v) {
+inline std::ostream& operator<<(std::ostream& o, const Vec3f& v)
+{
o << "(" << v[0] << "," << v[1] << "," << v[2] << ")";
return o;
}
#endif
+