SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLNode.cpp
Go to the documentation of this file.
1 /**
2  * \file SLNode.cpp
3  * \date July 2014
4  * \remarks Please use clangformat to format the code. See more code style on
5  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
6  * \authors Marc Wacker, Marcus Hudritsch, Jan Dellsperger
7  * \copyright http://opensource.org/licenses/GPL-3.0
8 */
9 
10 #include <SLAnimation.h>
11 #include <SLKeyframeCamera.h>
12 #include <SLLightDirect.h>
13 #include <SLLightRect.h>
14 #include <SLLightSpot.h>
15 #include <SLNode.h>
16 #include <SLText.h>
17 #include <SLScene.h>
18 #include <SLEntities.h>
19 #include <SLSceneView.h>
20 #include <Profiler.h>
21 
22 using std::cout;
23 using std::endl;
24 
25 unsigned int SLNode::instanceIndex = 0;
26 
27 //-----------------------------------------------------------------------------
28 // Static updateRec counter
30 //-----------------------------------------------------------------------------
31 /**
32  * @brief Construct a new SLNode::SLNode object
33  * @remarks It is important that during instantiation NO OpenGL functions (gl*)
34  * get called because this constructor will be most probably called in a parallel
35  * thread from within an SLScene::registerAssetsToLoad or SLScene::assemble
36  * function. All objects that get rendered have to do their OpenGL initialization
37  * when they are used the first time during rendering in the main thread.
38  * @param name Name of the node
39  */
40 SLNode::SLNode(const SLstring& name) : SLObject(name)
41 {
42  _parent = nullptr;
43  _depth = 1;
44  _entityID = INT32_MIN;
45  _om.identity();
46  _wm.identity();
47  _wmI.identity();
48  _drawBits.allOff();
49  _animation = nullptr;
50  _castsShadows = true;
51  _isWMUpToDate = false;
52  _isWMIUpToDate = false;
53  _isAABBUpToDate = false;
54  _isSelected = false;
55  _mesh = nullptr;
56  _minLodCoverage = 0.0f;
57  _levelForSM = 0;
58 }
59 //-----------------------------------------------------------------------------
60 /*!
61 Constructor with a mesh pointer and name.
62 It is important that during instantiation NO OpenGL functions (gl*) get called
63 because this constructor will be most probably called in a parallel thread from
64 within a SLScene::assemble function. All objects that get rendered have to do
65 their OpenGL initialization when they are used the first time during rendering
66 in the main thread.
67 */
68 SLNode::SLNode(SLMesh* mesh, const SLstring& name) : SLObject(name)
69 {
70  assert(mesh && "No mesh passed");
71 
72  _parent = nullptr;
73  _depth = 1;
74  _entityID = INT32_MIN;
75  _om.identity();
76  _wm.identity();
77  _wmI.identity();
78  _drawBits.allOff();
79  _animation = nullptr;
80  _castsShadows = true;
81  _isWMUpToDate = false;
82  _isWMIUpToDate = false;
83  _isAABBUpToDate = false;
84  _isSelected = false;
85  _minLodCoverage = 0.0f;
86  _levelForSM = 0;
87  _mesh = nullptr;
88 
89  addMesh(mesh);
90 }
91 //-----------------------------------------------------------------------------
92 /*!
93 Constructor with a mesh pointer, translation vector and name.
94 It is important that during instantiation NO OpenGL functions (gl*) get called
95 because this constructor will be most probably called in a parallel thread from
96 within a SLScene::assemble function. All objects that get rendered have to do
97 their OpenGL initialization when they are used the first time during rendering
98 in the main thread.
99 */
101  const SLVec3f& translation,
102  const SLstring& name) : SLObject(name)
103 {
104  assert(mesh && "No mesh passed");
105 
106  _parent = nullptr;
107  _depth = 1;
108  _entityID = INT32_MIN;
109  _om.identity();
111  _wm.identity();
112  _wmI.identity();
113  _drawBits.allOff();
114  _animation = nullptr;
115  _castsShadows = true;
116  _isWMUpToDate = false;
117  _isWMIUpToDate = false;
118  _isAABBUpToDate = false;
119  _isSelected = false;
120  _minLodCoverage = 0.0f;
121  _levelForSM = 0;
122  _mesh = nullptr;
123 
124  addMesh(mesh);
125 }
126 //-----------------------------------------------------------------------------
127 /*!
128 Destructor deletes all children recursively and the animation.
129 The mesh is not deleted. Meshes get deleted at the end by the SLAssetManager
130 vector. The entire scenegraph is deleted by deleting the SLScene::_root3D node.
131 Nodes that are not in the scenegraph will not be deleted at scene destruction.
132 */
134 {
135 #ifdef SL_USE_ENTITIES
136  SLint entityID = SLScene::entities.getEntityID(this);
137  SLint parentID = SLScene::entities.getParentID(this);
138  if (entityID != INT32_MIN && parentID != INT32_MIN)
139  {
140  if (parentID == -1)
141  SLScene::entities.clear();
142  else
143  SLScene::entities.deleteEntity(entityID);
144  }
145 #endif
146 
147  for (auto* child : _children)
148  delete child;
149  _children.clear();
150 
151  delete _animation;
152 }
153 //-----------------------------------------------------------------------------
154 /*!
155 Simply adds a mesh to its mesh pointer vector of the node.
156 */
158 {
159  assert(mesh && "No mesh passed");
160 
161  // Take over mesh name if node name is default name
162  if (_name == "Node" && mesh->name() != "Mesh")
163  _name = mesh->name() + "-Node";
164 
165  _mesh = mesh;
166 
167  _isAABBUpToDate = false;
168  mesh->init(this);
169 }
170 //-----------------------------------------------------------------------------
171 /*!
172 Inserts a mesh pointer in the mesh pointer vector after the
173 specified afterM pointer.
174 */
175 //! Draws the single mesh
177 {
178  if (_mesh)
179  _mesh->draw(sv, this);
180 }
181 //-----------------------------------------------------------------------------
182 //! Returns true if a mesh was assigned and set it to nullptr
184 {
185  if (_mesh)
186  {
187  _mesh = nullptr;
188  return true;
189  }
190  return false;
191 }
192 //-----------------------------------------------------------------------------
193 //! Returns true if the passed mesh was assigned and sets it to nullptr
195 {
196  if (_mesh == mesh && mesh != nullptr)
197  {
198  _mesh = nullptr;
199  return true;
200  }
201  return false;
202 }
203 //-----------------------------------------------------------------------------
204 /*!
205 Adds a child node to the children vector
206 */
208 {
209  assert(child && "The child pointer is null.");
210  assert(this != child && "You can not add the node to itself.");
211  assert(!child->parent() && "The child has already a parent.");
212 
213  _children.push_back(child);
214  _isAABBUpToDate = false;
215  child->parent(this);
216 
217 #ifdef SL_USE_ENTITIES
218  // Only add child to existing parents in entities
219  if (_entityID != INT32_MIN)
220  {
221  SLScene::entities.addChildEntity(_entityID, SLEntity(child));
222  }
223 #endif
224 }
225 //-----------------------------------------------------------------------------
226 /*!
227 Inserts a child node in the children vector after the afterC node.
228 */
229 bool SLNode::insertChild(SLNode* insertC, SLNode* afterC)
230 {
231  assert(insertC && afterC);
232  assert(insertC != afterC);
233 
234  auto found = std::find(_children.begin(), _children.end(), afterC);
235  if (found != _children.end())
236  {
237  _children.insert(found, insertC);
238  insertC->parent(this);
239  _isAABBUpToDate = false;
240  return true;
241  }
242  return false;
243 }
244 //-----------------------------------------------------------------------------
245 /*!
246 Deletes all child nodes.
247 */
249 {
250  for (auto& i : _children)
251  delete i;
252  _children.clear();
253 
254 #ifdef SL_USE_ENTITIES
255  SLint entityID = SLScene::entities.getEntityID(this);
256  SLint parentID = SLScene::entities.getParentID(this);
257  if (entityID != INT32_MIN && parentID != INT32_MIN)
258  {
259  SLScene::entities.deleteChildren(entityID);
260  }
261 #endif
262 }
263 //-----------------------------------------------------------------------------
264 /*!
265 Deletes the last child in the child vector.
266 */
268 {
269  if (!_children.empty())
270  {
271  delete _children.back();
272  _children.pop_back();
273  _isAABBUpToDate = false;
274  return true;
275  }
276  return false;
277 }
278 //-----------------------------------------------------------------------------
279 /*!
280 Deletes a child from the child vector.
281 */
283 {
284  assert(child);
285  for (SLulong i = 0; i < _children.size(); ++i)
286  {
287  if (_children[i] == child)
288  {
289  _children.erase(_children.begin() + (long)i);
290  delete child;
291  _isAABBUpToDate = false;
292  return true;
293  }
294  }
295  return false;
296 }
297 //-----------------------------------------------------------------------------
298 /*!
299 Searches for a child with the name 'name' and deletes it.
300 */
301 bool SLNode::deleteChild(const SLstring& name)
302 {
303  assert(!name.empty());
304  SLNode* found = findChild<SLNode>(name);
305  if (found) return deleteChild(found);
306  return false;
307 }
308 //-----------------------------------------------------------------------------
309 /*!
310 Searches for all nodes that contain the provided mesh
311 */
312 std::deque<SLNode*>
314  SLbool findRecursive)
315 {
316  std::deque<SLNode*> list;
317  findChildrenHelper(mesh, list, findRecursive);
318 
319  return list;
320 }
321 //-----------------------------------------------------------------------------
322 /*!
323 Helper function of findChildren for the passed mesh pointer
324 */
326  deque<SLNode*>& list,
327  SLbool findRecursive)
328 {
329  for (auto* child : _children)
330  {
331  if (child->_mesh == mesh)
332  list.push_back(child);
333  if (findRecursive)
334  child->findChildrenHelper(mesh, list, findRecursive);
335  }
336 }
337 //-----------------------------------------------------------------------------
338 /*!
339 Searches for all nodes that contain the provided mesh
340 */
341 deque<SLNode*>
343  SLbool findRecursive)
344 {
345  deque<SLNode*> list;
346  findChildrenHelper(drawbit, list, findRecursive);
347  return list;
348 }
349 //-----------------------------------------------------------------------------
350 /*!
351 Helper function of findChildren for passed drawing bit
352 */
354  deque<SLNode*>& list,
355  SLbool findRecursive)
356 {
357  for (auto* child : _children)
358  {
359  if (child->drawBits()->get(drawbit))
360  list.push_back(child);
361  if (findRecursive)
362  child->findChildrenHelper(drawbit, list, findRecursive);
363  }
364 }
365 //-----------------------------------------------------------------------------
366 //! remove child from vector of children. Removes false if not found, else true.
368 {
369  assert(child);
370  for (auto it = _children.begin(); it != _children.end(); ++it)
371  {
372  if (*it == child)
373  {
374  (*it)->parent(nullptr);
375  _children.erase(it);
376  return true;
377  }
378  }
379 
380  return false;
381 }
382 //-----------------------------------------------------------------------------
383 //! Initializer function to call SLNode::cull3DRec recursively
385 {
386  for (auto* child : _children)
387  child->cull3DRec(sv);
388 }
389 //-----------------------------------------------------------------------------
390 /*! Does the view frustum culling by checking whether the AABB is inside the 3D
391  * cameras view frustum. The check is done in world space. If a AABB is visible
392  * the nodes children are checked recursively. If a node is visible its mesh
393  * material is added to the SLSceneview::_visibleMaterials3D set and the node
394  * to the SLMaterials::nodesVisible3D vector. See also SLSceneView::draw3DGLAll
395  * for more details.
396  */
398 {
399  if (!this->drawBit(SL_DB_HIDDEN))
400  {
401  // Do frustum culling for all shapes except cameras & lights
402  if (sv->doFrustumCulling() &&
403  _parent != nullptr && // hsm4: do not frustum check the root node
404  !dynamic_cast<SLCamera*>(this) && // Ghm1: Checking for typeid fails if someone adds a custom camera that inherits SLCamera
405  typeid(*this) != typeid(SLLightRect) &&
406  typeid(*this) != typeid(SLLightSpot) &&
407  typeid(*this) != typeid(SLLightDirect))
408  {
409  sv->camera()->isInFrustum(&_aabb);
410  }
411  else
412  _aabb.isVisible(true);
413 
414  // For particle system updating (Break, no update, setup to resume)
415  SLParticleSystem* tempPS = dynamic_cast<SLParticleSystem*>(this->mesh());
416  if (tempPS && !_aabb.isVisible())
417  tempPS->setNotVisibleInFrustum();
418 
419  // Cull the group nodes recursively
420  if (_aabb.isVisible())
421  {
423 
424  if (this->drawBit(SL_DB_OVERDRAW))
425  sv->nodesOverdrawn().push_back(this);
426  else
427  {
428  // All nodes with meshes get rendered sorted by their material
429  if (this->mesh())
430  {
431  sv->visibleMaterials3D().insert(this->mesh()->mat());
432  this->mesh()->mat()->nodesVisible3D().push_back(this);
433  }
434  else
435  {
436  // Add camera or selected node without mesh to opaque vector for line drawing
437  if (dynamic_cast<SLCamera*>(this) || this->_isSelected)
438  sv->nodesOpaque3D().push_back(this);
439 
440  // Add special text node to blended vector
441  else if (typeid(*this) == typeid(SLText))
442  sv->nodesBlended3D().push_back(this);
443  }
444  }
445  }
446  }
447 }
448 //-----------------------------------------------------------------------------
449 /*!
450 Does the 2D frustum culling. If a node is visible its mesh material is added
451 to the SLSceneview::_visibleMaterials2D set and the node to the
452 SLMaterials::nodesVisible2D vector.
453 See also SLSceneView::draw3DGLAll for more details.
454 */
456 {
457  // PROFILE_FUNCTION();
458 
459  _aabb.isVisible(true);
460 
461  // Cull the group nodes recursively
462  for (auto* child : _children)
463  child->cull2DRec(sv);
464 
465  // Add all nodes to the opaque 2D vector
466  if (this->mesh())
467  {
468  sv->visibleMaterials2D().insert(this->mesh()->mat());
469  this->mesh()->mat()->nodesVisible2D().push_back(this);
470  }
471  else if (typeid(*this) == typeid(SLText))
472  sv->nodesBlended2D().push_back(this);
473 }
474 //-----------------------------------------------------------------------------
475 /*!
476 Updates the statistic numbers of the passed SLNodeStats struct
477 and calls recursively the same method for all children.
478 */
480 {
481  // PROFILE_FUNCTION();
482 
483  stats.numBytes += sizeof(SLNode);
484  stats.numNodes++;
485 
486  if (_children.empty())
487  stats.numNodesLeaf++;
488  else
489  stats.numNodesGroup++;
490 
491  if (typeid(*this) == typeid(SLLightSpot)) stats.numLights++;
492  if (typeid(*this) == typeid(SLLightRect)) stats.numLights++;
493  if (typeid(*this) == typeid(SLLightDirect)) stats.numLights++;
494 
495  if (_mesh)
496  _mesh->addStats(stats);
497 
498  for (auto* child : _children)
499  child->statsRec(stats);
500 }
501 //-----------------------------------------------------------------------------
502 /*!
503 Intersects the nodes meshes with the given ray. The intersection
504 test is only done if the AABB is intersected. The ray-mesh intersection is
505 done in the nodes object space. The rays origin and direction is therefore
506 transformed into the object space.
507 */
509 {
510  assert(ray != nullptr);
511 
512  // Do not test hidden nodes
514  return false;
515 
516  // Do not test origin node for shadow rays
517  // This restriction is not valid for objects that can shadow itself
518  // if (this == ray->srcNode && ray->type == SHADOW)
519  // return false;
520 
521  // Check first AABB for intersection
522  if (!_aabb.isHitInWS(ray))
523  return false;
524 
525  SLbool meshWasHit = false;
526 
527  // Transform ray to object space for non-groups
528  if (_mesh == nullptr)
529  {
530  // Special selection for cameras
531  if (dynamic_cast<SLCamera*>(this) && ray->sv->camera() != this)
532  {
533  ray->hitNode = this;
534  ray->hitMesh = nullptr;
535  SLVec3f OC = _aabb.centerWS() - ray->origin;
536  ray->length = OC.length();
537  return true;
538  }
539  }
540  else
541  {
542  // transform origin position to object space
543  ray->originOS.set(updateAndGetWMI().multVec(ray->origin));
544 
545  // transform the direction only with the linear sub matrix
546  ray->setDirOS(_wmI.mat3() * ray->dir);
547 
548  // test the mesh
549  if (_mesh->hit(ray, this) && !meshWasHit)
550  meshWasHit = true;
551 
552  if (ray->isShaded())
553  return true;
554  }
555 
556  // Test children nodes
557  for (auto* child : _children)
558  {
559  if (child->hitRec(ray) && !meshWasHit)
560  meshWasHit = true;
561  if (ray->isShaded())
562  return true;
563  }
564 
565  return meshWasHit;
566 }
567 //-----------------------------------------------------------------------------
568 /*!
569  Returns a deep copy of the node and its children recursively. The meshes do
570  not get copied.
571 */
573 {
574  SLNode* copy = new SLNode(name());
575  copy->_om.setMatrix(_om);
576  copy->_depth = _depth;
579  copy->_drawBits = _drawBits;
580  copy->_aabb = _aabb;
582 
583  if (_animation)
584  copy->_animation = new SLAnimation(*_animation);
585  else
586  copy->_animation = nullptr;
587 
588  if (_mesh)
589  copy->addMesh(_mesh);
590 
591  for (auto* child : _children)
592  copy->addChild(child->copyRec());
593 
594  return copy;
595 }
596 //-----------------------------------------------------------------------------
597 /*!
598 Sets the parent for this node and updates its depth
599 */
601 {
602  _parent = p;
603 
604  if (_parent)
605  _depth = _parent->depth() + 1;
606  else
607  _depth = 1;
608 }
609 //-----------------------------------------------------------------------------
610 /*!
611 Flags this node for an updateRec. This function is called
612 automatically if the local transform of the node or of its parent changed.
613 Nodes that are flagged for updating will recalculate their world transform
614 the next time it is requested by updateAndGetWM().
615 */
617 {
618 #ifdef SL_USE_ENTITIES
619  if (_entityID != INT32_MIN)
620  SLScene::entities.getEntity(_entityID)->om.setMatrix(_om);
621 #endif
622 
623  // stop if we reach a node that is already flagged.
624  if (!_isWMUpToDate)
625  return;
626 
627  _isWMUpToDate = false;
628  _isWMIUpToDate = false;
629 
630  // mark the WM of the children dirty since their parent just changed
631  for (auto* child : _children)
632  child->needUpdate();
633 
634  // flag AABB for an updateRec
635  needAABBUpdate();
636 }
637 //-----------------------------------------------------------------------------
638 /*!
639 Flags this node for a wm updateRec. It is almost
640 identical to the needUpdate function but it won't flag AABBs.
641 This function is currently not in use but could give a slight performance
642 boost if it was called instead of needUpdate for the children of a
643 node that changed.
644 */
646 {
647  // stop if we reach a node that is already flagged.
648  if (!_isWMUpToDate)
649  return;
650 
651  _isWMUpToDate = false;
652  _isWMIUpToDate = false;
653 
654  // mark the WM of the children dirty since their parent just changed
655  for (auto* child : _children)
656  child->needWMUpdate();
657 }
658 //-----------------------------------------------------------------------------
659 /*!
660 Flags this node's AABB for an updateRec. If a node
661 changed we need to updateRec it's world space AABB. This needs to also be propagated
662 up the parent chain since the AABB of a node incorporates the AABB's of child
663 nodes.
664 */
666 {
667  // stop if we reach a node that is already flagged.
668  if (!_isAABBUpToDate)
669  return;
670 
671  _isAABBUpToDate = false;
672 
673  // flag parent's for an AABB updateRec too since they need to
674  // merge the child AABBs
675  if (_parent)
677 }
678 //-----------------------------------------------------------------------------
679 /*!
680 A helper function that updates the current _wm to reflect the local matrix.
681 recursively calls the updateAndGetWM of the node's parent.
682 @note
683 This function is const because it has to be called from inside the updateAndGetWM
684 function which has to be const. Since we only updateRec the private cache of this
685 class it is ok.
686 */
687 void SLNode::updateWM() const
688 {
689  // PROFILE_FUNCTION();
690 
691  if (_parent)
693  else
694  _wm.setMatrix(_om);
695 
696  _isWMUpToDate = true;
697  numWMUpdates++;
698 }
699 //-----------------------------------------------------------------------------
700 /*! Returns the current world matrix for this node. If the world matrix is out
701  * of date it will updateRec it and return a current result.
702  */
704 {
705  if (!_isWMUpToDate)
706  updateWM();
707 
708  return _wm;
709 }
710 //-----------------------------------------------------------------------------
711 /*! Returns the current world inverse matrix for this node. If the world matrix
712  * is out of date it will updateRec it and return a current result.
713  */
715 {
716  if (!_isWMUpToDate)
717  updateWM();
718 
719  if (!_isWMIUpToDate)
720  {
721  _wmI.setMatrix(_wm);
722  _wmI.invert();
723  _isWMIUpToDate = true;
724  }
725 
726  return _wmI;
727 }
728 //-----------------------------------------------------------------------------
729 /*! Updates the axis aligned bounding box in world space recursively.
730  */
732 {
733  if (_isAABBUpToDate)
734  return _aabb;
735 
736  // empty the AABB (= max negative AABB)
737  if (_mesh || !_children.empty())
738  {
739  _aabb.minWS(SLVec3f(FLT_MAX, FLT_MAX, FLT_MAX));
740  _aabb.maxWS(SLVec3f(-FLT_MAX, -FLT_MAX, -FLT_MAX));
741  }
742 
743  // Update special case of camera because it has no mesh
744  if (dynamic_cast<SLCamera*>(this))
745  ((SLCamera*)this)->buildAABB(_aabb, updateAndGetWM());
746 
747  // Build or updateRec AABB of meshes & merge them to the nodes aabb in WS
748  if (_mesh)
749  {
750  SLAABBox aabbMesh;
751  _mesh->buildAABB(aabbMesh, updateAndGetWM());
752  _aabb.mergeWS(aabbMesh);
753  }
754 
755  // Merge children in WS recursively
756  for (auto* child : _children)
757  _aabb.mergeWS(child->updateAABBRec(updateAlsoAABBinOS));
758 
759  // We need min & max also in OS for the uniform grid intersection in OS
760  // This is used for ray casts (picking) and raytracing.
761  if (updateAlsoAABBinOS)
763 
765 
766  // For visualizing the nodes' orientation we finally updateRec the axis in WS
768 
769  _isAABBUpToDate = true;
770  return _aabb;
771 }
772 //-----------------------------------------------------------------------------
773 /*! Prints the node name with the names of the meshes recursively
774  */
776 {
777  // dump node
778  for (SLint i = 0; i < _depth; ++i)
779  cout << " ";
780  cout << "Node: " << _name << endl;
781 
782  // dump meshes of node
783  for (SLint i = 0; i < _depth; ++i)
784  cout << " ";
785 
786  if (_mesh)
787  {
788  cout << "- Mesh: " << _mesh->name();
789  cout << ", " << _mesh->numI() * 3 << " tri";
790  if (_mesh->mat())
791  cout << ", Mat: " << _mesh->mat()->name();
792  }
793  else
794  cout << "- Mesh: none";
795  cout << endl;
796 
797  // dump children nodes
798  for (auto* child : _children)
799  child->dumpRec();
800 }
801 //-----------------------------------------------------------------------------
802 /*! Recursively sets the specified drawbit on or off. See also SLDrawBits.
803  */
805 {
806  _drawBits.set(bit, state);
807  for (auto* child : _children)
808  child->setDrawBitsRec(bit, state);
809 }
810 //-----------------------------------------------------------------------------
811 /*! Recursively sets the specified OpenGL primitive type.
812  */
814 {
815  for (auto* child : _children)
816  child->setPrimitiveTypeRec(primitiveType);
817 
818  _mesh->primitive(primitiveType);
819 }
820 //-----------------------------------------------------------------------------
821 
822 //-----------------------------------------------------------------------------
823 /*!
824 sets the position of this node to pos in 'relativeTo' space.
825 @note using TS_Object for this function yields the same result as calling
826 translate(pos, TS_Object)
827 */
828 void SLNode::translation(const SLVec3f& pos, SLTransformSpace relativeTo)
829 {
830  if (relativeTo == TS_world && _parent)
831  { // transform position to local space
832  SLVec3f localPos = _parent->updateAndGetWMI() * pos;
833  _om.translation(localPos);
834  }
835  else
836  _om.translation(pos);
837 
838  needUpdate();
839 }
840 //-----------------------------------------------------------------------------
841 /*!
842 sets the rotation of this node. The axis parameter
843 will be transformed into 'relativeTo' space. So an passing in an axis
844 of (0, 1, 0) with TS_Object will rotate the node around its own up axis.
845 */
846 void SLNode::rotation(const SLQuat4f& rot,
847  SLTransformSpace relativeTo)
848 {
849  SLMat4f rotation = rot.toMat4();
850 
851  if (_parent && relativeTo == TS_world)
852  {
853  // get the inverse parent rotation to remove it from our current rotation
854  // we want the input quaternion to absolutely set our new rotation relative
855  // to the world axes
856  SLMat4f parentRotInv = _parent->updateAndGetWMI();
857  parentRotInv.translation(0, 0, 0);
858 
859  // set the om rotation to the inverse of the parents rotation to achieve a
860  // 0, 0, 0 relative rotation in world space
861  _om.rotation(0, 0, 0, 0);
862  _om.setMatrix(_om * parentRotInv);
863  rotate(rot, relativeTo);
864  }
865  else if (relativeTo == TS_parent)
866  { // relative to parent, reset current rotation and just rotate again
867  _om.rotation(0, 0, 0, 0);
868  rotate(rot, relativeTo);
869  }
870  else
871  {
872  // in TS_Object everything is relative to our current orientation
873  _om.rotation(0, 0, 0, 0);
875  }
876  needUpdate();
877 }
878 //-----------------------------------------------------------------------------
879 /*!
880 sets the rotation of this node. The axis parameter
881 will be transformed into 'relativeTo' space. So a passing in an axis
882 of (0, 1, 0) with TS_Object will rotate the node around its own up axis.
883 */
884 void SLNode::rotation(SLfloat angleDeg,
885  const SLVec3f& axis,
886  SLTransformSpace relativeTo)
887 {
888  SLQuat4f rot(angleDeg, axis);
889  rotation(rot, relativeTo);
890 }
891 //-----------------------------------------------------------------------------
892 /*!
893 Sets the scaling of current object matrix
894 @note this modifier doesn't allow for different transform spaces, so there
895 isn't the possiblity for shearing an object currently.
896 */
897 void SLNode::scaling(const SLVec3f& scaling)
898 {
900  needUpdate();
901 }
902 //-----------------------------------------------------------------------------
903 /*!
904 Moves the node by the vector 'delta' relative to the space expressed by 'relativeTo'.
905 */
906 void SLNode::translate(const SLVec3f& delta, SLTransformSpace relativeTo)
907 {
908  switch (relativeTo)
909  {
910  case TS_object:
911  _om.translate(delta);
912  break;
913 
914  case TS_world:
915  if (_parent)
916  {
917  SLVec3f localVec = _parent->updateAndGetWMI().mat3() * delta;
918  _om.translation(localVec + _om.translation());
919  }
920  else
921  _om.translation(delta + _om.translation());
922  break;
923 
924  case TS_parent:
925  _om.translation(delta + _om.translation());
926  break;
927  }
928  needUpdate();
929 }
930 //-----------------------------------------------------------------------------
931 /*!
932 Rotates the node around its local origin relative to the space expressed by 'relativeTo'.
933 */
934 void SLNode::rotate(SLfloat angleDeg,
935  const SLVec3f& axis,
936  SLTransformSpace relativeTo)
937 {
938  SLQuat4f rot(angleDeg, axis);
939  rotate(rot, relativeTo);
940 }
941 //-----------------------------------------------------------------------------
942 /*!
943 Rotates the node around its local origin relative to the space expressed by 'relativeTo'.
944 */
945 void SLNode::rotate(const SLQuat4f& rot, SLTransformSpace relativeTo)
946 {
947  SLMat4f rotation = rot.toMat4();
948 
949  if (relativeTo == TS_object)
950  {
952  }
953  else if (_parent && relativeTo == TS_world)
954  {
955  SLMat4f rotWS;
957  rotWS.multiply(rotation);
959 
961  }
962  else // relativeTo == TS_Parent || relativeTo == TS_World && !_parent
963  {
964  SLMat4f rotOS;
965  rotOS.translate(translationOS());
966  rotOS.multiply(rotation);
967  rotOS.translate(-translationOS());
968 
969  _om.setMatrix(rotOS * _om);
970  }
971 
972  needUpdate();
973 }
974 //-----------------------------------------------------------------------------
975 /*!
976 Rotates the node around an arbitrary point. The 'axis' and 'point' parameter
977 are relative to the space described by 'relativeTo'.
978 */
979 void SLNode::rotateAround(const SLVec3f& point,
980  SLVec3f& axis,
981  SLfloat angleDeg,
982  SLTransformSpace relativeTo)
983 {
984  SLVec3f localPoint = point;
985  SLVec3f localAxis = axis;
986 
987  if (relativeTo == TS_world && _parent)
988  {
989  localPoint = _parent->updateAndGetWMI() * point;
990  localAxis = _parent->updateAndGetWMI().mat3() * axis;
991  }
992 
993  SLMat4f rot;
994  rot.translate(localPoint);
995  rot.rotate(angleDeg, localAxis);
996  rot.translate(-localPoint);
997 
998  if (relativeTo == TS_object)
999  _om.setMatrix(_om * rot);
1000  else
1001  _om.setMatrix(rot * _om);
1002 
1003  needUpdate();
1004 }
1005 //-----------------------------------------------------------------------------
1006 /*!
1007 Adds a scale transform to the current object matrix
1008 @note this is not a setter but a scale modifier.
1009 @note this modifier doesn't allow for different transform spaces, so there
1010 isn't the possibility for shearing an object currently.
1011 */
1012 void SLNode::scale(const SLVec3f& scale)
1013 {
1014  _om.scale(scale);
1015  needUpdate();
1016 }
1017 //-----------------------------------------------------------------------------
1018 /*!
1019 Rotates the object so that it's forward vector is pointing towards the 'target'
1020 point. Default forward is -Z. The 'relativeTo' parameter defines in what space
1021 the 'target' parameter is to be interpreted in.
1022 */
1023 void SLNode::lookAt(const SLVec3f& target,
1024  const SLVec3f& up,
1025  SLTransformSpace relativeTo)
1026 {
1027  SLVec3f pos = translationOS();
1028  SLVec3f dir;
1029  SLVec3f localUp = up;
1030 
1031  if (relativeTo == TS_world && _parent)
1032  {
1033  SLVec3f localTarget = _parent->updateAndGetWMI() * target;
1034  localUp = _parent->updateAndGetWMI().mat3() * up;
1035  dir = localTarget - translationOS();
1036  }
1037  else if (relativeTo == TS_object)
1038  dir = _om * target - translationOS();
1039  else
1040  dir = target - translationOS();
1041 
1042  dir.normalize();
1043 
1044  SLfloat cosAngle = localUp.dot(dir);
1045 
1046  // dir and up are parallel and facing in the same direction
1047  // or facing in opposite directions.
1048  // in this case we just rotate the up vector by 90� around
1049  // our current right vector
1050  // @todo This check might make more sense to be in Mat3.posAtUp
1051  if (fabs(cosAngle - 1.0) <= FLT_EPSILON || fabs(cosAngle + 1.0) <= FLT_EPSILON)
1052  {
1053  SLMat3f rot;
1054  rot.rotation(-90.0f, rightOS());
1055 
1056  localUp = rot * localUp;
1057  }
1058 
1059  _om.posAtUp(pos, pos + dir, localUp);
1060 
1061  needUpdate();
1062 }
1063 //-----------------------------------------------------------------------------
1064 /*!
1065 Scales and translates the node so that its largest
1066 dimension is maxDim and the center is in [0,0,0].
1067 */
1069 {
1070  _aabb = updateAABBRec(true);
1071  SLVec3f size(_aabb.maxWS() - _aabb.minWS());
1072  SLVec3f center((_aabb.maxWS() + _aabb.minWS()) * 0.5f);
1073  SLfloat scaleFactor = maxDim / size.maxXYZ();
1074  if (fabs(scaleFactor) > FLT_EPSILON)
1075  scale(scaleFactor);
1076  else
1077  cout << "Node can't be scaled: " << name().c_str() << endl;
1078  translate(-center);
1079 }
1080 //-----------------------------------------------------------------------------
1081 /*!
1082 Saves the current position as the initial state
1083 */
1085 {
1086  _initialOM = _om;
1087 }
1088 //-----------------------------------------------------------------------------
1089 /*!
1090 Resets this object to its initial state
1091 */
1093 {
1095  needUpdate();
1096 }
1097 //-----------------------------------------------------------------------------
1098 //! Returns the first skeleton found in the meshes
1099 const SLAnimSkeleton*
1101 {
1102  if (_mesh && _mesh->skeleton())
1103  return _mesh->skeleton();
1104  return nullptr;
1105 }
1106 //-----------------------------------------------------------------------------
1108 {
1109  // if (_parent == nullptr) PROFILE_FUNCTION();
1110 
1111  // Call optional update callback of attached
1112  if (_onUpdateCB)
1113  _onUpdateCB();
1114 
1115  // Call doUpdate for inherited classes if implemented
1116  doUpdate();
1117 
1118  for (auto* child : _children)
1119  child->updateRec();
1120 }
1121 //-----------------------------------------------------------------------------
1122 //! Update all skinned meshes recursively.
1123 /*! Do software skinning on all changed skeletons && updateRec any out of date
1124  acceleration structure for RT or if they're being rendered.
1125 */
1126 bool SLNode::updateMeshSkins(bool forceCPUSkinning,
1127  const function<void(SLMesh*)>& cbInformNodes)
1128 {
1129  if (drawBit(SL_DB_WITHEDGES) ||
1132  forceCPUSkinning = true;
1133 
1134  bool hasChanges = false;
1135 
1136  // Do software skinning on changed skeleton
1137  if (_mesh && _mesh->skeleton() && _mesh->skeleton()->changed())
1138  {
1139  _mesh->transformSkin(forceCPUSkinning, cbInformNodes);
1140  hasChanges = true;
1141  }
1142 
1143  for (auto* child : _children)
1144  hasChanges |= child->updateMeshSkins(forceCPUSkinning, cbInformNodes);
1145 
1146  return hasChanges;
1147 }
1148 //-----------------------------------------------------------------------------
1150 {
1151  PROFILE_FUNCTION();
1152 
1155 
1156  for (auto* child : _children)
1157  child->updateMeshAccelStructs();
1158 }
1159 //-----------------------------------------------------------------------------
1160 //! Updates the mesh material recursively with a material lambda
1161 void SLNode::updateMeshMat(function<void(SLMaterial* m)> setMat, bool recursive)
1162 {
1163  if (_mesh && _mesh->mat())
1164  setMat(_mesh->mat());
1165 
1166  if (recursive)
1167  for (auto* child : _children)
1168  child->updateMeshMat(setMat, recursive);
1169 }
1170 //-----------------------------------------------------------------------------
1171 //! Set the mesh material recursively
1172 void SLNode::setMeshMat(SLMaterial* mat, bool recursive)
1173 {
1174  if (_mesh)
1175  _mesh->mat(mat);
1176 
1177  if (recursive)
1178  for (auto* child : _children)
1179  child->setMeshMat(mat, recursive);
1180 }
1181 //-----------------------------------------------------------------------------
1182 #ifdef SL_HAS_OPTIX
1183 void SLNode::createInstanceAccelerationStructureTree()
1184 {
1185  vector<OptixInstance> instances;
1186 
1187  for (auto child : children())
1188  {
1189  if (!child->optixTraversableHandle())
1190  {
1191  child->createInstanceAccelerationStructureTree();
1192  }
1193 
1194  if (child->optixTraversableHandle())
1195  {
1196  OptixInstance instance;
1197 
1198  const SLMat4f mat4x4 = om();
1199  float transform[12] = {mat4x4.m(0),
1200  mat4x4.m(4),
1201  mat4x4.m(8),
1202  mat4x4.m(12),
1203  mat4x4.m(1),
1204  mat4x4.m(5),
1205  mat4x4.m(9),
1206  mat4x4.m(13),
1207  mat4x4.m(2),
1208  mat4x4.m(6),
1209  mat4x4.m(10),
1210  mat4x4.m(14)};
1211  memcpy(instance.transform, transform, sizeof(float) * 12);
1212 
1213  instance.instanceId = instanceIndex++;
1214  instance.visibilityMask = 255;
1215  instance.flags = OPTIX_INSTANCE_FLAG_NONE;
1216  instance.traversableHandle = child->optixTraversableHandle();
1217  instance.sbtOffset = 0;
1218 
1219  instances.push_back(instance);
1220  }
1221  }
1222 
1223  if (mesh())
1224  {
1225  _mesh->updateMeshAccelerationStructure();
1226  OptixInstance instance;
1227 
1228  const SLMat4f& mat4x4 = om();
1229  float transform[12] = {mat4x4.m(0),
1230  mat4x4.m(4),
1231  mat4x4.m(8),
1232  mat4x4.m(12),
1233  mat4x4.m(1),
1234  mat4x4.m(5),
1235  mat4x4.m(9),
1236  mat4x4.m(13),
1237  mat4x4.m(2),
1238  mat4x4.m(6),
1239  mat4x4.m(10),
1240  mat4x4.m(14)};
1241 
1242  memcpy(instance.transform, transform, sizeof(float) * 12);
1243 
1244  instance.instanceId = instanceIndex++;
1245  if (_mesh->mat()->emissive().length() > 0)
1246  {
1247  instance.visibilityMask = 253;
1248  }
1249  else
1250  {
1251  instance.visibilityMask = 255;
1252  }
1253  instance.flags = OPTIX_INSTANCE_FLAG_NONE;
1254  instance.traversableHandle = _mesh->optixTraversableHandle();
1255  instance.sbtOffset = _mesh->sbtIndex();
1256 
1257  instances.push_back(instance);
1258  }
1259 
1260  if (instances.empty())
1261  {
1262  return;
1263  }
1264 
1265  SLOptixCudaBuffer<OptixInstance> instanceBuffer = SLOptixCudaBuffer<OptixInstance>();
1266  instanceBuffer.alloc_and_upload(instances);
1267 
1268  _buildInput.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES;
1269  _buildInput.instanceArray.instances = instanceBuffer.devicePointer();
1270  _buildInput.instanceArray.numInstances = (SLuint)instances.size();
1271 
1272  buildAccelerationStructure();
1273 }
1274 //-----------------------------------------------------------------------------
1275 void SLNode::createInstanceAccelerationStructureFlat()
1276 {
1277  vector<OptixInstance> instances;
1278 
1279  createOptixInstances(instances);
1280 
1281  if (instances.empty())
1282  {
1283  return;
1284  }
1285 
1286  SLOptixCudaBuffer<OptixInstance> instanceBuffer = SLOptixCudaBuffer<OptixInstance>();
1287  instanceBuffer.alloc_and_upload(instances);
1288 
1289  _buildInput.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES;
1290  _buildInput.instanceArray.instances = instanceBuffer.devicePointer();
1291  _buildInput.instanceArray.numInstances = (SLuint)instances.size();
1292 
1293  buildAccelerationStructure();
1294 }
1295 //-----------------------------------------------------------------------------
1296 void SLNode::createOptixInstances(vector<OptixInstance>& instances)
1297 {
1298  for (auto child : children())
1299  {
1300  child->createOptixInstances(instances);
1301  }
1302 
1303  if (_mesh)
1304  {
1305  _mesh->updateMeshAccelerationStructure();
1306  OptixInstance instance;
1307 
1308  const SLMat4f& mat4x4 = updateAndGetWM();
1309  float transform[12] = {mat4x4.m(0),
1310  mat4x4.m(4),
1311  mat4x4.m(8),
1312  mat4x4.m(12),
1313  mat4x4.m(1),
1314  mat4x4.m(5),
1315  mat4x4.m(9),
1316  mat4x4.m(13),
1317  mat4x4.m(2),
1318  mat4x4.m(6),
1319  mat4x4.m(10),
1320  mat4x4.m(14)};
1321  memcpy(instance.transform, transform, sizeof(float) * 12);
1322 
1323  instance.instanceId = instanceIndex++;
1324  if (_mesh->name().find("LightSpot") != -1 ||
1325  _mesh->name() == "line")
1326  {
1327  instance.visibilityMask = 252;
1328  }
1329  else if (_mesh->name().find("LightRect") != -1)
1330  {
1331  instance.visibilityMask = 254;
1332  }
1333  else
1334  {
1335  instance.visibilityMask = 255;
1336  }
1337  instance.flags = OPTIX_INSTANCE_FLAG_NONE;
1338  instance.traversableHandle = _mesh->optixTraversableHandle();
1339  instance.sbtOffset = _mesh->sbtIndex();
1340 
1341  instances.push_back(instance);
1342  }
1343 }
1344 #endif
1345 //-----------------------------------------------------------------------------
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
float SLfloat
Definition: SL.h:173
unsigned long SLulong
Definition: SL.h:165
unsigned int SLuint
Definition: SL.h:171
bool SLbool
Definition: SL.h:175
string SLstring
Definition: SL.h:158
int SLint
Definition: SL.h:170
#define SL_DB_ONLYEDGES
Draw only hard edges.
Definition: SLDrawBits.h:31
#define SL_DB_WITHEDGES
Draw faces with hard edges.
Definition: SLDrawBits.h:30
#define SL_DB_OVERDRAW
Draw node over all other nodes.
Definition: SLDrawBits.h:29
#define SL_DB_VOXELS
Draw the voxels of the uniform grid.
Definition: SLDrawBits.h:26
#define SL_DB_HIDDEN
Flags an object as hidden.
Definition: SLDrawBits.h:20
SLTransformSpace
Describes the relative space a transformation is applied in.
Definition: SLEnums.h:206
@ TS_world
Definition: SLEnums.h:208
@ TS_parent
Definition: SLEnums.h:209
@ TS_object
Definition: SLEnums.h:210
SLGLPrimitiveType
Definition: SLGLEnums.h:30
SLVec3< SLfloat > SLVec3f
Definition: SLVec3.h:318
Defines an axis aligned bounding box.
Definition: SLAABBox.h:34
SLVec3f centerWS()
Definition: SLAABBox.h:50
void mergeWS(SLAABBox &bb)
Merges the bounding box bb to this one by extending this one axis aligned.
Definition: SLAABBox.cpp:390
SLbool isHitInWS(SLRay *ray)
SLAABBox::isHitInWS: Ray - AABB Intersection Test in world space.
Definition: SLAABBox.cpp:361
void isVisible(SLbool visible)
Definition: SLAABBox.h:44
void minWS(const SLVec3f &minC)
Definition: SLAABBox.h:39
void fromWStoOS(const SLVec3f &minWS, const SLVec3f &maxWS, const SLMat4f &wmI)
Recalculate min and max before transformation in object coords.
Definition: SLAABBox.cpp:96
void maxWS(const SLVec3f &maxC)
Definition: SLAABBox.h:40
void updateAxisWS(const SLMat4f &wm)
Updates the axis of the owning node.
Definition: SLAABBox.cpp:141
void setCenterAndRadiusWS()
Calculates center & radius of the bounding sphere around the AABB.
Definition: SLAABBox.cpp:204
SLAnimSkeleton keeps track of a skeletons joints and animations.
SLbool changed() const
SLAnimation is the base container for all animation data.
Definition: SLAnimation.h:33
Active or visible camera node class.
Definition: SLCamera.h:54
SLbool get(SLuint bit)
Returns the specified bit.
Definition: SLDrawBits.h:69
void set(SLuint bit, SLbool state)
Sets the specified bit to the passed state.
Definition: SLDrawBits.h:57
void allOff()
Turns all bits off.
Definition: SLDrawBits.h:48
SLLightDirect class for a directional light source.
Definition: SLLightDirect.h:40
Light node class for a rectangular light source.
Definition: SLLightRect.h:39
SLLightSpot class for a spot light source.
Definition: SLLightSpot.h:36
void rotation(const T angleDEG, const SLVec3< T > &axis)
Sets the rotation components
Definition: SLMat3.h:392
void scale(T sxyz)
Definition: SLMat4.h:667
SLVec3< T > translation() const
Definition: SLMat4.h:184
void posAtUp(T PosX, T PosY, T PosZ, T dirAtX=0, T dirAtY=0, T dirAtZ=0, T dirUpX=0, T dirUpY=0, T dirUpZ=0)
Same as lightAt.
Definition: SLMat4.h:822
SLMat3< T > mat3() const
Definition: SLMat4.h:98
void setMatrix(const SLMat4 &A)
Set matrix by other 4x4 matrix.
Definition: SLMat4.h:335
void rotation(T degAng, const SLVec3< T > &axis, SLbool keepTranslation=true)
Sets the rotation with or without overwriting the translation.
Definition: SLMat4.h:978
void invert()
Inverts the matrix.
Definition: SLMat4.h:1364
void m(int i, T val)
Definition: SLMat4.h:93
void rotate(T degAng, T axisx, T axisy, T axisz)
Definition: SLMat4.h:656
void multiply(const SLMat4 &A)
Definition: SLMat4.h:536
SLMat4< T > inverted() const
Computes the inverse of a 4x4 non-singular matrix.
Definition: SLMat4.h:1371
void identity()
Sets the identity matrix.
Definition: SLMat4.h:1333
void scaling(T sxyz, SLbool keepTrans=true)
Sets the scaling with or without overwriting the translation.
Definition: SLMat4.h:1146
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
SLVNode & nodesVisible2D()
Definition: SLMaterial.h:231
SLVNode & nodesVisible3D()
Definition: SLMaterial.h:232
void emissive(const SLCol4f &emis)
Definition: SLMaterial.h:174
An SLMesh object is a triangulated mesh, drawn with one draw call.
Definition: SLMesh.h:134
void updateAccelStruct()
Definition: SLMesh.cpp:1133
SLGLPrimitiveType primitive() const
Definition: SLMesh.h:179
void transformSkin(bool forceCPUSkinning, const std::function< void(SLMesh *)> &cbInformNodes)
Transforms the vertex positions and normals with by joint weights.
Definition: SLMesh.cpp:1573
virtual void init(SLNode *node)
SLMesh::shapeInit sets the transparency flag of the AABB.
Definition: SLMesh.cpp:296
SLbool accelStructIsOutOfDate()
Definition: SLMesh.h:189
virtual void draw(SLSceneView *sv, SLNode *node, SLuint intances=0)
Definition: SLMesh.cpp:389
SLbool hit(SLRay *ray, SLNode *node)
Definition: SLMesh.cpp:910
void addStats(SLNodeStats &stats)
Definition: SLMesh.cpp:950
virtual void buildAABB(SLAABBox &aabb, const SLMat4f &wmNode)
Definition: SLMesh.cpp:1111
const SLAnimSkeleton * skeleton() const
Definition: SLMesh.h:180
SLuint numI() const
Definition: SLMesh.h:181
SLMaterial * mat() const
Definition: SLMesh.h:177
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
bool updateMeshSkins(bool forceCPUSkinning, const std::function< void(SLMesh *)> &cbInformNodes)
Update all skinned meshes recursively.
Definition: SLNode.cpp:1126
void resetToInitialState()
Definition: SLNode.cpp:1092
virtual void drawMesh(SLSceneView *sv)
Draws the single mesh.
Definition: SLNode.cpp:176
SLint entityID() const
Definition: SLNode.h:294
void rotation(const SLQuat4f &rot, SLTransformSpace relativeTo=TS_parent)
Definition: SLNode.cpp:846
function< void()> _onUpdateCB
Optional lambda callback once per update.
Definition: SLNode.h:364
~SLNode() override
Definition: SLNode.cpp:133
void addChild(SLNode *child)
Definition: SLNode.cpp:207
SLubyte _levelForSM
Level of LOD to use for shadow mapping (0 = the visible one will be drawn)
Definition: SLNode.h:363
SLVNode & children()
Definition: SLNode.h:305
SLMat4f _wmI
inverse world matrix
Definition: SLNode.h:353
SLbool drawBit(SLuint bit)
Definition: SLNode.h:300
void updateWM() const
Definition: SLNode.cpp:687
void translation(const SLVec3f &pos, SLTransformSpace relativeTo=TS_parent)
Definition: SLNode.cpp:828
bool removeMesh()
Returns true if a mesh was assigned and set it to nullptr.
Definition: SLNode.cpp:183
void parent(SLNode *p)
Definition: SLNode.cpp:600
virtual void dumpRec()
Definition: SLNode.cpp:775
SLAnimation * _animation
animation of the node
Definition: SLNode.h:361
const SLMat4f & om()
Definition: SLNode.h:295
void needWMUpdate()
Definition: SLNode.cpp:645
virtual void needUpdate()
Definition: SLNode.cpp:616
SLNode * parent()
Definition: SLNode.h:292
SLDrawBits _drawBits
node level drawing flags
Definition: SLNode.h:359
void rotate(const SLQuat4f &rot, SLTransformSpace relativeTo=TS_object)
Definition: SLNode.cpp:945
SLAABBox _aabb
axis aligned bounding box
Definition: SLNode.h:360
SLNode * _parent
pointer to the parent node
Definition: SLNode.h:344
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
void scale(SLfloat s)
Definition: SLNode.h:640
SLMesh * mesh()
Definition: SLNode.h:304
static SLuint numWMUpdates
NO. of calls to updateWMRec per frame.
Definition: SLNode.h:319
virtual SLNode * copyRec()
Definition: SLNode.cpp:572
void needAABBUpdate()
Definition: SLNode.cpp:665
SLMat4f _om
object matrix for local transforms
Definition: SLNode.h:350
static unsigned int instanceIndex
???
Definition: SLNode.h:321
bool insertChild(SLNode *insertC, SLNode *afterC)
Definition: SLNode.cpp:229
SLbool _isAABBUpToDate
is the saved aabb still valid
Definition: SLNode.h:356
const SLAnimSkeleton * skeleton()
Returns the first skeleton found in the meshes.
Definition: SLNode.cpp:1100
void setPrimitiveTypeRec(SLGLPrimitiveType primitiveType)
Definition: SLNode.cpp:813
void deleteChildren()
Definition: SLNode.cpp:248
SLVec3f rightOS() const
Definition: SLNode.h:486
SLfloat _minLodCoverage
Min. LOD coverage for visibility (0.0 < _minLodCoverage < 1.0)
Definition: SLNode.h:362
SLVec3f translationOS() const
Definition: SLNode.h:468
void updateRec()
Definition: SLNode.cpp:1107
SLMat4f _initialOM
the initial om state
Definition: SLNode.h:351
bool _isSelected
flag if node and one or more of its meshes are selected
Definition: SLNode.h:358
bool _castsShadows
flag if meshes of node should cast shadows
Definition: SLNode.h:357
void setMeshMat(SLMaterial *mat, bool recursive)
Set the mesh material recursively.
Definition: SLNode.cpp:1172
virtual void cullChildren3D(SLSceneView *sv)
Initializer function to call SLNode::cull3DRec recursively.
Definition: SLNode.cpp:384
virtual void addMesh(SLMesh *mesh)
Definition: SLNode.cpp:157
void updateMeshAccelStructs()
Definition: SLNode.cpp:1149
void setInitialState()
Definition: SLNode.cpp:1084
SLVNode _children
vector of children nodes
Definition: SLNode.h:345
virtual void doUpdate()
Definition: SLNode.h:308
virtual void statsRec(SLNodeStats &stats)
Definition: SLNode.cpp:479
void scaling(SLfloat s)
Definition: SLNode.h:607
const SLMat4f & updateAndGetWMI() const
Definition: SLNode.cpp:714
void lookAt(SLfloat targetX, SLfloat targetY, SLfloat targetZ, SLfloat upX=0, SLfloat upY=1, SLfloat upZ=0, SLTransformSpace relativeTo=TS_world)
Definition: SLNode.h:652
SLMesh * _mesh
pointer to a single mesh
Definition: SLNode.h:346
void updateMeshMat(std::function< void(SLMaterial *m)> setMat, bool recursive)
Updates the mesh material recursively with a material lambda.
Definition: SLNode.cpp:1161
SLNode(const SLstring &name="Node")
Construct a new SLNode::SLNode object.
Definition: SLNode.cpp:40
virtual SLAABBox & updateAABBRec(SLbool updateAlsoAABBinOS)
Definition: SLNode.cpp:731
deque< T * > findChildren(const SLstring &name="", SLbool findRecursive=true, SLbool canContain=false)
Definition: SLNode.h:416
SLMat4f _wm
world matrix for world transform
Definition: SLNode.h:352
virtual void cull2DRec(SLSceneView *sv)
Definition: SLNode.cpp:455
bool removeChild(SLNode *child)
remove child from vector of children. Removes false if not found, else true.
Definition: SLNode.cpp:367
void scaleToCenter(SLfloat maxDim)
Definition: SLNode.cpp:1068
SLbool _isWMIUpToDate
is the inverse WM of this node still valid
Definition: SLNode.h:355
SLint _entityID
ID in the SLVEntity graph for Data Oriented Design.
Definition: SLNode.h:349
bool deleteChild()
Definition: SLNode.cpp:267
SLint _depth
depth of the node in a scene tree
Definition: SLNode.h:348
void findChildrenHelper(const SLstring &name, deque< T * > &list, SLbool findRecursive, SLbool canContain=false)
Definition: SLNode.h:431
virtual bool hitRec(SLRay *ray)
Definition: SLNode.cpp:508
SLbool _isWMUpToDate
is the WM of this node still valid
Definition: SLNode.h:354
void setDrawBitsRec(SLuint bit, SLbool state)
Definition: SLNode.cpp:804
virtual void cull3DRec(SLSceneView *sv)
Definition: SLNode.cpp:397
void rotateAround(const SLVec3f &point, SLVec3f &axis, SLfloat angleDeg, SLTransformSpace relativeTo=TS_world)
Definition: SLNode.cpp:979
SLint depth() const
Definition: SLNode.h:293
void translate(const SLVec3f &vec, SLTransformSpace relativeTo=TS_object)
Definition: SLNode.cpp:906
Base class for all other classes.
Definition: SLObject.h:23
void name(const SLstring &Name)
Definition: SLObject.h:34
SLstring _name
name of an object
Definition: SLObject.h:42
const SLstring & name() const
Definition: SLObject.h:38
SLParticleSystem creates a particle meshes from a point primitive buffer.
SLMat4< T > toMat4() const
Definition: SLQuat4.h:337
Ray class with ray and intersection properties.
Definition: SLRay.h:40
SLVec3f origin
Vector to the origin of ray in WS.
Definition: SLRay.h:75
SLMesh * hitMesh
Points to the intersected mesh.
Definition: SLRay.h:106
SLVec3f dir
Direction vector of ray in WS.
Definition: SLRay.h:76
SLfloat length
length from origin to an intersection
Definition: SLRay.h:77
SLNode * hitNode
Points to the intersected node.
Definition: SLRay.h:105
void setDirOS(const SLVec3f &Dir)
Setter for the rays direction in object space also setting the inverse direction.
Definition: SLRay.h:159
SLVec3f originOS
Vector to the origin of ray in OS.
Definition: SLRay.h:80
SLSceneView * sv
Pointer to the sceneview.
Definition: SLRay.h:101
SLbool isShaded() const
Returns true if a shadow ray hits an object on the ray to the light.
Definition: SLRay.h:187
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
SLVNode & nodesOpaque3D()
Definition: SLSceneView.h:189
SLVNode & nodesBlended2D()
Definition: SLSceneView.h:192
std::unordered_set< SLMaterial * > & visibleMaterials3D()
Definition: SLSceneView.h:209
void camera(SLCamera *camera)
Definition: SLSceneView.h:145
SLVNode & nodesBlended3D()
Definition: SLSceneView.h:190
SLVNode & nodesOverdrawn()
Definition: SLSceneView.h:193
void doFrustumCulling(SLbool doFC)
Definition: SLSceneView.h:152
std::unordered_set< SLMaterial * > & visibleMaterials2D()
Definition: SLSceneView.h:208
SLText creates a mesh using a textured font from SLTexFont.
Definition: SLText.h:30
SLVec3 & normalize()
Definition: SLVec3.h:124
T length() const
Definition: SLVec3.h:122
void set(const T X, const T Y, const T Z)
Definition: SLVec3.h:59
T dot(const SLVec3 &v) const
Definition: SLVec3.h:117
T maxXYZ()
Definition: SLVec3.h:150
SLEntity is the Data Oriented Design version of a SLNode.
Definition: SLEntities.h:28
Struct for scene graph statistics.
Definition: SLNode.h:37
SLuint numNodes
NO. of children nodes.
Definition: SLNode.h:38
SLuint numLights
NO. of lights in mesh.
Definition: SLNode.h:46
SLuint numNodesLeaf
NO. of leaf nodes.
Definition: SLNode.h:42
SLuint numNodesGroup
NO. of group nodes.
Definition: SLNode.h:41
SLuint numBytes
NO. of bytes allocated.
Definition: SLNode.h:39