7 #include "imstkScene.h" 8 #include "imstkCamera.h" 9 #include "imstkDeviceControl.h" 10 #include "imstkCameraController.h" 11 #include "imstkCollisionDetectionAlgorithm.h" 12 #include "imstkFeDeformableObject.h" 13 #include "imstkFemDeformableBodyModel.h" 14 #include "imstkLight.h" 15 #include "imstkLogger.h" 16 #include "imstkParallelUtils.h" 18 #include "imstkSequentialTaskGraphController.h" 19 #include "imstkTaskGraph.h" 20 #include "imstkTaskGraphVizWriter.h" 21 #include "imstkTbbTaskGraphController.h" 22 #include "imstkTimer.h" 23 #include "imstkTrackingDeviceControl.h" 24 #include "imstkVisualModel.h" 25 #include "imstkAbstractDynamicalModel.h" 29 Scene::Scene(
const std::string& name, std::shared_ptr<SceneConfig> config) :
32 m_activeCamera(nullptr),
33 m_taskGraph(
std::make_shared<TaskGraph>(
"Scene_" + name +
"_Source",
"Scene_" + name +
"_Sink")),
34 m_computeTimesLock(
std::make_shared<ParallelUtils::SpinLock>())
36 auto defaultCam = std::make_shared<Camera>();
37 defaultCam->setPosition(0.0, 2.0, -15.0);
38 defaultCam->setFocalPoint(0.0, 0.0, 0.0);
40 auto debugCam = std::make_shared<Camera>();
41 debugCam->setPosition(0.0, 4.0, -30.0);
42 debugCam->setFocalPoint(0.0, 0.0, 0.0);
44 m_cameras[
"default"] = defaultCam;
45 m_cameras[
"debug"] = debugCam;
46 setActiveCamera(
"default");
54 std::unordered_set<std::shared_ptr<AbstractDynamicalModel>> systems;
55 for (
const auto& ent : m_sceneEntities)
57 if (
auto dynObj = std::dynamic_pointer_cast<DynamicObject>(ent))
59 systems.insert(dynObj->getDynamicalModel());
64 for (
const auto& ent : m_sceneEntities)
66 if (
auto obj = std::dynamic_pointer_cast<SceneObject>(ent))
68 CHECK(obj->initialize()) <<
"Error initializing scene object: " << obj->getName();
71 if (
auto deviceObj = std::dynamic_pointer_cast<DeviceControl>(obj))
73 deviceObj->printControls();
81 std::unordered_map<std::shared_ptr<Component>,
bool> compIsInitd;
82 for (
const auto& ent : m_sceneEntities)
84 std::vector<std::shared_ptr<Component>> compsToInit = ent->getComponents();
85 while (compsToInit.size() > 0)
88 for (
const auto& comp : compsToInit)
91 compIsInitd[comp] =
true;
96 std::vector<std::shared_ptr<Component>> newComps = ent->getComponents();
98 for (
const auto& comp : newComps)
100 if (!compIsInitd[comp])
102 compsToInit.push_back(comp);
109 for (
const auto& system : systems)
111 CHECK(system->initialize()) <<
"Error initializing system";
124 if (m_config->debugCamBoundingBox)
126 Vec3d globalMin, globalMax;
129 const Vec3d center = (globalMin + globalMax) * 0.5;
130 const double size = (globalMax - globalMin).norm();
131 m_cameras[
"debug"]->setFocalPoint(center);
132 m_cameras[
"debug"]->setPosition(center + Vec3d(0.0, 1.0, 1.0).normalized() * size);
137 LOG(INFO) <<
"Scene '" << this->
getName() <<
"' initialized!";
144 if (this->getSceneObjects().size() == 0)
146 lowerCorner = Vec3d(0., 0., 0.);
147 upperCorner = Vec3d(0., 0., 0.);
151 lowerCorner = Vec3d(IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX);
152 upperCorner = Vec3d(IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN);
154 for (
const auto& ent : m_sceneEntities)
156 for (
const auto& visualModel : ent->getComponents<
VisualModel>())
158 Vec3d min = Vec3d(IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX);
159 Vec3d max = Vec3d(IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN);
160 std::shared_ptr<Geometry> geom = visualModel->getGeometry();
163 geom->computeBoundingBox(min, max);
164 lowerCorner = lowerCorner.cwiseMin(min);
165 upperCorner = upperCorner.cwiseMax(max);
169 const Vec3d range = upperCorner - lowerCorner;
170 lowerCorner = lowerCorner - range * (paddingPercent / 100.0);
171 upperCorner = upperCorner + range * (paddingPercent / 100.0);
185 for (
const auto& ent : m_sceneEntities)
187 if (
auto obj = std::dynamic_pointer_cast<SceneObject>(ent))
189 obj->initGraphEdges();
191 for (
const auto& comp : ent->getComponents())
194 if (behaviour !=
nullptr && behaviour->getTaskGraph() !=
nullptr)
203 for (
const auto& ent : m_sceneEntities)
205 if (
auto obj = std::dynamic_pointer_cast<SceneObject>(ent))
207 std::shared_ptr<TaskGraph> taskGraph = obj->getTaskGraph();
208 if (taskGraph !=
nullptr)
211 taskGraph = TaskGraph::removeUnusedNodes(taskGraph);
216 for (
const auto& comp : ent->getComponents())
218 if (
auto taskBehaviour = std::dynamic_pointer_cast<SceneBehaviour>(comp))
220 std::shared_ptr<TaskGraph> taskGraph = taskBehaviour->getTaskGraph();
221 if (taskGraph !=
nullptr)
224 taskGraph = TaskGraph::removeUnusedNodes(taskGraph);
239 m_taskGraphController = std::make_shared<SequentialTaskGraphController>();
243 if (m_config->writeTaskGraph)
250 LOG(FATAL) <<
"Scene TaskGraph is cyclic, cannot proceed";
254 if (m_config->graphReductionEnabled)
260 for (std::shared_ptr<TaskNode> node :
m_taskGraph->getNodes())
262 node->m_enableTiming = m_config->taskTimingEnabled;
267 m_nodeComputeTimes.clear();
269 if (m_config->writeTaskGraph)
278 m_taskGraphController->initialize();
284 m_config->taskTimingEnabled = enabled;
286 for (std::shared_ptr<TaskNode> node :
m_taskGraph->getNodes())
288 node->m_enableTiming = m_config->taskTimingEnabled;
295 addSceneObject(interaction);
298 std::shared_ptr<Entity>
301 auto iter = std::find_if(m_sceneEntities.begin(), m_sceneEntities.end(),
302 [name](
const std::shared_ptr<Entity>& i) {
return i->getName() == name; });
303 return (iter == m_sceneEntities.end()) ?
nullptr : *iter;
310 if (m_sceneEntities.find(entity) != m_sceneEntities.end())
312 LOG(WARNING) <<
"Entity " << entity->getName() <<
" already in the scene, not added";
317 const std::string orgName = entity->getName();
318 const std::string uniqueName = getUniqueName(orgName);
319 if (orgName != uniqueName)
321 LOG(INFO) <<
"Entity with name " << orgName <<
" already in scene. Renamed to " << uniqueName;
322 entity->setName(uniqueName);
325 m_sceneEntities.insert(entity);
327 LOG(INFO) << uniqueName <<
" entity added to " <<
m_name <<
" scene";
333 std::shared_ptr<Entity> ent = getSceneObject(name);
336 LOG(WARNING) <<
"No entity named '" << name
337 <<
"' was registered in this scene.";
340 removeSceneObject(ent);
346 if (m_sceneEntities.count(entity) != 0)
348 m_sceneEntities.erase(entity);
350 LOG(INFO) << entity->getName() <<
" object removed from scene " <<
m_name;
354 LOG(WARNING) <<
"Could not remove Entity '" << entity->getName() <<
"', does not exist in the scene";
359 const std::vector<std::shared_ptr<Light>>
362 std::vector<std::shared_ptr<Light>> v;
364 for (
auto it = m_lightsMap.begin();
365 it != m_lightsMap.end();
368 v.push_back(it->second);
374 std::shared_ptr<Light>
377 if ((m_lightsMap.find(lightName) == m_lightsMap.end()))
379 LOG(WARNING) <<
"No light named '" << lightName
380 <<
"' was registered in this scene.";
384 return m_lightsMap.at(lightName);
390 if (m_lightsMap.find(name) != m_lightsMap.cend())
392 LOG(WARNING) <<
"Cannot add light: '" << name
393 <<
"' is already registered in this scene.";
397 m_lightsMap[name] = newLight;
399 LOG(INFO) << name <<
" light added to " <<
m_name;
405 if (this->getLight(lightName) ==
nullptr)
407 LOG(WARNING) <<
"No light named '" << lightName
408 <<
"' was registered in this scene.";
412 m_lightsMap.erase(lightName);
413 LOG(INFO) << lightName <<
" light removed from " <<
m_name;
420 std::string uniqueName = name;
422 while (getSceneObject(uniqueName) !=
nullptr)
424 uniqueName = name +
"_" + std::to_string(i);
433 using MapType = std::unordered_map<std::string, std::shared_ptr<Camera>>;
434 auto i = std::find_if(m_cameras.begin(), m_cameras.end(),
435 [&cam](
const MapType::value_type& j) {
return j.second == cam; });
436 if (i != m_cameras.end())
446 std::shared_ptr<imstk::Camera>
449 auto i = m_cameras.find(name);
450 if (i != m_cameras.end())
463 if (m_cameras.find(name) != m_cameras.end())
465 LOG(WARNING) <<
"Cannot add camera: Camera with the name " << name <<
" already exists.";
467 m_cameras[name] = cam;
473 auto i = m_cameras.find(name);
474 if (i != m_cameras.end())
476 m_activeCamera = m_cameras[name];
483 auto i = m_cameras.find(name);
484 if (i != m_cameras.end() && !(name ==
"default" || name ==
"debug"))
486 m_cameras.erase(name);
487 LOG(INFO) << name <<
" camera removed from " <<
m_name;
491 LOG(WARNING) <<
"No camera named '" << name
492 <<
"' is part of the scene.";
499 auto obj = std::make_shared<SceneObject>();
500 obj->addComponent(control);
508 m_resetRequested =
true;
515 for (
const auto& ent : m_sceneEntities)
517 if (
auto obj = std::dynamic_pointer_cast<SceneObject>(ent))
530 for (
auto obj : this->getSceneObjects())
532 if (
auto dynaObj = std::dynamic_pointer_cast<DynamicObject>(obj))
534 if (dynaObj->getDynamicalModel()->getTimeStepSizeType() == TimeSteppingType::RealTime)
536 dynaObj->getDynamicalModel()->setTimeStep(dt);
542 for (
auto obj : this->getSceneObjects())
544 if (
auto defObj = std::dynamic_pointer_cast<FeDeformableObject>(obj))
546 defObj->getFEMModel()->getContactForce().setConstant(0.0);
552 for (
auto obj : this->getSceneObjects())
555 if (
auto sceneObj = std::dynamic_pointer_cast<SceneObject>(obj))
559 for (
auto comp : obj->getComponents())
561 if (
auto behaviour = std::dynamic_pointer_cast<SceneBehaviour>(comp))
563 behaviour->update(dt);
569 if (m_taskGraphController !=
nullptr)
571 m_taskGraphController->execute();
575 if (m_resetRequested)
579 m_resetRequested =
false;
583 const double elapsedTime = wwt.
getTimeElapsed(StopWatch::TimeUnitType::seconds);
584 m_fps = 1.0 / elapsedTime;
585 m_frameTimes.pushBack(elapsedTime);
588 if (m_config->taskTimingEnabled)
591 for (std::shared_ptr<TaskNode> node :
m_taskGraph->getNodes())
593 m_nodeComputeTimes[node->m_name] = node->m_computeTime;
595 unlockComputeTimes();
602 for (
const auto& ent : m_sceneEntities)
604 if (
auto obj = std::dynamic_pointer_cast<SceneObject>(ent))
608 for (
auto comp : ent->getComponents())
610 if (
auto behaviour = std::dynamic_pointer_cast<SceneBehaviour>(comp))
612 behaviour->visualUpdate(dt);
621 m_computeTimesLock->lock();
625 Scene::unlockComputeTimes()
627 m_computeTimesLock->unlock();
void setActiveCamera(const std::string name)
Switch the active camera to the one requested by name. If the requested on doesn't exist...
void initTaskGraph()
Initializes the graph after its in a built state.
void computeBoundingBox(Vec3d &lowerCorner, Vec3d &upperCorner, const double paddingPercent=0.0)
Compute the bounding box of the scene as an union of bounding boxes of its objects.
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
virtual bool initialize()
Initialize the scene.
static bool isCyclic(std::shared_ptr< TaskGraph > graph)
Returns if Graph is cyclic or not.
Writes a TaskGraph to an svg file. Produces unique node names from duplicates with postfix...
const std::vector< std::shared_ptr< Light > > getLights() const
Return a vector of lights in the scene.
virtual void start()
Start the appropriate timer.
void lockComputeTimes()
Lock/Unlock the compute times resource.
void setEnableTaskTiming(const bool enabled)
If true, tasks will be time and a table produced every scene advance of the times.
static std::shared_ptr< TaskGraph > reduce(std::shared_ptr< TaskGraph > graph)
Simplifies the graph in a way that retains functionality Performs transitive reduction then redundant...
std::string getCameraName(const std::shared_ptr< Camera > cam) const
Get the name of the camera given the object (if it exists)
void write()
Writes the graph to a file given the filename.
void setFileName(std::string fileName)
The filename and path to write too.
A Behaviour represents a single component system A template is used here for UpdateInfo to keep the C...
void addCamera(const std::string &name, std::shared_ptr< Camera > cam)
Set the camera for the scene.
virtual void updateVisuals(const double dt)
Update visuals of all scene objects.
void addControl(std::shared_ptr< DeviceControl > control)
Adds a device control to a newly created SceneObject.
void reset()
Async reset the scene, will reset next update.
const std::string & getName() const
Get/Set the name of the entity.
static TaskNodeNameMap getUniqueNodeNames(std::shared_ptr< TaskGraph > graph, bool apply=false)
Nodes may not have unique names. Iterates the names with numeric postfix to generate uniques...
void removeLight(const std::string &lightName)
Remove light with a given name from the scene.
void buildTaskGraph()
Setup the task graph, this completely rebuilds the graph.
std::shared_ptr< Entity > getSceneObject(const std::string &name) const
Get SceneObject by name, returns nullptr if doesn't exist.
void initTaskGraphEdges()
Setup the edges/connections of the TaskGraph.
std::string getUniqueName(const std::string &name) const
Given a desired name, produce a unique one. This name would be iterated with a postfix # should one a...
void addSceneObject(std::shared_ptr< Entity > entity)
Add a scene object.
Stop Watch utility class.
void setInput(std::shared_ptr< TaskGraph > graph)
The graph to write.
void addLight(const std::string &name, std::shared_ptr< Light > newLight)
Add light from the scene.
void removeSceneObject(const std::string &name)
Remove scene object by name.
void removeCamera(const std::string name)
Remove the camera with a given name.
void postEvent(const T &e)
Emits the event Direct observers will be immediately called, in sync Queued observers will receive th...
void addInteraction(std::shared_ptr< Entity > interaction)
Add an interaction.
std::shared_ptr< TaskGraph > m_taskGraph
Computational Graph.
virtual double getTimeElapsed(const TimeUnitType unitType=TimeUnitType::milliSeconds)
Returns the time elapsed since calling start.
std::string m_name
Not unique name.
void resetSceneObjects()
Sync reset, resets immediately.
std::shared_ptr< Light > getLight(const std::string &lightName) const
Get a light with a given name.
virtual void advance(const double dt)
Advance the scene from current to next frame with specified timestep.
std::shared_ptr< Camera > getCamera(const std::string name) const
Get camera object given the name.
Contains geometric, material, and render information.