diff --git a/main/Scene-load.cc b/main/Scene-load.cc index af1c1b0..48f9c73 100644 --- a/main/Scene-load.cc +++ b/main/Scene-load.cc @@ -57,6 +57,10 @@ void Scene::processNode(refptr node) { processTransformBlock(node); } + else if ( typeid(*node) == typeid(MaterialDefinitionNode) ) + { + processMaterialDefinition(node); + } else { cerr << __FILE__ << ": " << __LINE__ @@ -183,8 +187,38 @@ void Scene::processTransformBlock(refptr node) m_transforms.pop(); } +void Scene::processMaterialDefinition(refptr node) +{ + map< string, refptr >::iterator it = + m_materials.find(node->getString()); + if ( it == m_materials.end() ) + { + m_materials[node->getString()] = processMaterial(node); + } + else + { + cerr << "Error: duplicate material definition for material '" + << node->getString() << "'" << endl; + exit(4); + } +} + refptr Scene::processMaterial(refptr node) { + if ( typeid(*node) == typeid(MaterialRefNode) ) + { + map< string, refptr >::iterator it = + m_materials.find(node->getString()); + if ( it == m_materials.end() ) + { + cerr << "Undefined material '" << node->getString() + << "' requested!" << endl; + exit(4); + } + + return m_materials[node->getString()]; + } + refptr material = new Material(); for (Node_Iterator it = node->getChildren().begin(); @@ -236,7 +270,7 @@ refptr Scene::processBox(refptr node) { size = (*it)->getVector(); } - else if ( typeid(**it) == typeid(MaterialNode) ) + else if ( (*it)->isMaterial() ) { material = processMaterial(*it); } @@ -273,7 +307,7 @@ refptr Scene::processCyl(refptr node) radius2 = v[1]; height = v[2]; } - else if ( typeid(**it) == typeid(MaterialNode) ) + else if ( (*it)->isMaterial() ) { material = processMaterial(*it); } @@ -340,7 +374,7 @@ refptr Scene::processPlane(refptr node) normal = *(*it)->getVector(); dist = (*it)->getNumber(); } - else if ( typeid(**it) == typeid(MaterialNode) ) + else if ( (*it)->isMaterial() ) { material = processMaterial(*it); } @@ -375,7 +409,7 @@ refptr Scene::processSphere(refptr node) { radius = (*it)->getNumber(); } - else if ( typeid(**it) == typeid(MaterialNode) ) + else if ( (*it)->isMaterial() ) { material = processMaterial(*it); } @@ -415,7 +449,7 @@ refptr Scene::processBool(refptr node) } shapes_seen++; } - else if ( typeid(**it) == typeid(MaterialNode) ) + else if ( (*it)->isMaterial() ) { material = processMaterial(*it); } diff --git a/main/Scene.h b/main/Scene.h index a689273..8630109 100644 --- a/main/Scene.h +++ b/main/Scene.h @@ -70,6 +70,7 @@ class Scene void processCamera(refptr node); void processOptions(refptr node); void processTransformBlock(refptr node); + void processMaterialDefinition(refptr node); /* rendering parameters */ int m_width; @@ -89,6 +90,7 @@ class Scene int m_multisample_level_squared; double m_sample_span; double m_half_sample_span; + std::map< std::string, refptr > m_materials; /* framebuffer */ unsigned char * m_data; diff --git a/parser/nodes.h b/parser/nodes.h index f3a4767..12b9ea6 100644 --- a/parser/nodes.h +++ b/parser/nodes.h @@ -22,6 +22,7 @@ class Node return refptr(NULL); } virtual bool isShape() { return false; } + virtual bool isMaterial() { return false; } virtual std::string getString() { return ""; } protected: @@ -135,6 +136,8 @@ class LookAtNode : public VectorNode class MaterialNode : public Node { + public: + bool isMaterial() { return true; } }; class MaterialDefinitionNode : public IdentifierNode @@ -147,6 +150,7 @@ class MaterialRefNode : public IdentifierNode { public: MaterialRefNode(const std::string & str) : IdentifierNode(str) {} + bool isMaterial() { return true; } }; class MultisampleNode : public IntegerNode