SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLSceneView.cpp
Go to the documentation of this file.
1 /**
2  * \file SLSceneView.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
7  * \copyright http://opensource.org/licenses/GPL-3.0
8  */
9 
10 #include "SL.h"
11 #include "SLEnums.h"
12 #include <SLAnimManager.h>
13 #include <SLCamera.h>
14 #include <SLLight.h>
15 #include <SLSceneView.h>
16 #include <SLSkybox.h>
17 #include <SLFileStorage.h>
18 #include <GlobalTimer.h>
19 #include <SLInputManager.h>
20 #include <Profiler.h>
21 #include <SLImGui.h>
22 #include <SLUiInterface.h>
23 #include <utility>
24 
25 #ifdef SL_EMSCRIPTEN
26 # define STB_IMAGE_WRITE_IMPLEMENTATION
27 # include "stb_image_write.h"
28 #endif
29 
30 //-----------------------------------------------------------------------------
31 //! SLSceneView default constructor
32 /*! The default constructor adds the this pointer to the sceneView vector in
33 SLScene. If an in between element in the vector is zero (from previous sceneviews)
34 it will be replaced. The sceneviews _index is the index in the sceneview vector.
35 It never changes throughout the life of a sceneview.
36 */
38  : SLObject(),
39  _s(s),
40  _dpi(dpi),
41  _inputManager(inputManager),
42  _shadowMapTimesMS(60, 0.0f),
43  _cullTimesMS(60, 0.0f),
44  _draw3DTimesMS(60, 0.0f),
45  _draw2DTimesMS(60, 0.0f),
46  _screenCaptureIsRequested(false),
47  _screenCaptureWaitFrames(0)
48 {
49 }
50 //-----------------------------------------------------------------------------
52 {
53 }
54 //-----------------------------------------------------------------------------
55 /*! SLSceneView::init initializes default values for an empty scene
56 @param name Name of the sceneview
57 @param screenWidth Width of the OpenGL frame buffer.
58 @param screenHeight Height of the OpenGL frame buffer.
59 @param onWndUpdateCallback Callback for ray tracing update
60 @param onSelectNodeMeshCallback Callback on node and mesh selection
61 @param gui Interface for the external Gui build function
62 @param configPath Path to the config file
63 */
65  SLint screenWidth,
66  SLint screenHeight,
67  void* onWndUpdateCallback,
68  void* onSelectNodeMeshCallback,
69  SLUiInterface* gui,
70  const string& configPath)
71 {
72  _gui = gui;
73  _name = std::move(name);
74  _scrW = screenWidth;
75  _scrH = screenHeight;
76  _gotPainted = true;
77 
78  // The window update callback function is used to refresh the ray tracing
79  // image during the rendering process. The ray tracing image is drawn by OpenGL
80  // as a texture on a single quad.
81  onWndUpdate = (cbOnWndUpdate)onWndUpdateCallback;
82 
83  // The on select node callback is called when a node got selected on double
84  // click, so that the UI can react on it.
85  onSelectedNodeMesh = (cbOnSelectNodeMesh)onSelectNodeMeshCallback;
86 
88 
89  // enables and modes
90  _mouseDownL = false;
91  _mouseDownR = false;
92  _mouseDownM = false;
93  _touchDowns = 0;
94 
95  _doDepthTest = true;
96  _doMultiSampling = true;
97  _doFrustumCulling = true;
98  _doAlphaSorting = true;
99  _doWaitOnIdle = true;
100  _drawBits.allOff();
101 
102  _stats2D.clear();
103  _stats3D.clear();
104 
105  _scrWdiv2 = _scrW >> 1;
106  _scrHdiv2 = _scrH >> 1;
108 
109  _renderType = RT_gl;
110 
112 
113 #if defined(SL_OS_ANDROID) || defined(SL_OS_MACIOS) || defined(SL_EMSCRIPTEN)
115 #else
117 #endif
118 
119  if (_gui)
120  _gui->init(configPath);
121 
122  // Set default viewport ratio to the same as the screen
124 
125  onStartup();
126 }
127 //-----------------------------------------------------------------------------
129 {
131  _mouseDownL = false;
132  _mouseDownR = false;
133  _mouseDownM = false;
134  _touchDowns = 0;
135 
136  _renderType = RT_gl;
137 
138  _doDepthTest = true;
139  _doMultiSampling = true;
140  _doFrustumCulling = true;
141  _doAlphaSorting = true;
142  _doWaitOnIdle = true;
143  _drawBits.allOff();
144 
145  for (auto* material : _visibleMaterials2D)
146  material->nodesVisible2D().clear();
147  _visibleMaterials2D.clear();
148 
149  for (auto* material : _visibleMaterials3D)
150  material->nodesVisible3D().clear();
151  _visibleMaterials3D.clear();
152 
153  _stats2D.clear();
154  _stats3D.clear();
155  _s = nullptr;
156 }
157 //-----------------------------------------------------------------------------
158 /*!
159 SLSceneView::onInitialize is called by the window system before the first
160 rendering. It applies all scene rendering attributes with the according
161 OpenGL function.
162 */
164 {
166  _sceneViewCamera.name("SceneView Camera");
168  _sceneViewCamera.clipFar(2000.0f);
173 
174  // fit scenes bounding box in view frustum
175  if (_s && _s->root3D())
176  {
177  // we want to fit the scenes combined aabb in the view frustum
178  SLAABBox* sceneBounds = _s->root3D()->aabb();
179 
181  _sceneViewCamera.lookAt(sceneBounds->centerWS() + dir,
183  TS_parent);
184 
185  SLfloat minX = sceneBounds->minWS().x;
186  SLfloat minY = sceneBounds->minWS().y;
187  SLfloat minZ = sceneBounds->minWS().z;
188  SLfloat maxX = sceneBounds->maxWS().x;
189  SLfloat maxY = sceneBounds->maxWS().y;
190  SLfloat maxZ = sceneBounds->maxWS().z;
191 
192  // calculate the min and max points in view space
193  SLVec4f vsCorners[8];
194 
195  vsCorners[0] = SLVec4f(minX, minY, minZ);
196  vsCorners[1] = SLVec4f(maxX, minY, minZ);
197  vsCorners[2] = SLVec4f(minX, maxY, minZ);
198  vsCorners[3] = SLVec4f(maxX, maxY, minZ);
199  vsCorners[4] = SLVec4f(minX, minY, maxZ);
200  vsCorners[5] = SLVec4f(maxX, minY, maxZ);
201  vsCorners[6] = SLVec4f(minX, maxY, maxZ);
202  vsCorners[7] = SLVec4f(maxX, maxY, maxZ);
203 
204  SLVec3f vsMin(FLT_MAX, FLT_MAX, FLT_MAX);
205  SLVec3f vsMax(FLT_MIN, FLT_MIN, FLT_MIN);
206 
208 
209  for (auto& vsCorner : vsCorners)
210  {
211  vsCorner = vm * vsCorner;
212 
213  vsMin.x = std::min(vsMin.x, vsCorner.x);
214  vsMin.y = std::min(vsMin.y, vsCorner.y);
215  vsMin.z = std::min(vsMin.z, vsCorner.z);
216 
217  vsMax.x = std::max(vsMax.x, vsCorner.x);
218  vsMax.y = std::max(vsMax.y, vsCorner.y);
219  vsMax.z = std::max(vsMax.z, vsCorner.z);
220  }
221 
222  SLfloat distX = 0.0f;
223  SLfloat distY = 0.0f;
224  SLfloat halfTan = tan(Utils::DEG2RAD * _sceneViewCamera.fovV() * 0.5f);
225 
226  // @todo There is still a bug when OSX doesn't pass correct GLWidget size
227  // correctly set the camera distance...
229 
230  // special case for orthographic cameras
231  if (proj == P_monoOrthographic)
232  {
233  // NOTE, the orthographic camera has the ability to zoom by using the following:
234  // tan(SL_DEG2RAD*_fovV*0.5f) * pos.length();
235 
236  distX = vsMax.x / (ar * halfTan);
237  distY = vsMax.y / halfTan;
238  }
239  else
240  {
241  // for now we treat all other cases as having a single frustum
242  distX = (vsMax.x - vsMin.x) * 0.5f / (ar * halfTan);
243  distY = (vsMax.y - vsMin.y) * 0.5f / halfTan;
244 
245  distX += vsMax.z;
246  distY += vsMax.z;
247  }
248 
249  SLfloat dist = std::max(distX, distY);
250 
251  // set focal distance
254  }
255 
258 
259  // if no camera exists or in VR mode use the sceneViewCamera
260  if (_camera == nullptr)
261  {
263  }
264 
265  _camera->needUpdate();
266 }
267 //-----------------------------------------------------------------------------
268 /*!
269 SLSceneView::switchToSceneViewCamera the general idea for this function is
270 to switch to the editor camera from a scene camera. It could provide
271 functionality to stay at the position of the previous camera, or to be reset
272 to the init position etc..
273 */
275 {
276  // if we have an active camera, use its position and orientation
277  if (_camera)
278  {
279  SLMat4f currentWM = _camera->updateAndGetWM();
280  SLVec3f position = currentWM.translation();
281  SLVec3f forward(-currentWM.m(8), -currentWM.m(9), -currentWM.m(10));
282  _sceneViewCamera.translation(position);
283  _sceneViewCamera.lookAt(position + forward);
284  }
285 
287 }
288 //-----------------------------------------------------------------------------
289 //! Sets the active camera to the next in the scene
291 {
292  if (!_s)
293  return;
294 
295  SLCamera* nextCam = _s->nextCameraInScene(this->camera());
296 
297  if (nextCam == nullptr)
298  return;
299 
300  if (nextCam != _camera)
301  _camera = nextCam;
302  else
304 
306 }
307 //-----------------------------------------------------------------------------
308 //! Sets the viewport ratio and the viewport rectangle
310  SLViewportAlign vpAlign,
311  SLbool vpSameAsVideo)
312 {
313  assert(_scrW > 0 && _scrH > 0 && "SLSceneView::setViewportFromRatio: Invalid screen size");
314 
315  _viewportRatio = vpRatio;
316  _viewportAlign = vpAlign;
317  _viewportSameAsVideo = vpSameAsVideo;
318 
319  // Shortcut if viewport is the same as the screen
320  if (vpRatio == SLVec2i::ZERO)
321  {
322  _viewportRect.set(0, 0, _scrW, _scrH);
324  if (_gui)
326  return;
327  }
328 
329  // Calculate viewport rect from viewport aspect ratio
330  SLfloat vpWdivH = (float)vpRatio.x / (float)vpRatio.y;
331  _scrWdivH = (float)_scrW / (float)_scrH;
332  SLRecti vpRect;
333 
334  if (_scrWdivH > vpWdivH)
335  {
336  vpRect.width = (int)((float)_scrH * vpWdivH);
337  vpRect.height = _scrH;
338  vpRect.y = 0;
339 
340  switch (vpAlign)
341  {
342  // viewport coordinates are bottom-left
343  case VA_leftOrBottom: vpRect.x = 0; break;
344  case VA_center:
345  default: vpRect.x = (_scrW - vpRect.width) / 2; break;
346  }
347  }
348  else
349  {
350  vpRect.width = _scrW;
351  vpRect.height = (SLint)((float)_scrW / (float)vpWdivH);
352  vpRect.x = 0;
353 
354  switch (vpAlign)
355  {
356  // viewport coordinates are bottom-left
357  case VA_leftOrBottom: vpRect.y = 0; break;
358  case VA_center:
359  default: vpRect.y = (_scrH - vpRect.height) / 2; break;
360  }
361  }
362 
363  if (SLRecti(_scrW, _scrH).contains(vpRect))
364  {
365  _viewportRect = vpRect;
366  if (_gui)
368  }
369  else
370  SL_EXIT_MSG("SLSceneView::viewport: Viewport is bigger than the screen!");
371 }
372 //-----------------------------------------------------------------------------
373 /*!
374 SLSceneView::onInitialize is called by the window system before the first
375 rendering. It applies all scene rendering attributes with the according
376 OpenGL function.
377 */
379 {
381 
382  SLGLState* stateGL = SLGLState::instance();
383 
384  if (_camera)
385  stateGL->onInitialize(_camera->background().colors()[0]);
386  else
387  stateGL->onInitialize(SLCol4f::GRAY);
388 
389  _visibleMaterials2D.clear();
390  _visibleMaterials3D.clear();
391  _nodesOverdrawn.clear();
392  _stats2D.clear();
393  _stats3D.clear();
394 
395  _raytracer.deleteData(false);
396  _renderType = RT_gl;
397  _isFirstFrame = true;
398 
399 #ifdef SL_HAS_OPTIX
400  _optixRaytracer.setupOptix();
401  _optixPathtracer.setupOptix();
402 #endif
403 
404  // init 3D scene with initial depth 1
405  if (_s && _s->root3D() && _s->root3D()->aabb()->radiusOS() < 0.0001f)
406  {
407  // Init camera so that its frustum is set
408  if (_camera)
410 
411  // build axis aligned bounding box hierarchy after init
412  clock_t t = clock();
413  _s->root3D()->updateAABBRec(true);
414  _s->root3D()->updateMeshAccelStructs();
415 
416  SL_LOG_DEBUG("Time for AABBs : %5.3f sec.",
417  (SLfloat)(clock() - t) / (SLfloat)CLOCKS_PER_SEC);
418 
419  // Collect node statistics
420  _s->root3D()->statsRec(_stats3D);
421 
422  // Warn if there are no light in scene
423  if (_s->lights().empty())
424  SL_LOG_DEBUG("sv->onInitialize : No Lights found in scene!");
425 
426  //_s->root3D()->dumpRec();
427  }
428 
429  // init 2D scene with initial depth 1
430  if (_s && _s->root2D() && _s->root2D()->aabb()->radiusOS() < 0.0001f)
431  {
432  // build axis aligned bounding box hierarchy after init
433  _s->root2D()->updateAABBRec(true);
434 
435  // Collect node statistics
436  _stats2D.clear();
437  _s->root2D()->statsRec(_stats2D);
438  }
439 
440  // Reset timing variables
441  _shadowMapTimeMS = 0.0f;
442  _cullTimeMS = 0.0f;
443  _draw3DTimeMS = 0.0f;
444  _draw2DTimeMS = 0.0f;
445  _cullTimesMS.init(60, 0.0f);
446  _draw3DTimesMS.init(60, 0.0f);
447  _draw2DTimesMS.init(60, 0.0f);
448 
450 
451  if (_gui)
453 }
454 //-----------------------------------------------------------------------------
455 /*!
456 SLSceneView::onResize is called by the window system before the first
457 rendering and whenever the window changes its size.
458 */
459 void SLSceneView::onResize(SLint width, SLint height)
460 {
461  // On OSX and Qt this can be called with invalid values > so exit
462  if (width == 0 || height == 0) return;
463 
464  if (_scrW != width || _scrH != height)
465  {
466  _scrW = width;
467  _scrH = height;
468  _scrWdiv2 = _scrW >> 1; // width / 2
469  _scrHdiv2 = _scrH >> 1; // height / 2
471 
475 
476  // Resize Oculus framebuffer
478  {
482  }
483 
484  // Stop raytracing & pathtracing on resize
485  if (_renderType != RT_gl)
486  {
487  _renderType = RT_gl;
488  _raytracer.doContinuous(false);
489  }
490  }
491 }
492 //-----------------------------------------------------------------------------
493 /*!
494 SLSceneView::onPaint is called by window system whenever the window and therefore
495 the scene needs to be painted. Depending on the renderer it calls first
496 SLSceneView::draw3DGL, SLSceneView::draw3DRT or SLSceneView::draw3DPT and
497 then SLSceneView::draw2DGL for all UI in 2D. The method returns true if either
498 the 2D or 3D graph was updated or waitEvents is false.
499 */
501 {
503 
504  // SL_LOG("onPaint: -----------------------------------------------------");
505 
510 
511  SLbool sceneHasChanged = false;
512  SLbool viewConsumedEvents = false;
513 
514  // Only update scene if sceneview got repainted: This check is necessary if
515  // this function is called for multiple SceneViews. In this way we only
516  // update the geometric representations if all SceneViews got painted once.
517  // (can only happen during raytracing)
518  if (_gotPainted)
519  {
520  _gotPainted = false;
521 
522  // Process queued up system events and poll custom input devices
523  viewConsumedEvents = _inputManager.pollAndProcessEvents(this);
524 
525  if (_s)
526  {
527  // update current scene
528  sceneHasChanged = _s->onUpdate((_renderType == RT_rt),
532  }
533  }
534 
535  SLbool camUpdated = false;
536 
537  // Init and build GUI for all projections except distorted stereo
539  _gui->onInitNewFrame(_s, this);
540 
541  // Clear NO. of draw calls after UI creation
545 
546  if (_s && _camera)
547  { // Render the 3D scenegraph by raytracing, pathtracing or OpenGL
548  switch (_renderType)
549  {
550  case RT_gl: camUpdated = draw3DGL(_s->elapsedTimeMS()); break;
551  case RT_rt: camUpdated = draw3DRT(); break;
552  case RT_pt: camUpdated = draw3DPT(); break;
553 #ifdef SL_HAS_OPTIX
554  case RT_optix_rt: camUpdated = draw3DOptixRT(); break;
555  case RT_optix_pt: camUpdated = draw3DOptixPT(); break;
556 #endif
557  }
558  }
559 
560  // Render the 2D stuff inclusive the ImGui
561  draw2DGL();
562 
564 
565  // Finish Oculus framebuffer
568  _scrH,
569  _oculusFB.texID(),
570  _camera->background().colors()[0]);
571 
572  // Set gotPainted only to true if RT is not busy
574 
575  // Return true if it is the first frame or a repaint is needed
576  if (_isFirstFrame)
577  {
578  _isFirstFrame = false;
579  return true;
580  }
581 
582  return !_doWaitOnIdle || camUpdated || sceneHasChanged || viewConsumedEvents;
583 }
584 //-----------------------------------------------------------------------------
585 //! Draws the 3D scene with OpenGL
586 /*! This is the main routine for updating and drawing the 3D scene for one frame.
587 The following steps are processed:
588 <ol>
589 <li>
590 <b>Render shadow maps</b>:
591 Renders all shadow maps for lights in SLLight::renderShadowMap
592 </li>
593 <li>
594 <b>Updates the camera</b>:
595 If the active camera has an animation it gets updated first in SLCamera::camUpdate
596 </li>
597 <li>
598 <b>Clear all buffers</b>:
599 The color and depth buffer are cleared in this step. If the projection is
600 the Oculus stereo projection also the framebuffer target is bound.
601 </li>
602 <li>
603 <b>Set viewport</b>:
604 Depending on the projection we set the camera projection and the view
605 for the center or left eye.
606 </li>
607 <li>
608 <b>Render background</b>:
609  If no skybox is used the background is rendered. This can be the camera image
610  if the camera is turned on.
611 </li>
612 <li>
613 <b>Set projection and view</b>:
614  Sets the camera projection matrix
615 </li>
616 <li>
617 <b>Frustum culling</b>:
618 During the cull traversal all materials that are seen in the view frustum get
619 collected in _visibleMaterials. All nodes with their meshes get collected in
620 SLMaterial::_nodesVisible3D. These materials and nodes get drawn in draw3DGLAll.
621 </li>
622 <li>
623 <b>Draw skybox</b>:
624 The skybox is draw as first object with frozen depth buffer.
625 The skybox is always around the active camera.
626 </li>
627 <li>
628 <b>Draw all visible nodes</b>:
629  By calling the SLSceneView::draw3DGL all visible nodes of all visible materials
630  get drawn sorted by material and transparency. If a stereo projection is set,
631  the scene gets drawn a second time for the right eye.
632 </li>
633 <li>
634 <b>Draw right eye for stereo projections</b>
635 </li>
636 </ol>
637 */
639 {
641 
642  SLGLState* stateGL = SLGLState::instance();
643 
644  preDraw();
645 
646  ///////////////////////////
647  // 1. Render shadow maps //
648  ///////////////////////////
649 
650  SLfloat startMS = GlobalTimer::timeMS();
651 
652  // Render shadow map for each light which creates shadows
653  for (SLLight* light : _s->lights())
654  {
655  if (light->createsShadows())
656  light->renderShadowMap(this, _s->root3D());
657  }
658 
660 
661  /////////////////////////
662  // 2. Do camera update //
663  /////////////////////////
664 
665  startMS = GlobalTimer::timeMS();
666 
667  // Update camera animation separately (smooth transition on key movement)
668  // todo: ghm1: this is currently only necessary for walking animation (which is somehow always enabled)
669  // A problem is also, that it only updates the current camera.
670  // This is maybe not what we want for sensor rotated camera.
671 
672  SLbool camUpdated = _camera->camUpdate(this, elapsedTimeMS);
673 
674  //////////////////////
675  // 3. Clear buffers //
676  //////////////////////
677 
678  // Render into framebuffer if Oculus stereo projection is used
680  {
681  _s->oculus()->beginFrame();
684  }
685 
686  // Clear color buffer
687  stateGL->clearColor(SLVec4f(0.00001f, 0.00001f, 0.00001f, 1.0f));
688  stateGL->clearColorDepthBuffer();
689 
690  /////////////////////
691  // 4. Set viewport //
692  /////////////////////
693 
695  _camera->setViewport(this, ET_left);
696  else
697  _camera->setViewport(this, ET_center);
698 
699  //////////////////////////
700  // 5. Render background //
701  //////////////////////////
702 
703  // Render solid color, gradient or textured background from active camera
704  if (!_s->skybox())
707 
708  // Change state (only when changed)
709  stateGL->multiSample(_doMultiSampling);
710  stateGL->depthTest(_doDepthTest);
711 
712  //////////////////////////////
713  // 6. Set projection & View //
714  //////////////////////////////
715 
716  // Set projection
718  {
719  _camera->setProjection(this, ET_left);
720  _camera->setView(this, ET_left);
721  }
722  else
723  {
725  _camera->setView(this, ET_center);
726  }
727 
728  ////////////////////////
729  // 7. Frustum culling //
730  ////////////////////////
731 
732  // Delete all visible nodes from the last frame
733  for (auto* material : _visibleMaterials3D)
734  material->nodesVisible3D().clear();
735 
736  _visibleMaterials3D.clear();
737  _nodesOpaque3D.clear();
738  _nodesBlended3D.clear();
739  _nodesOverdrawn.clear();
743 
744  if (_s->root3D())
745  _s->root3D()->cull3DRec(this);
746 
747  _cullTimeMS = GlobalTimer::timeMS() - startMS;
748 
749  ////////////////////
750  // 8. Draw skybox //
751  ////////////////////
752 
753  if (_s->skybox())
754  _s->skybox()->drawAroundCamera(this);
755 
756  ////////////////////////////
757  // 9. Draw all visible nodes
758  ////////////////////////////
759 
760  startMS = GlobalTimer::timeMS();
761 
762  draw3DGLAll();
763 
764  ///////////////////////////////////////////////
765  // 10. Draw right eye for stereo projections //
766  ///////////////////////////////////////////////
767 
769  {
770  _camera->setViewport(this, ET_right);
771 
772  // Only draw backgrounds for stereo projections in different viewports
773  if (!_s->skybox() && _camera->projType() < P_stereoLineByLine)
775 
777  _camera->setView(this, ET_right);
778  stateGL->depthTest(true);
779  if (_s->skybox())
780  _s->skybox()->drawAroundCamera(this);
781  draw3DGLAll();
782  }
783 
784  // Enable all color channels again
785  stateGL->colorMask(1, 1, 1, 1);
786 
787  _draw3DTimeMS = GlobalTimer::timeMS() - startMS;
788 
789  postDraw();
790 
791  GET_GL_ERROR; // Check if any OGL errors occurred
792  return camUpdated;
793 }
794 //-----------------------------------------------------------------------------
795 /*!
796  SLSceneView::draw3DGLAll renders by material sorted to avoid expensive material
797  switches on the GPU. During the cull traversal all materials that are seen in
798  the view frustum get collected in _visibleMaterials. All nodes with their
799  meshes get collected in SLMaterial::_nodesVisible3D. <br>
800 The 3D rendering has then the following steps:
801 1) Draw nodes with meshes with opaque materials and all helper lines sorted by material<br>
802 2) Draw remaining opaque nodes (SLCameras, needs redesign)<br>
803 3) Draw nodes with meshes with blended materials sorted by material and sorted back to front<br>
804 4) Draw remaining blended nodes (SLText, needs redesign)<br>
805 5) Draw helpers in overlay mode (not depth buffered)<br>
806 6) Draw visualization lines of animation curves<br>
807 */
809 {
811 
812  // a) Draw nodes with meshes with opaque materials and all helper lines sorted by material
813  for (auto material : _visibleMaterials3D)
814  {
815  if (!material->hasAlpha())
816  {
817  draw3DGLNodes(material->nodesVisible3D(), false, false);
818  _stats3D.numNodesOpaque += (SLuint)material->nodesVisible3D().size();
819  }
820  draw3DGLLines(material->nodesVisible3D());
821  }
822 
823  // b) Draw remaining opaque nodes without meshes
825  draw3DGLNodes(_nodesOpaque3D, false, false);
827 
828  // c) Draw nodes with meshes with blended materials sorted by material and sorted back to front
829  for (auto material : _visibleMaterials3D)
830  {
831  if (material->hasAlpha())
832  {
833  draw3DGLNodes(material->nodesVisible3D(), true, _doAlphaSorting);
834  _stats3D.numNodesBlended += (SLuint)material->nodesVisible3D().size();
835  }
836  }
837 
838  // d) Draw remaining blended nodes (SLText, needs redesign)
841 
842  // e) Draw helpers in overlay mode (not depth buffered)
843  for (auto material : _visibleMaterials3D)
844  draw3DGLLinesOverlay(material->nodesVisible3D());
845 
848 
849  // f) Draw visualization lines of animation curves
850  _s->animManager().drawVisuals(this);
851 
852  // g) Turn blending off again for correct anaglyph stereo modes
853  SLGLState* stateGL = SLGLState::instance();
854  stateGL->blend(false);
855  stateGL->depthMask(true);
856  stateGL->depthTest(true);
857 }
858 //-----------------------------------------------------------------------------
859 /*!
860 SLSceneView::draw3DGLNodes draws the nodes meshes from the passed node vector
861 directly with their world transform after the view transform.
862 */
864  SLbool alphaBlended,
865  SLbool depthSorted)
866 {
867  // PROFILE_FUNCTION();
868 
869  if (nodes.empty()) return;
870 
871  // For blended nodes we activate OpenGL blending and stop depth buffer updates
872  SLGLState* stateGL = SLGLState::instance();
873  stateGL->blend(alphaBlended);
874  stateGL->depthMask(!alphaBlended);
875 
876  // Important and expensive step for blended nodes with alpha meshes
877  // Depth sort with lambda function by their view distance
878  if (depthSorted)
879  {
880  std::sort(nodes.begin(), nodes.end(), [](SLNode* a, SLNode* b)
881  {
882  if (!a) return false;
883  if (!b) return true;
884  return a->aabb()->sqrViewDist() > b->aabb()->sqrViewDist(); });
885  }
886 
887  // draw the shapes directly with their wm transform
888  for (auto* node : nodes)
889  {
890  // Set model matrix as the nodes model to world matrix
891  stateGL->modelMatrix = node->updateAndGetWM();
892 
893  // Finally, draw the nodes mesh
894  node->drawMesh(this);
895  }
896 
897  GET_GL_ERROR; // Check if any OGL errors occurred
898 }
899 //-----------------------------------------------------------------------------
900 /*!
901 SLSceneView::draw3DGLLines draws the AABB from the passed node vector directly
902 with their world coordinates after the view transform. The lines must be drawn
903 without blending.
904 Colors:
905 Red : AABB of nodes with meshes
906 Pink : AABB of nodes without meshes (only child nodes)
907 Yellow: AABB of selected node
908 */
910 {
912 
913  if (nodes.empty()) return;
914 
915  SLGLState* stateGL = SLGLState::instance();
916  stateGL->blend(false);
917  stateGL->depthMask(true);
918 
919  // Set the view transform for drawing in world space
920  stateGL->modelMatrix.identity();
921 
922  // draw the opaque shapes directly w. their wm transform
923  for (auto* node : nodes)
924  {
925  if (node != _camera)
926  {
927  // Draw first AABB of the shapes but not the camera
928  if ((drawBit(SL_DB_BBOX) || node->drawBit(SL_DB_BBOX)) &&
929  !node->isSelected())
930  {
931  if (node->mesh())
932  node->aabb()->drawWS(SLCol4f::RED);
933  else
934  node->aabb()->drawWS(SLCol4f::MAGENTA);
935  }
936 
937  // Draw AABB for selected shapes
938  if (node->isSelected())
939  {
940  node->aabb()->drawWS(SLCol4f::YELLOW);
941  }
942  }
943  }
944 
945  GET_GL_ERROR; // Check if any OGL errors occurred
946 }
947 //-----------------------------------------------------------------------------
948 /*!
949 SLSceneView::draw3DGLLinesOverlay draws the nodes axis and skeleton joints
950 as overlay
951 */
953 {
955 
956  SLGLState* stateGL = SLGLState::instance();
957 
958  // draw the opaque shapes directly w. their wm transform
959  for (auto* node : nodes)
960  {
961  if (node != _camera)
962  {
963  if (drawBit(SL_DB_AXIS) || node->drawBit(SL_DB_AXIS) ||
964  drawBit(SL_DB_SKELETON) || node->drawBit(SL_DB_SKELETON) ||
965  node->isSelected())
966  {
967  // Set the view transform
968  stateGL->modelMatrix.identity();
969  stateGL->blend(false); // Turn off blending for overlay
970  stateGL->depthMask(true); // Freeze depth buffer for blending
971  stateGL->depthTest(false); // Turn of depth test for overlay
972 
973  // Draw axis
974  if (drawBit(SL_DB_AXIS) ||
975  node->drawBit(SL_DB_AXIS) ||
976  node->isSelected())
977  {
978  node->aabb()->drawAxisWS();
979  }
980 
981  // Draw skeleton
982  if (drawBit(SL_DB_SKELETON) ||
983  node->drawBit(SL_DB_SKELETON))
984  {
985  // Draw axis of the skeleton joints and its parent bones
986  const SLAnimSkeleton* skeleton = node->skeleton();
987  if (skeleton)
988  {
989  for (auto joint : skeleton->joints())
990  {
991  // Get the node wm & apply the joints wm
992  SLMat4f wm = node->updateAndGetWM();
993  wm *= joint->updateAndGetWM();
994 
995  // Get parent node wm & apply the parent joint wm
996  SLMat4f parentWM;
997  if (joint->parent())
998  {
999  parentWM = node->parent()->updateAndGetWM();
1000  parentWM *= joint->parent()->updateAndGetWM();
1001  joint->aabb()->updateBoneWS(parentWM, false, wm);
1002  }
1003  else
1004  joint->aabb()->updateBoneWS(parentWM, true, wm);
1005 
1006  joint->aabb()->drawBoneWS();
1007  }
1008  }
1009  }
1010  }
1011  else if (drawBit(SL_DB_BRECT) || node->drawBit(SL_DB_BRECT))
1012  {
1013  node->aabb()->calculateRectSS();
1014 
1015  SLMat4f prevProjMat = stateGL->projectionMatrix;
1016  SLMat4f prevViewMat = stateGL->viewMatrix;
1017  SLfloat w2 = (SLfloat)_scrWdiv2;
1018  SLfloat h2 = (SLfloat)_scrHdiv2;
1019  stateGL->projectionMatrix.ortho(-w2, w2, -h2, h2, 1.0f, -1.0f);
1020  stateGL->viewport(0, 0, _scrW, _scrH);
1021  stateGL->viewMatrix.identity();
1022  stateGL->modelMatrix.identity();
1023  stateGL->modelMatrix.translate(-w2, h2, 1.0f);
1024  stateGL->depthMask(false); // Freeze depth buffer for blending
1025  stateGL->depthTest(false); // Disable depth testing
1026 
1027  node->aabb()->rectSS().drawGL(SLCol4f::GREEN);
1028 
1029  stateGL->depthMask(true); // Freeze depth buffer for blending
1030  stateGL->depthTest(true); // Disable depth testing
1031  stateGL->projectionMatrix = prevProjMat;
1032  stateGL->viewMatrix = prevViewMat;
1033  }
1034  else if (node->drawBit(SL_DB_OVERDRAW))
1035  {
1036  if (node->mesh() && node->mesh()->mat())
1037  {
1038  SLMesh* mesh = node->mesh();
1039  bool hasAlpha = mesh->mat()->hasAlpha();
1040 
1041  // For blended nodes we activate OpenGL blending and stop depth buffer updates
1042  stateGL->blend(hasAlpha);
1043  stateGL->depthMask(!hasAlpha);
1044  stateGL->depthTest(false); // Turn of depth test for overlay
1045 
1046  // Set model & view transform
1047  stateGL->viewMatrix = stateGL->viewMatrix;
1048  stateGL->modelMatrix = node->updateAndGetWM();
1049 
1050  // Finally, draw the nodes mesh
1051  node->drawMesh(this);
1052  GET_GL_ERROR; // Check if any OGL errors occurred
1053  }
1054  }
1055  }
1056  }
1057 
1058  GET_GL_ERROR; // Check if any OGL errors occurred
1059 }
1060 //-----------------------------------------------------------------------------
1061 /*!
1062 SLSceneView::draw2DGL draws all 2D stuff in ortho projection. So far no
1063 update is done to the 2D scenegraph.
1064 */
1066 {
1067  PROFILE_FUNCTION();
1068 
1069  SLGLState* stateGL = SLGLState::instance();
1070  SLfloat startMS = GlobalTimer::timeMS();
1071 
1072  SLfloat w2 = (SLfloat)_scrWdiv2;
1073  SLfloat h2 = (SLfloat)_scrHdiv2;
1076 
1077  // Set orthographic projection with 0,0,0 in the screen center
1078  if (_s)
1079  {
1080  // 1. Set Projection & View
1081  stateGL->projectionMatrix.ortho(-w2, w2, -h2, h2, 1.0f, -1.0f);
1082  stateGL->viewport(0, 0, _scrW, _scrH);
1083 
1084  // 2. Pseudo 2D Frustum Culling
1085  for (auto material : _visibleMaterials2D)
1086  material->nodesVisible2D().clear();
1087  _visibleMaterials2D.clear();
1088  _nodesOpaque2D.clear();
1089  _nodesBlended2D.clear();
1090  if (_s->root2D())
1091  _s->root2D()->cull2DRec(this);
1092 
1093  // 3. Draw all 2D nodes opaque
1094  draw2DGLNodes();
1095 
1096  // Draw selection rectangle. See also SLMesh::handleRectangleSelection
1097  if (!_camera->selectRect().isEmpty())
1098  {
1099  SLMat4f prevViewMat = stateGL->viewMatrix;
1100  stateGL->viewMatrix.identity();
1101  stateGL->modelMatrix.identity();
1102  stateGL->modelMatrix.translate(-w2, h2, 1.0f);
1103  stateGL->depthMask(false); // Freeze depth buffer for blending
1104  stateGL->depthTest(false); // Disable depth testing
1106  stateGL->depthMask(true); // enable depth buffer writing
1107  stateGL->depthTest(true); // enable depth testing
1108  stateGL->viewMatrix = prevViewMat;
1109  }
1110 
1111  // Draw deselection rectangle. See also SLMesh::handleRectangleSelection
1112  if (!_camera->deselectRect().isEmpty())
1113  {
1114  SLMat4f prevViewMat = stateGL->viewMatrix;
1115  stateGL->viewMatrix.identity();
1116  stateGL->modelMatrix.identity();
1117  stateGL->modelMatrix.translate(-w2, h2, 1.0f);
1118  stateGL->depthMask(false); // Freeze depth buffer for blending
1119  stateGL->depthTest(false); // Disable depth testing
1121  stateGL->depthMask(true); // enable depth buffer writing
1122  stateGL->depthTest(true); // enable depth testing
1123  stateGL->viewMatrix = prevViewMat;
1124  }
1125  }
1126 
1127  // 4. Draw UI
1128  if (_gui)
1130 
1131  _draw2DTimeMS = GlobalTimer::timeMS() - startMS;
1132 }
1133 //-----------------------------------------------------------------------------
1134 /*!
1135 SLSceneView::draw2DGLNodes draws 2D nodes from root2D in orthographic projection
1136 */
1138 {
1139  PROFILE_FUNCTION();
1140 
1141  SLfloat depth = 1.0f; // Render depth between -1 & 1
1142  SLfloat cs = std::min((float)_scrW, (float)_scrH) * 0.01f; // center size
1143  SLGLState* stateGL = SLGLState::instance();
1144 
1145  SLMat4f prevViewMat(stateGL->viewMatrix);
1146  stateGL->viewMatrix.identity();
1147  stateGL->depthMask(false); // Freeze depth buffer for blending
1148  stateGL->depthTest(false); // Disable depth testing
1149  stateGL->blend(true); // Enable blending
1150  stateGL->polygonLine(false); // Only filled polygons
1151 
1152  // Draw all 2D nodes blended (mostly text font textures)
1153  // draw the shapes directly with their wm transform
1154  for (auto material : _visibleMaterials2D)
1155  {
1156  _stats2D.numNodesOpaque += (SLuint)material->nodesVisible2D().size();
1157  for (auto* node : material->nodesVisible2D())
1158  {
1159  // Apply world transform
1160  stateGL->modelMatrix = node->updateAndGetWM();
1161 
1162  // Finally, the nodes meshes
1163  node->drawMesh(this);
1164  }
1165  }
1166 
1167  // Deprecated: SLText node need to be meshes as well
1169  for (auto* node : _nodesBlended2D)
1170  {
1171  // Apply world transform
1172  stateGL->modelMatrix = node->updateAndGetWM();
1173 
1174  // Finally, the nodes meshes
1175  node->drawMesh(this);
1176  }
1177 
1178  // Draw rotation helpers during camera animations
1179  if ((_mouseDownL || _mouseDownM) && _touchDowns == 0)
1180  {
1181  if (_camera->camAnim() == CA_turntableYUp ||
1183  {
1184  stateGL->modelMatrix.identity();
1185  stateGL->modelMatrix.translate(0, 0, depth);
1186 
1187  SLVVec3f centerRombusPoints = {{-cs, 0, 0},
1188  {0, -cs, 0},
1189  {cs, 0, 0},
1190  {0, cs, 0}};
1192  _vaoTouch.generateVertexPos(&centerRombusPoints);
1193  SLCol4f yelloAlpha(1.0f, 1.0f, 0.0f, 0.5f);
1194 
1196  }
1197  else if (_camera->camAnim() == CA_trackball)
1198  {
1199  stateGL->modelMatrix.identity();
1200  stateGL->modelMatrix.translate(0, 0, depth);
1201 
1202  // radius = half width or height
1203  SLfloat r = (SLfloat)(_scrW < _scrH
1204  ? _scrW / 2
1205  : _scrH / 2) *
1207 
1208  SLVVec3f rombusAndCirclePoints; // = {{-cs,0,0},{0,-cs,0},{cs,0,0},{0,cs,0}};
1209 
1210  // Add points for circle over window
1211  SLint circlePoints = 60;
1212  SLfloat deltaPhi = Utils::TWOPI / (SLfloat)circlePoints;
1213  for (SLint i = 0; i < circlePoints; ++i)
1214  {
1215  SLVec2f c;
1216  c.fromPolar(r, (float)i * deltaPhi);
1217  rombusAndCirclePoints.push_back(SLVec3f(c.x, c.y, 0));
1218  }
1220  _vaoTouch.generateVertexPos(&rombusAndCirclePoints);
1221  SLCol4f yelloAlpha(1.0f, 1.0f, 0.0f, 0.5f);
1222 
1224  }
1225  }
1226 
1227  stateGL->viewMatrix = prevViewMat;
1228  stateGL->blend(false); // turn off blending
1229  stateGL->depthMask(true); // enable depth buffer writing
1230  stateGL->depthTest(true); // enable depth testing
1231  GET_GL_ERROR; // check if any OGL errors occurred
1232 }
1233 //-----------------------------------------------------------------------------
1234 
1235 //-----------------------------------------------------------------------------
1236 /*!
1237 SLSceneView::onMouseDown gets called whenever a mouse button gets pressed and
1238 dispatches the event to the currently attached event handler object.
1239 */
1241  SLint scrX,
1242  SLint scrY,
1243  SLKey mod)
1244 {
1245  // Correct viewport offset
1246  // mouse coordinates are top-left, viewport is bottom-left)
1247  SLint x = scrX - _viewportRect.x;
1248  SLint y = scrY - ((_scrH - _viewportRect.height) - _viewportRect.y);
1249 
1250  // Pass the event to imgui
1251  if (_gui)
1252  {
1253  _gui->onMouseDown(button, x, y);
1254 
1255  // Touch devices on iOS or Android have no mouse move event when the
1256  // finger isn't touching the screen. Therefore, imgui can not detect hovering
1257  // over an imgui window. Without this extra frame you would have to touch
1258  // the display twice to open e.g. a menu.
1259  _gui->renderExtraFrame(_s, this, x, y);
1260 
1261  if (_gui->doNotDispatchMouse())
1262  return true;
1263  }
1264 
1265  _mouseDownL = (button == MB_left);
1266  _mouseDownR = (button == MB_right);
1267  _mouseDownM = (button == MB_middle);
1268  _mouseMod = mod;
1269 
1270  SLbool result = false;
1271  if (_s && _camera && _s->root3D())
1272  {
1273  SLbool eventConsumed = false;
1274  for (auto* eh : _s->eventHandlers())
1275  {
1276  if (eh->onMouseDown(button, x, y, mod))
1277  eventConsumed = true;
1278  }
1279 
1280  if (!eventConsumed)
1281  result = _camera->onMouseDown(button, x, y, mod);
1282  else
1283  result = true;
1284  }
1285 
1286  return result;
1287 }
1288 //-----------------------------------------------------------------------------
1289 /*!
1290 SLSceneView::onMouseUp gets called whenever a mouse button gets released.
1291 */
1293  SLint scrX,
1294  SLint scrY,
1295  SLKey mod)
1296 {
1297  _touchDowns = 0;
1298 
1299  // Correct viewport offset
1300  // mouse coordinates are top-left, viewport is bottom-left)
1301  SLint x = scrX - _viewportRect.x;
1302  SLint y = scrY - ((_scrH - _viewportRect.height) - _viewportRect.y);
1303 
1304  // Continue with ray tracing
1305  if (_raytracer.state() == rtMoveGL)
1306  {
1307  _renderType = RT_rt;
1309  }
1310 
1311  // Continue with path tracing
1312  if (_pathtracer.state() == rtMoveGL)
1313  {
1314  _renderType = RT_pt;
1316  }
1317 
1318  // Pass the event to imgui
1319  if (_gui)
1320  {
1321  _gui->onMouseUp(button, x, y);
1322  if (_gui->doNotDispatchMouse())
1323  return true;
1324 
1325  // Touch devices on iOS or Android have no mouse move event when the
1326  // finger isn't touching the screen. Therefore imgui can not detect hovering
1327  // over an imgui window. Without this extra frame you would have to touch
1328  // the display twice to open e.g. a menu.
1329  _gui->renderExtraFrame(_s, this, x, y);
1330  }
1331 
1332  _mouseDownL = false;
1333  _mouseDownR = false;
1334  _mouseDownM = false;
1335 
1336  if (_s && _camera && _s->root3D())
1337  {
1338  SLbool result = false;
1339  SLbool eventConsumed = false;
1340  for (auto* eh : _s->eventHandlers())
1341  {
1342  if (eh->onMouseUp(button, x, y, mod))
1343  eventConsumed = true;
1344  }
1345 
1346  if (!eventConsumed)
1347  {
1348  result = _camera->onMouseUp(button, x, y, mod);
1349  }
1350  else
1351  {
1352  result = true;
1353  }
1354 
1355  return result;
1356  }
1357 
1358  return false;
1359 }
1360 //-----------------------------------------------------------------------------
1361 /*!
1362 SLSceneView::onMouseMove gets called whenever the mouse is moved.
1363 */
1365 {
1366  // Correct viewport offset
1367  // mouse corrds are top-left, viewport is bottom-left)
1368  SLint x = scrX - _viewportRect.x;
1369  SLint y = scrY - ((_scrH - _viewportRect.height) - _viewportRect.y);
1370 
1371  // Pass the event to imgui
1372  if (_gui)
1373  {
1374  _gui->onMouseMove(x, y);
1375  if (_gui->doNotDispatchMouse())
1376  return true;
1377  }
1378 
1379  if (!_s || !_s->root3D())
1380  return false;
1381 
1382  _touchDowns = 0;
1383  SLbool result = false;
1384 
1385  SLMouseButton btn;
1386  if (_mouseDownL)
1387  btn = MB_left;
1388  else if (_mouseDownR)
1389  btn = MB_right;
1390  else if (_mouseDownM)
1391  btn = MB_middle;
1392  else
1393  btn = MB_none;
1394 
1396  {
1397  // Handle move in ray tracing
1399  {
1400  if (_raytracer.state() == rtFinished)
1402  else
1403  _raytracer.doContinuous(false);
1404 
1405  _renderType = RT_gl;
1406  }
1407 
1408  // Handle move in path tracing
1409  if (_renderType == RT_pt)
1410  {
1411  if (_pathtracer.state() == rtFinished)
1413 
1414  _renderType = RT_gl;
1415  }
1416  }
1417 
1418  SLbool eventConsumed = false;
1419  for (auto* eh : _s->eventHandlers())
1420  {
1421  if (eh->onMouseMove(btn, x, y, _mouseMod))
1422  eventConsumed = true;
1423  }
1424 
1425  if (!eventConsumed)
1426  result = _camera->onMouseMove(btn, x, y, _mouseMod);
1427  else
1428  result = true;
1429 
1430  return result;
1431 }
1432 //-----------------------------------------------------------------------------
1433 /*!
1434 SLSceneView::onMouseWheel gets called whenever the mouse wheel is turned.
1435 The parameter wheelPos is an increasing or decreeing counter number.
1436 */
1438 {
1439  static SLint lastMouseWheelPos = 0;
1440  SLint delta = wheelPos - lastMouseWheelPos;
1441  lastMouseWheelPos = wheelPos;
1442  return onMouseWheel(delta, mod);
1443 }
1444 //-----------------------------------------------------------------------------
1445 /*!
1446 SLSceneView::onMouseWheel gets called whenever the mouse wheel is turned.
1447 The parameter delta is positive/negative depending on the wheel direction
1448 */
1450 {
1451  // Pass the event to imgui
1452  if (_gui)
1453  {
1454  if (_gui->doNotDispatchMouse())
1455  {
1456  _gui->onMouseWheel((SLfloat)delta);
1457  return true;
1458  }
1459  }
1460 
1461  if (!_s || !_s->root3D())
1462  return false;
1463 
1464  // Handle mouse wheel in RT mode
1465  if (_renderType == RT_rt && !_raytracer.doContinuous() &&
1468 
1469  // Handle mouse wheel in PT mode
1470  if (_renderType == RT_pt && _pathtracer.state() == rtFinished)
1472 
1473  SLbool result = _camera->onMouseWheel(delta, mod);
1474 
1475  for (auto* eh : _s->eventHandlers())
1476  {
1477  if (eh->onMouseWheel(delta, mod))
1478  result = true;
1479  }
1480  return result;
1481 }
1482 //-----------------------------------------------------------------------------
1483 /*!
1484 SLSceneView::onDoubleClick gets called when a mouse double click or finger
1485 double tab occurs.
1486 */
1488  SLint scrX,
1489  SLint scrY,
1490  SLKey mod)
1491 {
1492  if (!_s || !_s->root3D())
1493  return false;
1494 
1495  // Correct viewport offset
1496  // mouse coordinates are top-left, viewport is bottom-left)
1497  SLint x = scrX - _viewportRect.x;
1498  SLint y = scrY - ((_scrH - _viewportRect.height) - _viewportRect.y);
1499 
1500  SLbool result = false;
1501 
1502  // Do object picking with ray cast
1503  if (button == MB_left)
1504  {
1505  _mouseDownR = false;
1506 
1507  SLRay pickRay(this);
1508  if (_camera)
1509  {
1510  _camera->eyeToPixelRay((SLfloat)x, (SLfloat)y, &pickRay);
1511 
1512  // Update the AABB min & max points in OS
1513  _s->root3D()->updateAABBRec(true);
1514 
1515  _s->root3D()->hitRec(&pickRay);
1516  if (pickRay.hitNode)
1517  SL_LOG("NODE HIT: %s", pickRay.hitNode->name().c_str());
1518  }
1519 
1520  if (pickRay.length < FLT_MAX)
1521  {
1522  if (mod & K_shift)
1523  {
1524  _s->selectNodeMesh(pickRay.hitNode, pickRay.hitMesh);
1525  if (onSelectedNodeMesh)
1526  onSelectedNodeMesh(pickRay.hitNode, pickRay.hitMesh);
1527  }
1528  else
1529  {
1530  if (_s->singleNodeSelected() != pickRay.hitNode)
1532 
1533  _s->selectNodeMesh(pickRay.hitNode, pickRay.hitMesh);
1534  if (onSelectedNodeMesh)
1535  onSelectedNodeMesh(pickRay.hitNode, pickRay.hitMesh);
1536  }
1537  result = true;
1538  }
1539  }
1540  else
1541  {
1542  result = _camera->onDoubleClick(button, x, y, mod);
1543  for (auto* eh : _s->eventHandlers())
1544  {
1545  if (eh->onDoubleClick(button, x, y, mod))
1546  result = true;
1547  }
1548  }
1549  return result;
1550 }
1551 //-----------------------------------------------------------------------------
1552 /*!
1553 SLSceneView::onTouch2Down gets called whenever two fingers touch a handheld
1554 screen.
1555 */
1557  SLint scrY1,
1558  SLint scrX2,
1559  SLint scrY2)
1560 {
1561  if (!_s || !_s->root3D())
1562  return false;
1563 
1564  // Correct viewport offset
1565  // mouse coordinates are top-left, viewport is bottom-left)
1566  SLint x1 = scrX1 - _viewportRect.x;
1567  SLint y1 = scrY1 - ((_scrH - _viewportRect.height) - _viewportRect.y);
1568  SLint x2 = scrX2 - _viewportRect.x;
1569  SLint y2 = scrY2 - ((_scrH - _viewportRect.height) - _viewportRect.y);
1570 
1571  _touch[0].set(x1, y1);
1572  _touch[1].set(x2, y2);
1573  _touchDowns = 2;
1574 
1575  SLbool result = _camera->onTouch2Down(x1, y1, x2, y2);
1576 
1577  for (auto* eh : _s->eventHandlers())
1578  {
1579  if (eh->onTouch2Down(x1, y1, x2, y2))
1580  result = true;
1581  }
1582  return result;
1583 }
1584 //-----------------------------------------------------------------------------
1585 /*!
1586 SLSceneView::onTouch2Move gets called whenever two fingers touch a handheld
1587 screen.
1588 */
1590  SLint scrY1,
1591  SLint scrX2,
1592  SLint scrY2)
1593 {
1594  if (!_s || !_s->root3D())
1595  return false;
1596 
1597  // Correct viewport offset
1598  SLint x1 = scrX1 - _viewportRect.x;
1599  SLint y1 = scrY1 - ((_scrH - _viewportRect.height) - _viewportRect.y);
1600  SLint x2 = scrX2 - _viewportRect.x;
1601  SLint y2 = scrY2 - ((_scrH - _viewportRect.height) - _viewportRect.y);
1602 
1603  _touch[0].set(x1, y1);
1604  _touch[1].set(x2, y2);
1605 
1606  SLbool result = false;
1607  if (_touchDowns == 2)
1608  {
1609  result = _camera->onTouch2Move(x1, y1, x2, y2);
1610  for (auto* eh : _s->eventHandlers())
1611  {
1612  if (eh->onTouch2Move(x1, y1, x2, y2))
1613  result = true;
1614  }
1615  }
1616  return result;
1617 }
1618 //-----------------------------------------------------------------------------
1619 /*!
1620 SLSceneView::onTouch2Up gets called whenever two fingers lift off a handheld
1621 screen.
1622 */
1624  SLint scrY1,
1625  SLint scrX2,
1626  SLint scrY2)
1627 {
1628  if (!_s || !_s->root3D())
1629  return false;
1630 
1631  // Correct viewport offset
1632  SLint x1 = scrX1 - _viewportRect.x;
1633  SLint y1 = scrY1 - ((_scrH - _viewportRect.height) - _viewportRect.y);
1634  SLint x2 = scrX2 - _viewportRect.x;
1635  SLint y2 = scrY2 - ((_scrH - _viewportRect.height) - _viewportRect.y);
1636 
1637  _touch[0].set(x1, y1);
1638  _touch[1].set(x2, y2);
1639  _touchDowns = 0;
1640 
1641  SLbool result = _camera->onTouch2Up(x1, y1, x2, y2);
1642  for (auto* eh : _s->eventHandlers())
1643  {
1644  if (eh->onTouch2Up(x1, y1, x2, y2))
1645  result = true;
1646  }
1647  return result;
1648 }
1649 //-----------------------------------------------------------------------------
1650 /*!
1651 SLSceneView::onKeyPress gets get called whenever a key is pressed. Before
1652 passing the command to the eventhandlers the main key commands are handled by
1653 forwarding them to onCommand.
1654 */
1656 {
1657  // Pass the event to imgui
1658  if (_gui)
1659  {
1660  if (_gui->doNotDispatchKeyboard())
1661  {
1662  _gui->onKeyPress(key, mod);
1663  return true;
1664  }
1665  }
1666 
1667  if (!_s || !_s->root3D())
1668  return false;
1669 
1670  // clang-format off
1671  // We have to coordinate these shortcuts in SLDemoGui::buildMenuBar
1672  if (key=='L') {doMultiSampling(!doMultiSampling()); return true;}
1673  if (key=='I') {doWaitOnIdle(!doWaitOnIdle()); return true;}
1674  if (key=='F') {doFrustumCulling(!doFrustumCulling()); return true;}
1675  if (key=='J') {doAlphaSorting(!doAlphaSorting()); return true;}
1676  if (key=='T') {doDepthTest(!doDepthTest()); return true;}
1677  if (key==K_space) {_s->stopAnimations(!_s->stopAnimations()); return true;}
1678 
1679  if (key=='R') {startRaytracing(5);}
1680  if (key=='P') {startPathtracing(5, 10);}
1681 #ifdef SL_HAS_OPTIX
1682  if (key=='R' && mod==K_shift) {startOptixRaytracing(5);}
1683  if (key=='P' && mod==K_shift) {startOptixPathtracing(5, 100);}
1684 #endif
1685 
1686  if (key=='M') {drawBits()->toggle(SL_DB_MESHWIRED); return true;}
1687  if (key=='H') {drawBits()->toggle(SL_DB_WITHEDGES); return true;}
1688  if (key=='O') {drawBits()->toggle(SL_DB_ONLYEDGES); return true;}
1689  if (key=='N') {drawBits()->toggle(SL_DB_NORMALS); return true;}
1690  if (key=='B') {drawBits()->toggle(SL_DB_BBOX); return true;}
1691  if (key=='U') {drawBits()->toggle(SL_DB_BRECT); return true;}
1692  if (key=='V') {drawBits()->toggle(SL_DB_VOXELS); return true;}
1693  if (key=='X') {drawBits()->toggle(SL_DB_AXIS); return true;}
1694  if (key=='C') {drawBits()->toggle(SL_DB_CULLOFF); return true;}
1695  if (key=='K') {drawBits()->toggle(SL_DB_SKELETON); return true;}
1696 
1697  if (key=='5')
1698  { if (_camera->projType() == P_monoPerspective)
1701  if (_renderType == RT_rt && !_raytracer.doContinuous() &&
1704  }
1705 
1706  if (key==K_tab) {switchToNextCameraInScene(); return true;}
1707 
1708  if (key==K_esc)
1709  {
1712 
1713  if (!_s->selectedNodes().empty() ||
1714  !_camera->selectRect().isEmpty() ||
1716  {
1718  _camera->selectRect().setZero();
1720  return true;
1721  }
1722 
1723  if(_renderType == RT_rt) _stopRT = true;
1724  if(_renderType == RT_pt) _stopPT = true;
1725 #ifdef SL_HAS_OPTIX
1726  if(_renderType == RT_optix_rt) _stopOptixRT = true;
1727  if(_renderType == RT_optix_pt) _stopOptixPT = true;
1728 #endif
1729  return true;
1730  }
1731  // clang-format on
1732 
1733  SLbool result = false;
1734  if (key || mod)
1735  {
1736  // 1) pass it to the camera
1737  result = _camera->onKeyPress(key, mod);
1738 
1739  // 2) pass it to any other eventhandler
1740  for (auto* eh : _s->eventHandlers())
1741  {
1742  if (eh->onKeyPress(key, mod))
1743  result = true;
1744  }
1745  }
1746  return result;
1747 }
1748 //-----------------------------------------------------------------------------
1749 /*!
1750 SLSceneView::onKeyRelease get called whenever a key is released.
1751 */
1753 {
1754  // Pass the event to imgui
1755  if (_gui)
1756  {
1757  if (_gui->doNotDispatchKeyboard())
1758  {
1759  _gui->onKeyRelease(key, mod);
1760  return true;
1761  }
1762  }
1763 
1764  if (!_s || !_s->root3D())
1765  return false;
1766 
1767  SLbool result = false;
1768 
1769  if (key || mod)
1770  {
1771  // 1) pass it to the camera
1772  result = _camera->onKeyRelease(key, mod);
1773 
1774  // 2) pass it to any other eventhandler
1775  for (auto* eh : _s->eventHandlers())
1776  {
1777  if (eh->onKeyRelease(key, mod))
1778  result = true;
1779  }
1780  }
1781  return result;
1782 }
1783 //-----------------------------------------------------------------------------
1784 /*!
1785 SLSceneView::onCharInput get called whenever a new charcter comes in
1786 */
1788 {
1789  if (_gui)
1790  {
1791  if (_gui->doNotDispatchKeyboard())
1792  {
1793  _gui->onCharInput(c);
1794  return true;
1795  }
1796  }
1797 
1798  return false;
1799 }
1800 //-----------------------------------------------------------------------------
1801 /*!
1802 Returns the window title with name & FPS
1803 */
1805 {
1806  SLchar title[255];
1807  SLstring profiling = "";
1808 
1809 #if PROFILING
1810  profiling = " *** PROFILING *** ";
1811 #endif
1812 
1813  if (_s)
1814  {
1815  if (_renderType == RT_rt)
1816  {
1817  SLuint numThreads = _raytracer.doDistributed() ? _raytracer.numThreads() : 1;
1818 
1819  if (_raytracer.doContinuous())
1820  {
1821  snprintf(title,
1822  sizeof(title),
1823  "Ray Tracing: %s (fps: %4.1f, Threads: %d)",
1824  _s->name().c_str(),
1825  _s->fps(),
1826  numThreads);
1827  }
1828  else
1829  {
1830  snprintf(title,
1831  sizeof(title),
1832  "Ray Tracing: %s (Threads: %d)",
1833  _s->name().c_str(),
1834  numThreads);
1835  }
1836  }
1837  else if (_renderType == RT_pt)
1838  {
1839  snprintf(title,
1840  sizeof(title),
1841  "Path Tracing: %s (Threads: %d)",
1842  _s->name().c_str(),
1844  }
1845  else
1846  {
1847  string format;
1848  if (_s->fps() > 5)
1849  format = "OpenGL Renderer: %s (fps: %4.0f, %u nodes of %u rendered)";
1850  else
1851  format = "OpenGL Renderer: %s (fps: %4.1f, %u nodes of %u rendered)";
1852 
1853  snprintf(title,
1854  sizeof(title),
1855  format.c_str(),
1856  _s->name().c_str(),
1857  _s->fps(),
1859  _stats3D.numNodes);
1860  }
1861  }
1862  else
1863  snprintf(title, sizeof(title), "Scene is loading ...");
1864 
1865  return profiling + SLstring(title) + profiling;
1866 }
1867 //-----------------------------------------------------------------------------
1868 /*!
1869 Starts the ray tracing & sets the RT menu
1870 */
1872 {
1873  _renderType = RT_rt;
1874  _stopRT = false;
1875  _raytracer.maxDepth(maxDepth);
1876 }
1877 //-----------------------------------------------------------------------------
1878 /*!
1879 SLSceneView::updateAndRT3D starts the raytracing or refreshes the current RT
1880 image during rendering. The function returns true if an animation was done
1881 prior to the rendering start.
1882 */
1884 {
1885  SLbool updated = false;
1886 
1887  // if the raytracer not yet got started
1888  if (_raytracer.state() == rtReady)
1889  {
1890  if (_s->root3D())
1891  {
1892  // Update transforms and AABBs
1893  // @Todo: causes multithreading bug in RT
1894  // s->root3D()->needUpdate();
1895 
1896  // Do software skinning on all changed skeletons
1897  _s->root3D()->updateMeshAccelStructs();
1898  }
1899 
1900  // Start raytracing
1901  if (_raytracer.doDistributed())
1902  _raytracer.renderDistrib(this);
1903  else
1904  _raytracer.renderClassic(this);
1905  }
1906 
1907  // Refresh the render image during RT
1908  _raytracer.renderImage(true);
1909 
1910  // React on the stop flag (e.g. ESC)
1911  if (_stopRT)
1912  {
1913  _renderType = RT_gl;
1914  updated = true;
1915  }
1916 
1917  return updated;
1918 }
1919 //-----------------------------------------------------------------------------
1920 /*!
1921 Starts the pathtracing
1922 */
1924 {
1925  _renderType = RT_pt;
1926  _stopPT = false;
1927  _pathtracer.maxDepth(maxDepth);
1928  _pathtracer.aaSamples(samples);
1929 }
1930 //-----------------------------------------------------------------------------
1931 /*!
1932 SLSceneView::updateAndRT3D starts the raytracing or refreshes the current RT
1933 image during rendering. The function returns true if an animation was done
1934 prior to the rendering start.
1935 */
1937 {
1938  SLbool updated = false;
1939 
1940  // if the pathtracer not yet got started
1941  if (_pathtracer.state() == rtReady)
1942  {
1943  if (_s->root3D())
1944  {
1945  // Update transforms and AABBs
1946  // @Todo: causes multithreading bug in RT
1947  // s->root3D()->needUpdate();
1948 
1949  // Do software skinning on all changed skeletons
1950  _s->root3D()->updateMeshAccelStructs();
1951  }
1952 
1953  // Start raytracing
1954  _pathtracer.render(this);
1955  }
1956 
1957  // Refresh the render image during PT
1958  _pathtracer.renderImage(true);
1959 
1960  // React on the stop flag (e.g. ESC)
1961  if (_stopPT)
1962  {
1963  _renderType = RT_gl;
1964  updated = true;
1965  }
1966 
1967  return updated;
1968 }
1969 //-----------------------------------------------------------------------------
1970 #ifdef SL_HAS_OPTIX
1971 void SLSceneView::startOptixRaytracing(SLint maxDepth)
1972 {
1974  _stopOptixRT = false;
1975  _optixRaytracer.maxDepth(maxDepth);
1976  _optixRaytracer.setupScene(this, s()->assetManager());
1977 }
1978 //-----------------------------------------------------------------------------
1979 SLbool SLSceneView::draw3DOptixRT()
1980 {
1981  SLbool updated = false;
1982 
1983  // if the raytracer not yet got started
1984  if (_optixRaytracer.state() == rtReady)
1985  {
1986  s()->root3D()->needUpdate();
1987 
1988  _optixRaytracer.updateScene(this);
1989 
1990  if (_optixRaytracer.doDistributed())
1991  _optixRaytracer.renderDistrib();
1992  else
1993  _optixRaytracer.renderClassic();
1994  }
1995 
1996  // Refresh the render image during RT
1997  _optixRaytracer.renderImage(false);
1998 
1999  // React on the stop flag (e.g. ESC)
2000  if (_stopOptixRT)
2001  {
2002  _renderType = RT_gl;
2003  updated = true;
2004  }
2005 
2006  return updated;
2007 }
2008 //-----------------------------------------------------------------------------
2009 void SLSceneView::startOptixPathtracing(SLint maxDepth, SLint samples)
2010 {
2012  _stopOptixPT = false;
2013  _optixPathtracer.maxDepth(maxDepth);
2014  _optixPathtracer.samples(samples);
2015  _optixPathtracer.setupScene(this, s()->assetManager());
2016 }
2017 //-----------------------------------------------------------------------------
2018 SLbool SLSceneView::draw3DOptixPT()
2019 {
2020  SLbool updated = false;
2021 
2022  // if the path tracer not yet got started
2023  if (_optixPathtracer.state() == rtReady)
2024  {
2025  s()->root3D()->needUpdate();
2026 
2027  // Start path tracing
2028  _optixPathtracer.updateScene(this);
2029  _optixPathtracer.render();
2030  }
2031 
2032  // Refresh the render image during RT
2033  _optixPathtracer.renderImage(false);
2034 
2035  // React on the stop flag (e.g. ESC)
2036  if (_stopOptixPT)
2037  {
2038  _renderType = RT_gl;
2039  updated = true;
2040  }
2041 
2042  return updated;
2043 }
2044 #endif
2045 //-----------------------------------------------------------------------------
2046 //! Saves after n wait frames the front frame buffer as a PNG image.
2047 /* Due to the fact that ImGui needs several frame the render its UI we have to
2048  * wait a few frames until we can be sure that the executing menu command has
2049  * disappeared before we can save the screen.
2050  */
2052  cv::Size targetSize)
2053 {
2054  if (_screenCaptureWaitFrames == 0)
2055  {
2056  SLint fbW = _viewportRect.width;
2057  SLint fbH = _viewportRect.height;
2058 
2059 #ifndef SL_EMSCRIPTEN
2060  GLsizei nrChannels = 3;
2061 #else
2062  GLsizei nrChannels = 4;
2063 #endif
2064 
2065  GLsizei stride = nrChannels * fbW;
2066  stride += (stride % 4) ? (4 - stride % 4) : 0;
2067  GLsizei bufferSize = stride * fbH;
2068  vector<uchar> buffer(bufferSize);
2069 
2070  SLGLState::instance()->readPixels(buffer.data());
2071 
2072 #ifndef SL_EMSCRIPTEN
2073  CVMat rgbImg = CVMat(fbH, fbW, CV_8UC3, (void*)buffer.data(), stride);
2074  cv::cvtColor(rgbImg, rgbImg, cv::COLOR_BGR2RGB);
2075 #else
2076  CVMat rgbImg = CVMat(fbH,
2077  fbW,
2078  CV_8UC4,
2079  (void*)buffer.data(),
2080  stride);
2081  cv::cvtColor(rgbImg, rgbImg, cv::COLOR_RGBA2RGB);
2082  nrChannels = 3;
2083  stride = nrChannels * fbW;
2084 #endif
2085 
2086  cv::flip(rgbImg, rgbImg, 0);
2087  if (targetSize.width > 0 && targetSize.height > 0)
2088  cv::resize(rgbImg, rgbImg, targetSize);
2089 
2090 #ifndef SL_EMSCRIPTEN
2091  vector<int> compression_params;
2092  compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
2093  compression_params.push_back(6);
2094 
2095  try
2096  {
2097  imwrite(pathFilename, rgbImg, compression_params);
2098  string msg = "Screenshot saved to: " + pathFilename;
2099  SL_LOG(msg.c_str());
2100  }
2101  catch (std::runtime_error& ex)
2102  {
2103  string msg = "SLSceneView::saveFrameBufferAsImage: Exception: ";
2104  msg += ex.what();
2105  Utils::exitMsg("SLProject", msg.c_str(), __LINE__, __FILE__);
2106  }
2107 #else
2108  auto writer = [](void* context, void* data, int size)
2109  {
2110  SLIOStream* stream = (SLIOStream*)context;
2111  stream->write(data, size);
2112  };
2113 
2114  SLIOStream* stream = SLFileStorage::open(pathFilename,
2115  IOK_image,
2116  IOM_write);
2117  stbi_write_png_to_func(writer,
2118  (void*)stream,
2119  fbW,
2120  fbH,
2121  nrChannels,
2122  rgbImg.data,
2123  stride);
2124  SLFileStorage::close(stream);
2125 #endif
2126 
2127 #if !defined(SL_OS_ANDROID) && !defined(SL_OS_MACIOS) && !defined(SL_EMSCRIPTEN)
2128  _gui->drawMouseCursor(true);
2129 #endif
2130  _screenCaptureIsRequested = false;
2131  }
2132  else
2134 }
2135 //-----------------------------------------------------------------------------
static SLint dpi
Dot per inch resolution of screen.
Definition: AppGLFW.cpp:41
cv::Mat CVMat
Definition: CVTypedefs.h:38
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
float SLfloat
Definition: SL.h:173
#define SL_LOG_DEBUG(...)
Definition: SL.h:237
#define SL_LOG(...)
Definition: SL.h:233
unsigned int SLuint
Definition: SL.h:171
char SLchar
Definition: SL.h:162
bool SLbool
Definition: SL.h:175
#define SL_EXIT_MSG(message)
Definition: SL.h:240
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_NORMALS
Draw the vertex normals.
Definition: SLDrawBits.h:23
#define SL_DB_SKELETON
Draw the skeletons joints.
Definition: SLDrawBits.h:27
#define SL_DB_WITHEDGES
Draw faces with hard edges.
Definition: SLDrawBits.h:30
#define SL_DB_AXIS
Draw the coordinate axis of a node.
Definition: SLDrawBits.h:25
#define SL_DB_BRECT
Draw the bounding rectangle of a node.
Definition: SLDrawBits.h:32
#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_GPU_SKINNING
Perform skinning on the GPU.
Definition: SLDrawBits.h:33
#define SL_DB_CULLOFF
Turn off face culling.
Definition: SLDrawBits.h:28
#define SL_DB_MESHWIRED
Draw polygons as wired mesh.
Definition: SLDrawBits.h:22
#define SL_DB_BBOX
Draw the bounding boxes of a node.
Definition: SLDrawBits.h:24
@ CA_turntableYUp
Orbiting around central object w. turntable rotation around y & right axis.
Definition: SLEnums.h:122
@ CA_trackball
Orbiting around central object w. one rotation around one axis.
Definition: SLEnums.h:124
@ CA_turntableZUp
Orbiting around central object w. turntable rotation around z & right axis.
Definition: SLEnums.h:123
SLProjType
Enumeration for different camera projections.
Definition: SLEnums.h:134
@ P_monoPerspective
standard mono pinhole perspective projection
Definition: SLEnums.h:135
@ P_stereoSideBySideD
side-by-side distorted for Oculus Rift like glasses
Definition: SLEnums.h:140
@ P_stereoLineByLine
line-by-line
Definition: SLEnums.h:141
@ P_monoOrthographic
standard mono orthographic projection
Definition: SLEnums.h:137
@ RT_rt
Ray Tracing.
Definition: SLEnums.h:71
@ RT_pt
Path Tracing.
Definition: SLEnums.h:72
@ RT_gl
OpenGL.
Definition: SLEnums.h:70
@ RT_optix_pt
Path Tracing with OptiX.
Definition: SLEnums.h:74
@ RT_optix_rt
Ray Tracing with OptiX.
Definition: SLEnums.h:73
@ TS_world
Definition: SLEnums.h:208
@ TS_parent
Definition: SLEnums.h:209
@ TS_object
Definition: SLEnums.h:210
SLMouseButton
Mouse button codes.
Definition: SLEnums.h:98
@ MB_none
Definition: SLEnums.h:99
@ MB_left
Definition: SLEnums.h:100
@ MB_right
Definition: SLEnums.h:102
@ MB_middle
Definition: SLEnums.h:101
SLViewportAlign
Mouse button codes.
Definition: SLEnums.h:254
@ VA_leftOrBottom
Definition: SLEnums.h:256
@ VA_center
Definition: SLEnums.h:255
@ ET_center
Definition: SLEnums.h:154
@ ET_right
Definition: SLEnums.h:155
@ ET_left
Definition: SLEnums.h:153
SLKey
Keyboard key codes enumeration.
Definition: SLEnums.h:16
@ K_space
Definition: SLEnums.h:18
@ K_esc
Definition: SLEnums.h:21
@ K_tab
Definition: SLEnums.h:19
@ K_shift
Definition: SLEnums.h:62
@ IOM_write
Definition: SLFileStorage.h:51
@ IOK_image
Definition: SLFileStorage.h:40
@ PT_lineLoop
Definition: SLGLEnums.h:33
#define GET_GL_ERROR
Definition: SLGLState.h:56
Wrapper Class around the external ImGui GUI-framework.
deque< SLNode * > SLVNode
SLVNode typedef for a vector of SLNodes.
Definition: SLNode.h:26
@ rtBusy
Definition: SLRaytracer.h:30
@ rtMoveGL
Definition: SLRaytracer.h:32
@ rtFinished
Definition: SLRaytracer.h:31
@ rtReady
Definition: SLRaytracer.h:29
SLRect< SLint, SLVec2i > SLRecti
Definition: SLRect.h:104
void(SL_STDCALL * cbOnSelectNodeMesh)(SLNode *, SLMesh *)
Callback function typedef for select node.
Definition: SLSceneView.h:51
SLbool(SL_STDCALL * cbOnWndUpdate)()
Callback function typedef for GUI window updateRec.
Definition: SLSceneView.h:48
SLVec2< SLint > SLVec2i
Definition: SLVec2.h:140
vector< SLVec3f > SLVVec3f
Definition: SLVec3.h:325
SLVec3< SLfloat > SLVec3f
Definition: SLVec3.h:318
SLVec4< SLfloat > SLVec4f
Definition: SLVec4.h:235
static float timeMS()
Definition: GlobalTimer.cpp:25
Defines an axis aligned bounding box.
Definition: SLAABBox.h:34
SLVec3f centerWS()
Definition: SLAABBox.h:50
void minWS(const SLVec3f &minC)
Definition: SLAABBox.h:39
void maxWS(const SLVec3f &maxC)
Definition: SLAABBox.h:40
void drawVisuals(SLSceneView *sv)
Draws the animation visualizations.
SLAnimSkeleton keeps track of a skeletons joints and animations.
const SLVJoint & joints() const
void rebuild()
Definition: SLBackground.h:42
void render(SLint widthPX, SLint heightPX)
Draws the background as 2D rectangle with OpenGL buffers.
void colors(const SLCol4f &uniformColor)
Sets a uniform background color.
Active or visible camera node class.
Definition: SLCamera.h:54
SLbool onTouch2Down(SLint x1, SLint y1, SLint x2, SLint y2) override
Definition: SLCamera.cpp:1280
SLbool onKeyRelease(SLKey key, SLKey mod) override
Definition: SLCamera.cpp:1470
SLfloat trackballSize() const
Definition: SLCamera.h:164
void setViewport(SLSceneView *sv, SLEyeType eye)
Sets the viewport transform depending on the projection.
Definition: SLCamera.cpp:459
SLbool onMouseUp(SLMouseButton button, SLint x, SLint y, SLKey mod) override
Gets called whenever the mouse button is released.
Definition: SLCamera.cpp:1207
void stereoEyeSeparation(const SLfloat es)
Definition: SLCamera.h:119
SLfloat fovV() const
Vertical field of view.
Definition: SLCamera.h:135
void clipFar(const SLfloat cFar)
Definition: SLCamera.h:109
void clipNear(const SLfloat cNear)
Definition: SLCamera.h:108
void focalDist(const SLfloat f)
Definition: SLCamera.h:116
void maxSpeed(const SLfloat ms)
Definition: SLCamera.h:112
SLbool onMouseMove(SLMouseButton button, SLint x, SLint y, SLKey mod) override
Gets called whenever the mouse is moved.
Definition: SLCamera.cpp:1031
void setView(SLSceneView *sv, SLEyeType eye)
Definition: SLCamera.cpp:719
void projType(SLProjType p)
Definition: SLCamera.h:92
void eyeToPixelRay(SLfloat x, SLfloat y, SLRay *ray)
eyeToPixelRay returns the a ray from the eye to the center of a pixel.
Definition: SLCamera.cpp:1514
SLRectf & deselectRect()
Definition: SLCamera.h:172
virtual SLbool camUpdate(SLSceneView *sv, SLfloat timeMS)
Definition: SLCamera.cpp:98
void setFrustumPlanes()
SLCamera::setFrustumPlanes set the 6 plane from the view frustum.
Definition: SLCamera.cpp:1495
SLBackground & background()
Definition: SLCamera.h:165
SLRectf & selectRect()
Definition: SLCamera.h:171
SLbool onTouch2Up(SLint x1, SLint y1, SLint x2, SLint y2) override
Definition: SLCamera.cpp:1412
SLbool onMouseDown(SLMouseButton button, SLint x, SLint y, SLKey mod) override
Gets called whenever a mouse button gets pressed.
Definition: SLCamera.cpp:1005
void setProjection(SLSceneView *sv, SLEyeType eye)
Definition: SLCamera.cpp:513
SLbool onTouch2Move(SLint x1, SLint y1, SLint x2, SLint y2) override
Definition: SLCamera.cpp:1295
SLfloat aspect() const
Definition: SLCamera.h:139
SLbool onKeyPress(SLKey key, SLKey mod) override
Definition: SLCamera.cpp:1425
SLbool onMouseWheel(SLint delta, SLKey mod) override
Definition: SLCamera.cpp:1243
void camAnim(SLCamAnim ca)
Definition: SLCamera.h:103
void toggle(SLuint bit)
Toggles the specified bit.
Definition: SLDrawBits.h:66
void allOff()
Turns all bits off.
Definition: SLDrawBits.h:48
virtual SLbool onDoubleClick(const SLMouseButton button, const SLint x, const SLint y, const SLKey mod)
void updateSize(SLint scrWidth, SLint scrHeight)
SLuint texID()
Definition: SLGLOculusFB.h:40
void bindFramebuffer(SLint scrWidth, SLint scrHeight)
void beginFrame()
Definition: SLGLOculus.cpp:195
SLfloat resolutionScale()
Definition: SLGLOculus.h:51
void renderDistortion(SLint width, SLint height, SLuint tex, const SLCol4f &background)
Definition: SLGLOculus.cpp:79
void renderResolution(SLint width, SLint height)
Definition: SLGLOculus.cpp:182
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
void clearColor(const SLCol4f &c)
Definition: SLGLState.cpp:157
SLMat4f modelMatrix
Init all states.
Definition: SLGLState.h:89
void depthMask(SLbool state)
Definition: SLGLState.cpp:190
void viewport(SLint x, SLint y, SLsizei width, SLsizei height)
Definition: SLGLState.cpp:378
void multiSample(SLbool state)
Definition: SLGLState.cpp:267
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
SLMat4f viewMatrix
matrix for the active cameras view transform
Definition: SLGLState.h:91
void unbindAnythingAndFlush()
finishes all GL commands
Definition: SLGLState.cpp:465
void colorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a)
Definition: SLGLState.cpp:394
void blend(SLbool state)
Definition: SLGLState.cpp:236
void onInitialize(const SLCol4f &clearColor)
On init GL.
Definition: SLGLState.cpp:137
SLMat4f projectionMatrix
matrix for projection transform
Definition: SLGLState.h:90
void polygonLine(SLbool state)
Definition: SLGLState.cpp:290
void readPixels(void *buffer)
Reads the front framebuffer pixels into the passed buffer.
Definition: SLGLState.cpp:639
void clearColorDepthBuffer()
Definition: SLGLState.h:123
void depthTest(SLbool state)
Definition: SLGLState.cpp:172
void deleteData(SLbool deleteAlsoOnGPU)
Delete all data (CVImages and GPU textures)
void generateVertexPos(SLVVec2f *p)
Adds or updates & generates a position vertex attribute for colored line or point drawing.
void drawArrayAsColored(SLGLPrimitiveType primitiveType, SLCol4f color, SLfloat lineOrPointSize=1.0f, SLuint indexFirstVertex=0, SLuint countVertices=0)
Draws the array as the specified primitive with the color.
void clearAttribs()
Clears the attribute definition.
static SLuint totalDrawCalls
static SLuint totalPrimitivesRendered
static total no. of draw calls
Interface for accessing external data using streams.
Definition: SLFileStorage.h:62
virtual size_t write(const void *buffer, size_t size)
Definition: SLFileStorage.h:73
SLInputManager. manages system input and custom input devices.
SLbool pollAndProcessEvents(SLSceneView *sv)
Abstract Light class for OpenGL light sources.
Definition: SLLight.h:61
SLVec3< T > translation() const
Definition: SLMat4.h:184
void ortho(T l, T r, T b, T t, T n, T f)
Defines a orthographic projection matrix with a field of view angle.
Definition: SLMat4.h:911
void m(int i, T val)
Definition: SLMat4.h:93
void identity()
Sets the identity matrix.
Definition: SLMat4.h:1333
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
SLbool hasAlpha()
Returns true if there is any transparency in diffuse alpha or textures.
Definition: SLMaterial.h:125
An SLMesh object is a triangulated mesh, drawn with one draw call.
Definition: SLMesh.h:134
SLMaterial * mat() const
Definition: SLMesh.h:177
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
void translation(const SLVec3f &pos, SLTransformSpace relativeTo=TS_parent)
Definition: SLNode.cpp:828
virtual void needUpdate()
Definition: SLNode.cpp:616
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
void setInitialState()
Definition: SLNode.cpp:1084
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
virtual SLAABBox & updateAABBRec(SLbool updateAlsoAABBinOS)
Definition: SLNode.cpp:731
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
SLbool render(SLSceneView *sv)
Ray class with ray and intersection properties.
Definition: SLRay.h:40
SLMesh * hitMesh
Points to the intersected mesh.
Definition: SLRay.h:106
SLfloat length
length from origin to an intersection
Definition: SLRay.h:77
SLNode * hitNode
Points to the intersected node.
Definition: SLRay.h:105
SLbool renderClassic(SLSceneView *sv)
Definition: SLRaytracer.cpp:56
void doContinuous(SLbool cont)
Definition: SLRaytracer.h:91
void state(SLRTState state)
Definition: SLRaytracer.h:80
static SLuint numThreads()
Definition: SLRaytracer.h:119
SLbool renderDistrib(SLSceneView *sv)
virtual void renderImage(bool updateTextureGL)
void maxDepth(SLint depth)
Definition: SLRaytracer.h:84
void aaSamples(SLint samples)
Definition: SLRaytracer.h:101
void doDistributed(SLbool distrib)
Definition: SLRaytracer.h:90
T width
Definition: SLRect.h:29
T y
Definition: SLRect.h:29
void set(const T X, const T Y, const T WIDTH, const T HEIGHT)
Definition: SLRect.h:42
SLbool isEmpty() const
Definition: SLRect.h:74
T x
Definition: SLRect.h:29
SLbool contains(T X, T Y)
Definition: SLRect.h:76
void drawGL(const SLCol4f &color)
Definition: SLRect.h:88
T height
Definition: SLRect.h:29
void setZero()
Definition: SLRect.h:49
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
bool onUpdate(bool renderTypeIsRT, bool voxelsAreShown, bool forceCPUSkinning)
Updates animations and AABBs.
Definition: SLScene.cpp:124
void deselectAllNodesAndMeshes()
Deselects all nodes and its meshes.
Definition: SLScene.cpp:338
SLCamera * nextCameraInScene(SLCamera *activeSVCam)
Returns the next camera in the scene if there is one.
Definition: SLScene.cpp:361
SLVEventHandler & eventHandlers()
Definition: SLScene.h:105
SLVLight & lights()
Definition: SLScene.h:107
void root2D(SLNode *root2D)
Definition: SLScene.h:90
SLAnimManager & animManager()
Definition: SLScene.h:97
void selectNodeMesh(SLNode *nodeToSelect, SLMesh *meshToSelect)
Handles the full mesh selection from double-clicks.
Definition: SLScene.cpp:234
SLfloat elapsedTimeMS() const
Definition: SLScene.h:103
void skybox(SLSkybox *skybox)
Definition: SLScene.h:91
SLfloat fps() const
Definition: SLScene.h:108
void root3D(SLNode *root3D)
Definition: SLScene.h:78
SLGLOculus * oculus()
Definition: SLScene.h:140
SLNode * singleNodeSelected()
Returns the node if only one is selected. See also SLMesh::selectNodeMesh.
Definition: SLScene.h:116
SLVNode & selectedNodes()
Definition: SLScene.h:124
void stopAnimations(SLbool stop)
Definition: SLScene.h:92
SLKey _mouseMod
mouse modifier key on key down
Definition: SLSceneView.h:249
SLfloat _draw2DTimeMS
time for 2D drawing in ms
Definition: SLSceneView.h:244
SLbool _screenCaptureIsRequested
Flag if screen capture is requested.
Definition: SLSceneView.h:266
SLPathtracer _pathtracer
Pathtracer.
Definition: SLSceneView.h:282
virtual void onStartup()
Definition: SLSceneView.h:94
std::unordered_set< SLMaterial * > _visibleMaterials2D
visible materials 2D per frame
Definition: SLSceneView.h:272
SLint _scrW
Screen width in pixels.
Definition: SLSceneView.h:256
void draw3DGLLinesOverlay(SLVNode &nodes)
SLDrawBits * drawBits()
Definition: SLSceneView.h:198
void switchToNextCameraInScene()
Sets the active camera to the next in the scene.
std::unordered_set< SLMaterial * > _visibleMaterials3D
visible materials 3D per frame
Definition: SLSceneView.h:271
virtual void postDraw()
Definition: SLSceneView.h:96
SLbool doWaitOnIdle() const
Definition: SLSceneView.h:188
SLbool _stopPT
Flag to stop the PT.
Definition: SLSceneView.h:283
SLNodeStats _stats3D
Statistic numbers for 3D nodes.
Definition: SLSceneView.h:229
SLfloat _scrWdivH
Screen side aspect ratio.
Definition: SLSceneView.h:260
SLint _screenCaptureWaitFrames
Frames to delay the screen capture.
Definition: SLSceneView.h:267
virtual SLbool onDoubleClick(SLMouseButton button, SLint x, SLint y, SLKey mod)
void draw3DGLAll()
SLint _scrH
Screen height in pixels.
Definition: SLSceneView.h:257
SLRaytracer _raytracer
Whitted style raytracer.
Definition: SLSceneView.h:280
SLbool _gotPainted
flag if this sceneview got painted
Definition: SLSceneView.h:230
virtual SLbool onMouseWheelPos(SLint wheelPos, SLKey mod)
SLbool _mouseDownM
Flag if middle mouse button is pressed.
Definition: SLSceneView.h:248
SLVNode _nodesBlended3D
Vector of visible blended nodes not in _visibleMaterials3D rendered in 3D.
Definition: SLSceneView.h:277
SLVNode _nodesOverdrawn
Vector of helper nodes drawn over all others.
Definition: SLSceneView.h:278
void draw3DGLNodes(SLVNode &nodes, SLbool alphaBlended, SLbool depthSorted)
cbOnWndUpdate onWndUpdate
C-Callback for app for intermediate window repaint.
Definition: SLSceneView.h:141
SLVNode _nodesOpaque2D
Vector of visible opaque nodes not in _visibleMaterials2D rendered in 2D.
Definition: SLSceneView.h:274
virtual SLbool onCharInput(SLuint c)
SLVNode _nodesBlended2D
Vector of visible blended nodes not in _visibleMaterials2D rendered in 2D.
Definition: SLSceneView.h:275
SLbool doDepthTest() const
Definition: SLSceneView.h:187
SLbool _doMultiSampling
Flag if multisampling is on.
Definition: SLSceneView.h:234
SLRenderType _renderType
rendering type (GL,RT,PT)
Definition: SLSceneView.h:231
SLGLOculusFB _oculusFB
Oculus framebuffer.
Definition: SLSceneView.h:269
void draw3DGLLines(SLVNode &nodes)
void startPathtracing(SLint maxDepth, SLint samples)
void onResize(SLint width, SLint height)
cbOnSelectNodeMesh onSelectedNodeMesh
C-Callback for app on node selection.
Definition: SLSceneView.h:142
SLbool _mouseDownL
Flag if left mouse button is pressed.
Definition: SLSceneView.h:246
void switchToSceneViewCamera()
SLRecti _viewportRect
rectangle of viewport
Definition: SLSceneView.h:264
SLVNode _nodesOpaque3D
Vector of visible opaque nodes not in _visibleMaterials3D rendered in 3D.
Definition: SLSceneView.h:276
SLGLVertexArrayExt _vaoTouch
Buffer for touch pos. rendering.
Definition: SLSceneView.h:253
SLUiInterface * _gui
new tighter imgui wrapper
Definition: SLSceneView.h:227
SLbool doFrustumCulling() const
Definition: SLSceneView.h:184
SLViewportAlign _viewportAlign
alignment of viewport
Definition: SLSceneView.h:263
SLbool _doFrustumCulling
Flag if view frustum culling is on.
Definition: SLSceneView.h:235
SLfloat _draw3DTimeMS
time for 3D drawing in ms
Definition: SLSceneView.h:243
SLint _scrWdiv2
Screen half width in pixels.
Definition: SLSceneView.h:258
void draw2DGLNodes()
SLbool _doWaitOnIdle
Flag for Event waiting.
Definition: SLSceneView.h:237
virtual SLbool onMouseMove(SLint x, SLint y)
virtual void preDraw()
Definition: SLSceneView.h:95
SLbool draw3DPT()
SLbool _doAlphaSorting
Flag if alpha sorting in blending is on.
Definition: SLSceneView.h:236
SLint _scrHdiv2
Screen half height in pixels.
Definition: SLSceneView.h:259
AvgFloat _shadowMapTimesMS
Averaged time for drawing the shadow maps in ms.
Definition: SLSceneView.h:294
SLstring windowTitle()
SLNodeStats _stats2D
Statistic numbers for 2D nodes.
Definition: SLSceneView.h:228
SLbool _mouseDownR
Flag if right mouse button is pressed.
Definition: SLSceneView.h:247
void init(SLstring name, SLint screenWidth, SLint screenHeight, void *onWndUpdateCallback, void *onSelectNodeMeshCallback, SLUiInterface *gui, const string &configPath)
Definition: SLSceneView.cpp:64
SLbool doMultiSampling() const
Definition: SLSceneView.h:186
void startRaytracing(SLint maxDepth)
SLbool drawBit(SLuint bit)
Definition: SLSceneView.h:199
void initSceneViewCamera(const SLVec3f &dir=-SLVec3f::AXISZ, SLProjType proj=P_monoPerspective)
virtual SLbool onKeyRelease(SLKey key, SLKey mod)
SLbool doAlphaSorting() const
Definition: SLSceneView.h:185
SLbool _viewportSameAsVideo
Adapt viewport aspect to the input video.
Definition: SLSceneView.h:265
SLbool _doDepthTest
Flag if depth test is turned on.
Definition: SLSceneView.h:233
SLbool _isFirstFrame
Flag if it is the first frame rendering.
Definition: SLSceneView.h:238
void saveFrameBufferAsImage(SLstring pathFilename, cv::Size targetSize=cv::Size(-1, -1))
Saves after n wait frames the front frame buffer as a PNG image.
~SLSceneView() override
Definition: SLSceneView.cpp:51
SLSceneView(SLScene *s, int dpi, SLInputManager &inputManager)
SLSceneView default constructor.
Definition: SLSceneView.cpp:37
AvgFloat _cullTimesMS
Averaged time for culling in ms.
Definition: SLSceneView.h:295
SLbool draw3DRT()
void onInitialize()
virtual SLbool onMouseWheel(SLint delta, SLKey mod)
SLint _touchDowns
finger touch down count
Definition: SLSceneView.h:250
SLbool onPaint()
SLVec2i _touch[3]
up to 3 finger touch coordinates
Definition: SLSceneView.h:251
SLInputManager & _inputManager
Definition: SLSceneView.h:292
SLCamera _sceneViewCamera
Default camera for this SceneView (default cam not in scenegraph)
Definition: SLSceneView.h:226
AvgFloat _draw2DTimesMS
Averaged time for 2D drawing in ms.
Definition: SLSceneView.h:297
SLfloat _cullTimeMS
time for culling in ms
Definition: SLSceneView.h:242
SLRaytracer * raytracer()
Definition: SLSceneView.h:194
SLVec2i _viewportRatio
ratio of viewport
Definition: SLSceneView.h:262
virtual SLbool onTouch2Move(SLint scrX1, SLint scrY1, SLint scrX2, SLint scrY2)
virtual SLbool onMouseUp(SLMouseButton button, SLint scrX, SLint scrY, SLKey mod)
SLScene * _s
Pointer to the scene observed by this scene view.
Definition: SLSceneView.h:224
SLfloat _shadowMapTimeMS
time for drawing the shadow maps in ms
Definition: SLSceneView.h:241
void setViewportFromRatio(const SLVec2i &vpRatio, SLViewportAlign vpAlignment, SLbool vpSameAsVideo)
Sets the viewport ratio and the viewport rectangle.
virtual SLbool onKeyPress(SLKey key, SLKey mod)
AvgFloat _draw3DTimesMS
Averaged time for 3D drawing in ms.
Definition: SLSceneView.h:296
virtual SLbool onMouseDown(SLMouseButton button, SLint scrX, SLint scrY, SLKey mod)
SLScene * s()
Definition: SLSceneView.h:167
SLCamera * camera()
Definition: SLSceneView.h:168
virtual SLbool onTouch2Up(SLint scrX1, SLint scrY1, SLint scrX2, SLint scrY2)
SLCamera * _camera
Pointer to the _active camera.
Definition: SLSceneView.h:225
SLDrawBits _drawBits
Sceneview level drawing flags.
Definition: SLSceneView.h:239
SLbool _stopRT
Flag to stop the RT.
Definition: SLSceneView.h:281
SLbool draw3DGL(SLfloat elapsedTimeSec)
Draws the 3D scene with OpenGL.
virtual SLbool onTouch2Down(SLint scrX1, SLint scrY1, SLint scrX2, SLint scrY2)
SLUiInterface * gui()
Definition: SLSceneView.h:183
static SLuint drawCalls
NO. of draw calls for shadow mapping.
Definition: SLShadowMap.h:92
Interface for ui integration in SLSceneView.
Definition: SLUiInterface.h:24
virtual void onMouseDown(SLMouseButton button, SLint x, SLint y)
forward user input to ui
Definition: SLUiInterface.h:43
virtual void onPaint(const SLRecti &viewport)
ui render call (called by SLSceneView draw2DGL)
Definition: SLUiInterface.h:39
virtual void onMouseMove(SLint xPos, SLint yPos)
forward user input to ui
Definition: SLUiInterface.h:47
virtual void init(const string &configPath)
initialization (called by SLSceneView init)
Definition: SLUiInterface.h:29
virtual void onKeyPress(SLKey key, SLKey mod)
forward user input to ui
Definition: SLUiInterface.h:51
virtual void renderExtraFrame(SLScene *s, SLSceneView *sv, SLint mouseX, SLint mouseY)
Definition: SLUiInterface.h:40
virtual bool doNotDispatchKeyboard()
inform if user keyboard input was consumed by the ui
Definition: SLUiInterface.h:58
virtual void onResize(const SLRecti &viewportRect)
inform the ui about scene view size change
Definition: SLUiInterface.h:31
virtual void onMouseWheel(SLfloat yoffset)
forward user input to ui
Definition: SLUiInterface.h:49
virtual void onKeyRelease(SLKey key, SLKey mod)
forward user input to ui
Definition: SLUiInterface.h:53
virtual bool doNotDispatchMouse()
inform if user mouse input was consumed by the ui
Definition: SLUiInterface.h:64
virtual void onMouseUp(SLMouseButton button, SLint x, SLint y)
forward user input to ui
Definition: SLUiInterface.h:45
virtual void onInitNewFrame(SLScene *s, SLSceneView *sv)
prepare the ui for a new rendering, e.g. update visual ui representation (called by SLSceneView onPai...
Definition: SLUiInterface.h:36
virtual void onCharInput(SLuint c)
forward user input to ui
Definition: SLUiInterface.h:55
virtual void drawMouseCursor(bool doDraw)
Turns on or off the mouse cursor drawing.
Definition: SLUiInterface.h:67
static SLVec2 ZERO
Definition: SLVec2.h:135
T y
Definition: SLVec2.h:30
T x
Definition: SLVec2.h:30
void set(const T X, const T Y)
Definition: SLVec2.h:40
void fromPolar(T r, T phiRAD)
Calculates the vector from polar coords r & phi in radians (-pi < phi < pi)
Definition: SLVec2.h:101
T y
Definition: SLVec3.h:43
static SLVec3 AXISY
Definition: SLVec3.h:298
T x
Definition: SLVec3.h:43
T z
Definition: SLVec3.h:43
static SLVec4 GREEN
Definition: SLVec4.h:217
static SLVec4 WHITE
Definition: SLVec4.h:215
static SLVec4 GRAY
Definition: SLVec4.h:214
static SLVec4 YELLOW
Definition: SLVec4.h:219
static SLVec4 MAGENTA
Definition: SLVec4.h:221
static SLVec4 RED
Definition: SLVec4.h:216
void init(int numValues, T initValue)
Initializes the average value array to a given value.
Definition: Averaged.h:41
void set(T value)
Sets the current value in the value array and builds the average.
Definition: Averaged.h:53
void close(SLIOStream *stream)
Closes and deletes a stream.
SLIOStream * open(std::string path, SLIOStreamKind kind, SLIOStreamMode mode)
Opens a file stream for I/O operations.
static const float DEG2RAD
Definition: Utils.h:239
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1135
static const float TWOPI
Definition: Utils.h:240
T mod(T a, T b)
Definition: Utils.h:250
SLuint numNodesOpaque
NO. of visible opaque nodes.
Definition: SLNode.h:43
SLuint numNodes
NO. of children nodes.
Definition: SLNode.h:38
void clear()
Resets all counters to zero.
Definition: SLNode.h:55
SLuint numNodesBlended
NO. of visible blended nodes.
Definition: SLNode.h:44