SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLTransformNode.cpp
Go to the documentation of this file.
1 /**
2  * \file SLTransformNode.cpp
3  * \authors Jan Dellsperger
4  * \date April 2020
5  * \authors Jan Dellsperger, Marcus Hudritsch
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #include <SLGLProgramManager.h>
12 #include <SLTransformNode.h>
13 #include <SLVec3.h>
14 #include <SLCoordAxisArrow.h>
15 #include <SLCircle.h>
16 #include <SLDisk.h>
17 
18 //-----------------------------------------------------------------------------
19 /**
20  * @brief Construct a new SLTransformNode::SLTransformNode object *
21  * @details It is important that during instantiation NO OpenGL functions (gl*)
22  * get called because this constructor will be most probably called in a parallel
23  * thread from within an SLScene::registerAssetsToLoad or SLScene::assemble
24  * function. All objects that get rendered have to do their OpenGL initialization
25  * when they are used the first time during rendering in the main thread.
26  * @param sv Pointer to the SLSceneView
27  * @param targetNode Pointer to the node that should be transformed.
28  * @param shaderDir Path to the shader files
29  */
31  SLNode* targetNode,
32  SLstring shaderDir)
33  : SLNode("Edit Gizmos"),
34  _sv(sv),
35  _targetNode(targetNode),
36  _editMode(NodeEditMode_None),
37  _mouseIsDown(false),
38  _gizmoScale(1.0f)
39 {
41 
42  _matR = new SLMaterial(nullptr, "Red Opaque", SLCol4f::RED, SLVec4f::WHITE, 100.0f, 0.0f, 0.0f, 0.0f, prog);
43  _matRT = new SLMaterial(nullptr, "Red Transp", SLCol4f::RED, SLVec4f::WHITE, 100.0f, 0.0f, 0.5f, 0.0f, prog);
44  _matG = new SLMaterial(nullptr, "Green Opaque", SLCol4f::GREEN, SLVec4f::WHITE, 100.0f, 0.0f, 0.0f, 0.0f, prog);
45  _matGT = new SLMaterial(nullptr, "Green Transp", SLCol4f::GREEN, SLVec4f::WHITE, 100.0f, 0.0f, 0.5f, 0.0f, prog);
46  _matB = new SLMaterial(nullptr, "Blue Opaque", SLCol4f::BLUE, SLVec4f::WHITE, 100.0f, 0.0f, 0.0f, 0.0f, prog);
47  _matBT = new SLMaterial(nullptr, "Blue Transp", SLCol4f::BLUE, SLVec4f::WHITE, 100.0f, 0.0f, 0.5f, 0.0f, prog);
48  _matY = new SLMaterial(nullptr, "Yellow Opaque", SLCol4f::YELLOW, SLVec4f::WHITE, 100.0f, 0.0f, 0.0f, 0.0f, prog);
49  _matYT = new SLMaterial(nullptr, "Yellow Transp", SLCol4f::YELLOW, SLVec4f::WHITE, 100.0f, 0.0f, 0.5f, 0.0f, prog);
50 
51  _axisR = new SLCoordAxisArrow(nullptr, _matRT);
52  _axisG = new SLCoordAxisArrow(nullptr, _matGT);
53  _axisB = new SLCoordAxisArrow(nullptr, _matBT);
54  SLNode* transAxisX = new SLNode(_axisR, "x-axis node");
55  SLNode* transAxisY = new SLNode(_axisG, "y-axis node");
56  SLNode* transAxisZ = new SLNode(_axisB, "z-axis node");
57  transAxisX->rotate(-90.0f, SLVec3f(0.0f, 0.0f, 1.0f));
58  transAxisZ->rotate(90.0f, SLVec3f(1.0f, 0.0f, 0.0f));
59  transAxisX->castsShadows(false);
60  transAxisY->castsShadows(false);
61  transAxisZ->castsShadows(false);
62 
63  SLVec3f startPoint = SLVec3f(0.0f, 0.0f, -1.0f);
64  SLVec3f endPoint = SLVec3f(0.0f, 0.0f, 1.0f);
65  SLVVec3f points;
66  points.push_back(startPoint);
67  points.push_back(endPoint);
68 
69  _lineR = new SLPolyline(nullptr, points, false, "Translation Line Mesh X", _matR);
70  _transLineX = new SLNode(_lineR);
71  _transLineX->rotate(90.0f, SLVec3f(0.0f, 1.0f, 0.0f));
72  _transLineX->scale(1000.0f);
73  _transLineX->castsShadows(false);
74 
75  _lineG = new SLPolyline(nullptr, points, false, "Translation Line Mesh Y", _matG);
76  _transLineY = new SLNode(_lineG);
77  _transLineY->rotate(-90.0f, SLVec3f(1.0f, 0.0f, 0.0f));
78  _transLineY->scale(1000.0f);
79  _transLineY->castsShadows(false);
80 
81  _lineB = new SLPolyline(nullptr, points, false, "Translation Line Mesh Z", _matB);
82  _transLineZ = new SLNode(_lineB);
83  _transLineZ->scale(1000.0f);
84  _transLineZ->castsShadows(false);
85 
86  _circY = new SLCircle(nullptr, "Scale Circle Mesh", _matY);
87  _scaleCirc = new SLNode(_circY, "Scale Circle");
88  _scaleCirc->castsShadows(false);
89  _diskY = new SLDisk(nullptr, 1.0f, SLVec3f::AXISZ, 36U, true, "Scale Disk", _matYT);
90  _scaleDisk = new SLNode(_diskY, "Scale Disk");
91  _scaleDisk->castsShadows(false);
92 
93  _circR = new SLCircle(nullptr, "Rotation Circle Mesh X", _matR);
94  _rotCircX = new SLNode(_circR, "Rotation Circle X");
95  _rotCircX->castsShadows(false);
96  _diskR = new SLDisk(nullptr, 1.0f, SLVec3f::AXISZ, 36U, true, "Rotation Disk X", _matRT);
97  _rotDiskX = new SLNode(_diskR, "Rotation Disk X");
98  _rotDiskX->castsShadows(false);
99  _circG = new SLCircle(nullptr, "Rotation Circle Mesh Y", _matG);
100  _rotCircY = new SLNode(_circG, "Rotation Circle Y");
101  _rotCircY->castsShadows(false);
102  _diskG = new SLDisk(nullptr, 1.0f, SLVec3f::AXISZ, 36U, true, "Rotation Disk Y", _matGT);
103  _rotDiskY = new SLNode(_diskG, "Rotation Disk Y");
104  _rotDiskY->castsShadows(false);
105  _circB = new SLCircle(nullptr, "Rotation Circle Mesh Z", _matB);
106  _rotCircZ = new SLNode(_circB, "Rotation Circle Z");
107  _rotCircZ->castsShadows(false);
108  _diskB = new SLDisk(nullptr, 1.0f, SLVec3f::AXISZ, 36U, true, "Rotation Disk Z", _matBT);
109  _rotDiskZ = new SLNode(_diskB, "Rotation Disk Z");
110  _rotDiskZ->castsShadows(false);
111 
112  SLNode* rotationGizmosX = new SLNode("Rotation Gizmos X");
113  rotationGizmosX->addChild(_rotCircX);
114  rotationGizmosX->addChild(_rotDiskX);
115 
116  SLNode* rotationGizmosY = new SLNode("Rotation Gizmos Y");
117  rotationGizmosY->addChild(_rotCircY);
118  rotationGizmosY->addChild(_rotDiskY);
119 
120  SLNode* rotationGizmosZ = new SLNode("Rotation Gizmos Z");
121  rotationGizmosZ->addChild(_rotCircZ);
122  rotationGizmosZ->addChild(_rotDiskZ);
123 
124  _selectedGizmo = nullptr;
125 
126  rotationGizmosX->rotate(90.0f, SLVec3f(0.0f, 1.0f, 0.0f));
127  rotationGizmosY->rotate(-90.0f, SLVec3f(1.0f, 0.0f, 0.0f));
128 
129  _transGizmos = new SLNode("Translation Gizmos");
130  _transGizmos->addChild(transAxisX);
132  _transGizmos->addChild(transAxisY);
134  _transGizmos->addChild(transAxisZ);
136 
137  _scaleGizmos = new SLNode("Scale Gizmos");
140 
141  _rotGizmos = new SLNode("Rotation Gizmos");
142  _rotGizmos->addChild(rotationGizmosX);
143  _rotGizmos->addChild(rotationGizmosY);
144  _rotGizmos->addChild(rotationGizmosZ);
145 
146  _gizmosNode = new SLNode("Gizmos");
150  this->addChild(_gizmosNode);
151 
152  this->updateAABBRec(true);
153 
155 
156  _sv->s()->eventHandlers().push_back(this);
157 }
158 //-----------------------------------------------------------------------------
159 /*!
160  * Destructor for a transform node.
161  * Because a transform node will be added and removed on the fly to the
162  * scenegraph it is the owner of its meshes (SLMesh), materials (SLMaterial)
163  * and shader programs (SLGLProgram). It has to delete them in here.
164  */
166 {
167  // delete gizmos
169  this->deleteChild(_gizmosNode);
170  this->deleteChildren();
171 
172  // delete all materials and meshes
173  delete _matR;
174  delete _matG;
175  delete _matB;
176  delete _matY;
177  delete _matRT;
178  delete _matGT;
179  delete _matBT;
180  delete _matYT;
181  delete _axisR;
182  delete _axisG;
183  delete _axisB;
184  delete _lineR;
185  delete _lineG;
186  delete _lineB;
187  delete _circR;
188  delete _circG;
189  delete _circB;
190  delete _circY;
191  delete _diskR;
192  delete _diskG;
193  delete _diskB;
194  delete _diskY;
195 }
196 //-----------------------------------------------------------------------------
197 /*!
198  * Setter function for the edit mode. It shows or hides the appropriate gizmo
199  * meshes for the mouse interaction.
200  * \param editMode New edit mode to switch to.
201  */
203 {
205 
206  if (_editMode)
207  {
208  if (_targetNode)
209  {
211 
212  SLVec2f p1 = _sv->camera()->projectWorldToNDC(SLVec4f(_gizmosNode->translationWS()));
213  SLVec2f p2 = _sv->camera()->projectWorldToNDC(SLVec4f(_gizmosNode->translationWS() +
214  _sv->camera()->upWS().normalize()));
215 
216  float actualHeight = (p1 - p2).length();
217  float targetHeight = 0.2f; // % of screen that gizmos should occupy
218  float scaleFactor = targetHeight / actualHeight;
219 
220  _gizmosNode->scale(scaleFactor / _gizmoScale);
221  _gizmoScale = scaleFactor;
222 
224  _gizmosNode->drawBits()->set(SL_DB_HIDDEN, false);
225 
226  switch (_editMode)
227  {
229  {
231  }
232  break;
233 
234  case NodeEditMode_Scale:
235  {
236  if (_sv->camera())
237  {
238  // TODO(dgj1): this behaviour is that of a billboard... introduce in SLProject?
240  }
241 
243  }
244  break;
245 
246  case NodeEditMode_Rotate:
247  {
249  }
250  break;
251 
252  case NodeEditMode_None:
253  default:
254  {
255  }
256  break;
257  }
258  }
259  }
260  else
261  {
264  }
265 }
266 //-----------------------------------------------------------------------------
267 //! onMouseDown event handler during editing interaction
269  SLint x,
270  SLint y,
271  SLKey mod)
272 {
273  bool result = false;
274 
275  if (_editMode && _selectedGizmo)
276  {
277  result = true;
278  _mouseIsDown = true;
279  }
280 
281  return result;
282 }
283 //-----------------------------------------------------------------------------
284 //! onMouseUp event handler during editing interaction
286  SLint x,
287  SLint y,
288  SLKey mod)
289 {
290  bool result = false;
291 
292  if (_editMode && _mouseIsDown)
293  {
294  result = true;
295 
296  if (_targetNode)
297  {
299  }
300 
301  _selectedGizmo = nullptr;
302  _mouseIsDown = false;
303  }
304 
305  return result;
306 }
307 //-----------------------------------------------------------------------------
308 //! onMouseMove event handler during editing interaction
310  SLint x,
311  SLint y,
312  const SLKey mod)
313 {
314  bool result = false;
315 
316  if (_editMode)
317  {
318  if (_sv->camera())
319  {
320  switch (_editMode)
321  {
323  {
324  if (_targetNode)
325  {
326  SLRay pickRay(_sv);
327  _sv->camera()->eyeToPixelRay((SLfloat)x, (SLfloat)y, &pickRay);
328 
329  SLVec3f pickRayPoint;
330  SLVec3f axisPoint;
331  if (_mouseIsDown)
332  {
333  float t1, t2;
335  pickRay.dir,
338  pickRayPoint,
339  t1,
340  axisPoint,
341  t2))
342  {
343  SLVec3f translationDiff = axisPoint - _hitCoordinate;
344  _targetNode->translate(translationDiff, TS_world);
346  _hitCoordinate = axisPoint;
347  }
348 
349  result = true;
350  }
351  else
352  {
353  _selectedGizmo = nullptr;
354 
358 
359  float nodeToCameraDist = (pickRay.origin - _transLineX->translationWS()).length();
360 
361  float dist = FLT_MAX;
362  SLVec3f axisPointCand;
363  float t1, t2;
364  float minDistToOrigin = std::min(nodeToCameraDist * 0.1f, 1.0f);
366  pickRay.dir,
369  pickRayPoint,
370  t1,
371  axisPointCand,
372  t2))
373  {
374  float distCand = (axisPointCand - pickRayPoint).length();
375 
376  if (distCand < dist && distCand < (_gizmoScale * 0.1f) && t1 > minDistToOrigin)
377  {
378  dist = distCand;
380  axisPoint = axisPointCand;
381  }
382  }
383 
385  pickRay.dir,
388  pickRayPoint,
389  t1,
390  axisPointCand,
391  t2))
392  {
393  float distCand = (axisPointCand - pickRayPoint).length();
394 
395  if (distCand < dist && distCand < (_gizmoScale * 0.1f) && t1 > minDistToOrigin)
396  {
397  dist = distCand;
399  axisPoint = axisPointCand;
400  }
401  }
402 
404  pickRay.dir,
407  pickRayPoint,
408  t1,
409  axisPointCand,
410  t2))
411  {
412  float distCand = (axisPointCand - pickRayPoint).length();
413 
414  if (distCand < dist && distCand < (_gizmoScale * 0.1f) && t1 > minDistToOrigin)
415  {
416  dist = distCand;
418  axisPoint = axisPointCand;
419  }
420  }
421 
422  if (_selectedGizmo)
423  {
424  // printf("Selected gizmo %s with dist %f\n", _selectedGizmo->name().c_str(), dist);
426  _hitCoordinate = axisPoint;
427  }
428  }
429  }
430  }
431  break;
432 
433  case NodeEditMode_Scale:
434  {
435  // TODO(dgj1): this behaviour is that of a billboard... introduce in SLProject?
437 
438  SLRay pickRay(_sv);
439  _sv->camera()->eyeToPixelRay((SLfloat)x, (SLfloat)y, &pickRay);
440 
441  if (_targetNode)
442  {
443  if (_mouseIsDown)
444  {
445  float t = FLT_MAX;
446  if (rayPlaneIntersect(pickRay.origin,
447  pickRay.dir,
450  t))
451  {
452  SLVec3f intersectionPointWS = pickRay.origin + pickRay.dir * t;
453  SLVec3f intersectionPoint = _selectedGizmo->updateAndGetWMI() * intersectionPointWS;
454 
455  float newRadius = (intersectionPoint - _selectedGizmo->translationOS()).length();
456  float oldRadius = (_hitCoordinate - _selectedGizmo->translationOS()).length();
457  float scaleFactor = newRadius / oldRadius;
458 
459  _targetNode->scale(scaleFactor);
460  _gizmoScale *= scaleFactor;
461  _gizmosNode->scale(scaleFactor);
462  }
463 
464  result = true;
465  }
466  else
467  {
468  _selectedGizmo = nullptr;
469 
470  float t = FLT_MAX;
471  if (rayDiscIntersect(pickRay.origin,
472  pickRay.dir,
475  _gizmoScale,
476  t))
477  {
479 
480  SLVec3f intersectionPointWS = pickRay.origin + pickRay.dir * t;
481  _hitCoordinate = _scaleCirc->updateAndGetWMI() * intersectionPointWS;
482 
483  _scaleDisk->drawBits()->set(SL_DB_HIDDEN, false);
484  }
485  else
486  {
487  _scaleDisk->drawBits()->set(SL_DB_HIDDEN, true);
488  }
489  }
490  }
491  }
492  break;
493 
494  case NodeEditMode_Rotate:
495  {
496  if (_targetNode)
497  {
498  SLRay pickRay(_sv);
499  _sv->camera()->eyeToPixelRay((SLfloat)x, (SLfloat)y, &pickRay);
500 
501  if (_mouseIsDown)
502  {
503  float t = FLT_MAX;
505  {
506  SLVec3f intersectionPointWS = pickRay.origin + pickRay.dir * t;
507  SLVec3f intersectionPoint = _selectedGizmo->updateAndGetWMI() * intersectionPointWS;
508  SLVec3f rotationStartVec = (_hitCoordinate - _selectedGizmo->translationOS()).normalize();
509  SLVec3f rotationVec = (intersectionPoint - _selectedGizmo->translationOS()).normalize();
510 
511  float angle = RAD2DEG * acos(rotationVec * rotationStartVec);
512 
513  if (angle > FLT_EPSILON || angle < -FLT_EPSILON)
514  {
515  // determine if we have to rotate ccw or cw
518  SLVec2f(intersectionPoint.x, intersectionPoint.y)))
519  {
520  angle = -angle;
521  }
522 
524 
525  _hitCoordinate = intersectionPoint;
526  }
527  }
528 
529  result = true;
530  }
531  else
532  {
533  _rotDiskX->drawBits()->set(SL_DB_HIDDEN, true);
534  _rotDiskY->drawBits()->set(SL_DB_HIDDEN, true);
535  _rotDiskZ->drawBits()->set(SL_DB_HIDDEN, true);
536 
537  _selectedGizmo = nullptr;
538 
539  float t = FLT_MAX;
540  float tCand = FLT_MAX;
541  if (rayDiscIntersect(pickRay.origin,
542  pickRay.dir,
544  _rotDiskX->forwardWS(),
545  _gizmoScale,
546  tCand))
547  {
549  t = tCand;
550  }
551 
552  if (rayDiscIntersect(pickRay.origin,
553  pickRay.dir,
555  _rotDiskY->forwardWS(),
556  _gizmoScale,
557  tCand))
558  {
559  if (tCand < t)
560  {
562  t = tCand;
563  }
564  }
565 
566  if (rayDiscIntersect(pickRay.origin,
567  pickRay.dir,
569  _rotDiskZ->forwardWS(),
570  _gizmoScale,
571  tCand))
572  {
573  if (tCand < t)
574  {
576  t = tCand;
577  }
578  }
579 
580  if (_selectedGizmo)
581  {
582  SLVec3f intersectionPointWS = pickRay.origin + pickRay.dir * t;
583  _hitCoordinate = _selectedGizmo->updateAndGetWMI() * intersectionPointWS;
584 
586  }
587  }
588  }
589  }
590  break;
591 
592  case NodeEditMode_None:
593  default:
594  {
595  }
596  break;
597  }
598  }
599  }
600 
601  return result;
602 }
603 //-----------------------------------------------------------------------------
605  const SLVec3f& ray1Dir,
606  const SLVec3f& ray2O,
607  const SLVec3f& ray2Dir,
608  SLVec3f& ray1P,
609  float& t1,
610  SLVec3f& ray2P,
611  float& t2)
612 {
613  bool result = false;
614 
615  // Check if lines are parallel
616  SLVec3f cross;
617  cross.cross(ray1Dir, ray2Dir);
618  float den = cross.lengthSqr();
619 
620  // printf("den: %f, sqrt(den): %f\n", den, cross.length());
621 
622  if (den > FLT_EPSILON)
623  {
624  SLVec3f diffO = ray2O - ray1O;
625 
626  // clang-format off
627  SLMat3f m1 = SLMat3f(diffO.x, ray2Dir.x, cross.x,
628  diffO.y, ray2Dir.y, cross.y,
629  diffO.z, ray2Dir.z, cross.z);
630  float det1 = m1.det();
631  t1 = det1 / den;
632  ray1P = ray1O + (ray1Dir * t1);
633 
634  SLMat3f m2 = SLMat3f(diffO.x, ray1Dir.x, cross.x,
635  diffO.y, ray1Dir.y, cross.y,
636  diffO.z, ray1Dir.z, cross.z);
637  float det2 = m2.det();
638  t2 = det2 / den;
639  ray2P = ray2O + (ray2Dir * t2);
640  // clang-format on
641 
642  result = true;
643  }
644 
645  return result;
646 }
647 //-----------------------------------------------------------------------------
649  const SLVec3f& pickRayDir,
650  const SLVec3f& axisRayO,
651  const SLVec3f& axisRayDir,
652  SLVec3f& axisPoint)
653 {
654  bool result = false;
655 
656  // Check if lines are parallel
657  SLVec3f cross;
658  cross.cross(pickRayDir, axisRayDir);
659  float den = cross.lengthSqr();
660 
661  if (den > FLT_EPSILON)
662  {
663  SLVec3f diffO = axisRayO - pickRayO;
664 
665  // clang-format off
666  SLMat3f m = SLMat3f(diffO.x, pickRayDir.x, cross.x,
667  diffO.y, pickRayDir.y, cross.y,
668  diffO.z, pickRayDir.z, cross.z);
669  // clang-format on
670 
671  float det = m.det();
672  float t = det / den;
673 
674  axisPoint = axisRayO + (axisRayDir * t);
675 
676  result = true;
677  }
678 
679  return result;
680 }
681 //-----------------------------------------------------------------------------
683  const SLVec3f& rayDir,
684  const SLVec3f& discO,
685  const SLVec3f& discN,
686  const float& discR,
687  float& t)
688 {
689  bool result = false;
690 
691  if (rayPlaneIntersect(rayO, rayDir, discO, discN, t))
692  {
693  SLVec3f intersectPoint = rayO + rayDir * t;
694  SLVec3f discPointDist = intersectPoint - discO;
695 
696  result = (discPointDist.length() <= discR);
697  }
698 
699  return result;
700 }
701 //-----------------------------------------------------------------------------
703  const SLVec3f& rayDir,
704  const SLVec3f& planeO,
705  const SLVec3f& planeN,
706  float& t)
707 {
708  bool result = false;
709 
710  float den = planeN * rayDir;
711  if (den > FLT_EPSILON || den < -FLT_EPSILON)
712  {
713  SLVec3f oDiff = planeO - rayO;
714  t = (oDiff * planeN) / den;
715 
716  result = (t >= 0);
717  }
718 
719  return result;
720 }
721 //-----------------------------------------------------------------------------
722 // uses signed area to determine winding order
723 // returns true if a,b,c are wound in ccw order, false otherwise
724 // https://www.quora.com/What-is-the-signed-Area-of-the-triangle
726  const SLVec2f& b,
727  const SLVec2f& c)
728 {
729  SLVec2f ac = a - c;
730  SLVec2f bc = b - c;
731 
732  float signedArea = 0.5f * (bc.x * ac.y - ac.x * bc.y);
733  bool result = (signedArea > 0.0f);
734 
735  return result;
736 }
737 //-----------------------------------------------------------------------------
739 {
740  node->drawBits()->set(bit, value);
741 
742  for (SLNode* child : node->children())
743  {
744  setDrawBitRecursive(bit, child, value);
745  }
746 }
747 //-----------------------------------------------------------------------------
749 {
750  // TODO(dgj1): this is a lookat function, because the one in SLNode doesn't work
751  // or maybe I don't understand how to use it
752  // TODO(dgj1): this is only correct for the case that the node doesn't have a scale
753  SLVec3f nodePos = node->translationWS();
754  SLVec3f nodeTarget = camera->translationWS();
755  SLVec3f nodeDir = (nodePos - nodeTarget).normalize();
756  SLVec3f up = SLVec3f(0.0f, 1.0f, 0.0f);
757  SLVec3f nodeRight = (up ^ nodeDir).normalize();
758  SLVec3f nodeUp = (nodeDir ^ nodeRight).normalize();
759 
760  SLVec3f nodeTranslation = node->om().translation();
761 
762  // clang-format off
763  SLMat4f updatedOm = SLMat4f(nodeRight.x, nodeUp.x, nodeDir.x, nodeTranslation.x,
764  nodeRight.y, nodeUp.y, nodeDir.y, nodeTranslation.y,
765  nodeRight.z, nodeUp.z, nodeDir.z, nodeTranslation.z,
766  0.0f, 0.0f, 0.0f, 1.0f);
767  // clang-format on
768 
769  node->om(updatedOm);
770 }
771 //-----------------------------------------------------------------------------
float SLfloat
Definition: SL.h:173
unsigned int SLuint
Definition: SL.h:171
bool SLbool
Definition: SL.h:175
string SLstring
Definition: SL.h:158
int SLint
Definition: SL.h:170
#define SL_DB_OVERDRAW
Draw node over all other nodes.
Definition: SLDrawBits.h:29
#define SL_DB_HIDDEN
Flags an object as hidden.
Definition: SLDrawBits.h:20
@ TS_world
Definition: SLEnums.h:208
SLMouseButton
Mouse button codes.
Definition: SLEnums.h:98
SLKey
Keyboard key codes enumeration.
Definition: SLEnums.h:16
@ SP_colorUniformPoint
SLMat3< SLfloat > SLMat3f
Definition: SLMat3.h:746
SLMat4< SLfloat > SLMat4f
Definition: SLMat4.h:1581
SLNodeEditMode
@ NodeEditMode_Translate
@ NodeEditMode_Scale
@ NodeEditMode_None
@ NodeEditMode_Rotate
SLVec2< SLfloat > SLVec2f
Definition: SLVec2.h:141
vector< SLVec3f > SLVVec3f
Definition: SLVec3.h:325
SLVec3< SLfloat > SLVec3f
Definition: SLVec3.h:318
SLVec4< SLfloat > SLVec4f
Definition: SLVec4.h:235
Active or visible camera node class.
Definition: SLCamera.h:54
Circle line mesh derived from SLPolyline.
Definition: SLCircle.h:27
Single arrow for coordinate axis.
SLDisk creates a disk mesh based on SLRevolver.
Definition: SLDisk.h:27
void set(SLuint bit, SLbool state)
Sets the specified bit to the passed state.
Definition: SLDrawBits.h:57
Encapsulation of an OpenGL shader program object.
Definition: SLGLProgram.h:56
static SLGLProgramGeneric * get(SLStdShaderProg id)
Get program reference for given id.
T det() const
det returns the determinant
Definition: SLMat3.h:493
SLVec3< T > translation() const
Definition: SLMat4.h:184
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
void addChild(SLNode *child)
Definition: SLNode.cpp:207
SLVNode & children()
Definition: SLNode.h:305
void translation(const SLVec3f &pos, SLTransformSpace relativeTo=TS_parent)
Definition: SLNode.cpp:828
void rotate(const SLQuat4f &rot, SLTransformSpace relativeTo=TS_object)
Definition: SLNode.cpp:945
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
void scale(SLfloat s)
Definition: SLNode.h:640
void castsShadows(SLbool castsShadows)
Definition: SLNode.h:282
SLVec3f translationWS() const
Definition: SLNode.h:531
void deleteChildren()
Definition: SLNode.cpp:248
SLVec3f translationOS() const
Definition: SLNode.h:468
SLDrawBits * drawBits()
Definition: SLNode.h:299
void om(const SLMat4f &mat)
Definition: SLNode.h:276
const SLMat4f & updateAndGetWMI() const
Definition: SLNode.cpp:714
SLNode(const SLstring &name="Node")
Construct a new SLNode::SLNode object.
Definition: SLNode.cpp:40
SLVec3f forwardWS() const
Definition: SLNode.h:541
virtual SLAABBox & updateAABBRec(SLbool updateAlsoAABBinOS)
Definition: SLNode.cpp:731
bool deleteChild()
Definition: SLNode.cpp:267
void translate(const SLVec3f &vec, SLTransformSpace relativeTo=TS_object)
Definition: SLNode.cpp:906
SLPolyline creates a polyline object.
Definition: SLPolyline.h:23
Ray class with ray and intersection properties.
Definition: SLRay.h:40
SLVec3f origin
Vector to the origin of ray in WS.
Definition: SLRay.h:75
SLVec3f dir
Direction vector of ray in WS.
Definition: SLRay.h:76
SLVEventHandler & eventHandlers()
Definition: SLScene.h:105
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
void camera(SLCamera *camera)
Definition: SLSceneView.h:145
SLScene * s()
Definition: SLSceneView.h:167
virtual SLbool onMouseUp(SLMouseButton button, SLint x, SLint y, SLKey mod) override
onMouseUp event handler during editing interaction
bool getClosestPointsBetweenRays(const SLVec3f &ray1O, const SLVec3f &ray1Dir, const SLVec3f &ray2O, const SLVec3f &ray2Dir, SLVec3f &ray1P, float &t1, SLVec3f &ray2P, float &t2)
SLSceneView * _sv
bool getClosestPointOnAxis(const SLVec3f &pickRayO, const SLVec3f &pickRayDir, const SLVec3f &axisRayO, const SLVec3f &axisRayDir, SLVec3f &axisPoint)
SLNode * _transLineZ
virtual SLbool onMouseDown(SLMouseButton button, SLint x, SLint y, SLKey mod) override
onMouseDown event handler during editing interaction
SLNodeEditMode _editMode
SLTransformNode(SLSceneView *sv, SLNode *targetNode, SLstring shaderDir)
Construct a new SLTransformNode::SLTransformNode object *.
SLNode * _targetNode
SLNode * _transLineY
virtual SLbool onMouseMove(SLMouseButton button, SLint x, SLint y, SLKey mod) override
onMouseMove event handler during editing interaction
bool rayPlaneIntersect(const SLVec3f &rayO, const SLVec3f &rayDir, const SLVec3f &discO, const SLVec3f &discN, float &t)
SLMaterial * _matB
SLMaterial * _matBT
~SLTransformNode() override
SLNode * _transLineX
SLNodeEditMode editMode()
SLMaterial * _matRT
void setDrawBitRecursive(SLuint bit, SLNode *node, bool value)
SLNode * _transGizmos
SLMaterial * _matYT
SLMaterial * _matY
bool rayDiscIntersect(const SLVec3f &rayO, const SLVec3f &rayDir, const SLVec3f &discO, const SLVec3f &discN, const float &distR, float &t)
SLNode * _selectedGizmo
SLMaterial * _matGT
bool isCCW(const SLVec2f &a, const SLVec2f &b, const SLVec2f &c)
SLNode * _scaleGizmos
SLMaterial * _matR
void lookAt(SLNode *node, SLCamera *camera)
SLVec3f _hitCoordinate
SLMaterial * _matG
T y
Definition: SLVec2.h:30
T x
Definition: SLVec2.h:30
T y
Definition: SLVec3.h:43
void cross(const SLVec3 &a, const SLVec3 &b)
Definition: SLVec3.h:118
T x
Definition: SLVec3.h:43
SLVec3 & normalize()
Definition: SLVec3.h:124
T length() const
Definition: SLVec3.h:122
T z
Definition: SLVec3.h:43
static SLVec3 AXISZ
Definition: SLVec3.h:299
T lengthSqr() const
Definition: SLVec3.h:123
static SLVec4 GREEN
Definition: SLVec4.h:217
static SLVec4 WHITE
Definition: SLVec4.h:215
static SLVec4 YELLOW
Definition: SLVec4.h:219
static SLVec4 RED
Definition: SLVec4.h:216
static SLVec4 BLUE
Definition: SLVec4.h:218
static const float RAD2DEG
Definition: Utils.h:238
T mod(T a, T b)
Definition: Utils.h:250