+#include <sstream>
+#include <fstream>
+
+
#include "Scene.hxx"
#include "PerspectiveCamera.hxx"
-#include <limits>
+#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);
}
+void
+Scene::Add(Light* l)
+{
+ m_lights.push_back(l);
+}
bool
Scene::Intersect(Ray& ray)
{
- bool hit = false;
- float t = std::numeric_limits<float>::max();
- for (std::vector<Primitive*>::iterator i = m_primitives.begin();
- i != m_primitives.end(); i++) {
- // store closest object hit
- if (hit |= (*i)->Intersect(ray)) {
- if (ray.t() < t) {
- ray.setHit(*i);
- t = ray.t();
- }
+ bool intersect = false;
+
+ for(unsigned int i = 0; i < m_primitives.size(); ++i)
+ {
+ intersect |= m_primitives[i]->Intersect(ray);
}
- }
- return hit;
+
+ return intersect;
}
bool
Scene::Occluded(Ray& ray)
{
- return false;
+ return this->Intersect(ray);
}
Vec3f
Scene::RayTrace(Ray& ray)
{
- if (Intersect(ray)) {
- return ray.hit()->shader()->Shade(ray);
- } else {
- return Vec3f(0,0,0);
- }
+ bool intersect = this->Intersect(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;
+}