00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "common.h"
00013 #ifdef GRAPHVIZ_SUPPORT
00014 #include <boost/graph/graphviz.hpp>
00015 #endif
00016 #include "scene.h"
00017 #include "flexilog.h"
00018 #include "geometrynode.h"
00019 #include "geometrytriangles.h"
00020 #include "scenemanager.h"
00021 #include "camera.h"
00022 #include "events.h"
00023 #include "eventhandler.h"
00024
00025 using namespace VRUT;
00026
00027
00028 Scene::Scene(SCENE_ID id, EventHandler * _msgSink)
00029 : sceneID(id),
00030 sceneManager((SceneManager *)NULL),
00031 msgSink(_msgSink)
00032 {
00033 rootID = NODE_ID_NONE;
00034 bvh = (BVH *)NULL;
00035 }
00036
00037
00038 Scene::~Scene()
00039 {
00040 if (bvh)
00041 {
00042 bvh->Destroy();
00043 delete bvh;
00044 }
00045 SAFE_DELETE_ARR_EACH(sceneNodes, sceneNodes.size());
00046 SAFE_DELETE_ARR_EACH(geometries, geometries.size());
00047 SAFE_DELETE_ARR_EACH(materials, materials.size());
00048 }
00049
00050
00051 void Scene::GetNodeIDs(std::vector<NODE_ID> * nodes) const
00052 {
00053 for (NodeList::const_iterator it = sceneNodes.begin(); it != sceneNodes.end(); it++)
00054 {
00055 if (*it)
00056 nodes->push_back((*it)->GetID());
00057 }
00058 }
00059
00060
00061 void Scene::setNodeValid(SceneNode * node, bool _valid, bool markBVH) const
00062 {
00063 if (!_valid)
00064 {
00065 for (SceneNode::NodeIDList::iterator it = node->children.begin();
00066 it != node->children.end(); it++)
00067 setNodeValid(getNode(*it), false);
00068 if (markBVH && node->IsOfType(SceneNode::GEOMETRY) && bvh)
00069 bvh->SetInvalid(bvh->GetBVHNodeAssignedTo(node->GetID()));
00070 }
00071 node->valid = _valid;
00072 }
00073
00074
00075 BVH * Scene::UpdateBVH()
00076 {
00077 if (!itemsPending.empty())
00078 {
00079 BVH * newbvh = new BVH(this);
00080 newbvh->Build(&itemsPending);
00081 if (newbvh->IsBuilt())
00082 {
00083 if (bvh)
00084 {
00085
00086 bvh->Insert(newbvh->root);
00087 delete newbvh;
00088 }
00089 else
00090 bvh = newbvh;
00091 }
00092 else
00093 delete newbvh;
00094
00095 itemsPending.clear();
00096 }
00097
00098 return bvh;
00099 }
00100
00101
00102 MATERIAL_ID Scene::AddMaterial(Material * material)
00103 {
00104 if (!material)
00105 LOGERROR(wxT("<Scene>No material to add"));
00106
00107 bool replace = false;
00108 MaterialIDHashMap::iterator old = materialIDMap.find(material->name);
00109 if (old != materialIDMap.end())
00110 {
00111 replace = true;
00112 LOGWARNING(wxT("<Scene>Material with name '") + material->name + wxT("' already exists, replacing with new one"));
00113 SAFE_DELETE(materials[old->second]);
00114 materials[old->second] = material;
00115 return old->second;
00116 }
00117
00118 MATERIAL_ID mid = MATERIAL_ID(materials.size());
00119 materials.push_back(material);
00120 MaterialIDHashMap::Insert_Result res = materialIDMap.insert(MaterialIDHashMap::value_type(material->name, mid));
00121
00122 if (msgSink)
00123 {
00124 if (replace)
00125 {
00126 for (NodeList::const_iterator it = sceneNodes.begin();
00127 it != sceneNodes.end(); it++)
00128 {
00129 if (*it && (*it)->IsOfType(SceneNode::GEOMETRY) && ((const GeometryNode *)(*it))->GetMaterialID() == mid)
00130 {
00131 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_MATERIAL_CHANGED(sceneID, (*it)->GetID());
00132 msgSink->PostEvent(ev);
00133 }
00134 }
00135 }
00136 wxCommandEvent ev = Event::GET_EVT_SCENE_MATERIAL_ADDED(sceneID, mid);
00137 msgSink->PostEvent(ev);
00138 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00139 msgSink->PostEvent(ev2);
00140 }
00141 #ifdef __WXDEBUG__
00142 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00143 LOGDEBUG(wxString::Format(wxT("<Scene>Material '%s' ID '%i' added to scene '%i'"), material->name.c_str(), mid, sceneID));
00144 #endif
00145 return mid;
00146 }
00147
00148
00149 bool Scene::RemoveMaterial(MATERIAL_ID matID)
00150 {
00151 if (GetMaterial(matID))
00152 {
00153 for (NodeList::const_iterator it = sceneNodes.begin();
00154 it != sceneNodes.end(); it++)
00155 {
00156 if ((*it) && (*it)->IsOfType(SceneNode::GEOMETRY)
00157 && ((GeometryNode *)(*it))->GetMaterialID() == matID)
00158 return false;
00159 }
00160 materialIDMap.erase(materials[matID]->name);
00161 SAFE_DELETE(materials[matID]);
00162 return true;
00163 }
00164
00165 return false;
00166 }
00167
00168
00169 const Image * Scene::GetImage(const wxString & texPath) const
00170 {
00171 if (sceneManager)
00172 return sceneManager->GetImage(texPath, false);
00173 else return (Image *)NULL;
00174 }
00175
00176
00177 GEOMETRY_ID Scene::AddGeometry(Geometry * geometry)
00178 {
00179 if (!geometry)
00180 LOGERROR(wxT("<Scene>No geometry to add"));
00181
00182 bool replace = false;
00183 GEOMETRY_ID geomID = GEOMETRY_ID_NONE;
00184 GeometryIDHashMap::iterator old = geometryIDMap.find(geometry->GetName());
00185 if (old != geometryIDMap.end())
00186 {
00187 replace = true;
00188 LOGWARNING(wxT("<Scene>Geometry with name '") + geometry->GetName() + wxT("' already exists, replacing with new one"));
00189 SAFE_DELETE(geometries[old->second]);
00190 geometries[old->second] = geometry;
00191 geomID = old->second;
00192 }
00193 else
00194 {
00195 geomID = GEOMETRY_ID(geometries.size());
00196 geometries.push_back(geometry);
00197 GeometryIDHashMap::Insert_Result res = geometryIDMap.insert(GeometryIDHashMap::value_type(geometry->GetName(), geomID));
00198 wxASSERT_MSG(res.second, wxT("<Scene>Failed to insert geometry ID to hash map"));
00199 }
00200
00202 geometry->BuildAABB();
00203
00204 if (replace)
00205 {
00206 for (NodeList::const_iterator it = sceneNodes.begin();
00207 it != sceneNodes.end(); it++)
00208 {
00209 if (*it && (*it)->IsOfType(SceneNode::GEOMETRY) && ((const GeometryNode *)(*it))->GetGeometryID() == geomID)
00210 {
00211 setNodeValid(*it, false);
00212 if (msgSink)
00213 {
00214 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_GEOMETRY_CHANGED(sceneID, (*it)->GetID());
00215 msgSink->PostEvent(ev);
00216 }
00217 }
00218 }
00219 }
00220 wxCommandEvent ev = Event::GET_EVT_SCENE_GEOMETRY_ADDED(sceneID, geomID);
00221 msgSink->PostEvent(ev);
00222 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00223 msgSink->PostEvent(ev2);
00224
00225 #ifdef __WXDEBUG__
00226 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00227 LOGDEBUG(wxString::Format(wxT("<Scene>Geometry '%s' ID '%i' added to scene '%i'"), geometry->GetName().c_str(), geomID, sceneID));
00228 #endif
00229 return geomID;
00230 }
00231
00232
00233 bool Scene::RemoveGeometry(GEOMETRY_ID geomID)
00234 {
00235 if (GetGeometry(geomID))
00236 {
00237 for (NodeList::const_iterator it = sceneNodes.begin();
00238 it != sceneNodes.end(); it++)
00239 {
00240 if ((*it) && (*it)->IsOfType(SceneNode::GEOMETRY)
00241 && ((GeometryNode *)(*it))->GetGeometryID() == geomID)
00242 return false;
00243 }
00244 geometryIDMap.erase(geometries[geomID]->GetName());
00245 SAFE_DELETE(geometries[geomID]);
00246 return true;
00247 }
00248
00249 return false;
00250 }
00251
00252
00253 #ifdef GRAPHVIZ_SUPPORT
00254 void Scene::CreateGraphVizFile() const
00255 {
00256 typedef std::pair<int,int> Edge;
00257 std::vector<Edge> edges;
00258
00259 std::vector<wxString> titles(sceneNodes.size() + 1);
00260 for (NodeList::const_iterator nodeIt = sceneNodes.begin();
00261 nodeIt != sceneNodes.end(); nodeIt++)
00262 {
00263 if (*nodeIt)
00264 {
00265 NODE_ID id = (*nodeIt)->GetID();
00266 UpdateTransformation(id);
00267 titles[id] = wxString::Format(wxT("%i_%s"), id, (*nodeIt)->GetName().c_str());
00268 const SceneNode::NodeIDList * children = (*nodeIt)->GetChildren();
00269 for (SceneNode::NodeIDList::const_iterator it = children->begin() ; it != children->end(); it++)
00270 edges.push_back(Edge(int(id), int(*it)));
00271 }
00272 }
00273
00274 std::vector<int> weights(edges.size());
00275 std::fill(weights.begin(), weights.end(), 1);
00276
00277 typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS,
00278 boost::property< boost::vertex_color_t, boost::default_color_type >,
00279 boost::property< boost::edge_weight_t, int > > Graph;
00280 Graph g(&(edges[0]), &(edges[0]) + edges.size(), &(weights[0]), sceneNodes.size());
00281
00282 unsigned ver = 0;
00283 wxString fname;
00284 do
00285 {
00286 fname = wxString::Format(wxT("%s.%i.%i.dot"), sceneName.c_str(), sceneID, ver++);
00287 }
00288 while (wxFileName(fname).FileExists());
00289
00290 std::ofstream fout(fname.ToAscii());
00291 if (fout.is_open())
00292 {
00293 write_graphviz(fout, g, wx_label_writer(&titles));
00294 LOG(wxT("<Scene>GraphViz definition file of scene graph saved as '") + fname + wxT("'"));
00295 fout.close();
00296 }
00297 else
00298 LOGERROR(wxT("<Scene>Could not save GraphViz definition file of scene graph"));
00299 }
00300 #endif
00301
00302 #ifdef __WXDEBUG__
00303 void Scene::Dump() const
00304 {
00305 unsigned ver = 0;
00306 wxString fname;
00307 do
00308 {
00309 fname = wxString::Format(wxT("%s.%i.%i.dump.txt"), sceneName.c_str(), sceneID, ver++);
00310 }
00311 while (wxFileName(fname).FileExists());
00312
00313 wxFileOutputStream fout(fname);
00314 if (!fout.IsOk())
00315 {
00316 LOGERROR(wxT("<Scene>Could not save scene dump file"));
00317 return;
00318 }
00319 wxTextOutputStream txtout(fout);
00320
00321 for (NodeList::const_iterator nodeIt = sceneNodes.begin();
00322 nodeIt != sceneNodes.end(); nodeIt++)
00323 {
00324 if (*nodeIt)
00325 {
00326 UpdateTransformation((*nodeIt)->GetID());
00327 txtout << (*nodeIt)->ToString();
00328 if (bvh && (*nodeIt)->IsOfType(SceneNode::GEOMETRY) && bvh->GetBVHNodeAssignedTo((*nodeIt)->GetID()))
00329 txtout << wxT("\n") << bvh->GetBVHNodeAssignedTo((*nodeIt)->GetID())->ToString();
00330 txtout << wxT("\n====================================================================================\n");
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 LOG(wxT("<Scene>Scene dump file saved as '") + fname + wxT("'"));
00352 }
00353 #endif
00354
00355
00359
00360 NODE_ID Scene::Insert(SceneNode * node, NODE_ID targetID)
00361 {
00362 SceneNode * parentNode = getNode(targetID);
00363
00364 wxASSERT_MSG( (node->parent == NODE_ID_NONE) && (node->GetID() == NODE_ID_NONE),
00365 wxT("<Scene>Inserting node that is probably already part of a scene"));
00366
00367 node->id = NODE_ID(sceneNodes.size());
00368 if (!parentNode)
00369 {
00370 wxASSERT_MSG(targetID == NODE_ID_NONE, wxT("<Scene>Invalid target node ID when inserting"));
00371 rootID = node->id;
00372 }
00373 else
00374 parentNode->children.push_back(node->id);
00375
00376 node->parent = targetID;
00377 sceneNodes.push_back(node);
00378 setNodeValid(node, false);
00379
00380 wxASSERT_MSG(sceneNodeIDMap.find(node->uid) == sceneNodeIDMap.end(), wxString::Format(wxT("<Scene>Node with same uid '%s' already inserted"), node->uid.c_str()));
00381 NodeIDHashMap::Insert_Result res = sceneNodeIDMap.insert(NodeIDHashMap::value_type(node->uid, node->id));
00382 wxASSERT_MSG( res.second, wxT("<Scene>Failed to insert node uid into hashmap") );
00383
00384 if (node->IsOfType(SceneNode::GEOMETRY) && ((GeometryNode *)node)->GetGeometryID() != GEOMETRY_ID_NONE)
00385 itemsPending.push_back(node->id);
00386
00387 if (node->IsOfType(SceneNode::LIGHT))
00388 lightNodeIDs.push_back(node->id);
00389
00390 if (msgSink)
00391 {
00392 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERTED(sceneID, node->id, node->uid);
00393 msgSink->PostEvent(ev);
00394 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00395 msgSink->PostEvent(ev2);
00396 }
00397 #ifdef __WXDEBUG__
00398 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00399 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' added to scene '%i'"), node->GetName().c_str(), node->GetID(), sceneID));
00400 #endif
00401 return node->id;
00402 }
00403
00404
00405 NODE_ID Scene::Copy(Scene * srcScene, NODE_ID srcID, NODE_ID targetID)
00406 {
00407 if (!srcScene)
00408 srcScene = this;
00409 if (srcID == NODE_ID_NONE)
00410 srcID = srcScene->GetRootID();
00411 if (targetID == NODE_ID_NONE)
00412 targetID = GetRootID();
00413
00415 std::deque<std::pair<NODE_ID, NODE_ID> > queue;
00416 std::pair<NODE_ID, NODE_ID> rootPair(targetID, srcID);
00417 queue.push_back(rootPair);
00418
00419 while (!queue.empty())
00420 {
00421 std::pair<NODE_ID, NODE_ID> actPair = queue.front();
00422 queue.pop_front();
00423 const SceneNode * node = srcScene->GetNode(actPair.second);
00424 if (node)
00425 {
00427 SceneNode::NodeIDList childrenCpy(node->children);
00428
00429 SceneNode * cloneNode = node->Clone();
00431 cloneNode->id = NODE_ID_NONE;
00432 cloneNode->parent = NODE_ID_NONE;
00433 cloneNode->children.clear();
00434
00436 while (GetNodeID(cloneNode->GetUid()) != NODE_ID_NONE)
00437 cloneNode->uid.append(wxT("_"));
00438
00439 NODE_ID parID = Insert(cloneNode, actPair.first);
00440
00441 if (srcScene != this && cloneNode->IsOfType(SceneNode::GEOMETRY))
00442 {
00443 GeometryNode * gcloneNode = (GeometryNode *)cloneNode;
00445 if (gcloneNode->GetMaterialID() != MATERIAL_ID_NONE)
00446 {
00447 const Material * mat = srcScene->GetMaterial(gcloneNode->GetMaterialID());
00448 gcloneNode->materialID = MATERIAL_ID_NONE;
00449 if (mat)
00450 {
00451 Material * cloneMat = mat->Clone();
00453 while (GetMaterialID(cloneMat->name) != MATERIAL_ID_NONE)
00454 cloneMat->name.append(wxT("_"));
00455 if (!mat->name.IsSameAs(cloneMat->name))
00456 LOGVERBOSE(wxString::Format(
00457 wxT("<Scene>Material '%s' from scene ID %i is copied under new name '%s'"),
00458 mat->name.c_str(), srcScene->GetID(), cloneMat->name.c_str()));
00459 MATERIAL_ID matID = AddMaterial(cloneMat);
00460 SetMaterial(parID, matID);
00461 }
00462 else
00463 LOGERROR(wxString::Format(wxT("<Scene>Invalid material defined in node '%s' from scene ID %i"), node->GetName().c_str(), srcScene->GetID()));
00464 }
00465
00467 if (gcloneNode->GetGeometryID() != GEOMETRY_ID_NONE)
00468 {
00469 const Geometry * geom = srcScene->GetGeometry(gcloneNode->GetGeometryID());
00470 gcloneNode->geometryID = GEOMETRY_ID_NONE;
00471 if (geom)
00472 {
00473 Geometry * cloneGeom = geom->Clone();
00475 while (GetGeometryID(cloneGeom->GetName()) != GEOMETRY_ID_NONE)
00476 cloneGeom->name.append(wxT("_"));
00477 if (!geom->GetName().IsSameAs(cloneGeom->GetName()))
00478 LOGVERBOSE(wxString::Format(
00479 wxT("<Scene>Geometry '%s' from scene ID %i is copied under new name '%s'"),
00480 geom->GetName().c_str(), srcScene->GetID(), cloneGeom->GetName().c_str()));
00481 GEOMETRY_ID geomID = AddGeometry(cloneGeom);
00482 SetGeometry(parID, geomID);
00483 }
00484 else
00485 LOGERROR(wxString::Format(wxT("<Scene>Invalid geometry defined in node '%s' from scene ID %i"), node->GetName().c_str(), srcScene->GetID()));
00486 }
00487 }
00488
00489 for (SceneNode::NodeIDList::const_iterator childIt = childrenCpy.begin();
00490 childIt != childrenCpy.end(); childIt++)
00491 {
00492 std::pair<NODE_ID, NODE_ID> childPair(parID, *childIt);
00493 queue.push_back(childPair);
00494 }
00495 }
00496 }
00497 const SceneNode * oldRoot = srcScene->GetNode(targetID);
00498 if (oldRoot)
00499 return GetNodeID(oldRoot->GetUid());
00500 else
00501 return NODE_ID_NONE;
00502 }
00503
00504
00505 void Scene::Move(NODE_ID srcID, NODE_ID targetID)
00506 {
00507 if (srcID == GetRootID())
00508 {
00509 LOGERROR(wxT("<Scene>Source cannot be root when moving nodes"));
00510 return;
00511 }
00512 SceneNode * srcNode = getNode(srcID);
00513 SceneNode * tgtNode = getNode(targetID);
00514 if ( !srcNode || !tgtNode)
00515 {
00516 LOGERROR(wxT("<Scene>Source or target not defined properly when moving nodes"));
00517 return;
00518 }
00519 wxASSERT_MSG( srcNode->parent != NODE_ID_NONE,
00520 wxT("<Scene>Source node must have parents when moving"));
00522 setNodeValid(srcNode, false);
00524 SceneNode * parNode = getNode(srcNode->parent);
00525 parNode->children.remove(srcID);
00527 srcNode->parent = targetID;
00528 tgtNode->children.push_back(srcID);
00529
00530 if (msgSink)
00531 {
00532 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_MOVED(sceneID, srcID);
00533 msgSink->PostEvent(ev);
00534 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00535 msgSink->PostEvent(ev2);
00536 }
00537 }
00538
00539
00540 void Scene::Remove(NODE_ID id)
00541 {
00542 SceneNode * node = getNode(id);
00543 if (node && node->type!=SceneNode::ROOT)
00544 {
00545 while (node->children.begin() != node->children.end())
00546 Remove(*node->children.begin());
00547
00548 SceneNode * parNode = getNode(node->parent);
00549 if (parNode)
00550 parNode->children.remove(id);
00551 node->parent = NODE_ID_NONE;
00552 if (node->IsOfType(SceneNode::GEOMETRY) && bvh)
00553 {
00554 BVHNode * bvhNode = bvh->Remove(bvh->GetBVHNodeAssignedTo(node->GetID()));
00555 SAFE_DELETE(bvhNode);
00556 }
00557
00558 setNodeValid(node, false);
00559 node->id = NODE_ID_NONE;
00560
00561 if (node->IsOfType(SceneNode::LIGHT))
00562 lightNodeIDs.remove(id);
00563
00564 NodeIDHashMap::iterator itmap = sceneNodeIDMap.find(node->uid);
00565 wxASSERT_MSG(itmap != sceneNodeIDMap.end(), wxT("<Scene>Removing node that is not in ID map"));
00566 sceneNodeIDMap.erase(itmap);
00567
00568 for (std::deque<NODE_ID>::iterator it = itemsPending.begin();
00569 it != itemsPending.end(); )
00570 {
00571 if (*it == id)
00572 it = itemsPending.erase(it);
00573 else
00574 it++;
00575 }
00576
00577 wxString nodeName = node->GetName();
00578 SAFE_DELETE(sceneNodes[id]);
00579
00580 if (msgSink)
00581 {
00582 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_REMOVED(sceneID, id);
00583 msgSink->PostEvent(ev);
00584 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00585 msgSink->PostEvent(ev2);
00586 }
00587 #ifdef __WXDEBUG__
00588 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00589 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' removed from scene '%i'"), nodeName.c_str(), id, sceneID));
00590 #endif
00591 }
00592 else
00593 LOGERROR(wxString::Format(wxT("<Scene>Cannot remove node with ID %i, node not found in scene or ROOT node"), id));
00594 }
00595
00596
00597 void Scene::SetUid(NODE_ID id, const wxString & uid)
00598 {
00599 SceneNode * node = getNode(id);
00600 if (node && node->uid != uid)
00601 {
00602 wxString oldUid = node->uid;
00603 NodeIDHashMap::iterator itmap = sceneNodeIDMap.find(oldUid);
00604 wxASSERT_MSG(itmap != sceneNodeIDMap.end(), wxT("<Scene>Changing of uid of node that is not in ID map"));
00605 if (sceneNodeIDMap.find(uid) != sceneNodeIDMap.end())
00606 LOGERROR(wxString::Format(wxT("<Scene>Node with same uid '%s' already inserted"), uid.c_str()));
00607 else
00608 {
00609 sceneNodeIDMap.erase(itmap);
00610 NodeIDHashMap::Insert_Result res = sceneNodeIDMap.insert(NodeIDHashMap::value_type(uid, node->id));
00611 wxASSERT_MSG( res.second, wxT("<Scene>Failed to insert node uid into hashmap") );
00612 }
00613 node->uid = CloneWxString(uid);
00614
00615 if (msgSink)
00616 {
00617 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_UID_CHANGED(sceneID, id);
00618 msgSink->PostEvent(ev);
00619 }
00620 #ifdef __WXDEBUG__
00621 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00622 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' uid changed to '%s' in scene '%i'"), oldUid.c_str(), id, node->uid.c_str(), sceneID));
00623 #endif
00624 }
00625 else
00626 LOGERROR(wxString::Format(wxT("<Scene>Cannot change uid of node with ID %i, node not found in scene"), id));
00627 }
00628
00629 void Scene::SetName(NODE_ID id, const wxString & name)
00630 {
00631 SceneNode * node = getNode(id);
00632 if (node && node->name != name)
00633 {
00634 wxString oldName = node->name;
00635 node->name = CloneWxString(name);
00636 if (msgSink)
00637 {
00638 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_NAME_CHANGED(sceneID, id);
00639 msgSink->PostEvent(ev);
00640 }
00641 #ifdef __WXDEBUG__
00642 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00643 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' renamed to '%s' in scene '%i'"), oldName.c_str(), id, node->name.c_str(), sceneID));
00644 #endif
00645 }
00646 else
00647 LOGERROR(wxString::Format(wxT("<Scene>Cannot rename node with ID %i, node not found in scene"), id));
00648 }
00649
00650 void Scene::SetTransformation(NODE_ID id, const MATRIX & matrix) const
00651 {
00652 SceneNode * node = getNode(id);
00653 if (node)
00654 {
00655 node->localTransMatrix = matrix;
00656 setNodeValid(node, false);
00657
00658 if (msgSink)
00659 {
00660 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORMED(sceneID, id);
00661 msgSink->PostEvent(ev);
00662 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00663 msgSink->PostEvent(ev2);
00664 }
00665 }
00666 else
00667 LOGERROR(wxString::Format(wxT("<Scene>Cannot transform node with ID %i, node not found in scene"), id));
00668 }
00669
00670
00671 void Scene::Transform(NODE_ID id, const MATRIX & matrix) const
00672 {
00673 SceneNode * node = getNode(id);
00674 if (node)
00675 {
00676 node->localTransMatrix *= matrix;
00677 setNodeValid(node, false);
00678
00679 if (msgSink)
00680 {
00681 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORMED(sceneID, id);
00682 msgSink->PostEvent(ev);
00683 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00684 msgSink->PostEvent(ev2);
00685 }
00686 }
00687 else
00688 LOGERROR(wxString::Format(wxT("<Scene>Cannot transform node with ID %i, node not found in scene"), id));
00689 }
00690
00691
00692 void Scene::UpdateTransformation(NODE_ID id) const
00693 {
00694 SceneNode * node = getNode(id);
00695 if (!node)
00696 {
00697 LOGERROR(wxString::Format(wxT("<Scene>Cannot transform node with ID %i, node not found in scene"), id));
00698 return;
00699 }
00700
00701 if (!node->IsValid())
00702 {
00703 SceneNode * parent = getNode(node->parent);
00704 MATRIX parMat;
00705 if (parent)
00706 {
00707 UpdateTransformation(node->parent);
00708 parMat = *parent->GetWorldTransMatrix();
00709 }
00710 node->worldTransMatrix = node->localTransMatrix * parMat;
00711
00713 setNodeValid(node, true);
00714
00715 if (node->IsOfType(SceneNode::CAMERA))
00716 {
00717 Camera * cam = (Camera *)node;
00718 cam->updateProjection();
00719 cam->extractFrustum();
00720 }
00721 }
00722 }
00723
00724
00725 void Scene::TranslateAbs(NODE_ID id, const VECTOR3 & transl) const
00726 {
00727 SceneNode * node = getNode(id);
00728 if (node)
00729 {
00730 node->localTransMatrix._m41 = transl.x;
00731 node->localTransMatrix._m42 = transl.y;
00732 node->localTransMatrix._m43 = transl.z;
00733 setNodeValid(node, false);
00734
00735 if (msgSink)
00736 {
00737 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORMED(sceneID, id);
00738 msgSink->PostEvent(ev);
00739 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00740 msgSink->PostEvent(ev2);
00741 }
00742 }
00743 else
00744 LOGERROR(wxString::Format(wxT("<Scene>Cannot transform node with ID %i, node not found in scene"), id));
00745 }
00746
00747
00748 void Scene::SetGeometry(NODE_ID id, GEOMETRY_ID geometryID)
00749 {
00750 SceneNode * snode = getNode(id);
00751 GeometryNode * node = ( snode && snode->IsOfType(SceneNode::GEOMETRY) ? (GeometryNode *)snode : (GeometryNode *)NULL );
00752 if (node)
00753 {
00754 node->geometryID = geometryID;
00755 if (geometryID != GEOMETRY_ID_NONE && (!bvh || !bvh->GetBVHNodeAssignedTo(node->GetID())))
00756 itemsPending.push_back(id);
00757
00758 setNodeValid(node, false);
00759
00760 if (msgSink)
00761 {
00762 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_GEOMETRY_CHANGED(sceneID, id);
00763 msgSink->PostEvent(ev);
00764 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00765 msgSink->PostEvent(ev2);
00766 }
00767 #ifdef __WXDEBUG__
00768 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00769 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' has new geometry '%s' ID '%i' in scene '%i'"),
00770 node->GetName().c_str(), node->GetID(), ( GetGeometry(geometryID) ? GetGeometry(geometryID)->GetName().c_str() : wxT("NULL") ),
00771 geometryID, sceneID));
00772 #endif
00773 }
00774 else
00775 LOGERROR(wxString::Format(wxT("<Scene>Cannot set geometry to node with ID %i, node not found in scene"), id));
00776 }
00777
00778
00779 void Scene::SetMaterial(NODE_ID id, MATERIAL_ID mid) const
00780 {
00781 SceneNode * snode = getNode(id);
00782 GeometryNode * node = ( snode && snode->IsOfType(SceneNode::GEOMETRY) ? (GeometryNode *)snode : (GeometryNode *)NULL );
00783 if (node)
00784 {
00785 node->materialID = mid;
00786
00787 if (msgSink)
00788 {
00789 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_MATERIAL_CHANGED(sceneID, id);
00790 msgSink->PostEvent(ev);
00791 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00792 msgSink->PostEvent(ev2);
00793 }
00794 #ifdef __WXDEBUG__
00795 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00796 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' has new material '%s' ID '%i' in scene '%i'"),
00797 node->GetName().c_str(), node->GetID(), ( GetMaterial(mid) ? GetMaterial(mid)->name.c_str() : wxT("NULL") ),
00798 mid, sceneID));
00799 #endif
00800 }
00801 else
00802 LOGERROR(wxString::Format(wxT("<Scene>Cannot set material to node with ID %i, node not found in scene"), id));
00803 }
00804
00805
00806 void Scene::SetLight(NODE_ID id, Light * light) const
00807 {
00808 SceneNode * snode = getNode(id);
00809 if (snode && snode->IsOfType(SceneNode::LIGHT))
00810 {
00811 ((LightNode *)snode)->light = light;
00812
00813 if (msgSink)
00814 {
00815 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_LIGHT_CHANGED(sceneID, id);
00816 msgSink->PostEvent(ev);
00817 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00818 msgSink->PostEvent(ev2);
00819 }
00820 #ifdef __WXDEBUG__
00821 if (wxLog::GetLogLevel() >= wxLOG_Debug)
00822 LOGDEBUG(wxString::Format(wxT("<Scene>Node '%s' ID '%i' has new light in scene '%i'"),
00823 snode->GetName().c_str(), id, sceneID));
00824 #endif
00825 }
00826 else
00827 LOGERROR(wxString::Format(wxT("<Scene>Cannot set light to node with ID %i, node not found in scene or is not of light type"), id));
00828 }
00829
00830
00831
00835
00836 void Scene::SetProjectionParams(NODE_ID camID,
00837 unsigned width,
00838 unsigned height,
00839 float nearPlane,
00840 float farPlane,
00841 float fov) const
00842 {
00843 SceneNode * node = getNode(camID);
00844 if (!node || !node->IsOfType(SceneNode::CAMERA))
00845 return;
00846 Camera * cam = (Camera *)node;
00847
00848 bool changed = false;
00849 if (width && cam->lastWidth != width)
00850 {
00851 changed = true;
00852 cam->lastWidth = width;
00853 }
00854 if (height && cam->lastHeight != height)
00855 {
00856 changed = true;
00857 cam->lastHeight = height;
00858 }
00859 if (nearPlane && cam->nearPlane != nearPlane)
00860 {
00861 changed = true;
00862 cam->nearPlane = nearPlane;
00863 }
00864 if (farPlane && cam->farPlane != farPlane)
00865 {
00866 changed = true;
00867 cam->farPlane = farPlane;
00868 }
00869 if (fov && cam->fov != fov)
00870 {
00871 changed = true;
00872 cam->fov = fov;
00873 }
00874
00875 if (changed)
00876 {
00877 setNodeValid(cam, false);
00878
00879 if (msgSink)
00880 {
00881 wxCommandEvent ev = Event::GET_EVT_SCENE_CAM_PROJECTION_CHANGED(sceneID, camID);
00882 msgSink->PostEvent(ev);
00883 wxCommandEvent ev2 = Event::GET_EVT_RENDER_UPDATE(sceneID);
00884 msgSink->PostEvent(ev2);
00885 }
00886 }
00887 }
00888
00889
00890 void Scene::Fit(NODE_ID camID, bool updateBVH, bool farNearOnly)
00891 {
00892 SceneNode * node = getNode(camID);
00893 if (!node || !node->IsOfType(SceneNode::CAMERA))
00894 {
00895 LOGERROR(wxString::Format(wxT("<Scene>Cannot transform camera node with ID %i, node not found in scene"), sceneID));
00896 return;
00897 }
00898 Camera * cam = (Camera *)node;
00899
00900 if (updateBVH)
00901 UpdateBVH();
00902 BVH * bvh = GetBVH();
00903 if (!bvh || !bvh->GetRoot())
00904 return;
00905
00906 bvh->UpdateBV();
00907 const BSphere * bsphere = bvh->GetRoot()->GetBSphere();
00908 float farPlane = (cam->GetWorldTransMatrix()->ExtractTranslation() - bsphere->Center).Length() + bsphere->Radius * 2;
00909 SetProjectionParams(camID, 0, 0, 0, farPlane);
00910 if (!farNearOnly)
00911 {
00912 UpdateTransformation(camID);
00913 VECTOR3 viewDir = cam->GetView().Normalize();
00914 TranslateAbs(camID, bsphere->Center - viewDir * (bsphere->Radius * 2));
00915 UpdateTransformation(camID);
00916 cam->centerDist = (cam->GetWorldTransMatrix()->ExtractTranslation() - bsphere->Center).Length();
00917 UpdateTransformation(camID);
00918 }
00919 }
00920
00921
00922 void Scene::ResetView(NODE_ID camID, bool updateBVH)
00923 {
00924 SceneNode * node = getNode(camID);
00925 if (!node || !node->IsOfType(SceneNode::CAMERA))
00926 {
00927 LOGERROR(wxString::Format(wxT("<Scene>Cannot set parameters to camera node with ID %i, node not found in scene"), sceneID));
00928 return;
00929 }
00930 Camera * cam = (Camera *)node;
00931
00932 MATRIX mat;
00933 mat.Translate(VECTOR3(0,0,30));
00934 cam->centerDist = 30.0f;
00935 SetTransformation(camID, mat);
00936 Fit(camID);
00937 }