From: Roland Hieber Date: Sun, 17 Jan 2010 18:35:14 +0000 (+0100) Subject: code for assignment 2 X-Git-Url: https://git.rohieb.name/MicroTrace.git/commitdiff_plain/0e3446ceb6fd6db0cb292671f37b46daaa2aed5b code for assignment 2 --- diff --git a/Camera.hxx b/Camera.hxx index 51f9865..b2bc711 100644 --- a/Camera.hxx +++ b/Camera.hxx @@ -8,7 +8,7 @@ class Camera 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; diff --git a/EyeLightShader.cxx b/EyeLightShader.cxx new file mode 100644 index 0000000..12578d7 --- /dev/null +++ b/EyeLightShader.cxx @@ -0,0 +1,24 @@ +#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(); +} diff --git a/EyeLightShader.hxx b/EyeLightShader.hxx new file mode 100644 index 0000000..9b4777e --- /dev/null +++ b/EyeLightShader.hxx @@ -0,0 +1,20 @@ +#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 diff --git a/FlatShader.cxx b/FlatShader.cxx new file mode 100644 index 0000000..fcae006 --- /dev/null +++ b/FlatShader.cxx @@ -0,0 +1,24 @@ +#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(); +} diff --git a/FlatShader.hxx b/FlatShader.hxx new file mode 100644 index 0000000..7606fb9 --- /dev/null +++ b/FlatShader.hxx @@ -0,0 +1,19 @@ +#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 diff --git a/InfinitePlane.cxx b/InfinitePlane.cxx new file mode 100644 index 0000000..442da19 --- /dev/null +++ b/InfinitePlane.cxx @@ -0,0 +1,30 @@ +#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(); +} diff --git a/InfinitePlane.hxx b/InfinitePlane.hxx new file mode 100644 index 0000000..06a5aa0 --- /dev/null +++ b/InfinitePlane.hxx @@ -0,0 +1,17 @@ +#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 diff --git a/Makefile b/Makefile index a9c458e..982c074 100644 --- a/Makefile +++ b/Makefile @@ -3,19 +3,34 @@ 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 diff --git a/MicroTrace.cxx b/MicroTrace.cxx index feb1eeb..53c56ee 100644 --- a/MicroTrace.cxx +++ b/MicroTrace.cxx @@ -1,116 +1,181 @@ #include -#include #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"); } diff --git a/PerspectiveCamera.cxx b/PerspectiveCamera.cxx index b7faff6..fb9282d 100644 --- a/PerspectiveCamera.cxx +++ b/PerspectiveCamera.cxx @@ -1,3 +1,6 @@ +#include +#include + #include "PerspectiveCamera.hxx" PerspectiveCamera::PerspectiveCamera() @@ -18,6 +21,21 @@ PerspectiveCamera::PerspectiveCamera(const Vec3f& pos, 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(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() @@ -39,8 +57,18 @@ bool 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(m_resX) - 0.5 ) * m_aspect ) ) + + m_yAxis * ( 2.0f * (y/static_cast(m_resY) - 0.5 ) ) + + ( m_zAxis * m_focus ); + dir.normalize(); + + ray.setDir(dir); + ray.setOrigin(m_pos); + float t = std::numeric_limits::max(); + ray.setT(t); + + return true; } diff --git a/PerspectiveCamera.hxx b/PerspectiveCamera.hxx index 8178087..e171d5b 100644 --- a/PerspectiveCamera.hxx +++ b/PerspectiveCamera.hxx @@ -15,7 +15,7 @@ public: ); ~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! diff --git a/Primitive.cxx b/Primitive.cxx new file mode 100644 index 0000000..850cb24 --- /dev/null +++ b/Primitive.cxx @@ -0,0 +1,22 @@ +#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; +} diff --git a/Primitive.hxx b/Primitive.hxx index f147b35..04e201f 100644 --- a/Primitive.hxx +++ b/Primitive.hxx @@ -2,11 +2,21 @@ #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 diff --git a/Ray.cxx b/Ray.cxx index be4a4f4..b7e5457 100644 --- a/Ray.cxx +++ b/Ray.cxx @@ -1,12 +1,22 @@ +#include + #include "Ray.hxx" Ray::Ray() + : m_org(Vec3f()), + m_dir(Vec3f()), + m_hit(0) { + m_t = std::numeric_limits::max(); } Ray::Ray(const Vec3f& org, const Vec3f& dir) + : m_org(org), + m_dir(dir), + m_hit(0) { + m_t = std::numeric_limits::max(); } Ray::~Ray() @@ -15,28 +25,75 @@ 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; } diff --git a/Ray.hxx b/Ray.hxx index a432830..f37425c 100644 --- a/Ray.hxx +++ b/Ray.hxx @@ -3,6 +3,8 @@ #include "Vec3f.hxx" +class Primitive; + class Ray { public: @@ -15,10 +17,22 @@ 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) diff --git a/ReflectiveEyeLightShader.cxx b/ReflectiveEyeLightShader.cxx new file mode 100644 index 0000000..2bd0db3 --- /dev/null +++ b/ReflectiveEyeLightShader.cxx @@ -0,0 +1,25 @@ +#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(); +} diff --git a/ReflectiveEyeLightShader.hxx b/ReflectiveEyeLightShader.hxx new file mode 100644 index 0000000..d7b8798 --- /dev/null +++ b/ReflectiveEyeLightShader.hxx @@ -0,0 +1,20 @@ +#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 diff --git a/Scene.cxx b/Scene.cxx new file mode 100644 index 0000000..184b7e1 --- /dev/null +++ b/Scene.cxx @@ -0,0 +1,60 @@ +#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; +} diff --git a/Scene.hxx b/Scene.hxx new file mode 100644 index 0000000..18deb79 --- /dev/null +++ b/Scene.hxx @@ -0,0 +1,39 @@ +#ifndef SCENE_HXX +#define SCENE_HXX + +#include + +#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 m_primitives; +}; +#endif diff --git a/Shader.cxx b/Shader.cxx new file mode 100644 index 0000000..80d31e2 --- /dev/null +++ b/Shader.cxx @@ -0,0 +1,25 @@ +#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; +} diff --git a/Shader.hxx b/Shader.hxx new file mode 100644 index 0000000..ac6de1d --- /dev/null +++ b/Shader.hxx @@ -0,0 +1,25 @@ +#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 diff --git a/Sphere.cxx b/Sphere.cxx new file mode 100644 index 0000000..3c19afa --- /dev/null +++ b/Sphere.cxx @@ -0,0 +1,43 @@ +#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(); +} diff --git a/Sphere.hxx b/Sphere.hxx new file mode 100644 index 0000000..28604e7 --- /dev/null +++ b/Sphere.hxx @@ -0,0 +1,19 @@ +#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 diff --git a/Triangle.cxx b/Triangle.cxx index ffddbc8..761abcb 100644 --- a/Triangle.cxx +++ b/Triangle.cxx @@ -2,8 +2,10 @@ 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) { @@ -49,3 +51,9 @@ Triangle::Intersect(Ray& ray) return true; } + +Vec3f +Triangle::GetNormal(Ray& ray) +{ + return Vec3f(); +} diff --git a/Triangle.hxx b/Triangle.hxx index 320cca5..fbf4e2c 100644 --- a/Triangle.hxx +++ b/Triangle.hxx @@ -6,10 +6,11 @@ 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; }; diff --git a/Vec3f.cxx b/Vec3f.cxx index b68f9e8..f656d29 100644 --- a/Vec3f.cxx +++ b/Vec3f.cxx @@ -2,143 +2,212 @@ #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]; } diff --git a/Vec3f.hxx b/Vec3f.hxx index 908a8fc..6b67d5b 100644 --- a/Vec3f.hxx +++ b/Vec3f.hxx @@ -4,86 +4,80 @@ #include #include + #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 +