344 lines
9.1 KiB
C++
344 lines
9.1 KiB
C++
|
|
#include <typeinfo>
|
|
#include <iostream>
|
|
#include "Scene.h"
|
|
#include "Light.h"
|
|
#include "parser/parser.h"
|
|
#include "parser/nodes.h"
|
|
|
|
using namespace std;
|
|
|
|
typedef vector< refptr<Node> >::const_iterator Node_Iterator;
|
|
|
|
void Scene::load(const char * filename)
|
|
{
|
|
/* TODO: parse file somehow */
|
|
// refptr<Node> node = parse(filename);
|
|
// processNode(node);
|
|
|
|
Transform transform;
|
|
|
|
refptr<Material> m = new Material();
|
|
m->setDiffuseColor(Color::white);
|
|
m->setAmbientColor(Color::white);
|
|
refptr<Shape> shape = new Plane(0, 0, 1, 2);
|
|
shape->setTransform(transform);
|
|
shape->setMaterial(m);
|
|
m_shapes.push_back(shape);
|
|
|
|
transform.translate(1.0, 5.0, 0.5);
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::red);
|
|
m->setAmbientColor(Color::red);
|
|
shape = new Sphere(1.0);
|
|
shape->setTransform(transform);
|
|
shape->setMaterial(m);
|
|
m_shapes.push_back(shape);
|
|
transform.translate(-1.0, -5.0, -0.5);
|
|
|
|
transform.translate(-1, 3, -0.5);
|
|
refptr<Shape> shape1 = new Sphere(0.8);
|
|
shape1->setMaterial(m);
|
|
shape1->setTransform(transform);
|
|
refptr<Shape> shape2 = new Box(new Vector(2, 2, 0.6));
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::magenta);
|
|
m->setAmbientColor(Color::magenta);
|
|
shape2->setMaterial(m);
|
|
transform.rotate(20, 0, 1, 0);
|
|
shape2->setTransform(transform);
|
|
shape = new Intersect(shape1, shape2);
|
|
m_shapes.push_back(shape);
|
|
transform.rotate(-20, 0, 1, 0);
|
|
transform.translate(1, -3, 0.5);
|
|
|
|
transform.translate(1.5, 3.2, -0.7);
|
|
transform.rotate(15, 0, 0, 1);
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::magenta);
|
|
m->setAmbientColor(Color::magenta);
|
|
shape1 = new Box(new Vector(1, 1, 1));
|
|
shape1->setMaterial(m);
|
|
shape1->setTransform(transform);
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::yellow);
|
|
m->setAmbientColor(Color::yellow);
|
|
shape2 = new Sphere(0.6);
|
|
transform.translate(-0.5, -0.5, 0.5);
|
|
shape2->setTransform(transform);
|
|
shape2->setMaterial(m);
|
|
shape = new Subtract(shape1, shape2);
|
|
m_shapes.push_back(shape);
|
|
transform.rotate(-15, 0, 0, 1);
|
|
transform.translate(-1.0, -2.7, 0.2);
|
|
|
|
transform.translate(1, 5, -1.5);
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::blue);
|
|
m->setAmbientColor(Color::blue);
|
|
shape = new Box(new Vector(1.8, 1.8, 0.5));
|
|
shape->setTransform(transform);
|
|
shape->setMaterial(m);
|
|
m_shapes.push_back(shape);
|
|
transform.translate(-1, -5, 1.5);
|
|
|
|
transform.translate(-0.5, 6.5, 1.5);
|
|
transform.rotate(45, 1, 0, 0);
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::cyan);
|
|
m->setAmbientColor(Color::cyan);
|
|
shape = new Cyl(1.0, 0.0, 2.0);
|
|
shape->setTransform(transform);
|
|
shape->setMaterial(m);
|
|
m_shapes.push_back(shape);
|
|
transform.rotate(-45, 1, 0, 0);
|
|
transform.translate(0.5, -6.5, -1.5);
|
|
|
|
transform.translate(-2.0, 5.0, 1.5);
|
|
transform.rotate(45, 0, 0, 1);
|
|
transform.rotate(45, 1, 0, 0);
|
|
m = new Material();
|
|
m->setDiffuseColor(Color::yellow);
|
|
m->setAmbientColor(Color::yellow);
|
|
shape = new Box(new Vector(1, 1, 1));
|
|
shape->setTransform(transform);
|
|
shape->setMaterial(m);
|
|
m_shapes.push_back(shape);
|
|
transform.rotate(-45, 1, 0, 0);
|
|
transform.rotate(-45, 0, 0, 1);
|
|
transform.translate(2.0, -5.0, -1.5);
|
|
|
|
refptr<Light> light = new PointLight();
|
|
light->setPosition(Vector(2, -1, 2));
|
|
m_lights.push_back(light);
|
|
}
|
|
|
|
void Scene::processNode(refptr<Node> node)
|
|
{
|
|
if (node.isNull())
|
|
return;
|
|
|
|
if ( typeid(*node) == typeid(SceneNode) )
|
|
{
|
|
processChildren(node);
|
|
}
|
|
else if ( typeid(*node) == typeid(BoxNode) )
|
|
{
|
|
cout << "saw a box" << endl;
|
|
}
|
|
else if ( typeid(*node) == typeid(MaterialNode) )
|
|
{
|
|
refptr<Material> mat = processMaterial(node);
|
|
}
|
|
else if ( typeid(*node) == typeid(PlaneNode) )
|
|
{
|
|
cout << "saw a plane" << endl;
|
|
}
|
|
else if ( typeid(*node) == typeid(SphereNode) )
|
|
{
|
|
cout << "saw a sphere" << endl;
|
|
}
|
|
|
|
}
|
|
|
|
void Scene::processChildren(refptr<Node> node)
|
|
{
|
|
std::vector< refptr<Node> > & children = node->getChildren();
|
|
for (int i = 0, sz = children.size(); i < sz; i++)
|
|
{
|
|
processNode(children[i]);
|
|
}
|
|
}
|
|
|
|
refptr<Material> Scene::processMaterial(refptr<Node> node)
|
|
{
|
|
refptr<Material> material = new Material();
|
|
|
|
for (Node_Iterator it = node->getChildren().begin();
|
|
it != node->getChildren().end();
|
|
it++)
|
|
{
|
|
if ( typeid(**it) == typeid(ColorNode) )
|
|
{
|
|
material->setDiffuseColor(Color((*it)->getVector()));
|
|
material->setAmbientColor(Color((*it)->getVector()));
|
|
}
|
|
else if ( typeid(**it) == typeid(AmbientNode) )
|
|
{
|
|
material->setAmbientColor(Color((*it)->getVector()));
|
|
}
|
|
else if ( typeid(**it) == typeid(DiffuseNode) )
|
|
{
|
|
material->setDiffuseColor(Color((*it)->getVector()));
|
|
}
|
|
else if ( typeid(**it) == typeid(SpecularNode) )
|
|
{
|
|
material->setSpecularColor(Color((*it)->getVector()));
|
|
}
|
|
else if ( typeid(**it) == typeid(ReflectanceNode) )
|
|
{
|
|
material->setReflectance((*it)->getNumber());
|
|
}
|
|
else if ( typeid(**it) == typeid(ShininessNode) )
|
|
{
|
|
material->setShininess((*it)->getNumber());
|
|
}
|
|
}
|
|
|
|
return material;
|
|
}
|
|
|
|
refptr<Shape> Scene::processBox(refptr<Node> node)
|
|
{
|
|
refptr<Vector> size = new Vector(1, 1, 1);
|
|
refptr<Material> material;
|
|
|
|
bool restore_transform = processTransforms(node);
|
|
|
|
for (Node_Iterator it = node->getChildren().begin();
|
|
it != node->getChildren().end();
|
|
it++)
|
|
{
|
|
if ( typeid(**it) == typeid(SizeNode) )
|
|
{
|
|
size = (*it)->getVector();
|
|
}
|
|
else if ( typeid(**it) == typeid(MaterialNode) )
|
|
{
|
|
material = processMaterial(*it);
|
|
}
|
|
}
|
|
|
|
refptr<Shape> box = new Box(size);
|
|
if ( ! material.isNull() )
|
|
box->setMaterial(material);
|
|
box->setTransform(m_transforms.top());
|
|
|
|
if (restore_transform)
|
|
m_transforms.pop();
|
|
|
|
return box;
|
|
}
|
|
|
|
refptr<Shape> Scene::processCyl(refptr<Node> node)
|
|
{
|
|
double radius1 = 1.0;
|
|
double radius2 = 1.0;
|
|
double height = 1.0;
|
|
refptr<Material> material;
|
|
|
|
bool restore_transform = processTransforms(node);
|
|
|
|
for (Node_Iterator it = node->getChildren().begin();
|
|
it != node->getChildren().end();
|
|
it++)
|
|
{
|
|
if ( typeid(**it) == typeid(SizeNode) )
|
|
{
|
|
const Vector & v = *(*it)->getVector();
|
|
radius1 = v[0];
|
|
radius2 = v[1];
|
|
height = v[2];
|
|
}
|
|
else if ( typeid(**it) == typeid(MaterialNode) )
|
|
{
|
|
material = processMaterial(*it);
|
|
}
|
|
}
|
|
|
|
refptr<Shape> cyl = new Cyl(radius1, radius2, height);
|
|
if ( ! material.isNull() )
|
|
cyl->setMaterial(material);
|
|
cyl->setTransform(m_transforms.top());
|
|
|
|
if (restore_transform)
|
|
m_transforms.pop();
|
|
|
|
return cyl;
|
|
}
|
|
|
|
refptr<Light> Scene::processLight(refptr<Node> node)
|
|
{
|
|
/* TODO: finish */
|
|
return refptr<Light>(NULL);
|
|
}
|
|
|
|
refptr<Shape> Scene::processPlane(refptr<Node> node)
|
|
{
|
|
/* TODO: finish */
|
|
return refptr<Shape>(NULL);
|
|
}
|
|
|
|
refptr<Shape> Scene::processSphere(refptr<Node> node)
|
|
{
|
|
double radius = 1.0;
|
|
refptr<Material> material;
|
|
|
|
bool restore_transform = processTransforms(node);
|
|
|
|
for (Node_Iterator it = node->getChildren().begin();
|
|
it != node->getChildren().end();
|
|
it++)
|
|
{
|
|
if ( typeid(**it) == typeid(RadiusNode) )
|
|
{
|
|
radius = (*it)->getNumber();
|
|
}
|
|
else if ( typeid(**it) == typeid(MaterialNode) )
|
|
{
|
|
material = processMaterial(*it);
|
|
}
|
|
}
|
|
|
|
refptr<Shape> sphere = new Sphere(radius);
|
|
if ( ! material.isNull() )
|
|
sphere->setMaterial(material);
|
|
sphere->setTransform(m_transforms.top());
|
|
|
|
if (restore_transform)
|
|
m_transforms.pop();
|
|
|
|
return sphere;
|
|
}
|
|
|
|
bool Scene::processTransforms(refptr<Node> node)
|
|
{
|
|
bool did_any = false;
|
|
|
|
for (Node_Iterator it = node->getChildren().begin();
|
|
it != node->getChildren().end();
|
|
it++)
|
|
{
|
|
if ( typeid(**it) == typeid(TranslateNode) )
|
|
{
|
|
if (did_any == false)
|
|
{
|
|
m_transforms.push(m_transforms.top());
|
|
did_any = true;
|
|
}
|
|
m_transforms.top().translate((*it)->getVector());
|
|
}
|
|
else if ( typeid(**it) == typeid(RotateNode) )
|
|
{
|
|
if (did_any == false)
|
|
{
|
|
m_transforms.push(m_transforms.top());
|
|
did_any = true;
|
|
}
|
|
m_transforms.top().rotate((*it)->getNumber(),
|
|
(*it)->getVector());
|
|
}
|
|
else if ( typeid(**it) == typeid(ScaleNode) )
|
|
{
|
|
if (did_any == false)
|
|
{
|
|
m_transforms.push(m_transforms.top());
|
|
did_any = true;
|
|
}
|
|
m_transforms.top().scale((*it)->getVector());
|
|
}
|
|
}
|
|
|
|
return did_any;
|
|
}
|