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