00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "SceneGraph.h"
00018 #include "PolyPrimitive.h"
00019
00020 using namespace Fluxus;
00021
00022 SceneGraph::SceneGraph()
00023 {
00024
00025 Clear();
00026 }
00027
00028 SceneGraph::~SceneGraph()
00029 {
00030 }
00031
00032 void SceneGraph::Render(Mode rendermode)
00033 {
00034
00035
00036 glGetFloatv(GL_MODELVIEW_MATRIX,m_TopTransform.arr());
00037
00038
00039 for (vector<Node*>::iterator i=m_Root->Children.begin(); i!=m_Root->Children.end(); ++i)
00040 {
00041 RenderWalk((SceneNode*)*i,0,rendermode);
00042 }
00043
00044
00045 m_DepthSorter.Render();
00046 m_DepthSorter.Clear();
00047 }
00048
00049 void SceneGraph::RenderWalk(SceneNode *node, int depth, Mode rendermode)
00050 {
00051
00052
00053
00054
00055
00056
00057
00058 if (node->Prim->Hidden()) return;
00059 if (rendermode==SELECT && !node->Prim->IsSelectable()) return;
00060
00061
00062 dMatrix parent;
00063
00064 if (node->Prim->GetState()->Hints & HINT_DEPTH_SORT)
00065 {
00066 glGetFloatv(GL_MODELVIEW_MATRIX,parent.arr());
00067 }
00068
00069 glPushMatrix();
00070
00071
00072
00073
00074 if (node->Prim->GetState()->Hints & HINT_LAZY_PARENT)
00075 {
00076 glLoadMatrixf(m_TopTransform.arr());
00077 }
00078
00079 node->Prim->ApplyState();
00080
00082
00083 {
00084 if (node->Prim->GetState()->Hints & HINT_DEPTH_SORT)
00085 {
00086
00087 m_DepthSorter.Add(parent,node->Prim,node->ID);
00088 }
00089 else
00090 {
00091 glPushName(node->ID);
00092 node->Prim->Prerender();
00093 node->Prim->Render();
00094 glPopName();
00095 }
00096
00097 depth++;
00098
00099 for (vector<Node*>::iterator i=node->Children.begin(); i!=node->Children.end(); ++i)
00100 {
00101 RenderWalk((SceneNode*)*i,depth,rendermode);
00102 }
00103 }
00104 glPopMatrix();
00105
00106 if (node->Prim->GetState()->Hints & HINT_CAST_SHADOW)
00107 {
00108 m_ShadowVolumeGen.Generate(node->Prim);
00109 }
00110 }
00111
00112
00113
00114
00115 bool SceneGraph::FrustumClip(SceneNode *node)
00116 {
00117
00118 dBoundingBox box;
00119 GetBoundingBox(node,box);
00120 dMatrix mat,proj;
00121 glGetFloatv(GL_MODELVIEW_MATRIX,mat.arr());
00122 glGetFloatv(GL_PROJECTION_MATRIX,proj.arr());
00123 mat=proj*mat;
00124 char cs = 0xff;
00125
00126 dVector p = mat.transform_persp(box.min);
00127 CohenSutherland(p,cs);
00128 p=mat.transform_persp(box.max);
00129 CohenSutherland(p,cs);
00130 p=mat.transform_persp(dVector(box.min.x,box.min.y,box.max.z));
00131 CohenSutherland(p,cs);
00132 p=mat.transform_persp(dVector(box.min.x,box.max.y,box.min.z));
00133 CohenSutherland(p,cs);
00134 p=mat.transform_persp(dVector(box.min.x,box.max.y,box.max.z));
00135 CohenSutherland(p,cs);
00136 p=mat.transform_persp(dVector(box.max.x,box.min.y,box.min.z));
00137 CohenSutherland(p,cs);
00138 p=mat.transform_persp(dVector(box.max.x,box.min.y,box.max.z));
00139 CohenSutherland(p,cs);
00140 p=mat.transform_persp(dVector(box.max.x,box.max.y,box.min.z));
00141 CohenSutherland(p,cs);
00142
00143 return cs!=0;
00144 }
00145
00146 void SceneGraph::CohenSutherland(const dVector &p, char &cs)
00147 {
00148 char t=0;
00149 if (p.z>0.0f)
00150 {
00151 if (p.x>1) t |= 0x01;
00152 else if (p.x<-1) t |= 0x02;
00153 if (p.y>1) t |= 0x04;
00154 else if (p.y<-1) t |= 0x08;
00155 }
00156 else
00157 {
00158 if (p.x<-1) t |= 0x01;
00159 else if (p.x>1) t |= 0x02;
00160 if (p.y<-1) t |= 0x04;
00161 else if (p.y>1) t |= 0x08;
00162 }
00163 cs&=t;
00164 }
00165
00166 void SceneGraph::Detach(SceneNode *node)
00167 {
00168 if (node->Parent!=m_Root)
00169 {
00170
00171 node->Prim->GetState()->Transform=GetGlobalTransform(node);
00172
00173
00174 node->Parent->RemoveChild(node->ID);
00175 m_Root->Children.push_back(node);
00176 node->Parent=m_Root;
00177 }
00178 }
00179
00180 dMatrix SceneGraph::GetGlobalTransform(const SceneNode *node) const
00181 {
00182 dMatrix Mat,Ret;
00183
00184 list<const SceneNode*> Path;
00185
00186 const SceneNode* current=node;
00187
00188
00189
00190
00191
00192 bool foundlazy=false;
00193 while(current!=NULL && !foundlazy)
00194 {
00195 if (current && current->Prim)
00196 {
00197 Path.push_front(current);
00198 foundlazy = current->Prim->GetState()->Hints & HINT_LAZY_PARENT;
00199 }
00200 current=(const SceneNode*)current->Parent;
00201 }
00202
00203
00204 for (list<const SceneNode*>::iterator i=Path.begin(); i!=Path.end(); ++i)
00205 {
00206 Mat*=(*i)->Prim->GetState()->Transform;
00207 }
00208
00209 return Mat;
00210 }
00211
00212 void SceneGraph::GetBoundingBox(SceneNode *node, dBoundingBox &result)
00213 {
00214 dMatrix mat;
00215 GetBoundingBox(node, mat, result);
00216 }
00217
00218 void SceneGraph::GetBoundingBox(SceneNode *node, dMatrix mat, dBoundingBox &result)
00219 {
00220 if (!node) return;
00221
00222 if (node->Prim)
00223 {
00224 dVector point(0,0,0);
00225 dBoundingBox bbox=node->Prim->GetBoundingBox();
00226 bbox.min=mat.transform(bbox.min);
00227 bbox.max=mat.transform(bbox.max);
00228 result.expand(bbox);
00229 mat*=node->Prim->GetState()->Transform;
00230 }
00231
00232 for (vector<Node*>::iterator i=node->Children.begin(); i!=node->Children.end(); ++i)
00233 {
00234 GetBoundingBox((SceneNode*)*i,mat,result);
00235 }
00236 }
00237
00238 void SceneGraph::GetNodes(const Node *node, vector<const SceneNode*> &nodes) const
00239 {
00240 nodes.push_back(static_cast<const SceneNode*>(node));
00241
00242 for (vector<Node*>::const_iterator i=node->Children.begin();
00243 i!=node->Children.end(); i++)
00244 {
00245 GetNodes(*i,nodes);
00246 }
00247 }
00248
00249 void SceneGraph::GetConnections(const Node *node, vector<pair<const SceneNode*,const SceneNode*> > &connections) const
00250 {
00251 for (vector<Node*>::const_iterator i=node->Children.begin();
00252 i!=node->Children.end(); i++)
00253 {
00254 connections.push_back(pair<const SceneNode *,const SceneNode *>
00255 (static_cast<const SceneNode*>(node),
00256 static_cast<const SceneNode*>(*i)));
00257 GetConnections(*i,connections);
00258 }
00259 }
00260 void SceneGraph::Clear()
00261 {
00262 Tree::Clear();
00263 SceneNode *root = new SceneNode(NULL);
00264 AddNode(0,root);
00265 }