code for assignment 4, gitignored *.ppm, *.png
authorRoland Hieber <rohieb@rohieb.name>
Sat, 30 Jan 2010 18:58:01 +0000 (19:58 +0100)
committerRoland Hieber <rohieb@rohieb.name>
Sat, 30 Jan 2010 18:58:01 +0000 (19:58 +0100)
30 files changed:
.gitignore
Box.cxx [new file with mode: 0644]
Box.hxx [new file with mode: 0644]
Image.cxx
InfinitePlane.cxx
InfinitePlane.hxx
Light.hxx
Makefile
MicroTrace.cxx
PerspectiveCamera.cxx
PhongShader.cxx
PhongShader.hxx
PointLight.cxx
PointLight.hxx
Primitive.hxx
QuadAreaLight.cxx [new file with mode: 0644]
QuadAreaLight.hxx [new file with mode: 0644]
ReflectiveEyeLightShader.cxx
Scene.cxx
Scene.hxx
Sphere.cxx
Sphere.hxx
SpotLight.cxx
SpotLight.hxx
Triangle.cxx
Triangle.hxx
Vec3f.hxx
cone.obj [new file with mode: 0644]
kDTree.cxx [new file with mode: 0644]
kDTree.hxx [new file with mode: 0644]

index 3c86eb8..e1fe704 100644 (file)
@@ -1,2 +1,4 @@
 *.o
 MicroTrace
