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