SceneGraph.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   SceneGraph.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Bare-bones scene graph used during scene parsing
00009    <!-------------------------------------------------------------------->**/
00010 
00011 #include "SceneGraph.h"
00012 #include "MiltonJSONSceneLoader.h"
00013 #include <milton.h>
00014 
00015 #include <QtCore>
00016 #include <boost/any.hpp>
00017 #include <typeinfo>
00018 #include <iostream>
00019 #include <fstream>
00020 
00021 
00022 bool SceneGraph::flatten(JSONParseData &data) {
00023    data << "flattening scenegraph" << endl;
00024    
00025    ASSERT(data.sceneGraph.size() == 1);
00026    ASSERT(data.instance == 0);
00027    
00028    { // initialize default material
00029       Material *defaultMaterial = new Material();
00030       defaultMaterial->init();
00031       data.activeMaterial = defaultMaterial;
00032       data.materials.push_back(defaultMaterial);
00033    }
00034    
00035    { // traverse scenegraph
00036       SceneNode *root = data.sceneGraph.pop();
00037       
00038       bool retVal = 
00039          flatten(root, Matrix4x4::identity(), Matrix4x4::identity(), data);
00040       
00041       ASSERT(data.instance == 0);
00042       safeDelete(root);
00043       
00044       return retVal;
00045    }
00046 }
00047 
00048 bool SceneGraph::flatten(SceneNode *node, 
00049                          Matrix4x4 transform, 
00050                          Matrix4x4 transformInv, 
00051                          JSONParseData &data)
00052 {
00053    ASSERT(node);
00054    
00055    // pre-order traversal (visit current node before children)
00056    if (!node->flatten(transform, transformInv, data))
00057       return false;
00058    
00059    Material *activeMaterial = data.activeMaterial;
00060    ShapeSet *activeShapeSet = data.primitives;
00061    
00062    // traverse all children
00063    FOREACH(SceneNodeListIter, node->children, iter) {
00064       SceneNode *child = *iter;
00065       ASSERT(child);
00066       
00067       // recursively flatten current child
00068       if (!flatten(child, transform, transformInv, data))
00069          return false;
00070       
00071       // ensure active material is restored to current level
00072       data.activeMaterial = activeMaterial;
00073       data.primitives     = activeShapeSet;
00074    }
00075    
00076    return true;
00077 }
00078 
00079 
00080 bool SceneNodeTransform::flatten(Matrix4x4 &trans, 
00081                                  Matrix4x4 &transInv, 
00082                                  JSONParseData &data)
00083 {
00084    trans *= getTransform();
00085    // TODO: deal with inverses
00086    
00087    return true;
00088 }
00089 
00090 bool SceneNodeMaterial::flatten(Matrix4x4 &trans, 
00091                                 Matrix4x4 &transInv, 
00092                                 JSONParseData &data)
00093 {
00094    ASSERT(material);
00095    
00096    data.activeMaterial = material;
00097    data.materials.push_back(material);
00098    
00099    return true;
00100 }
00101 
00102 bool SceneNodeShape::flatten(Matrix4x4 &trans, 
00103                              Matrix4x4 &transInv, 
00104                              JSONParseData &data)
00105 {
00106    Shape *current = shape;
00107    
00108    if (data.instance > 0)
00109       current = new InstancedShape(current);
00110    
00111    current->setMaterial(data.activeMaterial);
00112    
00113    Transformable *t = NULL;
00114    try {
00115       t = dynamic_cast<Transformable*>(current);
00116    } catch(std::bad_cast&) { }
00117    
00118    // if the current shape is transformable
00119    if (t) {
00120       const Matrix4x4 &newTrans = trans * t->getTransToWorld();
00121       t->setTransToWorld(newTrans);
00122       // TODO: use transInv instead of trans.getInverse()
00123    }
00124    
00125    ShapeSet *shapeSet = NULL;
00126    try {
00127       shapeSet = dynamic_cast<ShapeSet*>(current);
00128    } catch(std::bad_cast&) { }
00129    
00130    if (shapeSet)
00131       data.primitives = shapeSet;
00132    else
00133       data.primitives->push_back(current);
00134    
00135    return true;
00136 }
00137 
00138 bool SceneNodeInstance::flatten(Matrix4x4 &trans, 
00139                                 Matrix4x4 &transInv, 
00140                                 JSONParseData &data)
00141 {
00142    InstancedNodeMapIter instanceeIter = data.instancedNodes.find(instancee);
00143    if (instanceeIter == data.instancedNodes.end()) {
00144       data << "error: instanced node '" << instancee << "' not found" << endl;
00145       
00146       return false;
00147    }
00148    
00149    SceneNode *node = instanceeIter->second;
00150    
00151    if (NULL == node) {
00152       data << "error: instanced node '" << instancee << "' not found" << endl;
00153       
00154       return false;
00155    }
00156    
00157    if (node->type != instanceeType) {
00158       data << "error: instanced node '" << instancee 
00159          << "' type mismatch with expected type" << endl;
00160       
00161       return false;
00162    }
00163    
00164    Material *activeMaterial = data.activeMaterial;
00165    ShapeSet *activeShapeSet = data.primitives;
00166    
00167    // record the fact that we're instanced
00168    ++data.instance;
00169    
00170    data.sceneGraph.flatten(node, trans, transInv, data);
00171    
00172    // pop this instance off of the implicit instance stack
00173    --data.instance;
00174    
00175    // ensure active material is restored to current level
00176    data.activeMaterial = activeMaterial;
00177    data.primitives     = activeShapeSet;
00178    
00179    return true;
00180 }
00181 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6