00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00128 #include "../include/IPSA/IpsaSimulator.h"
00129 #include "../include/IPSA/IpsaSimulatorDelegate.h"
00130 #include "../include/IPSA/ipsaclasses.h"
00131
00132 #include <iostream>
00133
00134 #include <Inventor/SoDB.h>
00135 #include <Inventor/SoInput.h>
00136 #include <Inventor/SoFullPath.h>
00137 #include <Inventor/nodes/SoFile.h>
00138 #include <Inventor/nodes/SoGroup.h>
00139 #include <Inventor/nodes/SoNode.h>
00140 #include <Inventor/actions/SoSearchAction.h>
00141 #include <Inventor/actions/SoWriteAction.h>
00142 #include <Inventor/lists/SbPList.h>
00143 #include <Inventor/lists/SoPathList.h>
00144
00149 IpsaSimulator::IpsaSimulator() :
00150 verboseOutput(true),
00151 isIpsaScheduled(false),
00152 sceneryFilename(""),
00153 simulationRoot(new SoSeparator),
00154 delegate(NULL)
00155 {
00156 SoWorldPhysics::initClasses();
00157 }
00158
00159
00163 IpsaSimulator::~IpsaSimulator()
00164 {
00165 SoWorldPhysics::DeInit();
00166 }
00167
00168
00172 void IpsaSimulator::setDelegate(IpsaSimulatorDelegate* delegate)
00173 {
00174 this->delegate = delegate;
00175 }
00176
00177
00181 SoNode* IpsaSimulator::getSceneGraph()
00182 {
00183 return simulationRoot;
00184 }
00185
00186
00198 bool IpsaSimulator::buildScenery()
00199 {
00200 SoNode* root = NULL;
00201 if (delegate)
00202 root = delegate->createScenery();
00203 else
00204 root = readSceneryFromFile();
00205
00206 if (!root)
00207 return false;
00208
00209 root->ref();
00210 simulationRoot = createPhysicsWorldIfMissing(root);
00211 root->unref();
00212
00213 if (!simulationRoot)
00214 return false;
00215
00216 this->applyPrefixNodes();
00217
00218 SoWorldPhysics::ApplyActionToWorldPhysicNodesInGraph(SoWorldPhysics::InitialiseWorldCB, simulationRoot);
00219
00220 return true;
00221 }
00222
00223
00235 SoNode* IpsaSimulator::readSceneryFromFile(bool expandFileNodesInGraph )
00236 {
00237 if (this->sceneryFilename.empty())
00238 return NULL;
00239
00240 SoInput mySceneInput;
00241 if (!mySceneInput.openFile(this->sceneryFilename.c_str()))
00242 {
00243 std::cerr << "Cannot open file " << this->sceneryFilename << std::endl;
00244 return NULL;
00245 }
00246
00247
00248 SoNode* root = SoDB::readAll(&mySceneInput);
00249 mySceneInput.closeFile();
00250
00251 if (NULL == root)
00252 {
00253 std::cerr
00254 << "[IpsaSimulator::readSceneryFromFile()] Problem reading file "
00255 << this->sceneryFilename << std::endl;
00256 return NULL;
00257 }
00258
00259 root->ref();
00260
00261 if (expandFileNodesInGraph)
00262 IpsaSimulator::ExpandFileNodes(root);
00263
00264 root->unrefNoDelete();
00265
00266 return root;
00267 }
00268
00269
00278 SoSeparator* IpsaSimulator::createPhysicsWorldIfMissing(SoNode* root)
00279 {
00280 if (NULL == root)
00281 return NULL;
00282 SoSearchAction sa;
00283 sa.setType(SoWorldPhysics::getClassTypeId());
00284 sa.setSearchingAll(TRUE);
00285
00286 sa.apply(root);
00287
00288 if (NULL != sa.getPath())
00289 {
00290
00291 SoSeparator* world = new SoSeparator();
00292 world->addChild(root);
00293 return world;
00294 }
00295
00296 SoSeparator* worldPhysics = new SoWorldPhysics("DefaultWorld");
00297 worldPhysics->addChild(root);
00298
00299 std::cerr << std::endl
00300 << "*******************************************************************************"
00301 << std::endl
00302 << "* Default SoWorldPhysics created because none was found in the Inventor Graph."
00303 << std::endl << "* Did you forget to specify one?" << std::endl
00304 << "*******************************************************************************"
00305 << std::endl << std::endl;
00306
00307 return worldPhysics;
00308 }
00309
00310
00314 void IpsaSimulator::applyPrefixNodes()
00315 {
00316 SoSearchAction sa;
00317 sa.setType(SoPrefixNode::getClassTypeId());
00318 sa.setInterest(SoSearchAction::ALL);
00319 sa.setSearchingAll(TRUE);
00320
00321 sa.apply(simulationRoot);
00322
00323 SoPathList pList = sa.getPaths();
00324
00325 for (int i = 0; i < pList.getLength(); i++)
00326 {
00327 SoPath* path = (pList[i]);
00328 if (NULL == path)
00329 continue;
00330 SoPrefixNode* prefixNode = dynamic_cast<SoPrefixNode*> (path->getTail());
00331 prefixNode->updatePrefixes();
00332 }
00333 }
00334
00335
00344 void IpsaSimulator::ExpandFileNodes(SoNode* root)
00345 {
00346 root->ref();
00347
00348
00349
00350 if (root->isOfType(SoFile::getClassTypeId()))
00351 {
00352 SoFile *f = dynamic_cast<SoFile*> (root);
00353 SoGroup *g = f->copyChildren();
00354 root->unref();
00355 root = dynamic_cast<SoSeparator*> (g);
00356 root->ref();
00357 }
00358
00359
00360 SoSearchAction sa;
00361 sa.setType(SoFile::getClassTypeId());
00362 sa.setInterest(SoSearchAction::FIRST);
00363 sa.setSearchingAll(TRUE);
00364
00365 sa.apply(root);
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 SoFullPath *p = (SoFullPath *) sa.getPath();
00377 while (p != NULL)
00378 {
00379 SoGroup *parent = (SoGroup *) p->getNodeFromTail(1);
00380 assert(parent != NULL);
00381
00382 SoFile *file = (SoFile *) p->getTail();
00383
00384
00385
00386 SbString filename = file->name.getValue();
00387
00388 printf("OI: expanding file %s\n", filename.getString());
00389
00390 int slashIndex = filename.find("/");
00391 if (-1 != slashIndex)
00392 {
00393 SbString searchPath = filename.getSubString(0, slashIndex - 1);
00394 SoInput::addDirectoryFirst(searchPath.getString());
00395 }
00396
00397 int fileIndex = p->getIndexFromTail(0);
00398 assert(fileIndex != -1);
00399
00400
00401
00402 SoGroup *fileGroup = file->copyChildren();
00403 fileGroup->ref();
00404 if (fileGroup != NULL)
00405 {
00406 parent->insertChild(fileGroup, fileIndex + 1);
00407 }
00408 else
00409 {
00410
00411
00412 parent->insertChild(new SoGroup, fileIndex + 1);
00413 }
00414
00415
00416
00417
00418
00419 parent->removeChild(fileIndex);
00420
00421 sa.apply(root);
00422 p = (SoFullPath *) sa.getPath();
00423 }
00424 root->unrefNoDelete();
00425 }
00426
00427
00432 void IpsaSimulator::reload()
00433 {
00434
00435 if (isIpsaScheduled)
00436 this->schedule();
00437
00438 SoWorldPhysics::DeInit();
00439
00440
00441 SoSeparator* scene = dynamic_cast<SoSeparator*>(simulationRoot);
00442 if (NULL != scene)
00443 scene->removeAllChildren();
00444
00445
00446 this->buildScenery();
00447 SoWorldPhysics::Init();
00448 }
00449
00450
00454 void IpsaSimulator::reset()
00455 {
00456
00457 if (isIpsaScheduled)
00458 this->schedule();
00459
00460 SoWorldPhysics::ApplyActionToWorldPhysicNodesInGraph(SoWorldPhysics::ResetWorldCB, simulationRoot);
00461 }
00462
00463
00468 void IpsaSimulator::save(const std::string& saveFile)
00469 {
00470 if (saveFile.empty())
00471 return;
00472
00473 printf("Saving scenegraph to file: %s\n", saveFile.c_str());
00474 SoOutput out;
00475 out.openFile(saveFile.c_str());
00476 SoWriteAction wa(&out);
00477 wa.apply(simulationRoot);
00478 out.closeFile();
00479 }
00480
00481
00488 void IpsaSimulator::schedule()
00489 {
00490 if (isIpsaScheduled)
00491 {
00492 SoWorldPhysics::ApplyActionToWorldPhysicNodesInGraph(
00493 SoWorldPhysics::UnscheduleWorldCB,
00494 simulationRoot);
00495 isIpsaScheduled = false;
00496 }
00497 else
00498 {
00499 SoWorldPhysics::ApplyActionToWorldPhysicNodesInGraph(
00500 SoWorldPhysics::ScheduleWorldCB,
00501 simulationRoot);
00502 isIpsaScheduled = true;
00503 }
00504 }