+*.png
+*.ppm
diff --git a/Box.cxx b/Box.cxx
new file mode 100644 (file)
index 0000000..ef9f750
--- /dev/null
+++ b/Box.cxx
@@ -0,0 +1,57 @@
+#include "Box.hxx"
+
+Box::Box()
+{
+}
+
+Box::~Box()
+{
+}
+
+Box::Box(const Box& b)
+{
+}
+
+Box&
+Box::operator=(const Box& b)
+{
+  return *this;
+}
+
+void
+Box::Clear()
+{
+}
+
+void
+Box::Extend(const Vec3f& a)
+{
+}
+
+void 
+Box::Extend(const Box& box)
+{
+}
+
+bool
+Box::Overlaps(const Box& b) const
+{
+  return false;
+}
+
+void
+Box::Clip(const Ray& ray, float& tnear, float& tfar) const
+{
+}
+
+const Vec3f&
+Box::min() const
+{
+  return m_min;
+}
+
+const Vec3f&
+Box::max() const
+{
+  return m_max;
+}
diff --git a/Box.hxx b/Box.hxx
new file mode 100644 (file)
index 0000000..1417e80
--- /dev/null
+++ b/Box.hxx
@@ -0,0 +1,33 @@
+#ifndef BOX_HXX
+#define BOX_HXX
+
+#include "Ray.hxx"
+
+class Box
+{
+public:
+  Box();
+  ~Box();
+
+  Box(const Box& b);
+  Box& operator=(const Box& b);
+  
+  //! Extend the bounding box to contain point a
+  void Extend(const Vec3f& a);
+  //! Clear the bounding box, i.e. set dimensions to infinity.
+  void Clear();
+  //! Extend the box to contain the given box.
+  void Extend(const Box& box);
+  //! Test for overlap with the given box b.
+  bool Overlaps(const Box& b) const;
+  //! Clip the given ray against the box. tnear and tfar should be filled by this function!
+  void Clip(const Ray& ray, float& tnear,float& tfar) const;
+
+  //! Query the dimension of the bounding box.
+  const Vec3f& min() const;
+  const Vec3f& max() const;
+private:
+  Vec3f m_min, m_max;
+};
+
+#endif
index bc8134b..b45cac9 100644 (file)
--- a/Image.cxx
+++ b/Image.cxx
@@ -39,34 +39,28 @@ Image::operator()(int x, int y)
 {
   assert(x >= 0 && x < m_resX);
   assert(y >= 0 && y < m_resY);
-
-  return m_pixel[y*m_resX+x];
+        
+  return m_pixel[y*m_resX+x];   
 }
 
 void Image::WritePPM(const std::string& fileName)
 {
   std::cerr << "(Image): Writing to file " << fileName << std::endl;
   std::ofstream file(fileName.c_str());
-
+  
   if(!file.is_open())
     {
       std::cerr << "(Image): Could not open file " << fileName << std::endl;
       return;
     }
-
+  
   file << "P3" << std::endl;
   file << m_resX << " " << m_resY << " " << 255 << std::endl;
-  for (int y=m_resY-1;y>=0;y--)
+  for (int y=m_resY-1;y>=0;y--) 
     {
       for (int x=0;x<m_resX;x++)
        {
-        if ((*this)(x,y)[0] < 0) (*this)(x,y)[0] = 0;
-        if ((*this)(x,y)[1] < 0) (*this)(x,y)[1] = 0;
-        if ((*this)(x,y)[2] < 0) (*this)(x,y)[2] = 0;
-        if ((*this)(x,y)[0] > 255) (*this)(x,y)[0] = 255;
-        if ((*this)(x,y)[1] > 255) (*this)(x,y)[1] = 255;
-        if ((*this)(x,y)[2] > 255) (*this)(x,y)[2] = 255;
-         file
+         file 
            << (int)(255.99999999 * (*this)(x,y)[0]) << " "
            << (int)(255.99999999 * (*this)(x,y)[1]) << " "
            << (int)(255.99999999 * (*this)(x,y)[2]) << " "
index f73d835..c11fb8a 100644 (file)
@@ -31,3 +31,15 @@ InfinitePlane::GetNormal(Ray& ray)
 {
   return m_n;
 }
+
+Box
+InfinitePlane::CalcBounds()
+{
+  return Box();
+}
+
+bool
+InfinitePlane::InVoxel(const Box& box)
+{
+  return false;
+}
index 06a5aa0..b855851 100644 (file)
@@ -11,6 +11,8 @@ public:
   
   virtual bool Intersect(Ray& ray);
   virtual Vec3f GetNormal(Ray& ray);
+  virtual Box CalcBounds();
+  virtual bool InVoxel(const Box& box);
 private:
   Vec3f m_a, m_n;
 };
index a152693..8392b1d 100644 (file)
--- a/Light.hxx
+++ b/Light.hxx
@@ -14,6 +14,7 @@ public:
   virtual ~Light();
   
   virtual bool Illuminate(Ray& shadowray, Vec3f& intensity) = 0;
+  virtual bool IsArea() = 0;
 protected:
   Scene* m_scene;
 
index f263909..ac86170 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 all: MicroTrace
 
 CC = g++ 
-CFLAGS = -O3 -Wall
+CFLAGS = -O3 -Wall -fopenmp
 
 
 OBJ = MicroTrace.o\
@@ -24,7 +24,10 @@ OBJ = MicroTrace.o\
       PointLight.o\
       SpotLight.o\
       Scene.o\
-      Primitive.o
+      Primitive.o\
+      QuadAreaLight.o\
+      Box.o\
+      kDTree.o
 
 %.o: %.cxx *.hxx
        $(CC) $(CFLAGS) -c $< -o $@
@@ -35,6 +38,6 @@ OBJ = MicroTrace.o\
 
 
 MicroTrace: $(OBJ)
-
+       g++  -fopenmp $(OBJ) -o MicroTrace
 clean: 
        rm *~ *.o *.a MicroTrace
index e0fd688..6bb474c 100644 (file)
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
 #include <string>
 
 #include "Vec3f.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 "PhongShader.hxx"
-#include "PointLight.hxx"
-#include "SpotLight.hxx"
 #include "Scene.hxx"
 
 
-void RenderFramePhongPointLight(const std::string& fileName)
+void RenderFrameCone(const std::string& fileName)
 {
   /* Scene definition */
   Scene scene;
   
-  /* Flat shaders */
-  PhongShader shd1(&scene, Vec3f(1,0,0),Vec3f(1,0,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // red surface
-  PhongShader shd2(&scene, Vec3f(0,1,0),Vec3f(0,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // green surface
-  PhongShader shd3(&scene, Vec3f(0,0,1),Vec3f(0,0,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // blue surface
-  PhongShader shd4(&scene, Vec3f(1,1,0),Vec3f(1,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // yellow surface
-  PhongShader shd5(&scene, Vec3f(0,1,1),Vec3f(0,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // cyan surface
-  PhongShader shd6(&scene, Vec3f(1,1,1),Vec3f(1,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // 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);
+  scene.ParseOBJ("cone.obj", 1.0f);
+  // alter the camera definition appropriately to see the cow
+  // you may need to implement some set/get routines for the scene class
+  scene.setCamera(new PerspectiveCamera(Vec3f(0,0,0.5),
+                                       Vec3f(0,0,-1),
+                                       Vec3f(0,1,0),
+                                       60,
+                                       640,
+                                       480));
   
-  /* light sources */
-  Vec3f lightPosition1(4,5,6);
-  Vec3f lightPosition2(-3,5,4);
-  Vec3f pointLightSourceIntensity(50,50,50);
   
-  PointLight pointLight1(&scene, lightPosition1, pointLightSourceIntensity);
-  PointLight pointLight2(&scene, lightPosition2, pointLightSourceIntensity);
-  scene.Add(&pointLight1);
-  scene.Add(&pointLight2);
-
-
   Image img(scene.camera()->resX(),scene.camera()->resY()); // image array
-  Ray ray;                            // primary ray
-  
+  // primary ray
+#pragma omp parallel for
   for(int y = 0; y < scene.camera()->resY(); y++)
     {
       for (int x = 0; x < scene.camera()->resX(); x++) 
        {
          
          /* Initialize your ray here */
-         
+         Ray ray;
          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 RenderFramePhongSpotLight(const std::string& fileName)
-{
-  /* Scene definition */
-  Scene scene;
-  
-  /* Flat shaders */
-  PhongShader shd1(&scene, Vec3f(1,0,0),Vec3f(1,0,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // red surface
-  PhongShader shd2(&scene, Vec3f(0,1,0),Vec3f(0,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // green surface
-  PhongShader shd3(&scene, Vec3f(0,0,1),Vec3f(0,0,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // blue surface
-  PhongShader shd4(&scene, Vec3f(1,1,0),Vec3f(1,1,0),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // yellow surface
-  PhongShader shd5(&scene, Vec3f(0,1,1),Vec3f(0,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // cyan surface
-  PhongShader shd6(&scene, Vec3f(1,1,1),Vec3f(1,1,1),Vec3f(1,1,1), 0.1, 0.5, 0.5, 40); // 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);
-  
-  /* light sources */
-  Vec3f lightPosition1(4,5,6);
-  Vec3f lightPosition2(-3,5,4);
-  Vec3f spotLightSourceIntensity(50,50,50);
-  Vec3f lightDir1 = lightPosition1 * (-1.0f);
-  lightDir1.normalize();
-  Vec3f lightDir2 = lightPosition2 *(-1.0f);
-  lightDir2.normalize();
-  float alpha_min = 15.0f;
-  float alpha_max = 30.0f;
-  
-  SpotLight spotLight1(&scene, lightPosition1, lightDir1, spotLightSourceIntensity, alpha_min, alpha_max);
-  SpotLight spotLight2(&scene, lightPosition2, lightDir2, spotLightSourceIntensity, alpha_min, alpha_max);
-  scene.Add(&spotLight1);
-  scene.Add(&spotLight2);
-
 
-  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
 
 int main(int, char**)
 {
-  RenderFramePhongPointLight("phong_point.ppm");
-  RenderFramePhongSpotLight("phong_spot.ppm");
+  RenderFrameCone("cone.ppm");
 }
index fb9282d..e97e956 100644 (file)
@@ -1,5 +1,6 @@
 #include <limits>
 #include <iostream>
+#include <cassert>
 
 #include "PerspectiveCamera.hxx"
 
@@ -21,7 +22,9 @@ PerspectiveCamera::PerspectiveCamera(const Vec3f& pos,
     m_angle(angle)    
 {
   // preprocess the values and fill the rest of the member variables here
-  
+  m_dir.normalize();
+  m_up.normalize();
+
   // compute local coordinate system
   m_zAxis = dir;
   m_xAxis = dir.cross(up);
@@ -50,6 +53,7 @@ PerspectiveCamera::PerspectiveCamera(const PerspectiveCamera& )
 PerspectiveCamera&
 PerspectiveCamera::operator=(const PerspectiveCamera& )
 {
+  assert(!"Not implemented!");
   return *this;
 }
 
index c44966e..f6bc870 100644 (file)
@@ -1,5 +1,8 @@
+#include <vector>
+
 #include "PhongShader.hxx"
 #include "Primitive.hxx"
+#include "Scene.hxx"
 
 PhongShader::PhongShader(Scene* scene,
                         const Vec3f& am_c,
@@ -32,34 +35,65 @@ PhongShader::~PhongShader()
 Vec3f
 PhongShader::Shade(Ray& ray)
 {
-  // surface normal at hit point of object
-  Vec3f normal = ray.hit()->GetNormal(ray);
-  // turn to front if angle > 90°
-  if(normal.dot(ray.direction()) < 0) {
-    normal = normal * -1;
-  }
-  // direction of reflection
-  Vec3f refl_dir = ray.direction() - normal * 2 * normal.dot(ray.direction());
-  refl_dir.normalize();
-
-  // ambient color term
-  Vec3f amb_color = m_ambient_color * m_ka;
+ // surface normal at hit point
+  Vec3f N = ray.hit()->GetNormal(ray);
+  // turn normal to front
+  if(N.dot(ray.direction()) > 0)
+    {
+      N *= -1;
+    }
+  // reflection vector
+  Vec3f R = ray.direction() - N*2*N.dot(ray.direction());
+  R.normalize();
 
-  Vec3f intensity, light_dir;
+  // ambient term
+  Vec3f color = m_ambient_color * 1.0 * m_ka;
+  
+  // construct shadow ray 
+  Vec3f shadow_org = ray.origin()+ray.direction()*ray.t();
+  Ray shadow_ray;
+  shadow_ray.setOrigin(shadow_org);
+  
 
-  // diffuse and specular color for each light source
-  Vec3f diff_sum;
-  Vec3f spec_sum;
-  for(std::vector<Light*>::iterator it = m_scene->m_lights.begin();
-    it != m_scene->m_lights.end(); it++) {
-    Ray light_ray;
-    (*it)->Illuminate(light_ray, intensity);
-    diff_sum += intensity * light_ray.direction().dot(normal);
-    Vec3f view_dir = ray.direction()*-1; // direction from hitpoint to viewer
-    spec_sum += intensity * pow(fmax(view_dir.dot(refl_dir),0), m_ke);
-  }
-  Vec3f diff_color = m_diffuse_color * m_kd * diff_sum;
-  Vec3f spec_color = m_specular_color * m_ks * spec_sum;
+  int n_area_rays = 1000;
+  std::vector<Light*> lights = m_scene->lights();
+  for(unsigned int i = 0; i < lights.size(); ++i)
+    {
+      Vec3f intensity;
 
-  return amb_color + diff_color + spec_color;
+      int max_s = (lights[i]->IsArea()) ? n_area_rays : 1;
+      Vec3f color_l(0.0f,0.0f,0.0f);
+      for(int s = 0; s < max_s; ++s)
+       {
+         
+         if(lights[i]->Illuminate(shadow_ray, intensity))
+           {
+             // check for occluders
+             if(m_scene->Occluded(shadow_ray))
+               {
+                 continue;
+               }
+             
+             float IdotN = shadow_ray.direction().dot(N);
+             if(IdotN > 0)
+               {
+                 // diffuse term
+                 color_l += m_diffuse_color * intensity * IdotN * m_kd;
+               }
+             
+             // specular term
+             float IdotR = shadow_ray.direction().dot(R);
+             if(IdotR > 0)
+               {
+                 color_l += m_specular_color * intensity * pow(IdotR,m_ke) * m_ks;
+               }
+           }
+       }
+      color_l /= static_cast<float>(max_s);
+      color += color_l;
+    }
+  color.clamp();
+  
+  return color;
 }
index 3a18d6c..b83e670 100644 (file)
@@ -2,7 +2,6 @@
 #define PHONGSHADER_HXX
 
 #include "Shader.hxx"
-#include "Scene.hxx"
 
 class PhongShader : public Shader
 {
@@ -16,11 +15,11 @@ public:
              float ks,
              float ke);
   virtual ~PhongShader();
-
+  
   virtual Vec3f Shade(Ray& ray);
 private:
   PhongShader();
-
+  
   Vec3f m_ambient_color, m_diffuse_color, m_specular_color;
   float m_ka, m_kd, m_ks, m_ke;
 };
index 925a6b5..61e4ec8 100644 (file)
@@ -1,7 +1,7 @@
 #include "PointLight.hxx"
 
 PointLight::PointLight(Scene* scene, const Vec3f& pos, const Vec3f& intensity)
-  : Light(scene),
+  : Light(scene), 
     m_pos(pos),
     m_intensity(intensity)
 {
@@ -12,27 +12,31 @@ PointLight::~PointLight()
 }
 
 PointLight::PointLight()
-  : Light(0),
+  : Light(0), 
     m_pos(Vec3f()),
     m_intensity(Vec3f())
 {
 }
 
 bool
-PointLight::Illuminate(Ray& ray, Vec3f& intensity)
+PointLight::Illuminate(Ray& shadow_ray, Vec3f& intensity)
 {
-  Vec3f dir = (ray.origin() + ray.direction() * (ray.t()-Epsilon)) - m_pos;
-  float dist = dir.norm();
+  // distance to light source
+  Vec3f dir = m_pos-shadow_ray.origin();
+  float r = dir.norm()-Epsilon;
+  float falloff = 1.0f/(r*r);
+  
+  
+  intensity = m_intensity * falloff;
+  
+  // modify ray for shadow computation
+  shadow_ray.setHit(0);
+  // for shadow calculation
+  shadow_ray.setT(r);
+  // set direction to light source
   dir.normalize();
-
-  float c1 = 1, c2 = 0.5, c3 = 0;
-  //float f_att = 1 / (dist*dist);
-  float f_att = 1 / (c1 + c2*dist + c3*dist*dist);
-
-  intensity = m_intensity * f_att;
-
-  // store direction from light to hitpoint
-  ray.setDir(dir);
+  shadow_ray.setDir(dir);
+  
   return true;
 }
 
@@ -48,4 +52,8 @@ PointLight::intensity() const
   return m_intensity;
 }
 
-
+bool
+PointLight::IsArea() 
+{
+  return false;
+}
index b086116..ffd4390 100644 (file)
@@ -14,6 +14,8 @@ public:
   const Vec3f& position() const;
   const Vec3f& intensity() const;
 
+  virtual bool IsArea();
+
 private:
   PointLight();
  
index 68dd11c..14233ad 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "Ray.hxx"
 #include "Shader.hxx"
+#include "Box.hxx"
 
 class Primitive
 {
@@ -13,6 +14,8 @@ public:
   virtual bool Intersect(Ray &ray) = 0;
   virtual bool Occluded(Ray& ray);
   virtual Vec3f GetNormal(Ray& ray) = 0;
+  virtual Box CalcBounds() = 0;
+  virtual bool InVoxel(const Box& box) = 0;
   Shader* shader();
   
 protected:
diff --git a/QuadAreaLight.cxx b/QuadAreaLight.cxx
new file mode 100644 (file)
index 0000000..ed64910
--- /dev/null
@@ -0,0 +1,74 @@
+#include <cmath>
+
+#include "QuadAreaLight.hxx"
+
+QuadAreaLight::QuadAreaLight(Scene* scene,
+                            const Vec3f& intensity,
+                            const Vec3f& p1,
+                            const Vec3f& p2,
+                            const Vec3f& p3,
+                            const Vec3f& p4)
+  : Light(scene),
+    m_p0(p1),
+    m_e1(p2-p1),
+    m_e2(p3-p1),
+    m_intensity(intensity)
+{
+  m_n = m_e1.cross(m_e2);
+  m_area = m_n.norm();
+  m_n.normalize(); 
+}
+
+QuadAreaLight::QuadAreaLight()
+  : Light(0),
+    m_p0(Vec3f()),
+    m_e1(Vec3f()),
+    m_e2(Vec3f()),
+    m_n(Vec3f()),
+    m_intensity(Vec3f())
+{
+}
+
+QuadAreaLight::~QuadAreaLight()
+{
+}
+
+bool
+QuadAreaLight::Illuminate(Ray& shadow_ray, Vec3f& intensity)
+{
+  // generate random factors 
+  float xi1 = drand48();
+  float xi2 = drand48();
+  
+  // bilinear interpolation of position
+  Vec3f pos = m_p0 + m_e1 * xi1 + m_e2* xi2;
+  // direction of shadow ray
+  Vec3f dir = pos-shadow_ray.origin();
+  
+  float dist = dir.norm();
+  float cosN = (dir.dot(m_n)) / dist;
+
+  if(cosN <= 0.0f )
+    return false;
+  
+  // squared falloff and projected area
+  intensity = m_intensity * ( m_area * cosN / ( dist*dist));
+
+  dir.normalize();
+  shadow_ray.setDir(dir);
+  shadow_ray.setT(dist);
+
+  return true;
+}
+
+bool
+QuadAreaLight::IsArea()
+{
+  return true;
+}
+
+const Vec3f&
+QuadAreaLight::GetNormal(const Vec3f& pos) const
+{
+  return m_n;
+}
diff --git a/QuadAreaLight.hxx b/QuadAreaLight.hxx
new file mode 100644 (file)
index 0000000..108d5c4
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef QUADAREALIGHT_HXX
+#define QUADAREALIGHT_HXX
+
+#include "Light.hxx"
+
+class QuadAreaLight : public Light
+{
+public:
+  //! Points p1 to p4 are assumed to define a planar rectangular region and have to be given counter-clockwise
+  QuadAreaLight(Scene* scene, const Vec3f& intensity, const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4);
+  virtual ~QuadAreaLight();
+               
+  virtual bool Illuminate(Ray& shadow_ray, Vec3f& intensity);
+  virtual bool IsArea();
+
+  const Vec3f& GetNormal(const Vec3f& position) const;
+
+private:
+  QuadAreaLight();
+  
+  // defines the quad by one point and to vectors
+  Vec3f m_p0, m_e1, m_e2;
+  // normal
+  Vec3f m_n;
+  // emission(red, green, blue)
+  Vec3f m_intensity;
+  // area
+  float m_area;
+};
+#endif
index 0adb174..59f9444 100644 (file)
@@ -24,11 +24,14 @@ Vec3f
 ReflectiveEyeLightShader::Shade(Ray& ray)
 {
   Vec3f N = ray.hit()->GetNormal(ray);
+  // turn normal to front
+  if(N.dot(ray.direction()) > 0)
+    N *= -1;
   
-  // diffuse color
-  Vec3f color = EyeLightShader::Shade(ray); 
+  float cos_phi = fabs(ray.direction().dot(N));
+
+  Vec3f color = m_color * cos_phi;
  
-  // add reflection
   if(ray.recursionDepth() < RecursionDepth)
     {
       // generate reflected ray
index a1d3acd..9d78bc6 100644 (file)
--- a/Scene.cxx
+++ b/Scene.cxx
@@ -1,21 +1,37 @@
+#include <sstream>
+#include <fstream>
+
+
 #include "Scene.hxx"
 #include "PerspectiveCamera.hxx"
+#include "EyeLightShader.hxx"
+#include "Triangle.hxx"
 
 Scene::Scene()
-  : m_camera(new PerspectiveCamera(Vec3f(0,0,8),
-                                  Vec3f(0,0,-1),
-                                  Vec3f(0,1,0),
-                                  50,
-                                  640,
+  : m_camera(new PerspectiveCamera(Vec3f(0,0,8), 
+                                  Vec3f(0,0,-1), 
+                                  Vec3f(0,1,0), 
+                                  60, 
+                                  640, 
                                   480)
             ),
-    m_bgColor(Vec3f(0,0,0))
+    m_bgColor(Vec3f(0,0,0)),
+    m_shader(0),
+    m_scene_box(Box())
 {
 }
 
 Scene::~Scene()
 {
   delete m_camera;
+  if(m_shader != 0)
+    delete m_shader;
+
+  for(unsigned int i = 0; i < m_primitives.size(); ++i)
+    {
+      delete m_primitives[i];
+    }
+  m_primitives.clear();
 }
 
 Scene::Scene(const Scene& s)
@@ -29,7 +45,7 @@ Scene::operator=(const Scene& s)
   return *this;
 }
 
-void
+void 
 Scene::Add(Primitive* p)
 {
   m_primitives.push_back(p);
@@ -50,14 +66,14 @@ Scene::Intersect(Ray& ray)
     {
       intersect |= m_primitives[i]->Intersect(ray);
     }
-
+  
   return intersect;
 }
 
 bool
 Scene::Occluded(Ray& ray)
 {
-  return false;
+  return this->Intersect(ray);
 }
 
 Vec3f
@@ -67,8 +83,129 @@ Scene::RayTrace(Ray& ray)
   return (intersect) ? ray.hit()->shader()->Shade(ray) : m_bgColor;
 }
 
-const Camera*
+const Camera* 
 Scene::camera() const
 {
   return m_camera;
 }
+
+std::vector<Light*> 
+Scene::lights() const
+{
+  return m_lights;
+}
+
+void
+Scene::setCamera(const Camera* camera)
+{
+  if(m_camera != 0)
+    delete m_camera;
+  m_camera = const_cast<Camera*>(camera);
+}
+
+void
+Scene::ParseOBJ(const std::string& file, float scale)
+{
+  std::cerr << "(Scene): Parsing OBJ file : " << file << std::endl;
+  
+  // clear old buffers
+  m_vertices.clear();
+  m_faces.clear();
+  
+  // for the moment, we will attach a white eyelight shader to each object
+  // in the future, you will extend your parser to also read in material definitiions
+  if(m_shader == 0) // not yet defined
+    m_shader = new EyeLightShader(this, Vec3f(1.0,1.0,1.0));
+  
+
+  // now open file
+  std::fstream in;
+  in.open(file.c_str(), std::ios::in);
+  if(in.bad() || in.fail())
+    {
+      std::cerr << "(Scene): Could not open file " << file << std::endl;
+      return;
+    }
+  
+  // read lines
+  std::string line;
+  while(!in.eof())
+    {
+      std::getline(in, line);
+      this->parseOBJLine(line);
+    }
+
+  // finished parsing file -> close fileStream
+  in.close();
+
+  // build triangle list from parsed vertices
+  this->buildTriangleList(scale);
+  
+  std::cerr << "(Scene): Finished parsing." << std::endl;
+}
+
+
+void
+Scene::parseOBJLine(const std::string& line)
+{
+  std::istringstream iss(line);
+  std::string key;
+  iss >> key;
+  if (key == "v") 
+    {
+      // parse vertex //
+      this->parseVertex(iss);
+    }
+  else if (key == "f") 
+    {
+      // parse face //
+      this->parseFace(iss);
+    }
+}
+
+void
+Scene::parseVertex(std::istringstream& iss)
+{
+  Vec3f v;
+  iss >> v[0] >> v[1] >> v[2];
+
+  m_vertices.push_back(v);
+  m_centroid += v;
+}
+
+void
+Scene::parseFace(std::istringstream& iss)
+{
+  Vec3f f;
+  iss >> f[0] >> f[1] >> f[2];
+  m_faces.push_back(f);
+}
+
+void
+Scene::buildTriangleList(float fac)
+{
+  for(unsigned int f = 0; f < m_faces.size(); ++f)
+    {
+      // stores indices of triangle into vertex list
+      // remember: indices start at 1!!
+      Vec3f face_idx = m_faces[f];
+      this->Add(new Triangle(m_vertices[ face_idx[0]-1 ] * fac, 
+                            m_vertices[ face_idx[1]-1 ] * fac, 
+                            m_vertices[ face_idx[2]-1 ] * fac,
+                            m_shader));
+      
+    } 
+  m_centroid /= static_cast<float>(m_vertices.size());
+  std::cerr << "(Scene): Model centroid = " << m_centroid * fac << std::endl;
+}
+
+void
+Scene::CalcBounds()
+{
+}
+
+const Box&
+Scene::GetSceneBox() const
+{
+  return m_scene_box;
+}
index 74154eb..baafce6 100644 (file)
--- a/Scene.hxx
+++ b/Scene.hxx
@@ -2,6 +2,9 @@
 #define SCENE_HXX
 
 #include <vector>
+#include <string>
+#include <fstream>
+
 
 #include "Ray.hxx"
 #include "Camera.hxx"
@@ -13,7 +16,7 @@ class Scene
 public:
   Scene();
   virtual ~Scene();
-
+  
   // add another primitive to the scene
   void Add(Primitive* p);
   // add another light source to the scene
@@ -23,22 +26,49 @@ public:
   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);
+    
+  // acces to camera and light sources
+  const Camera* camera() const; 
+  std::vector<Light*> lights() const;
 
-  const Camera* camera() const;
-  // lights
-  std::vector<Light*> m_lights;
+  // set new camera
+  void setCamera(const Camera* camera);
+
+  // reads in a scene description
+  void ParseOBJ(const std::string& file, float factor);
+  // calculate scene bounding box
+  void CalcBounds();
+
+  const Box& GetSceneBox() const;
 private:
   Scene(const Scene& );
   Scene& operator=(const Scene& );
 
+  void parseOBJLine(const std::string& line);
+  void parseVertex(std::istringstream& iss);
+  void parseFace(std::istringstream& iss);
+  void buildTriangleList(float scale);
+
   Camera* m_camera;
   // background color
   Vec3f m_bgColor;
-
+  
   // primitives
   std::vector<Primitive*> m_primitives;
+  // lights
+  std::vector<Light*> m_lights;
+
+  // shader used by loading routine
+  Shader* m_shader;
+
+  // storage for vertices and face indices
+  std::vector<Vec3f> m_vertices, m_faces;
+  Vec3f m_centroid;
+
+  // scene bounding box
+  Box m_scene_box;
 };
 #endif
index 6b8d943..fd9ba89 100644 (file)
@@ -48,3 +48,15 @@ Sphere::GetNormal(Ray& ray)
 
   return N;
 }
+
+Box
+Sphere::CalcBounds()
+{
+  return Box();
+}
+
+bool
+Sphere::InVoxel(const Box& box)
+{
+  return false;
+}
index 28604e7..cc07bfe 100644 (file)
@@ -12,6 +12,8 @@ public:
 
   virtual bool Intersect(Ray& ray);  
   virtual Vec3f GetNormal(Ray& ray);
+  virtual Box CalcBounds();
+  virtual bool InVoxel(const Box& box);
 private:
   Vec3f m_center;
   float m_radius;
index 8ec7cf6..0ccef8a 100644 (file)
@@ -4,15 +4,16 @@ SpotLight::SpotLight(Scene* scene,
                     const Vec3f& pos,
                     const Vec3f& dir,
                     const Vec3f& intensity,
-                    float alpha_min,
-                    float alpha_max)
+                    float alpha_min, // in degree
+                    float alpha_max) // in degree
   : Light(scene),
     m_pos(pos),
     m_dir(dir),
     m_intensity(intensity),
-    m_alpha_min(alpha_min),
+    m_alpha_min(alpha_min), 
     m_alpha_max(alpha_max)
 {
+  m_dir.normalize();
 }
 
 SpotLight::~SpotLight()
@@ -30,9 +31,47 @@ SpotLight::SpotLight()
 }
 
 bool
-SpotLight::Illuminate(Ray& ray, Vec3f& intensity)
+SpotLight::Illuminate(Ray& shadow_ray, Vec3f& intensity)
 {
-  return false;
+  // direction vector from light source to surface point
+  Vec3f D = shadow_ray.origin()-m_pos;
+  D.normalize();
+  // angle between light source dir and shadow ray dir
+  float phi = fabs(acos(D.dot(m_dir))*180/M_PI);
+  
+  // outside cone
+  if(phi > m_alpha_max) 
+    {
+      return false;
+    }
+  else 
+    {
+      Vec3f dir = m_pos-shadow_ray.origin();
+      float r = dir.norm()-Epsilon;
+      float falloff = 1.0f/(r*r); // falloff for distance
+      
+      // modify ray for shadow computation
+      shadow_ray.setHit(0);
+      // for shadow calculation
+      shadow_ray.setT(r);
+      // set direction to light source
+      dir.normalize();
+      shadow_ray.setDir(dir);
+
+      if(phi < m_alpha_min) 
+       {
+         intensity = m_intensity * falloff;
+       }
+      else 
+       {
+         // linear falloff from 1 at alpha_min to 0 at alpha_max 
+         float partial = 1.0f-(phi-m_alpha_min)/(m_alpha_max-m_alpha_min);
+         intensity = m_intensity * falloff * partial;
+         
+       }
+      return true;
+    }
+  return true;
 }
 
 const Vec3f&
@@ -46,3 +85,9 @@ SpotLight::direction() const
 {
   return m_dir;
 }
+
+bool
+SpotLight::IsArea()
+{
+  return false;
+}
index ed404d8..4a938b9 100644 (file)
@@ -10,10 +10,11 @@ public:
   virtual ~SpotLight();
 
   virtual bool Illuminate(Ray& ray, Vec3f& intensity);
+  virtual bool IsArea();
   
   const Vec3f& position() const;
   const Vec3f& direction() const;
+  
 private:
   SpotLight();
 
index 498757e..ed12db0 100644 (file)
@@ -60,3 +60,15 @@ Triangle::GetNormal(Ray& ray)
 {
   return m_n;
 }
+
+Box
+Triangle::CalcBounds()
+{
+  return Box();
+}
+
+bool
+Triangle::InVoxel(const Box& box)
+{
+  return false;
+}
index 6abbe53..8e56231 100644 (file)
@@ -11,6 +11,8 @@ public:
   
   virtual bool Intersect(Ray& ray);
   virtual Vec3f GetNormal(Ray& ray);
+  virtual Box CalcBounds();
+  virtual bool InVoxel(const Box& box);
 private:
   Vec3f m_a, m_b, m_c;
   Vec3f m_n;
index 81c0c8b..eef3409 100644 (file)
--- a/Vec3f.hxx
+++ b/Vec3f.hxx
@@ -11,7 +11,7 @@
 #endif
 
 
-#define Epsilon 1E-3
+#define Epsilon 1E-4
 #define Infinity HUGE_VAL
 
 //! Standard operators and useful methods for 3d vectors
diff --git a/cone.obj b/cone.obj
new file mode 100644 (file)
index 0000000..7cf97f8
--- /dev/null
+++ b/cone.obj
@@ -0,0 +1,99 @@
+cp# The units used in this file are centimeters.
+v 0.196157 -0.150000 -0.039018
+v 0.184776 -0.150000 -0.076537
+v 0.166294 -0.150000 -0.111114
+v 0.141421 -0.150000 -0.141421
+v 0.111114 -0.150000 -0.166294
+v 0.076537 -0.150000 -0.184776
+v 0.039018 -0.150000 -0.196157
+v 0.000000 -0.150000 -0.200000
+v -0.039018 -0.150000 -0.196157
+v -0.076537 -0.150000 -0.184776
+v -0.111114 -0.150000 -0.166294
+v -0.141421 -0.150000 -0.141421
+v -0.166294 -0.150000 -0.111114
+v -0.184776 -0.150000 -0.076537
+v -0.196157 -0.150000 -0.039018
+v -0.200000 -0.150000 -0.000000
+v -0.196157 -0.150000 0.039018
+v -0.184776 -0.150000 0.076537
+v -0.166294 -0.150000 0.111114
+v -0.141421 -0.150000 0.141421
+v -0.111114 -0.150000 0.166294
+v -0.076537 -0.150000 0.184776
+v -0.039018 -0.150000 0.196157
+v -0.000000 -0.150000 0.200000
+v 0.039018 -0.150000 0.196157
+v 0.076537 -0.150000 0.184776
+v 0.111114 -0.150000 0.166294
+v 0.141421 -0.150000 0.141421
+v 0.166294 -0.150000 0.111114
+v 0.184776 -0.150000 0.076537
+v 0.196157 -0.150000 0.039018
+v 0.200000 -0.150000 0.000000
+v 0.000000 -0.150000 0.000000
+v 0.000000 0.150000 0.000000
+f 2 1 33 
+f 3 2 33 
+f 4 3 33 
+f 5 4 33 
+f 6 5 33 
+f 7 6 33 
+f 8 7 33 
+f 9 8 33 
+f 10 9 33
+f 11 10 33 
+f 12 11 33 
+f 13 12 33 
+f 14 13 33 
+f 15 14 33 
+f 16 15 33 
+f 17 16 33 
+f 18 17 33 
+f 19 18 33 
+f 20 19 33 
+f 21 20 33 
+f 22 21 33 
+f 23 22 33 
+f 24 23 33 
+f 25 24 33 
+f 26 25 33 
+f 27 26 33 
+f 28 27 33 
+f 29 28 33 
+f 30 29 33 
+f 31 30 33 
+f 32 31 33 
+f 1 32 33 
+f 1 2 34 
+f 2 3 34 
+f 3 4 34 
+f 4 5 34 
+f 5 6 34 
+f 6 7 34 
+f 7 8 34 
+f 8 9 34 
+f 9 10 34 
+f 10 11 34 
+f 11 12 34 
+f 12 13 34 
+f 13 14 34 
+f 14 15 34 
+f 15 16 34 
+f 16 17 34 
+f 17 18 34 
+f 18 19 34 
+f 19 20 34 
+f 20 21 34 
+f 21 22 34 
+f 22 23 34 
+f 23 24 34 
+f 24 25 34 
+f 25 26 34 
+f 26 27 34 
+f 27 28 34 
+f 28 29 34 
+f 29 30 34 
+f 30 31 34 
+f 31 32 34 
+f 32 1 34 
diff --git a/kDTree.cxx b/kDTree.cxx
new file mode 100644 (file)
index 0000000..d329a83
--- /dev/null
@@ -0,0 +1,139 @@
+#include "kDTree.hxx"
+
+/*************** kDTreeInnerNode ******************/
+
+kDTreeInnerNode::kDTreeInnerNode(float split,
+                                int axis)
+  : m_split(split),
+    m_axis(axis)
+{
+}
+
+kDTreeInnerNode::~kDTreeInnerNode()
+{
+  // think about correct memory management!  
+}
+
+kDTreeInnerNode::kDTreeInnerNode()
+{
+}
+
+kDTreeInnerNode::kDTreeInnerNode(const kDTreeInnerNode& node)
+{
+  operator=(node);
+}
+
+kDTreeInnerNode&
+kDTreeInnerNode::operator=(const kDTreeInnerNode& )
+{
+  return *this;
+}
+
+bool
+kDTreeInnerNode::Traverse(Ray& ray, float& t0, float& t1)
+{
+  // implement the traversal of an inner node
+  // think about the correct order
+
+  return false;
+}
+
+void
+kDTreeInnerNode::setChildren(kDTreeNode* left,
+                            kDTreeNode* right)
+{
+  m_children[0] = left;
+  m_children[1] = right;
+}
+
+
+/******************** kDTreeLeafNode *******************/
+
+kDTreeLeafNode::kDTreeLeafNode(const std::vector<Primitive*>& prim)
+  : m_primitives(prim)
+{
+  
+}
+
+kDTreeLeafNode::~kDTreeLeafNode()
+{
+}
+
+kDTreeLeafNode::kDTreeLeafNode()
+{
+}
+
+kDTreeLeafNode::kDTreeLeafNode(const kDTreeLeafNode& node)
+{
+  operator=(node);
+}
+
+kDTreeLeafNode&
+kDTreeLeafNode::operator=(const kDTreeLeafNode& )
+{
+  return *this;
+}
+
+bool
+kDTreeLeafNode::Traverse(Ray& ray, float& t0, float& t1)
+{
+  // implement the leaf node traversal here
+  return false;
+}
+
+
+/******************** kDTree ***********************/
+
+kDTree::kDTree(const Box& bounds, 
+              const std::vector<Primitive*>& prim)
+  : m_root(0), 
+    m_bounds(bounds),
+    m_maxDepth(20),
+    m_minTri(3)
+{
+  m_root = BuildTree(m_bounds, prim, 0);
+}
+
+kDTree::~kDTree()
+{
+  // think about correct memory management
+  delete m_root;
+}
+
+kDTree::kDTree()
+  : m_root(0),
+    m_bounds(Box())
+{
+}
+
+kDTree::kDTree(const kDTree& tree)
+{
+  operator=(tree);
+}
+
+kDTree&
+kDTree::operator=(const kDTree& )
+{
+  return *this;
+}
+
+kDTreeNode*
+kDTree::BuildTree(const Box& bounds,
+                 const std::vector<Primitive*>& prim, 
+                 int depth)
+{
+  // setup tree structure here
+  // these two variables are only here to solve compilation issues!
+  float dummy_split = 0.0f;
+  int dummy_axis = 0;
+  kDTreeInnerNode* node = new kDTreeInnerNode(dummy_split, dummy_axis);
+
+  return node;
+}
+
+bool
+kDTree::Intersect(Ray& ray)
+{
+  // implement the tree traversal
+  return false;
+}
diff --git a/kDTree.hxx b/kDTree.hxx
new file mode 100644 (file)
index 0000000..13c1bc4
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef KDTREE_HXX
+#define KDTREE_HXX 
+
+#include <vector>
+
+#include "Box.hxx"
+#include "Primitive.hxx"
+
+//! Interface for tree nodes
+class kDTreeNode
+{
+public:
+  virtual ~kDTreeNode(){;};
+  // interface for the traversal. [t0,t1] code the active ray interval.
+  virtual bool Traverse(Ray &ray, float& t0, float& t1) = 0;
+};
+
+//! An inner node of the kD-tree
+class kDTreeInnerNode : public kDTreeNode
+{
+public:
+  kDTreeInnerNode(float split, int axis);   
+  virtual ~kDTreeInnerNode();
+  
+  virtual bool Traverse(Ray& ray, float& t0, float& t1);
+
+  void setChildren(kDTreeNode* left, kDTreeNode* right);
+private:
+  kDTreeInnerNode();
+  kDTreeInnerNode(const kDTreeInnerNode& );
+  kDTreeInnerNode& operator=(const kDTreeInnerNode& );
+
+  // pointer to the children
+  kDTreeNode* m_children[2]; 
+  // encodes the position of the splitting plane on the splitting axis
+  float m_split;
+  // encodes the splitting axis
+  int m_axis;
+};
+
+//! A leaf node of the kD-tree
+class kDTreeLeafNode : public kDTreeNode
+{
+public:
+  kDTreeLeafNode(const std::vector<Primitive*>& prim);
+  virtual ~kDTreeLeafNode();
+
+  virtual bool Traverse(Ray& ray, float& t0, float& t1);
+  
+private:
+  kDTreeLeafNode();
+  kDTreeLeafNode(const kDTreeLeafNode& );
+  kDTreeLeafNode& operator=(const kDTreeLeafNode& );
+
+  std::vector<Primitive *> m_primitives;
+};
+  
+//! The actual kDTree interface
+class kDTree
+{
+public:
+  kDTree(const Box& bounds, const std::vector<Primitive*>& prim);
+  ~kDTree();
+  
+  kDTreeNode* BuildTree(const Box& bounds,
+                       const std::vector<Primitive *>& prim,
+                       int depth); 
+  
+  bool Intersect(Ray &ray); 
+  
+private:
+  kDTree();
+  kDTree(const kDTree& );
+  kDTree& operator=(const kDTree& );
+
+  // root node
+  kDTreeNode* m_root;
+  // bounding box of the entire tree
+  Box m_bounds;
+  // maximal recursion depth
+  int m_maxDepth;
+  // minimal number of triangles per node
+  int m_minTri;
+};
+#endif
This page took 0.08675 seconds and 4 git commands to generate.