Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

sceneserver.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*-
00002 
00003    this file is part of rcssserver3D
00004    Fri May 9 2003
00005    Copyright (C) 2002,2003 Koblenz University
00006    Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group
00007    $Id: sceneserver.cpp,v 1.15 2004/05/06 09:38:22 rollmark Exp $
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; version 2 of the License.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 */
00022 
00023 #include "sceneserver.h"
00024 #include <zeitgeist/logserver/logserver.h>
00025 #include <zeitgeist/corecontext.h>
00026 #include <zeitgeist/fileserver/fileserver.h>
00027 #include <salt/vector.h>
00028 #include <salt/frustum.h>
00029 #include "transform.h"
00030 #include "scene.h"
00031 #include "sceneimporter.h"
00032 #include <oxygen/physicsserver/world.h>
00033 #include <oxygen/physicsserver/space.h>
00034 
00035 using namespace boost;
00036 using namespace oxygen;
00037 using namespace salt;
00038 using namespace zeitgeist;
00039 using namespace std;
00040 
00041 int SceneServer::mTransformMark = 0;
00042 
00043 SceneServer::SceneServer() : Node()
00044 {
00045 }
00046 
00047 SceneServer::~SceneServer()
00048 {
00049 }
00050 
00051 boost::shared_ptr<Scene> SceneServer::CreateScene(const std::string &location)
00052 {
00053     shared_ptr<CoreContext> context = GetCore()->CreateContext();
00054 
00055     shared_ptr<Scene> scene = shared_static_cast<Scene>
00056         (context->New("oxygen/Scene", location));
00057 
00058     if (scene.get() != 0)
00059         {
00060             ResetCache();
00061             mActiveScene = scene;
00062         }
00063 
00064     return scene;
00065 }
00066 
00067 bool SceneServer::SetActiveScene(const std::string &location)
00068 {
00069     shared_ptr<Scene> scene =
00070         shared_dynamic_cast<Scene>(GetCore()->Get(location));
00071 
00072     if (scene.get() != 0)
00073         {
00074             ResetCache();
00075             mActiveScene = scene;
00076             return true;
00077         }
00078 
00079     return false;
00080 }
00081 
00082 void SceneServer::ResetCache()
00083 {
00084     mActiveScene.reset();
00085     mActiveSpace.reset();
00086     mActiveWorld.reset();
00087 }
00088 
00089 void SceneServer::UpdateCache()
00090 {
00091     if (mActiveScene.get() == 0)
00092         {
00093             ResetCache();
00094             return;
00095         }
00096 
00097     if (mActiveSpace.get() == 0)
00098         {
00099             // cache the space reference
00100             mActiveSpace = shared_dynamic_cast<Space>
00101                 (mActiveScene->GetChildOfClass("Space"));
00102         }
00103 
00104     if (mActiveWorld.get() == 0)
00105         {
00106             // cache the world reference
00107             mActiveWorld = shared_dynamic_cast<World>
00108                 (mActiveScene->GetChildOfClass("World"));
00109         }
00110 }
00111 
00112 void SceneServer::OnUnlink()
00113 {
00114     ResetCache();
00115 }
00116 
00117 int SceneServer::GetTransformMark()
00118 {
00119     return mTransformMark;
00120 }
00121 
00160 void SceneServer::Update(float deltaTime)
00161 {
00162     if (
00163         (deltaTime == 0.0f) ||
00164         (mActiveScene.get() == 0)
00165         )
00166         {
00167             return;
00168         }
00169 
00170     UpdateCache();
00171     ++mTransformMark;
00172 
00173     mActiveScene->PrePhysicsUpdate(deltaTime);
00174 
00175     // determine collisions
00176     if (mActiveSpace.get() != 0)
00177         {
00178             mActiveSpace->Collide();
00179         }
00180 
00181     // do physics
00182     if (mActiveWorld.get() != 0)
00183         {
00184             mActiveWorld->Step(deltaTime);
00185         }
00186 
00187     mActiveScene->PostPhysicsUpdate();
00188     mActiveScene->UpdateHierarchy();
00189 }
00190 
00191 bool SceneServer::ImportScene(const string& fileName, shared_ptr<BaseNode> root,
00192                               shared_ptr<ParameterList> parameter)
00193 {
00194     if (! GetFile()->Exist(fileName))
00195         {
00196             GetLog()->Error() << "(SceneServer) ERROR: cannot locate file '"
00197                               << fileName << "'\n";
00198 
00199             return false;
00200         }
00201 
00202     TLeafList importer;
00203     ListChildrenSupportingClass<SceneImporter>(importer);
00204 
00205     if (importer.size() == 0)
00206         {
00207             GetLog()->Error()
00208                 << "(SceneServer) Warning: no SceneImporter registered\n";
00209         }
00210 
00211     for (
00212          TLeafList::iterator iter = importer.begin();
00213          iter != importer.end();
00214          ++iter
00215          )
00216         {
00217             shared_ptr<SceneImporter> importer =
00218                 shared_static_cast<SceneImporter>(*iter);
00219 
00220             if (importer->ImportScene(fileName,root,parameter))
00221                 {
00222                     GetLog()->Normal()
00223                         << "(SceneServer) imported scene file '"
00224                         << fileName << " with '"
00225                         << importer->GetName()
00226                         << " at " << root->GetFullPath() << endl;
00227 
00228                     RemoveTransformPaths(root);
00229 
00230                     // mark the corresponding scene as modified
00231                     shared_ptr<Scene> scene = root->GetScene();
00232                     if (scene.get() != 0)
00233                         {
00234                             scene->SetModified(true);
00235                         }
00236 
00237                     return true;
00238                 }
00239         }
00240 
00241     GetLog()->Error() << "(SceneServer) ERROR: cannot import scene file '"
00242                       << fileName << "'\n";
00243 
00244     return false;
00245 }
00246 
00247 void SceneServer::ReparentTransformChildren(shared_ptr<Transform> node)
00248 {
00249     shared_ptr<BaseNode> parent =
00250         shared_dynamic_cast<BaseNode>(make_shared(node->GetParent()));
00251 
00252     // while not empty
00253     while (node->begin() != node->end())
00254         {
00255             shared_ptr<Leaf> child = (*node->begin());
00256 
00257             shared_ptr<Transform> tChild
00258                 = shared_dynamic_cast<Transform>(child);
00259 
00260             if (tChild.get() != 0)
00261                 {
00262                     tChild->SetLocalTransform
00263                         (node->GetLocalTransform() * tChild->GetLocalTransform());
00264                 }
00265 
00266             child->Unlink();
00267             parent->AddChildReference(child);
00268         }
00269 }
00270 
00271 void SceneServer::RemoveTransformPaths(shared_ptr<Leaf> root)
00272 {
00273     if (root.get() == 0)
00274         {
00275             return;
00276         }
00277 
00278     // go top down and remove Transform nodes that only have Transform
00279     // node children and reparent them; note that reparented transform
00280     // nodes are automatically checked in the parent loop, as they are
00281     // appended to the child list in subsequent calls to
00282     // RemoveTransformPaths; this process leaves some transform node
00283     // without children, that are removed in a second pass
00284 
00285     for (
00286          TLeafList::iterator iter = root->begin();
00287          iter != root->end();
00288          ++iter
00289          )
00290         {
00291             RemoveTransformPaths(*iter);
00292         }
00293 
00294     shared_ptr<Transform> trans = shared_dynamic_cast<Transform>(root);
00295     bool tRoot = (trans.get() != 0);
00296     bool tChildOnly = true;
00297 
00298     TLeafList::iterator iter = root->begin();
00299     while (iter != root->end())
00300         {
00301             shared_ptr<Transform> tChild = shared_dynamic_cast<Transform>(*iter);
00302             if (tChild.get() == 0)
00303                 {
00304                     tChildOnly = false;
00305                 } else
00306                     {
00307                         if (tChild->begin() == tChild->end())
00308                             {
00309                                 // remove a transform node without
00310                                 // children
00311                                 tChild->Unlink();
00312 
00313                                 // restart as iter is now invalidated
00314                                 iter = root->begin();
00315                                 continue;
00316                             }
00317                     }
00318 
00319             ++iter;
00320         }
00321 
00322     if ( (tRoot) && (tChildOnly))
00323         {
00324             ReparentTransformChildren(trans);
00325         }
00326 }
00327 
00328 bool SceneServer::InitSceneImporter(const std::string& importerName)
00329 {
00330     shared_ptr<SceneImporter> importer
00331         = shared_dynamic_cast<SceneImporter>(GetCore()->New(importerName));
00332 
00333     if (importer.get() == 0)
00334         {
00335             GetLog()->Error() << "ERROR (SceneServer::InitSceneImporter) "
00336                               << "Unable to create '" << importerName << "'\n";
00337             return false;
00338         }
00339 
00340     importer->SetName(importerName);
00341     AddChildReference(importer);
00342 
00343     GetLog()->Normal()
00344         << "(SceneServer) SceneImporter '" << importerName << "' registered\n";
00345 
00346     return true;
00347 }
00348 
00349 

Generated on Thu Apr 6 15:25:39 2006 for rcssserver3d by  doxygen 1.4.4