From 0e3446ceb6fd6db0cb292671f37b46daaa2aed5b Mon Sep 17 00:00:00 2001 From: Roland Hieber Date: Sun, 17 Jan 2010 19:35:14 +0100 Subject: [PATCH] code for assignment 2 --- Camera.hxx | 2 +- EyeLightShader.cxx | 24 ++++ EyeLightShader.hxx | 20 +++ FlatShader.cxx | 24 ++++ FlatShader.hxx | 19 +++ InfinitePlane.cxx | 30 ++++ InfinitePlane.hxx | 17 +++ Makefile | 21 ++- MicroTrace.cxx | 265 ++++++++++++++++++++++------------- PerspectiveCamera.cxx | 32 ++++- PerspectiveCamera.hxx | 2 +- Primitive.cxx | 22 +++ Primitive.hxx | 10 ++ Ray.cxx | 63 ++++++++- Ray.hxx | 14 ++ ReflectiveEyeLightShader.cxx | 25 ++++ ReflectiveEyeLightShader.hxx | 20 +++ Scene.cxx | 60 ++++++++ Scene.hxx | 39 ++++++ Shader.cxx | 25 ++++ Shader.hxx | 25 ++++ Sphere.cxx | 43 ++++++ Sphere.hxx | 19 +++ Triangle.cxx | 12 +- Triangle.hxx | 3 +- Vec3f.cxx | 227 +++++++++++++++++++----------- Vec3f.hxx | 118 ++++++++-------- 27 files changed, 927 insertions(+), 254 deletions(-) create mode 100644 EyeLightShader.cxx create mode 100644 EyeLightShader.hxx create mode 100644 FlatShader.cxx create mode 100644 FlatShader.hxx create mode 100644 InfinitePlane.cxx create mode 100644 InfinitePlane.hxx create mode 100644 Primitive.cxx create mode 100644 ReflectiveEyeLightShader.cxx create mode 100644 ReflectiveEyeLightShader.hxx create mode 100644 Scene.cxx create mode 100644 Scene.hxx create mode 100644 Shader.cxx create mode 100644 Shader.hxx create mode 100644 Sphere.cxx create mode 100644 Sphere.hxx 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 + -- 2.20.1