*.o
MicroTrace
+*.png
+*.ppm
--- /dev/null
+#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;
+}
--- /dev/null
+#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
{
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]) << " "
{
return m_n;
}
+
+Box
+InfinitePlane::CalcBounds()
+{
+ return Box();
+}
+
+bool
+InfinitePlane::InVoxel(const Box& box)
+{
+ return false;
+}
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;
};
virtual ~Light();
virtual bool Illuminate(Ray& shadowray, Vec3f& intensity) = 0;
+ virtual bool IsArea() = 0;
protected:
Scene* m_scene;
all: MicroTrace
CC = g++
-CFLAGS = -O3 -Wall
+CFLAGS = -O3 -Wall -fopenmp
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 $@
MicroTrace: $(OBJ)
-
+ g++ -fopenmp $(OBJ) -o MicroTrace
clean:
rm *~ *.o *.a MicroTrace
+#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");
}
#include <limits>
#include <iostream>
+#include <cassert>
#include "PerspectiveCamera.hxx"
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);
PerspectiveCamera&
PerspectiveCamera::operator=(const PerspectiveCamera& )
{
+ assert(!"Not implemented!");
return *this;
}
+#include <vector>
+
#include "PhongShader.hxx"
#include "Primitive.hxx"
+#include "Scene.hxx"
PhongShader::PhongShader(Scene* scene,
const Vec3f& am_c,
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;
}
#define PHONGSHADER_HXX
#include "Shader.hxx"
-#include "Scene.hxx"
class PhongShader : public Shader
{
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;
};
#include "PointLight.hxx"
PointLight::PointLight(Scene* scene, const Vec3f& pos, const Vec3f& intensity)
- : Light(scene),
+ : Light(scene),
m_pos(pos),
m_intensity(intensity)
{
}
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;
}
return m_intensity;
}
-
+bool
+PointLight::IsArea()
+{
+ return false;
+}
const Vec3f& position() const;
const Vec3f& intensity() const;
+ virtual bool IsArea();
+
private:
PointLight();
#include "Ray.hxx"
#include "Shader.hxx"
+#include "Box.hxx"
class Primitive
{
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:
--- /dev/null
+#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;
+}
--- /dev/null
+#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
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
+#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)
return *this;
}
-void
+void
Scene::Add(Primitive* p)
{
m_primitives.push_back(p);
{
intersect |= m_primitives[i]->Intersect(ray);
}
-
+
return intersect;
}
bool
Scene::Occluded(Ray& ray)
{
- return false;
+ return this->Intersect(ray);
}
Vec3f
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;
+}
#define SCENE_HXX
#include <vector>
+#include <string>
+#include <fstream>
+
#include "Ray.hxx"
#include "Camera.hxx"
public:
Scene();
virtual ~Scene();
-
+
// add another primitive to the scene
void Add(Primitive* p);
// add another light source to 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);
+
+ // 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
return N;
}
+
+Box
+Sphere::CalcBounds()
+{
+ return Box();
+}
+
+bool
+Sphere::InVoxel(const Box& box)
+{
+ return false;
+}
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;
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()
}
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&
{
return m_dir;
}
+
+bool
+SpotLight::IsArea()
+{
+ return false;
+}
virtual ~SpotLight();
virtual bool Illuminate(Ray& ray, Vec3f& intensity);
+ virtual bool IsArea();
const Vec3f& position() const;
const Vec3f& direction() const;
-
+
private:
SpotLight();
{
return m_n;
}
+
+Box
+Triangle::CalcBounds()
+{
+ return Box();
+}
+
+bool
+Triangle::InVoxel(const Box& box)
+{
+ return false;
+}
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;
#endif
-#define Epsilon 1E-3
+#define Epsilon 1E-4
#define Infinity HUGE_VAL
//! Standard operators and useful methods for 3d vectors
--- /dev/null
+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
--- /dev/null
+#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;
+}
--- /dev/null
+#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