SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLMesh.cpp
Go to the documentation of this file.
1 /**
2  * \file SLMesh.cpp
3  * \date July 2014
4  * \authors Marcus Hudritsch
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #include <SLCompactGrid.h>
11 #include <SLNode.h>
12 #include <SLRay.h>
13 #include <SLRaytracer.h>
14 #include <SLSceneView.h>
15 #include <SLSkybox.h>
16 #include <SLMesh.h>
17 #include <SLAssetManager.h>
18 #include <Profiler.h>
19 
20 using std::set;
21 
22 #ifdef __clang__
23 # pragma clang diagnostic push
24 # pragma clang diagnostic ignored "-Weverything"
25 #endif
26 
27 #include <igl/remove_duplicate_vertices.h>
28 #include <igl/per_face_normals.h>
29 #include <igl/unique_edge_map.h>
30 
31 #ifdef __clang__
32 # pragma clang diagnostic pop
33 #endif
34 
35 //-----------------------------------------------------------------------------
36 /**
37  * @brief Construct a new SLMesh::SLMesh object
38  * @details Meshes can be used in multiple nodes (SLNode). Meshes can belong
39  * therefore to the global assets such as meshes (SLMesh), materials
40  * (SLMaterial), textures (SLGLTexture) and shader programs (SLGLProgram).\n
41  * It is important that during instantiation NO OpenGL functions (gl*)
42  * get called because this constructor will be most probably called in a parallel
43  * thread from within an SLScene::registerAssetsToLoad or SLScene::assemble
44  * function. All objects that get rendered have to do their OpenGL initialization
45  * when they are used the first time during rendering in the main thread.
46  * @param assetMgr Pointer to a global asset manager. If passed the asset
47  * manager is the owner of the instance and will do the deallocation. If a
48  * nullptr is passed the creator is responsible for the deallocation.
49  * @param name Name of the mesh
50  */
51 SLMesh::SLMesh(SLAssetManager* assetMgr, const SLstring& name) : SLObject(name)
52 {
54  _mat = nullptr;
55  _matOut = nullptr;
56  _finalP = &P;
57  _finalN = &N;
58  minP.set(FLT_MAX, FLT_MAX, FLT_MAX);
59  maxP.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
60 
61  _skeleton = nullptr;
62  _isVolume = true; // is used for RT to decide inside/outside
63  _accelStruct = nullptr; // no initial acceleration structure
65  _isSelected = false;
66  _edgeAngleDEG = 30.0f;
67  _edgeWidth = 2.0f;
69  _vertexPosEpsilon = 0.001f;
70 
71  // Add this mesh to the global resource vector for deallocation
72  if (assetMgr)
73  assetMgr->meshes().push_back(this);
74 }
75 //-----------------------------------------------------------------------------
76 //! The destructor deletes everything by calling deleteData.
77 /*!
78  * The destructor should be called by the owner of the mesh. If an asset manager
79  * was passed in the constructor it will do it after scene destruction.
80  * The material (SLMaterial) that the mesh uses will not be deallocated.
81  */
83 {
84  deleteData();
85 }
86 //-----------------------------------------------------------------------------
87 //! SLMesh::deleteData deletes all mesh data and vbo's
89 {
90  P.clear();
91  N.clear();
92  C.clear();
93  T.clear();
94  UV[0].clear();
95  UV[1].clear();
96  for (auto i : Ji) i.clear();
97  Ji.clear();
98  for (auto i : Jw) i.clear();
99  Jw.clear();
100  I16.clear();
101  I32.clear();
102  IS32.clear();
103  IE16.clear();
104  IE32.clear();
105 
106  _jointMatrices.clear();
107  skinnedP.clear();
108  skinnedN.clear();
109 
110  if (_accelStruct)
111  {
112  delete _accelStruct;
113  _accelStruct = nullptr;
114  }
115 
116  _vao.deleteGL();
117  _vaoN.deleteGL();
118  _vaoT.deleteGL();
119 
120 #ifdef SL_HAS_OPTIX
121  _vertexBuffer.free();
122  _normalBuffer.free();
123  _indexShortBuffer.free();
124  _indexIntBuffer.free();
125 #endif
126 }
127 //-----------------------------------------------------------------------------
129 {
130  _vao.deleteGL();
131  _vaoN.deleteGL();
132  _vaoT.deleteGL();
133 
134 #ifdef SL_HAS_OPTIX
135  _vertexBuffer.free();
136  _normalBuffer.free();
137  _indexShortBuffer.free();
138  _indexIntBuffer.free();
139 #endif
140 }
141 //-----------------------------------------------------------------------------
142 //! Deletes the rectangle selected vertices and the dependent triangles.
143 /*! The selection rectangle is defined in SLScene::selectRect and gets set and
144  drawn in SLCamera::onMouseDown and SLCamera::onMouseMove. All vertices that
145  are within the selectRect are listed in SLMesh::IS32. The selection evaluation
146  is done during drawing in SLMesh::handleRectangleSelection and is only valid
147  for the current frame. See also SLMesh::handleRectangleSelection.*/
149 {
150  // Loop over all rectangle selected indexes in IS32
151  for (SLulong i = 0; i < IS32.size(); ++i)
152  {
153  SLulong ixDel = IS32[i] - i;
154 
155  if (ixDel < P.size()) P.erase(P.begin() + ixDel);
156  if (ixDel < N.size()) N.erase(N.begin() + ixDel);
157  if (ixDel < C.size()) C.erase(C.begin() + ixDel);
158  if (ixDel < T.size()) T.erase(T.begin() + ixDel);
159  if (ixDel < UV[0].size()) UV[0].erase(UV[0].begin() + ixDel);
160  if (ixDel < UV[1].size()) UV[1].erase(UV[1].begin() + ixDel);
161  if (ixDel < Ji.size()) Ji.erase(Ji.begin() + ixDel);
162  if (ixDel < Jw.size()) Jw.erase(Jw.begin() + ixDel);
163 
164  // Loop over all 16 bit triangles indexes
165  if (!I16.empty())
166  {
167  SLVushort i16;
168  // copy the triangle that do not contain the index to delete
169  for (SLulong t = 0; t < I16.size(); t += 3)
170  {
171  if (I16[t] != ixDel &&
172  I16[t + 1] != ixDel &&
173  I16[t + 2] != ixDel)
174  {
175  if (I16[t] < ixDel)
176  i16.push_back(I16[t]);
177  else
178  i16.push_back(I16[t] - 1);
179  if (I16[t + 1] < ixDel)
180  i16.push_back(I16[t + 1]);
181  else
182  i16.push_back(I16[t + 1] - 1);
183  if (I16[t + 2] < ixDel)
184  i16.push_back(I16[t + 2]);
185  else
186  i16.push_back(I16[t + 2] - 1);
187  }
188  }
189  I16 = i16;
190  }
191 
192  // Loop over all 32 bit triangles indexes
193  if (!I32.empty())
194  {
195  SLVuint i32;
196  // copy the triangle that do not contain the index to delete
197  for (SLulong t = 0; t < I32.size(); t += 3)
198  {
199  if (I32[t] != ixDel &&
200  I32[t + 1] != ixDel &&
201  I32[t + 2] != ixDel)
202  {
203  if (I32[t] < ixDel)
204  i32.push_back(I32[t]);
205  else
206  i32.push_back(I32[t] - 1);
207  if (I32[t + 1] < ixDel)
208  i32.push_back(I32[t + 1]);
209  else
210  i32.push_back(I32[t + 1] - 1);
211  if (I32[t + 2] < ixDel)
212  i32.push_back(I32[t + 2]);
213  else
214  i32.push_back(I32[t + 2] - 1);
215  }
216  }
217  I32 = i32;
218  }
219  }
220 
221  deleteUnused();
222 
223  calcNormals();
224 
225  // build tangents for bump mapping
226  if (mat()->needsTangents() && !UV[0].empty() && T.empty())
227  calcTangents();
228 
229  // delete vertex array object so it gets regenerated
230  _vao.clearAttribs();
231  _vaoS.deleteGL();
232  _vaoN.deleteGL();
233  _vaoT.deleteGL();
234 
235  // delete the selection indexes
236  IS32.clear();
237 
238  // flag aabb and aceleration structure to be updated
239  node->needAABBUpdate();
241 }
242 //-----------------------------------------------------------------------------
243 //! Deletes unused vertices (= vertices that are not indexed in I16 or I32)
245 {
246  // SLPoints have no indexes, so nothing to remove
247  if (I16.empty() && I32.empty())
248  return;
249 
250  // A boolean for each vertex to flag it as used or not
251  SLVbool used(P.size());
252  for (auto&& u : used)
253  u = false;
254 
255  // Loop over all indexes and mark them as used
256  for (unsigned short i : I16)
257  used[i] = true;
258 
259  for (unsigned int i : I32)
260  used[i] = true;
261 
262  SLuint unused = 0;
263  for (SLulong u = 0; u < used.size(); ++u)
264  {
265  if (!used[u])
266  {
267  unused++;
268  SLulong ixDel = u - (unused - 1);
269 
270  if (ixDel < P.size()) P.erase(P.begin() + ixDel);
271  if (ixDel < N.size()) N.erase(N.begin() + ixDel);
272  if (ixDel < C.size()) C.erase(C.begin() + ixDel);
273  if (ixDel < T.size()) T.erase(T.begin() + ixDel);
274  if (ixDel < UV[0].size()) UV[0].erase(UV[0].begin() + ixDel);
275  if (ixDel < UV[1].size()) UV[1].erase(UV[1].begin() + ixDel);
276  if (ixDel < Ji.size()) Ji.erase(Ji.begin() + ixDel);
277  if (ixDel < Jw.size()) Jw.erase(Jw.begin() + ixDel);
278 
279  // decrease the indexes smaller than the deleted on
280  for (unsigned short& i : I16)
281  {
282  if (i > ixDel)
283  i--;
284  }
285 
286  for (unsigned int& i : I32)
287  {
288  if (i > ixDel)
289  i--;
290  }
291  }
292  }
293 }
294 //-----------------------------------------------------------------------------
295 //! SLMesh::shapeInit sets the transparency flag of the AABB
296 void SLMesh::init(SLNode* node)
297 {
298  // Check data
299  SLstring msg;
300  if (P.empty())
301  msg = "No vertex positions (P)\n";
302  if (_primitive != PT_points && I16.empty() && I32.empty())
303  msg += "No vertex indices (I16 or I32)\n";
304  if (msg.length() > 0)
305  SL_EXIT_MSG((msg + "in SLMesh::init: " + _name).c_str());
306 
307  if (N.empty()) calcNormals();
308 
309  // Set default materials if no materials are assigned
310  // If colors are available use diffuse color attribute shader
311  // otherwise use the default gray material
312  if (!mat())
313  {
314  if (!C.empty())
316  else
318  }
319 
320  // build tangents for bump mapping
321  if (mat()->needsTangents() && !UV[0].empty() && T.empty())
322  calcTangents();
323 
324  _isSelected = false;
325 }
326 //-----------------------------------------------------------------------------
327 //! Simplified drawing method for shadow map creation
328 /*! This is used from within SLShadowMap::drawNodesIntoDepthBufferRec
329  */
331  SLNode* node,
332  SLMaterial* depthMat)
333 {
334  SLGLState* stateGL = SLGLState::instance();
335 
336  // Check data
337  SLstring msg;
338  if (P.empty())
339  msg = "No vertex positions (P)\n";
340 
341  if (_primitive == PT_points && I16.empty() && I32.empty())
342  msg += "No vertex indices (I16 or I32)\n";
343 
344  if (msg.length() > 0)
345  {
346  SL_WARN_MSG((msg + "in SLMesh::draw: " + _name).c_str());
347  return;
348  }
349 
350  // Return if hidden
351  if (node->levelForSM() == 0 &&
352  (node->drawBit(SL_DB_HIDDEN) || _primitive == PT_points))
353  return;
354 
355  if (!_vao.vaoID())
356  generateVAO(_vao);
357 
358  // Now use the depth material
359  SLGLProgram* sp = depthMat->program();
360  sp->useProgram();
361  sp->uniformMatrix4fv("u_mMatrix", 1, (SLfloat*)&stateGL->modelMatrix);
362  sp->uniformMatrix4fv("u_vMatrix", 1, (SLfloat*)&stateGL->viewMatrix);
363  sp->uniformMatrix4fv("u_pMatrix", 1, (SLfloat*)&stateGL->projectionMatrix);
364 
366 }
367 //-----------------------------------------------------------------------------
368 /*!
369 SLMesh::draw does the OpenGL rendering of the mesh. The GL_TRIANGLES primitives
370 are rendered normally with the vertex position vector P, the normal vector N,
371 the vector UV1 and the index vector I16 or I32. GL_LINES & GL_POINTS don't have
372 normals and tex.coords. GL_POINTS don't have indexes (I16,I32) and are rendered
373 with glDrawArrays instead glDrawElements.
374 Optionally you can draw the normals and/or the uniform grid voxels.
375 <p> The method performs the following steps:</p>
376 <p>
377 1) Apply the drawing bits<br>
378 2) Generate Vertex Array Object once<br>
379 3) Apply the uniform variables to the shader<br>
380 3a) Activate a shader program if it is not yet in use and apply all its material parameters.<br>
381 3b) Pass the standard matrices to the shader program.<br>
382 4) Finally do the draw call by calling SLGLVertexArray::drawElementsAs<br>
383 5) Draw optional normals & tangents<br>
384 6) Draw optional acceleration structure<br>
385 7) Draw selected mesh with points<br>
386 </p>
387 Please view also the full process of rendering <a href="md_on_paint.html"><b>one frame</b></a>
388 */
389 void SLMesh::draw(SLSceneView* sv, SLNode* node, SLuint instances)
390 {
391  SLGLState* stateGL = SLGLState::instance();
392 
393  // Check data
394  SLstring msg;
395  if (P.empty())
396  msg = "No vertex positions (P)\n";
397  if (_primitive != PT_points && I16.empty() && I32.empty())
398  msg += "No vertex indices (I16 or I32)\n";
399  if (msg.length() > 0)
400  {
401  SL_WARN_MSG((msg + "in SLMesh::draw: " + _name).c_str());
402  return;
403  }
404 
405  ////////////////////////
406  // 1) Apply Drawing Bits
407  ////////////////////////
408 
409  // Return if hidden
410  if (sv->drawBit(SL_DB_HIDDEN) || node->drawBit(SL_DB_HIDDEN))
411  return;
412 
413  SLGLPrimitiveType primitiveType = _primitive;
414 
415  // Set polygon mode
416  if ((sv->drawBit(SL_DB_MESHWIRED) || node->drawBit(SL_DB_MESHWIRED)) &&
417  typeid(*node) != typeid(SLSkybox))
418  {
419 #ifdef SL_GLES
420  primitiveType = PT_lineLoop; // There is no polygon line or point mode on ES2!
421 #else
422  stateGL->polygonLine(true);
423 #endif
424  }
425  else
426  stateGL->polygonLine(false);
427 
428  // Set face culling
429  bool noFaceCulling = sv->drawBit(SL_DB_CULLOFF) || node->drawBit(SL_DB_CULLOFF);
430  stateGL->cullFace(!noFaceCulling);
431 
432  // enable polygon offset if voxels are drawn to avoid stitching
433  if (sv->drawBit(SL_DB_VOXELS) || node->drawBit(SL_DB_VOXELS))
434  stateGL->polygonOffsetLine(true, -1.0f, -1.0f);
435 
436  ///////////////////////////////////////
437  // 2) Generate Vertex Array Object once
438  ///////////////////////////////////////
439 
440  if (!_vao.vaoID())
441  generateVAO(_vao);
442 
443  /////////////////////////////
444  // 3) Apply Uniform Variables
445  /////////////////////////////
446 
447  // 3.a) Apply mesh material if exists & differs from current
448  // If a material is not created so far, it will be created here
449  _mat->activate(sv->camera(),
450  &sv->s()->lights(),
451  (!Ji.empty() && !Jw.empty()));
452 
453  // 3.b) Pass the standard matrices to the shader program
454  SLGLProgram* sp = _mat->program();
455  sp->uniformMatrix4fv("u_mMatrix", 1, (SLfloat*)&stateGL->modelMatrix);
456  sp->uniformMatrix4fv("u_vMatrix", 1, (SLfloat*)&stateGL->viewMatrix);
457  sp->uniformMatrix4fv("u_pMatrix", 1, (SLfloat*)&stateGL->projectionMatrix);
458 
459  // Pass skeleton joint matrices to the shader program
460  if (!Ji.empty() && !Jw.empty())
461  {
462  // Only perform skinning in the shader if we haven't performed CPU skinning and if there are joint IDs
463  SLbool skinningEnabled = !_isCPUSkinned;
464  sp->uniform1i("u_skinningEnabled", skinningEnabled);
465 
466  if (skinningEnabled && !_jointMatrices.empty())
467  sp->uniformMatrix4fv("u_jointMatrices",
468  (SLsizei)_jointMatrices.size(),
469  (SLfloat*)&_jointMatrices[0]);
470  }
471 
472  SLint locTM = sp->getUniformLocation("u_tMatrix");
473  if (locTM >= 0)
474  {
475  if (_mat->has3DTexture() && _mat->textures3d()[0]->autoCalcTM3D())
476  calcTex3DMatrix(node);
477  else
478  stateGL->textureMatrix = _mat->textures(TT_diffuse)[0]->tm();
479  sp->uniformMatrix4fv(locTM, 1, (SLfloat*)&stateGL->textureMatrix);
480  }
481 
482  ///////////////////////////////
483  // 4): Finally do the draw call
484  ///////////////////////////////
485 
486  if ((sv->drawBit(SL_DB_ONLYEDGES) || node->drawBit(SL_DB_ONLYEDGES)) &&
487  (!IE32.empty() || !IE16.empty()))
489  else
490  {
491  if (_primitive == PT_points)
493  else
494  {
495  if (instances > 1)
496  _vao.drawElementsInstanced(primitiveType, instances);
497  else
498  _vao.drawElementsAs(primitiveType);
499 
500  if ((sv->drawBit(SL_DB_WITHEDGES) || node->drawBit(SL_DB_WITHEDGES)) &&
501  (!IE32.empty() || !IE16.empty()))
502  {
503  stateGL->polygonOffsetLine(true, 1.0f, 1.0f);
505  stateGL->polygonOffsetLine(false);
506  }
507  }
508  }
509 
510  //////////////////////////////////////
511  // 5) Draw optional normals & tangents
512  //////////////////////////////////////
513 
514  // All helper lines must be drawn without blending
515  SLbool blended = stateGL->blend();
516  if (blended) stateGL->blend(false);
517 
518  if (!N.empty() && (sv->drawBit(SL_DB_NORMALS) || node->drawBit(SL_DB_NORMALS)))
519  {
520  // Scale factor r 2% from scaled radius for normals & tangents
521  // Build array between vertex and normal target point
522  float r = node->aabb()->radiusOS() * 0.02f;
523  SLVVec3f V2;
524  V2.resize(P.size() * 2);
525  for (SLulong i = 0; i < P.size(); ++i)
526  {
527  V2[i << 1] = finalP((SLuint)i);
528  V2[(i << 1) + 1].set(finalP((SLuint)i) + finalN((SLuint)i) * r);
529  }
530 
531  // Create or update VAO for normals
533 
534  if (!T.empty())
535  {
536  for (SLulong i = 0; i < P.size(); ++i)
537  {
538  V2[(i << 1) + 1].set(finalP((SLuint)i).x + T[i].x * r,
539  finalP((SLuint)i).y + T[i].y * r,
540  finalP((SLuint)i).z + T[i].z * r);
541  }
542 
543  // Create or update VAO for tangents
545  }
546 
547  // Draw normals
549 
550  // Draw tangents if available
551  if (!T.empty())
553  if (blended)
554  stateGL->blend(false);
555  }
556  else
557  { // release buffer objects for normal & tangent rendering
558  if (_vaoN.vaoID())
559  _vaoN.deleteGL();
560  if (_vaoT.vaoID())
561  _vaoT.deleteGL();
562  }
563 
564  //////////////////////////////////////////
565  // 6) Draw optional acceleration structure
566  //////////////////////////////////////////
567 
568  if (_accelStruct)
569  {
570  if (sv->drawBit(SL_DB_VOXELS) || node->drawBit(SL_DB_VOXELS))
571  {
572  _accelStruct->draw(sv);
573  stateGL->polygonOffsetLine(false);
574  }
575  else
576  { // Delete the visualization VBO if not rendered anymore
578  }
579  }
580 
581  ////////////////////////////////////
582  // 7: Draw selected mesh with points
583  ////////////////////////////////////
584 
585  if (!node->drawBit(SL_DB_NOTSELECTABLE))
586  handleRectangleSelection(sv, stateGL, node);
587 
588  if (blended)
589  stateGL->blend(true);
590 }
591 //-----------------------------------------------------------------------------
592 //! Handles the rectangle section of mesh vertices (partial selection)
593 /*
594  There are two different selection modes: Full or partial mesh selection.
595  <br>
596  The full selection is done by double-clicking a mesh. For more information
597  see SLScene::selectNodeMesh.
598  <br>
599  Partial meshes can be selected by drawing a rectangle with CTRL-LMB. The
600  selection rectangle is defined in the SLCamera::selectRect and gets set
601  in SLCamera::onMouseDown, SLCamera::onMouseMove and SLCamera::onMouseUp.
602  The partial selection in SLMesh::handleRectangleSelection. The selected
603  vertices are stored in SLMesh::IS32. A mesh that is used in multiple nodes
604  can only be partially selected from one node.
605 */
607  SLGLState* stateGL,
608  SLNode* node)
609 {
610  SLScene* s = sv->s();
611  SLCamera* cam = sv->camera();
612 
613  // Single node and mesh is selected
614  if (cam->selectRect().isEmpty() && cam->deselectRect().isEmpty())
615  {
616  if (node->isSelected() && _isSelected)
618  }
619  else // rect selection or deselection is going on
620  {
621  // Build full viewport-modelview-projection transform matrix
622  SLMat4f mvp(stateGL->projectionMatrix * stateGL->viewMatrix * node->updateAndGetWM());
623  SLMat4f v;
624  SLRecti vp = sv->viewportRect();
625  v.viewport((SLfloat)vp.x,
626  (SLfloat)vp.y,
627  (SLfloat)vp.width,
628  (SLfloat)vp.height);
629  SLMat4f v_mvp = v * mvp;
630  set<SLuint> tempIselected; // Temp. vector for selected vertex indices
631 
632  if (!cam->selectRect().isEmpty()) // Do rectangle Selection
633  {
634  // Select by transform all vertices and add the ones in the rect to tempInRect
635  set<SLuint> tempInRect;
636  for (SLulong i = 0; i < P.size(); ++i)
637  {
638  SLVec3f p = v_mvp * P[i];
639  if (cam->selectRect().contains(SLVec2f(p.x, p.y)))
640  tempInRect.insert((SLuint)i);
641  }
642 
643  // Merge the rectangle selected by doing a set union operation
644  set<SLuint> IS32set(IS32.begin(), IS32.end());
645  std::set_union(IS32set.begin(),
646  IS32set.end(),
647  tempInRect.begin(),
648  tempInRect.end(),
649  inserter(tempIselected, tempIselected.begin()));
650  }
651  else if (!cam->deselectRect().isEmpty()) // Do rectangle Deselection
652  {
653  // Deselect by transform all vertices and add the ones in the rect to tempIdeselected
654  set<SLuint> tempIdeselected; // Temp. vector for deselected vertex indices
655  for (SLulong i = 0; i < P.size(); ++i)
656  {
657  SLVec3f p = v_mvp * P[i];
658  if (cam->deselectRect().contains(SLVec2f(p.x, p.y)))
659  tempIdeselected.insert((SLuint)i);
660  }
661 
662  // Remove the deselected ones by doing a set difference operation
663  tempIselected.clear();
664  set<SLuint> IS32set(IS32.begin(), IS32.end());
665  std::set_difference(IS32set.begin(),
666  IS32set.end(),
667  tempIdeselected.begin(),
668  tempIdeselected.end(),
669  inserter(tempIselected, tempIselected.begin()));
670  }
671 
672  // Flag node and mesh for the first time a mesh gets rectangle selected.
673  if (!tempIselected.empty() && !node->isSelected() && !_isSelected)
674  {
675  node->isSelected(true);
676  s->selectedNodes().push_back(node);
677  _isSelected = true;
678  s->selectedMeshes().push_back(this);
680  }
681 
682  // Do not rect-select if the mesh is not selected because it got
683  // selected within another node.
684  if (node->isSelected() && _isSelected)
685  {
686  if (!tempIselected.empty())
687  IS32.assign(tempIselected.begin(), tempIselected.end());
688 
689  if (!IS32.empty())
691  }
692  }
693 }
694 //-----------------------------------------------------------------------------
695 /*! Clears the partial selection but not the flag SLMesh::_isSelected
696  See also SLMesh::handleRectangleSelection.
697  */
699 {
701  IS32.clear();
702 }
703 //-----------------------------------------------------------------------------
704 /*! If the entire mesh is selected all points will be drawn with an the vertex
705  array only without indices. If a subset is selected we use the extra index
706  array IS32. See also SLMesh::handleRectangleSelection.
707  */
709 
710 {
711  SLGLState* stateGL = SLGLState::instance();
712  stateGL->polygonOffsetPoint(true);
713  stateGL->depthMask(false);
714  stateGL->depthTest(false);
715 
716  if (IS32.empty())
717  {
718  // Draw all
721  }
722  else
723  {
724  // Draw only selected
729  }
730 
731  stateGL->polygonLine(false);
732  stateGL->polygonOffsetPoint(false);
733  stateGL->depthMask(true);
734  stateGL->depthTest(true);
735 }
736 //-----------------------------------------------------------------------------
737 //! Generate the Vertex Array Object for a specific shader program
739 {
741 
743  if (!N.empty()) vao.setAttrib(AT_normal, AT_normal, _finalN);
744  if (!UV[0].empty()) vao.setAttrib(AT_uv1, AT_uv1, &UV[0]);
745  if (!UV[1].empty()) vao.setAttrib(AT_uv2, AT_uv2, &UV[1]);
746  if (!C.empty()) vao.setAttrib(AT_color, AT_color, &C);
747  if (!T.empty()) vao.setAttrib(AT_tangent, AT_tangent, &T);
748 
749  if (!I16.empty() || !I32.empty())
750  {
751  // for triangle meshes compute hard edges and store indices behind the ones of the triangles
752  if (_primitive == PT_triangles)
753  {
754  IE16.clear();
755  IE32.clear();
757  if (!I16.empty()) vao.setIndices(&I16, &IE16);
758  if (!I32.empty()) vao.setIndices(&I32, &IE32);
759  }
760  else
761  {
762  // for points there are no indices at all
763  if (!I16.empty()) vao.setIndices(&I16);
764  if (!I32.empty()) vao.setIndices(&I32);
765  }
766  }
767 
768  SLVVec4i jointIndicesData; // indices are passed to the shader as ivec4s
769  SLVVec4f jointWeightsData; // weights are passed to the shader as vec4s
770 
771  if (!Ji.empty() && !Jw.empty())
772  {
773  assert(Ji.size() == P.size());
774  assert(Jw.size() == P.size());
775 
776  jointIndicesData = SLVVec4i(P.size(), SLVec4i(0, 0, 0, 0));
777  jointWeightsData = SLVVec4f(P.size(), SLVec4f(0.0f, 0.0f, 0.0f, 0.0f));
778 
779  // create the vec4 of indices for all points
780  for (unsigned i = 0; i < P.size(); i++)
781  {
782  const SLVuchar& curIndices = Ji[i];
783  assert(!curIndices.empty());
784 
785  jointIndicesData[i] = SLVec4i(curIndices.size() >= 1 ? curIndices[0] : 0,
786  curIndices.size() >= 2 ? curIndices[1] : 0,
787  curIndices.size() >= 3 ? curIndices[2] : 0,
788  curIndices.size() >= 4 ? curIndices[3] : 0);
789  }
790 
791  // create the vec4 of weights for all points
792  for (unsigned i = 0; i < P.size(); i++)
793  {
794  const SLVfloat& curWeights = Jw[i];
795  assert(curWeights.size() == Ji[i].size());
796 
797  jointWeightsData[i] = SLVec4f(curWeights.size() >= 1 ? curWeights[0] : 0.0f,
798  curWeights.size() >= 2 ? curWeights[1] : 0.0f,
799  curWeights.size() >= 3 ? curWeights[2] : 0.0f,
800  curWeights.size() >= 4 ? curWeights[3] : 0.0f);
801  }
802  vao.setAttrib(AT_jointIndex, AT_jointIndex, &jointIndicesData);
803  vao.setAttrib(AT_jointWeight, AT_jointWeight, &jointWeightsData);
804  }
805 
806  vao.generate((SLuint)P.size(),
807  !Ji.empty() ? BU_stream : BU_static,
808  Ji.empty());
809 }
810 //-----------------------------------------------------------------------------
811 //! computes the hard edges and stores the vertex indexes separately
812 /*! Hard edges are edges between faces where there normals have an angle
813  greater than angleDEG (by default 30°). If a mesh has only smooth edges such
814  as a sphere there will be no hard edges. The indices of those hard edges are
815  stored in the vector IE16 or IE32. For rendering these indices are appended
816  behind the indices for the triangle drawing. This is because the index the
817  same vertices of the same VAO. See SLMesh::generateVAO for the details.
818  */
820  float epsilon)
821 {
822  // dihedral angle considered to sharp
823  float angleRAD = angleDEG * Utils::DEG2RAD;
824 
825  if (_primitive != PT_triangles)
826  return;
827 
828  Eigen::MatrixXf V; // Input vertices for igl
829  Eigen::MatrixXi F; // Input faces (=triangle) indices for igl
830  Eigen::MatrixXf newV; // new vertices after duplicate removal
831  Eigen::MatrixXi newF; // new face indices after duplicate removal
832  Eigen::MatrixXi edges; // all edges
833  Eigen::MatrixXi edgeMap;
834  Eigen::MatrixXi uniqueEdges;
835  Eigen::MatrixXf faceN; // face normals
836  Eigen::VectorXi SVI; // new to old index mapping
837  Eigen::VectorXi SVJ; // old to new index mapping
838 
839  vector<vector<int>> uE2E;
840 
841  // fill input matrices
842  V.resize((Eigen::Index)_finalP->size(), 3);
843  for (int i = 0; i < _finalP->size(); i++)
844  V.row(i) << finalP(i).x, finalP(i).y, finalP(i).z;
845 
846  if (!I16.empty())
847  {
848  F.resize((Eigen::Index)I16.size() / 3, 3);
849  for (int j = 0, i = 0; i < I16.size(); j++, i += 3)
850  F.row(j) << I16[i], I16[i + 1], I16[i + 2];
851  }
852  if (!I32.empty())
853  {
854  F.resize((Eigen::Index)I32.size() / 3, 3);
855  for (int j = 0, i = 0; i < I32.size(); j++, i += 3)
856  F.row(j) << (int)I32[i], (int)I32[i + 1], (int)I32[i + 2];
857  }
858 
859  // extract sharp edges
860  igl::remove_duplicate_vertices(V, F, epsilon, newV, SVI, SVJ, newF);
861  igl::per_face_normals(newV, newF, faceN);
862  igl::unique_edge_map(newF, edges, uniqueEdges, edgeMap, uE2E);
863 
864  for (int u = 0; u < uE2E.size(); u++)
865  {
866  bool sharp = false;
867  if (uE2E[u].size() == 1) // edges at the border (with only one triangle)
868  sharp = true;
869 
870  // if more than one edge is passing here, compute dihedral angles
871  for (int i = 0; i < uE2E[u].size(); i++)
872  {
873  for (int j = i + 1; j < uE2E[u].size(); j++)
874  {
875  // E[faceId + |F| * c] opposite of vertex F[faceId][c]
876  // ei = fi + |F| * c -> ei % |F| = fi % |F| = fi; fi is the face adjacent to ei
877  // ej = fj + |F| * c -> ej % |F| = fj % |F| = fj; fj is the face adjacent to ej
878  const int ei = uE2E[u][i]; // edge i
879  const int fi = ei % (int)newF.rows();
880  const int ej = uE2E[u][j]; // edge j
881  const int fj = ej % (int)newF.rows();
882  Eigen::Matrix<float, 1, 3> ni = faceN.row(fi);
883  Eigen::Matrix<float, 1, 3> nj = faceN.row(fj);
884  Eigen::Matrix<float, 1, 3> ev = (newV.row(edges(ei, 1)) - newV.row(edges(ei, 0))).normalized();
885  float dij = Utils::PI - atan2((ni.cross(nj)).dot(ev), ni.dot(nj));
886  sharp = std::abs(dij - Utils::PI) > angleRAD;
887  }
888  }
889 
890  if (sharp)
891  {
892  if (!I16.empty())
893  {
894  IE16.push_back(SVI[uniqueEdges(u, 0)]);
895  IE16.push_back(SVI[uniqueEdges(u, 1)]);
896  }
897  else if (!I32.empty())
898  {
899  IE32.push_back(SVI[uniqueEdges(u, 0)]);
900  IE32.push_back(SVI[uniqueEdges(u, 1)]);
901  }
902  }
903  }
904 }
905 //-----------------------------------------------------------------------------
906 /*!
907 SLMesh::hit does the ray-mesh intersection test. If no acceleration
908 structure is defined all triangles are tested in a brute force manner.
909 */
911 {
912  // return true for point & line objects
913  if (_primitive != PT_triangles)
914  {
915  ray->hitNode = node;
916  ray->hitMesh = this;
917  SLVec3f OC = node->aabb()->centerWS() - ray->origin;
918  ray->length = OC.length();
919  return true;
920  }
921 
922  // Force the mesh to be skinned in software even if it would be normally
923  // skinned on the GPU. We need the results from the skinning on the CPU to
924  // perform the ray-triangle intersection.
925  if (_skeleton && _mat && (!Ji.empty() && !Jw.empty()) && !_isCPUSkinned)
926  transformSkin(true, [](SLMesh*) {});
927 
928  if (_accelStruct)
929  {
932 
933  return _accelStruct->intersect(ray, node);
934  }
935  else
936  { // intersect against all faces
937  SLbool wasHit = false;
938 
939  for (SLuint t = 0; t < numI(); t += 3)
940  if (hitTriangleOS(ray, node, t) && !wasHit)
941  wasHit = true;
942 
943  return wasHit;
944  }
945 }
946 //-----------------------------------------------------------------------------
947 /*!
948 SLMesh::updateStats updates the parent node statistics.
949 */
951 {
952  stats.numBytes += sizeof(SLMesh);
953  if (!P.empty()) stats.numBytes += SL_sizeOfVector(P);
954  if (!N.empty()) stats.numBytes += SL_sizeOfVector(N);
955  if (!UV[0].empty()) stats.numBytes += SL_sizeOfVector(UV[0]);
956  if (!UV[1].empty()) stats.numBytes += SL_sizeOfVector(UV[1]);
957  if (!C.empty()) stats.numBytes += SL_sizeOfVector(C);
958  if (!T.empty()) stats.numBytes += SL_sizeOfVector(T);
959  if (!Ji.empty()) stats.numBytes += SL_sizeOfVector(Ji);
960  if (!Jw.empty()) stats.numBytes += SL_sizeOfVector(Jw);
961 
962  if (!I16.empty())
963  stats.numBytes += (SLuint)(I16.size() * sizeof(SLushort));
964  else
965  stats.numBytes += (SLuint)(I32.size() * sizeof(SLuint));
966 
967  stats.numMeshes++;
968  if (_primitive == PT_triangles) stats.numTriangles += numI() / 3;
969  if (_primitive == PT_lines) stats.numLines += numI() / 2;
970 
971  if (_accelStruct)
972  _accelStruct->updateStats(stats);
973 }
974 //-----------------------------------------------------------------------------
975 /*!
976 SLMesh::calcMinMax calculates the axis alligned minimum and maximum point
977 */
979 {
980  // init min & max points
981  minP.set(FLT_MAX, FLT_MAX, FLT_MAX);
982  maxP.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
983 
984  // calc min and max point of all vertices
985  for (SLulong i = 0; i < P.size(); ++i)
986  {
987  if (finalP((SLuint)i).x < minP.x) minP.x = finalP((SLuint)i).x;
988  if (finalP((SLuint)i).x > maxP.x) maxP.x = finalP((SLuint)i).x;
989  if (finalP((SLuint)i).y < minP.y) minP.y = finalP((SLuint)i).y;
990  if (finalP((SLuint)i).y > maxP.y) maxP.y = finalP((SLuint)i).y;
991  if (finalP((SLuint)i).z < minP.z) minP.z = finalP((SLuint)i).z;
992  if (finalP((SLuint)i).z > maxP.z) maxP.z = finalP((SLuint)i).z;
993  }
994 }
995 //-----------------------------------------------------------------------------
996 /*!
997 SLMesh::calcCenterRad calculates the center and the radius of an almost minimal
998 bounding sphere. Code by Jack Ritter from Graphic Gems.
999 */
1000 void SLMesh::calcCenterRad(SLVec3f& center, SLfloat& radius)
1001 {
1002  SLulong i;
1003  SLfloat dx, dy, dz;
1004  SLfloat radius2, xspan, yspan, zspan, maxspan;
1005  SLfloat old_to_p, old_to_p_sq, old_to_new;
1006  SLVec3f xmin, xmax, ymin, ymax, zmin, zmax, dia1, dia2;
1007 
1008  // FIRST PASS: find 6 minima/maxima points
1009  xmin.x = ymin.y = zmin.z = FLT_MAX;
1010  xmax.x = ymax.y = zmax.z = -FLT_MAX;
1011 
1012  for (i = 0; i < P.size(); ++i)
1013  {
1014  if (P[i].x < xmin.x)
1015  xmin = P[i];
1016  else if (P[i].x > xmax.x)
1017  xmax = P[i];
1018  if (P[i].y < ymin.y)
1019  ymin = P[i];
1020  else if (P[i].y > ymax.y)
1021  ymax = P[i];
1022  if (P[i].z < zmin.z)
1023  zmin = P[i];
1024  else if (P[i].z > zmax.z)
1025  zmax = P[i];
1026  }
1027 
1028  // Set xspan = distance between the 2 points xmin & xmax (squared)
1029  dx = xmax.x - xmin.x;
1030  dy = xmax.y - xmin.y;
1031  dz = xmax.z - xmin.z;
1032  xspan = dx * dx + dy * dy + dz * dz;
1033 
1034  // Same for y & z spans
1035  dx = ymax.x - ymin.x;
1036  dy = ymax.y - ymin.y;
1037  dz = ymax.z - ymin.z;
1038  yspan = dx * dx + dy * dy + dz * dz;
1039 
1040  dx = zmax.x - zmin.x;
1041  dy = zmax.y - zmin.y;
1042  dz = zmax.z - zmin.z;
1043  zspan = dx * dx + dy * dy + dz * dz;
1044 
1045  // Set points dia1 & dia2 to the maximally separated pair
1046  dia1 = xmin;
1047  dia2 = xmax; // assume xspan biggest
1048  maxspan = xspan;
1049  if (yspan > maxspan)
1050  {
1051  maxspan = yspan;
1052  dia1 = ymin;
1053  dia2 = ymax;
1054  }
1055  if (zspan > maxspan)
1056  {
1057  dia1 = zmin;
1058  dia2 = zmax;
1059  }
1060 
1061  // dia1,dia2 is a diameter of initial sphere
1062  // calc initial center
1063  center.x = (dia1.x + dia2.x) * 0.5f;
1064  center.y = (dia1.y + dia2.y) * 0.5f;
1065  center.z = (dia1.z + dia2.z) * 0.5f;
1066 
1067  // calculate initial radius*radius and radius
1068  dx = dia2.x - center.x; // x component of radius vector
1069  dy = dia2.y - center.y; // y component of radius vector
1070  dz = dia2.z - center.z; // z component of radius vector
1071  radius2 = dx * dx + dy * dy + dz * dz;
1072  radius = sqrt(radius2);
1073 
1074  // SECOND PASS: increment current sphere
1075  for (i = 0; i < P.size(); ++i)
1076  {
1077  dx = P[i].x - center.x;
1078  dy = P[i].y - center.y;
1079  dz = P[i].z - center.z;
1080  old_to_p_sq = dx * dx + dy * dy + dz * dz;
1081 
1082  if (old_to_p_sq > radius2) // do r**2 test first
1083  {
1084  // this point is outside of current sphere
1085  old_to_p = sqrt(old_to_p_sq);
1086 
1087  // calc radius of new sphere
1088  radius = (radius + old_to_p) * 0.5f;
1089  radius2 = radius * radius; // for next r**2 compare
1090  old_to_new = old_to_p - radius;
1091 
1092  // calc center of new sphere
1093  center.x = (radius * center.x + old_to_new * P[i].x) / old_to_p;
1094  center.y = (radius * center.y + old_to_new * P[i].y) / old_to_p;
1095  center.z = (radius * center.z + old_to_new * P[i].z) / old_to_p;
1096 
1097  // Suppress if desired
1098  SL_LOG("\n New sphere: center,radius = %f %f %f %f",
1099  center.x,
1100  center.y,
1101  center.z,
1102  radius);
1103  }
1104  }
1105 }
1106 //-----------------------------------------------------------------------------
1107 /*!
1108 SLMesh::buildAABB builds the passed axis-aligned bounding box in OS and updates
1109 the min & max points in WS with the passed WM of the node.
1110 */
1111 void SLMesh::buildAABB(SLAABBox& aabb, const SLMat4f& wmNode)
1112 {
1113  // Update acceleration struct and calculate min max
1114  if (_skeleton)
1115  {
1116  minP = _skeleton->minOS();
1117  maxP = _skeleton->maxOS();
1118  }
1119  else
1120  {
1121  // For now, we just update the acceleration struct for non-skinned meshes
1122  // Building the entire voxelization of a mesh every frame is not feasible
1125  }
1126  // Apply world matrix
1127  aabb.fromOStoWS(minP, maxP, wmNode);
1128 }
1129 //-----------------------------------------------------------------------------
1130 /*! SLMesh::updateAccelStruct rebuilds the acceleration structure if the dirty
1131 flag is set. This can happen for mesh animations.
1132 */
1134 {
1135  calcMinMax();
1136 
1137  // Add half a percent in each direction to avoid zero size dimensions
1138  SLVec3f distMinMax = maxP - minP;
1139  SLfloat addon = distMinMax.length() * 0.005f;
1140  minP -= addon;
1141  maxP += addon;
1142 
1143  if (_primitive != PT_triangles)
1144  return;
1145 
1146  if (_accelStruct == nullptr)
1147  _accelStruct = new SLCompactGrid(this);
1148 
1149  if (_accelStruct && numI() > 15)
1150  {
1152  _accelStructIsOutOfDate = false;
1153  }
1154 }
1155 //-----------------------------------------------------------------------------
1156 //! SLMesh::calcNormals recalculates vertex normals for triangle meshes.
1157 /*! SLMesh::calcNormals recalculates the normals only from the vertices.
1158 This algorithms doesn't know anything about smoothgroups. It just loops over
1159 the triangle of the material faces and sums up the normal for each of its
1160 vertices. Note that the face normals are not normalized. The cross product of
1161 2 vectors is proportional to the area of the triangle. Like this the normal of
1162 big triangles are more weighted than small triangles and we get a better normal
1163 quality. At the end all vertex normals are normalized.
1164 */
1166 {
1167  // Set vector for the normals & Zero out the normals vector
1168  N.clear();
1169 
1170  if (_primitive != PT_triangles)
1171  return;
1172 
1173  // Create vector and fill with zero vectors
1174  N.resize(P.size());
1175  std::fill(N.begin(), N.end(), SLVec3f::ZERO);
1176 
1177  if (!I16.empty())
1178  {
1179  // Loop over all triangles
1180  for (SLulong i = 0; i < I16.size(); i += 3)
1181  {
1182  // Calculate the face's normal
1183  SLVec3f e1, e2, n;
1184 
1185  // Calculate edges of triangle
1186  e1.sub(P[I16[i + 1]], P[I16[i + 2]]); // e1 = B - C
1187  e2.sub(P[I16[i + 1]], P[I16[i]]); // e2 = B - A
1188 
1189  // Build normal with cross product but do NOT normalize it.
1190  n.cross(e1, e2); // n = e1 x e2
1191 
1192  // Add this normal to its vertices normals
1193  N[I16[i]] += n;
1194  N[I16[i + 1]] += n;
1195  N[I16[i + 2]] += n;
1196  }
1197  }
1198  else
1199  {
1200  for (SLulong i = 0; i < I32.size(); i += 3)
1201  {
1202  // Calculate the face's normal
1203  SLVec3f e1, e2, n;
1204 
1205  // Calculate edges of triangle
1206  e1.sub(P[I32[i + 1]], P[I32[i + 2]]); // e1 = B - C
1207  e2.sub(P[I32[i + 1]], P[I32[i]]); // e2 = B - A
1208 
1209  // Build normal with cross product but do NOT normalize it.
1210  n.cross(e1, e2); // n = e1 x e2
1211 
1212  // Add this normal to its vertices normals
1213  N[I32[i]] += n;
1214  N[I32[i + 1]] += n;
1215  N[I32[i + 2]] += n;
1216  }
1217  }
1218 
1219  // normalize vertex normals
1220  for (SLulong i = 0; i < P.size(); ++i)
1221  N[i].normalize();
1222 }
1223 //-----------------------------------------------------------------------------
1224 //! SLMesh::calcTangents computes the tangents per vertex for triangle meshes.
1225 /*! SLMesh::calcTangents computes the tangent and bi-tangent per vertex used
1226 for GLSL normal map bump mapping. The code and mathematical derivation is in
1227 detail explained in: http://www.terathon.com/code/tangent.html
1228 */
1230 {
1231  if (!P.empty() &&
1232  !N.empty() && !UV[0].empty() &&
1233  (!I16.empty() || !I32.empty()))
1234  {
1235  // Delete old tangents
1236  T.clear();
1237 
1238  if (_primitive != PT_triangles)
1239  return;
1240 
1241  // allocate tangents
1242  T.resize(P.size());
1243 
1244  // allocate temp arrays for tangents
1245  SLVVec3f T1;
1246  T1.resize(P.size());
1247  fill(T1.begin(), T1.end(), SLVec3f::ZERO);
1248  SLVVec3f T2;
1249  T2.resize(P.size());
1250  fill(T2.begin(), T2.end(), SLVec3f::ZERO);
1251 
1252  SLuint iVA, iVB, iVC;
1253  SLuint numT = numI() / 3; // NO. of triangles
1254 
1255  for (SLuint t = 0; t < numT; ++t)
1256  {
1257  SLuint i = t * 3; // vertex index
1258 
1259  // Get the 3 vertex indices
1260  if (!I16.empty())
1261  {
1262  iVA = I16[i];
1263  iVB = I16[i + 1];
1264  iVC = I16[i + 2];
1265  }
1266  else
1267  {
1268  iVA = I32[i];
1269  iVB = I32[i + 1];
1270  iVC = I32[i + 2];
1271  }
1272 
1273  float x1 = P[iVB].x - P[iVA].x;
1274  float x2 = P[iVC].x - P[iVA].x;
1275  float y1 = P[iVB].y - P[iVA].y;
1276  float y2 = P[iVC].y - P[iVA].y;
1277  float z1 = P[iVB].z - P[iVA].z;
1278  float z2 = P[iVC].z - P[iVA].z;
1279 
1280  float s1 = UV[0][iVB].x - UV[0][iVA].x;
1281  float s2 = UV[0][iVC].x - UV[0][iVA].x;
1282  float t1 = UV[0][iVB].y - UV[0][iVA].y;
1283  float t2 = UV[0][iVC].y - UV[0][iVA].y;
1284 
1285  float r = 1.0F / (s1 * t2 - s2 * t1);
1286  SLVec3f sdir((t2 * x1 - t1 * x2) * r,
1287  (t2 * y1 - t1 * y2) * r,
1288  (t2 * z1 - t1 * z2) * r);
1289  SLVec3f tdir((s1 * x2 - s2 * x1) * r,
1290  (s1 * y2 - s2 * y1) * r,
1291  (s1 * z2 - s2 * z1) * r);
1292 
1293  T1[iVA] += sdir;
1294  T1[iVB] += sdir;
1295  T1[iVC] += sdir;
1296 
1297  T2[iVA] += tdir;
1298  T2[iVB] += tdir;
1299  T2[iVC] += tdir;
1300  }
1301 
1302  for (SLulong i = 0; i < P.size(); ++i)
1303  {
1304  // Gram-Schmidt orthogonalization
1305  T[i] = T1[i] - N[i] * N[i].dot(T1[i]);
1306  T[i].normalize();
1307 
1308  // Calculate temp. bi-tangent and store its handedness in T.w
1309  SLVec3f bitangent;
1310  bitangent.cross(N[i], T1[i]);
1311  T[i].w = (bitangent.dot(T2[i]) < 0.0f) ? -1.0f : 1.0f;
1312  }
1313  }
1314 }
1315 //-----------------------------------------------------------------------------
1316 /* Calculate the texture matrix for 3D texture mapping from the AABB so that
1317 the texture volume surrounds the AABB centrally.
1318 */
1320 {
1321  SLVec3f max = node->aabb()->maxOS();
1322  SLVec3f ctr = node->aabb()->centerOS();
1323  SLVec3f ext = max - ctr;
1324 
1325  // determine the scale factor s from the max. AABB extension
1326  SLint dim;
1327  SLfloat maxExt = ext.maxXYZ(dim);
1328  SLfloat s = 1.0f / (2.0f * maxExt);
1329 
1330  // scale and translate the texture matrix
1331  SLGLState* stateGL = SLGLState::instance();
1332  stateGL->textureMatrix.identity();
1333  stateGL->textureMatrix.scale(s);
1334  stateGL->textureMatrix.translate(-ctr);
1335  stateGL->textureMatrix.translate(-ext.comp[dim],
1336  -ext.comp[dim],
1337  -ext.comp[dim]);
1338 }
1339 //-----------------------------------------------------------------------------
1340 /*!
1341 SLMesh::hitTriangleOS is the fast and minimum storage ray-triangle
1342 intersection test by Tomas Moeller and Ben Trumbore (Journal of graphics
1343 tools 2, 1997).
1344 */
1346 {
1347  assert(ray && "ray pointer is null");
1348  assert(node && "node pointer is null");
1349  assert(_mat && "material pointer is null");
1350 
1351  ++SLRay::tests;
1352 
1353  if (_primitive != PT_triangles)
1354  return false;
1355 
1356  // prevent self-intersection of triangle
1357  if (ray->srcMesh == this && ray->srcTriangle == (SLint)iT)
1358  return false;
1359 
1360  SLVec3f cornerA, cornerB, cornerC;
1361  SLVec3f e1, e2; // edge 1 and 2
1362  SLVec3f AO, K, Q;
1363 
1364  // get the corner vertices
1365  if (!I16.empty())
1366  {
1367  cornerA = finalP(I16[iT]);
1368  cornerB = finalP(I16[iT + 1]);
1369  cornerC = finalP(I16[iT + 2]);
1370  }
1371  else
1372  {
1373  cornerA = finalP(I32[iT]);
1374  cornerB = finalP(I32[iT + 1]);
1375  cornerC = finalP(I32[iT + 2]);
1376  }
1377 
1378  // find vectors for two edges sharing the triangle vertex A
1379  e1.sub(cornerB, cornerA);
1380  e2.sub(cornerC, cornerA);
1381 
1382  // begin calculating determinant - also used to calculate U parameter
1383  K.cross(ray->dirOS, e2);
1384 
1385  // if determinant is near zero, ray lies in plane of triangle
1386  const SLfloat det = e1.dot(K);
1387 
1388  SLfloat inv_det, t, u, v;
1389 
1390  // if ray is outside do test with face culling
1391  if (ray->isOutside && _isVolume)
1392  { // check only front side triangles
1393 
1394  // exit if ray is from behind or parallel
1395  if (det < FLT_EPSILON) return false;
1396 
1397  // calculate distance from corner A to ray origin
1398  AO.sub(ray->originOS, cornerA);
1399 
1400  // Calculate barycentric coordinates: u>0 && v>0 && u+v<=1
1401  u = AO.dot(K);
1402  if (u < 0.0f || u > det) return false;
1403 
1404  // prepare to test v parameter
1405  Q.cross(AO, e1);
1406 
1407  // calculate v parameter and test bounds
1408  v = Q.dot(ray->dirOS);
1409  if (v < 0.0f || u + v > det) return false;
1410 
1411  // calculate intersection distance t
1412  inv_det = 1.0f / det;
1413  t = e2.dot(Q) * inv_det;
1414 
1415  // if intersection is closer replace ray intersection parameters
1416  if (t > ray->length || t < 0.0f) return false;
1417 
1418  ray->length = t;
1419 
1420  // scale down u & v so that u+v<=1
1421  ray->hitU = u * inv_det;
1422  ray->hitV = v * inv_det;
1423  }
1424  else
1425  { // check front & backside triangles
1426  // exit if ray is parallel
1427  if (det < FLT_EPSILON && det > -FLT_EPSILON) return false;
1428 
1429  inv_det = 1.0f / det;
1430 
1431  // calculate distance from corner A to ray origin
1432  AO.sub(ray->originOS, cornerA);
1433 
1434  // Calculate barycentric coordinates: u>0 && v>0 && u+v<=1
1435  u = AO.dot(K) * inv_det;
1436  if (u < 0.0f || u > 1.0f) return false;
1437 
1438  // prepare to test v parameter
1439  Q.cross(AO, e1);
1440 
1441  // calculate v parameter and test bounds
1442  v = Q.dot(ray->dirOS) * inv_det;
1443  if (v < 0.0f || u + v > 1.0f) return false;
1444 
1445  // calculate t, ray intersects triangle
1446  t = e2.dot(Q) * inv_det;
1447 
1448  // if intersection is closer replace ray intersection parameters
1449  if (t > ray->length || t < 0.0f) return false;
1450 
1451  ray->length = t;
1452  ray->hitU = u;
1453  ray->hitV = v;
1454  }
1455 
1456  ray->hitTriangle = (SLint)iT;
1457  ray->hitNode = node;
1458  ray->hitMesh = this;
1459 
1461 
1462  return true;
1463 }
1464 //-----------------------------------------------------------------------------
1465 /*!
1466 SLMesh::preShade calculates the rest of the intersection information
1467 after the final hit point is determined. Should be called just before the
1468 shading when the final intersection point of the closest triangle was found.
1469 */
1471 {
1472  if (_primitive != PT_triangles)
1473  return;
1474 
1475  // Get the triangle indices
1476  SLuint iA, iB, iC;
1477  if (!I16.empty())
1478  {
1479  iA = I16[(SLushort)ray->hitTriangle];
1480  iB = I16[(SLushort)ray->hitTriangle + 1];
1481  iC = I16[(SLushort)ray->hitTriangle + 2];
1482  }
1483  else
1484  {
1485  iA = I32[(SLuint)ray->hitTriangle];
1486  iB = I32[(SLuint)ray->hitTriangle + 1];
1487  iC = I32[(SLuint)ray->hitTriangle + 2];
1488  }
1489 
1490  // calculate the hit point in world space
1491  ray->hitPoint.set(ray->origin + ray->length * ray->dir);
1492 
1493  // calculate the interpolated normal with vertex normals in object space
1494  ray->hitNormal.set(finalN(iA) * (1 - (ray->hitU + ray->hitV)) +
1495  finalN(iB) * ray->hitU +
1496  finalN(iC) * ray->hitV);
1497 
1498  // transform normal back to world space
1499  SLMat3f wmN(ray->hitNode->updateAndGetWM().mat3());
1500  ray->hitNormal.set(wmN * ray->hitNormal);
1501 
1502  // for shading the normal is expected to be unit length
1503  ray->hitNormal.normalize();
1504 
1505  // calculate interpolated texture coordinates
1506  SLVGLTexture& diffuseTex = ray->hitMesh->mat()->textures(TT_diffuse);
1507 
1508  if (!diffuseTex.empty() &&
1509  !diffuseTex[0]->images().empty() &&
1510  !UV[0].empty())
1511  {
1512  SLVec2f Tu(UV[0][iB] - UV[0][iA]);
1513  SLVec2f Tv(UV[0][iC] - UV[0][iA]);
1514  SLVec2f tc(UV[0][iA] + ray->hitU * Tu + ray->hitV * Tv);
1515  ray->hitTexColor.set(diffuseTex[0]->getTexelf(tc.x, tc.y));
1516 
1517  // bump mapping
1518  SLVGLTexture& bumpTex = ray->hitMesh->mat()->textures(TT_normal);
1519  if (!bumpTex.empty() && !bumpTex[0]->images().empty())
1520  {
1521  if (!T.empty())
1522  {
1523  // calculate the interpolated tangent with vertex tangent in object space
1524  SLVec4f hitT(T[iA] * (1 - (ray->hitU + ray->hitV)) +
1525  T[iB] * ray->hitU +
1526  T[iC] * ray->hitV);
1527 
1528  SLVec3f T3(hitT.x, hitT.y, hitT.z); // tangent with 3 components
1529  T3.set(wmN * T3); // transform tangent back to world space
1530  SLVec2f d = bumpTex[0]->dudv(tc.x, tc.y); // slope of bump-map at tc
1531  SLVec3f Nrm = ray->hitNormal; // unperturbated normal
1532  SLVec3f B(Nrm ^ T3); // bi-normal tangent B
1533  B *= T[iA].w; // correct handedness
1534  SLVec3f D(d.x * T3 + d.y * B); // perturbation vector D
1535  Nrm += D;
1536  Nrm.normalize();
1537  ray->hitNormal.set(Nrm);
1538  }
1539  }
1540 
1541  // Get ambient occlusion
1542  SLVGLTexture& aoTex = ray->hitMesh->mat()->textures(TT_occlusion);
1543  if (!UV[1].empty())
1544  {
1545  SLVec2f Tu2(UV[1][iB] - UV[1][iA]);
1546  SLVec2f Tv2(UV[1][iC] - UV[1][iA]);
1547  SLVec2f tc2(UV[1][iA] + ray->hitU * Tu2 + ray->hitV * Tv2);
1548 
1549  if (!aoTex.empty())
1550  ray->hitAO = aoTex[0]->getTexelf(tc2.x, tc2.y).r;
1551  }
1552  }
1553 
1554  // calculate interpolated color for meshes with color attributes
1555  if (!ray->hitMesh->C.empty())
1556  {
1557  SLCol4f CA = ray->hitMesh->C[iA];
1558  SLCol4f CB = ray->hitMesh->C[iB];
1559  SLCol4f CC = ray->hitMesh->C[iC];
1560  ray->hitTexColor.set(CA * (1 - (ray->hitU + ray->hitV)) +
1561  CB * ray->hitU +
1562  CC * ray->hitV);
1563  }
1564 }
1565 //-----------------------------------------------------------------------------
1566 //! Transforms the vertex positions and normals with by joint weights
1567 /*! If the mesh is used for skinned skeleton animation this method transforms
1568 each vertex and normal by max. four joints of the skeleton. Each joint has
1569 a weight and an index. After the transform the VBO have to be updated.
1570 This skinning process can also be done (a lot faster) on the GPU.
1571 This software skinning is also needed for ray or path tracing.
1572 */
1573 void SLMesh::transformSkin(bool forceCPUSkinning,
1574  const std::function<void(SLMesh*)>& cbInformNodes)
1575 {
1576  if (_isSelected)
1577  forceCPUSkinning = true;
1578 
1579  // create the secondary buffers for P and N once
1580  if (skinnedP.empty())
1581  {
1582  skinnedP.resize(P.size());
1583  for (SLulong i = 0; i < P.size(); ++i)
1584  skinnedP[i] = P[i];
1585  }
1586  if (skinnedN.empty() && !N.empty())
1587  {
1588  skinnedN.resize(P.size());
1589  for (SLulong i = 0; i < P.size(); ++i)
1590  skinnedN[i] = N[i];
1591  }
1592 
1593  // Create array for joint matrices once
1594  if (_jointMatrices.empty())
1595  {
1596  _jointMatrices.clear();
1598  }
1599 
1600  // update the joint matrix array
1602 
1603  // notify parent nodes to update AABB
1604  cbInformNodes(this);
1605 
1606  // flag acceleration structure to be rebuilt
1607  _accelStructIsOutOfDate = true;
1608 
1609  // remember if this node has been skinned on the CPU
1610  _isCPUSkinned = forceCPUSkinning;
1611 
1612  // Perform software skinning if the material doesn't support CPU skinning or
1613  // if the results of the skinning process are required somewhere else.
1614  if (forceCPUSkinning)
1615  {
1616  _finalP = &skinnedP;
1617  _finalN = &skinnedN;
1618 
1619  // iterate over all vertices and write to new buffers
1620  for (SLulong i = 0; i < P.size(); ++i)
1621  {
1622  skinnedP[i] = SLVec3f::ZERO;
1623  if (!N.empty()) skinnedN[i] = SLVec3f::ZERO;
1624 
1625  // accumulate final normal and positions
1626  for (SLulong j = 0; j < Ji[i].size(); ++j)
1627  {
1628  const SLMat4f& jm = _jointMatrices[Ji[i][j]];
1629  SLVec4f tempPos = SLVec4f(jm * P[i]);
1630  skinnedP[i].x += tempPos.x * Jw[i][j];
1631  skinnedP[i].y += tempPos.y * Jw[i][j];
1632  skinnedP[i].z += tempPos.z * Jw[i][j];
1633 
1634  if (!N.empty())
1635  {
1636  // Build the 3x3 submatrix in GLSL 110 (= mat3 jt3 = mat3(jt))
1637  // for the normal transform that is the normally the inverse transpose.
1638  // The inverse transpose can be ignored as long as we only have
1639  // rotation and uniform scaling in the 3x3 submatrix.
1640  SLMat3f jnm = jm.mat3();
1641  skinnedN[i] += jnm * N[i] * Jw[i][j];
1642  }
1643  }
1644  }
1645  }
1646  else
1647  {
1648  _finalP = &P;
1649  _finalN = &N;
1650  }
1651 
1652  // update or create buffers
1653  if (_vao.vaoID())
1654  {
1656  if (!N.empty()) _vao.updateAttrib(AT_normal, _finalN);
1657  }
1658 }
1659 //-----------------------------------------------------------------------------
1660 #ifdef SL_HAS_OPTIX
1661 unsigned int SLMesh::meshIndex = 0;
1662 //-----------------------------------------------------------------------------
1663 void SLMesh::allocAndUploadData()
1664 {
1665  _vertexBuffer.alloc_and_upload(P);
1666 
1667  _normalBuffer.alloc_and_upload(N);
1668 
1669  if (!UV[0].empty())
1670  _textureBuffer.alloc_and_upload(UV[0]);
1671 
1672  if (!UV[1].empty())
1673  _textureBuffer.alloc_and_upload(UV[1]);
1674 
1675  if (!I16.empty())
1676  _indexShortBuffer.alloc_and_upload(I16);
1677  else
1678  _indexIntBuffer.alloc_and_upload(I32);
1679 }
1680 //-----------------------------------------------------------------------------
1681 void SLMesh::uploadData()
1682 {
1683  _vertexBuffer.upload(*_finalP);
1684  _normalBuffer.upload(*_finalN);
1685 }
1686 //-----------------------------------------------------------------------------
1687 void SLMesh::createMeshAccelerationStructure()
1688 {
1689  if (!_vertexBuffer.isAllocated())
1690  {
1691  allocAndUploadData();
1692  }
1693 
1694  // Build triangle GAS
1695  uint32_t _buildInput_flags[1] = {OPTIX_GEOMETRY_FLAG_NONE};
1696 
1697  _buildInput.type = OPTIX_BUILD_INPUT_TYPE_TRIANGLES;
1698  if (!I16.empty())
1699  {
1700  _buildInput.triangleArray.indexFormat = OPTIX_INDICES_FORMAT_UNSIGNED_SHORT3;
1701  _buildInput.triangleArray.numIndexTriplets = (SLuint)(I16.size() / 3);
1702  _buildInput.triangleArray.indexBuffer = _indexShortBuffer.devicePointer();
1703  }
1704  else
1705  {
1706  _buildInput.triangleArray.indexFormat = OPTIX_INDICES_FORMAT_UNSIGNED_INT3;
1707  _buildInput.triangleArray.numIndexTriplets = (SLuint)(I32.size() / 3);
1708  _buildInput.triangleArray.indexBuffer = _indexIntBuffer.devicePointer();
1709  }
1710  _buildInput.triangleArray.vertexFormat = OPTIX_VERTEX_FORMAT_FLOAT3;
1711  _buildInput.triangleArray.vertexBuffers = _vertexBuffer.devicePointerPointer();
1712  _buildInput.triangleArray.numVertices = (SLuint)P.size();
1713  _buildInput.triangleArray.flags = _buildInput_flags;
1714  _buildInput.triangleArray.numSbtRecords = 1;
1715  _buildInput.triangleArray.sbtIndexOffsetBuffer = 0;
1716  _buildInput.triangleArray.sbtIndexOffsetSizeInBytes = 0;
1717  _buildInput.triangleArray.sbtIndexOffsetStrideInBytes = 0;
1718 
1719  _sbtIndex = RAY_TYPE_COUNT * meshIndex++;
1720 
1721  buildAccelerationStructure();
1722 }
1723 //-----------------------------------------------------------------------------
1724 void SLMesh::updateMeshAccelerationStructure()
1725 {
1727  return;
1728 
1729  uploadData();
1730 
1731  // Build triangle GAS
1732  uint32_t _buildInput_flags[1] = {OPTIX_GEOMETRY_FLAG_NONE};
1733  _buildInput.triangleArray.flags = _buildInput_flags;
1734 
1735  updateAccelerationStructure();
1736 }
1737 //-----------------------------------------------------------------------------
1738 ortHitData SLMesh::createHitData()
1739 {
1740  ortHitData hitData = {};
1741 
1742  hitData.sbtIndex = 0;
1743  hitData.normals = reinterpret_cast<float3*>(_normalBuffer.devicePointer());
1744  hitData.indices = reinterpret_cast<short3*>(_indexShortBuffer.devicePointer());
1745  hitData.texCords = reinterpret_cast<float2*>(_textureBuffer.devicePointer());
1746  if (mat()->numTextures())
1747  {
1748  hitData.textureObject = mat()->textures(TT_diffuse)[0]->getCudaTextureObject();
1749  }
1750  hitData.material.kn = mat()->kn();
1751  hitData.material.kt = mat()->kt();
1752  hitData.material.kr = mat()->kr();
1753  hitData.material.shininess = mat()->shininess();
1754  hitData.material.ambient_color = make_float4(mat()->ambient());
1755  hitData.material.specular_color = make_float4(mat()->specular());
1756  hitData.material.transmissiv_color = make_float4(mat()->transmissive());
1757  hitData.material.diffuse_color = make_float4(mat()->diffuse());
1758  hitData.material.emissive_color = make_float4(mat()->emissive());
1759 
1760  return hitData;
1761 }
1762 #endif
1763 //-----------------------------------------------------------------------------
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
float SLfloat
Definition: SL.h:173
#define SL_LOG(...)
Definition: SL.h:233
unsigned long SLulong
Definition: SL.h:165
unsigned int SLuint
Definition: SL.h:171
#define SL_WARN_MSG(message)
Definition: SL.h:241
vector< SLuchar > SLVuchar
Definition: SL.h:193
bool SLbool
Definition: SL.h:175
unsigned short SLushort
Definition: SL.h:169
vector< SLfloat > SLVfloat
Definition: SL.h:200
vector< SLbool > SLVbool
Definition: SL.h:189
#define SL_EXIT_MSG(message)
Definition: SL.h:240
vector< SLushort > SLVushort
Definition: SL.h:195
int SLsizei
Definition: SL.h:172
SLuint SL_sizeOfVector(const T &vector)
Definition: SL.h:217
vector< SLuint > SLVuint
Definition: SL.h:197
string SLstring
Definition: SL.h:158
int SLint
Definition: SL.h:170
#define SL_DB_ONLYEDGES
Draw only hard edges.
Definition: SLDrawBits.h:31
#define SL_DB_NORMALS
Draw the vertex normals.
Definition: SLDrawBits.h:23
#define SL_DB_WITHEDGES
Draw faces with hard edges.
Definition: SLDrawBits.h:30
#define SL_DB_NOTSELECTABLE
Flags an object as selected.
Definition: SLDrawBits.h:21
#define SL_DB_VOXELS
Draw the voxels of the uniform grid.
Definition: SLDrawBits.h:26
#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_HIDDEN
Flags an object as hidden.
Definition: SLDrawBits.h:20
@ AT_jointWeight
Vertex joint weight for vertex skinning.
Definition: SLGLEnums.h:65
@ AT_jointIndex
Vertex joint id for vertex skinning.
Definition: SLGLEnums.h:64
@ AT_position
Vertex position as a 2, 3 or 4 component vectors.
Definition: SLGLEnums.h:58
@ AT_normal
Vertex normal as a 3 component vector.
Definition: SLGLEnums.h:59
@ AT_color
Vertex color as 3 or 4 component vector.
Definition: SLGLEnums.h:62
@ AT_uv1
Vertex 1st texture coordinate as 2 component vector.
Definition: SLGLEnums.h:60
@ AT_uv2
Vertex 2nd texture coordinate as 2 component vector.
Definition: SLGLEnums.h:61
@ AT_tangent
Vertex tangent as a 4 component vector (see SLMesh)
Definition: SLGLEnums.h:63
SLGLPrimitiveType
Definition: SLGLEnums.h:30
@ PT_points
Definition: SLGLEnums.h:31
@ PT_lines
Definition: SLGLEnums.h:32
@ PT_triangles
Definition: SLGLEnums.h:35
@ PT_lineLoop
Definition: SLGLEnums.h:33
@ BU_stream
Buffer will be modified once and used at most a few times.
Definition: SLGLEnums.h:92
@ BU_static
Buffer will be modified once and used many times.
Definition: SLGLEnums.h:91
@ TT_normal
Definition: SLGLTexture.h:79
@ TT_diffuse
Definition: SLGLTexture.h:78
@ TT_occlusion
Definition: SLGLTexture.h:83
vector< SLGLTexture * > SLVGLTexture
STL vector of SLGLTexture pointers.
Definition: SLGLTexture.h:342
vector< SLVec3f > SLVVec3f
Definition: SLVec3.h:325
vector< SLVec4f > SLVVec4f
Definition: SLVec4.h:239
vector< SLVec4i > SLVVec4i
Definition: SLVec4.h:240
SLVec4< SLint > SLVec4i
Definition: SLVec4.h:236
SLVec4< SLfloat > SLVec4f
Definition: SLVec4.h:235
Defines an axis aligned bounding box.
Definition: SLAABBox.h:34
SLVec3f centerWS()
Definition: SLAABBox.h:50
void fromOStoWS(const SLVec3f &minOS, const SLVec3f &maxOS, const SLMat4f &wm)
Recalculate min and max after transformation in world coords.
Definition: SLAABBox.cpp:46
SLfloat radiusOS()
Definition: SLAABBox.h:55
void maxOS(const SLVec3f &maxC)
Definition: SLAABBox.h:42
SLVec3f centerOS()
Definition: SLAABBox.h:54
virtual void updateStats(SLNodeStats &stats)=0
virtual void build(SLVec3f minV, SLVec3f maxV)=0
virtual void draw(SLSceneView *sv)=0
virtual SLbool intersect(SLRay *ray, SLNode *node)=0
virtual void disposeBuffers()=0
SLint numJoints() const
const SLVec3f & maxOS()
void getJointMatrices(SLVMat4f &jointWM)
const SLVec3f & minOS()
Toplevel holder of the assets meshes, materials, textures and shaders.
SLVMesh & meshes()
Active or visible camera node class.
Definition: SLCamera.h:54
SLRectf & deselectRect()
Definition: SLCamera.h:172
SLRectf & selectRect()
Definition: SLCamera.h:171
Class for compact uniform grid acceleration structure.
Definition: SLCompactGrid.h:30
Encapsulation of an OpenGL shader program object.
Definition: SLGLProgram.h:56
SLint uniformMatrix4fv(const SLchar *name, SLsizei count, const SLfloat *value, GLboolean transpose=false) const
Passes a 4x4 float matrix values py pointer to the uniform variable "name".
SLint getUniformLocation(const SLchar *name) const
void useProgram()
SLint uniform1i(const SLchar *name, SLint v0) const
Passes the int values v0 to the uniform variable "name".
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
SLMat4f textureMatrix
matrix for the texture transform
Definition: SLGLState.h:92
SLMat4f modelMatrix
Init all states.
Definition: SLGLState.h:89
void polygonOffsetPoint(SLbool enabled, SLfloat factor=-1.0f, SLfloat units=-1.0f)
Definition: SLGLState.cpp:311
void depthMask(SLbool state)
Definition: SLGLState.cpp:190
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
void polygonOffsetLine(SLbool enabled, SLfloat factor=-1.0f, SLfloat units=-1.0f)
Definition: SLGLState.cpp:335
SLMat4f viewMatrix
matrix for the active cameras view transform
Definition: SLGLState.h:91
void blend(SLbool state)
Definition: SLGLState.cpp:236
SLMat4f projectionMatrix
matrix for projection transform
Definition: SLGLState.h:90
void polygonLine(SLbool state)
Definition: SLGLState.cpp:290
void cullFace(SLbool state)
Definition: SLGLState.cpp:219
void depthTest(SLbool state)
Definition: SLGLState.cpp:172
void generateVertexPos(SLVVec2f *p)
Adds or updates & generates a position vertex attribute for colored line or point drawing.
void drawElementAsColored(SLGLPrimitiveType primitiveType, SLCol4f color, SLfloat pointSize, SLuint indexFirstVertex=0, SLuint countVertices=0)
Draws the VAO by element indices with the specified primitive with the color.
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.
SLGLVertexArray encapsulates the core OpenGL drawing.
void clearAttribs()
Clears the attribute definition.
void updateAttrib(SLGLAttributeType type, SLint elementSize, void *dataPointer)
Updates a specific vertex attribute in the VBO.
void drawElementsAs(SLGLPrimitiveType primitiveType, SLuint numIndexes=0, SLuint indexOffsetBytes=0)
Draws the VAO by element indices with a primitive type.
void setAttrib(SLGLAttributeType type, SLint elementSize, SLint location, void *dataPointer, SLGLBufferType dataType=BT_float)
Adds a vertex attribute with data pointer and an element size.
void drawArrayAs(SLGLPrimitiveType primitiveType, SLint firstVertex=0, SLsizei countVertices=0)
Draws the VAO as an array with a primitive type.
void drawElementsInstanced(SLGLPrimitiveType primitiveType, SLuint countInstance=0, SLuint numIndexes=0, SLuint indexOffset=0)
Draws the VAO as an array with instance primitive type.
SLuint vaoID() const
Returns either the VAO id or the VBO id.
void setIndices(SLuint numIndicesElements, SLGLBufferType indexDataType, void *indexDataElements, SLuint numIndicesEdges=0, void *indexDataEdges=nullptr)
Adds the index array for indexed element drawing.
void generate(SLuint numVertices, SLGLBufferUsage usage=BU_static, SLbool outputInterleaved=true, SLuint divisor=0)
Generates the VA & VB objects for a NO. of vertices.
void drawEdges(SLCol4f color, SLfloat lineWidth=1.0f)
Draws the hard edges of the VAO with the edge indices.
void deleteGL()
Deletes all vertex array & vertex buffer objects.
void scale(T sxyz)
Definition: SLMat4.h:667
SLMat3< T > mat3() const
Definition: SLMat4.h:98
void identity()
Sets the identity matrix.
Definition: SLMat4.h:1333
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
void viewport(T x, T y, T ww, T wh, T n=0.0f, T f=1.0f)
Defines the viewport matrix.
Definition: SLMat4.h:930
static SLMaterialDefaultColorAttribute * instance()
Definition: SLMaterial.h:315
static SLMaterialDefaultGray * instance()
Definition: SLMaterial.h:286
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
SLbool has3DTexture()
Returns true if a material has a 3D texture.
Definition: SLMaterial.h:139
SLuint numTextures()
Definition: SLMaterial.h:226
void activate(SLCamera *cam, SLVLight *lights, SLbool supportGPUSkinning)
Definition: SLMaterial.cpp:507
void kt(SLfloat kt)
Definition: SLMaterial.h:190
void shininess(SLfloat shin)
Definition: SLMaterial.h:177
SLVGLTexture & textures(SLTextureType type)
Definition: SLMaterial.h:233
SLVGLTexture & textures3d()
Definition: SLMaterial.h:234
void kr(SLfloat kr)
Definition: SLMaterial.h:184
void kn(SLfloat kn)
Definition: SLMaterial.h:199
void program(SLGLProgram *sp)
Definition: SLMaterial.h:205
An SLMesh object is a triangulated mesh, drawn with one draw call.
Definition: SLMesh.h:134
SLMesh(SLAssetManager *assetMgr, const SLstring &name="Mesh")
Construct a new SLMesh::SLMesh object.
Definition: SLMesh.cpp:51
SLVec3f maxP
max. vertex in OS
Definition: SLMesh.h:221
void handleRectangleSelection(SLSceneView *sv, SLGLState *stateGL, SLNode *node)
Handles the rectangle section of mesh vertices (partial selection)
Definition: SLMesh.cpp:606
void updateAccelStruct()
Definition: SLMesh.cpp:1133
SLVuint IS32
Vector of rectangle selected vertex indices 32 bit.
Definition: SLMesh.h:216
SLVuint I32
Vector of vertex indices 32 bit.
Definition: SLMesh.h:215
SLVushort I16
Vector of vertex indices 16 bit.
Definition: SLMesh.h:214
SLVec3f finalP(SLuint i)
Definition: SLMesh.h:187
virtual void calcNormals()
SLMesh::calcNormals recalculates vertex normals for triangle meshes.
Definition: SLMesh.cpp:1165
void deselectPartialSelection()
Definition: SLMesh.cpp:698
SLbool _isVolume
Flag for RT if mesh is a closed volume.
Definition: SLMesh.h:253
SLGLVertexArrayExt _vaoT
OpenGL VAO for optional tangent drawing.
Definition: SLMesh.h:236
SLVVec4f T
Vector of vertex tangents (opt.) layout (location = 5)
Definition: SLMesh.h:207
void transformSkin(bool forceCPUSkinning, const std::function< void(SLMesh *)> &cbInformNodes)
Transforms the vertex positions and normals with by joint weights.
Definition: SLMesh.cpp:1573
virtual void calcMinMax()
Definition: SLMesh.cpp:978
SLVuint IE32
Vector of hard edges vertex indices 32 bit (see computeHardEdgesIndices)
Definition: SLMesh.h:218
SLfloat _edgeAngleDEG
Edge crease angle in degrees between face normals (30 deg. default)
Definition: SLMesh.h:239
virtual void init(SLNode *node)
SLMesh::shapeInit sets the transparency flag of the AABB.
Definition: SLMesh.cpp:296
virtual void draw(SLSceneView *sv, SLNode *node, SLuint intances=0)
Definition: SLMesh.cpp:389
void calcCenterRad(SLVec3f &center, SLfloat &radius)
Definition: SLMesh.cpp:1000
SLbool hit(SLRay *ray, SLNode *node)
Definition: SLMesh.cpp:910
SLbool _isSelected
Flag if mesh is partially of fully selected.
Definition: SLMesh.h:238
SLfloat _vertexPosEpsilon
Vertex position epsilon used in computeHardEdgesIndices.
Definition: SLMesh.h:242
SLVCol4f C
Vector of vertex colors (opt.) layout (location = 4)
Definition: SLMesh.h:206
SLVVec3f skinnedN
temp. vector for CPU skinned vertex normals
Definition: SLMesh.h:211
void computeHardEdgesIndices(float angleRAD, float epsilon)
computes the hard edges and stores the vertex indexes separately
Definition: SLMesh.cpp:819
void deleteSelected(SLNode *node)
Deletes the rectangle selected vertices and the dependent triangles.
Definition: SLMesh.cpp:148
void drawSelectedVertices()
Definition: SLMesh.cpp:708
virtual void deleteDataGpu()
Definition: SLMesh.cpp:128
void addStats(SLNodeStats &stats)
Definition: SLMesh.cpp:950
SLVushort IE16
Vector of hard edges vertex indices 16 bit (see computeHardEdgesIndices)
Definition: SLMesh.h:217
SLGLPrimitiveType _primitive
Primitive type (default triangles)
Definition: SLMesh.h:231
virtual void generateVAO(SLGLVertexArray &vao)
Generate the Vertex Array Object for a specific shader program.
Definition: SLMesh.cpp:738
SLVVec3f * _finalN
pointer to final vertex normal vector
Definition: SLMesh.h:260
static void calcTex3DMatrix(SLNode *node)
Definition: SLMesh.cpp:1319
SLfloat _edgeWidth
Line width for hard edge drawing.
Definition: SLMesh.h:240
SLGLVertexArrayExt _vaoN
OpenGL VAO for optional normal drawing.
Definition: SLMesh.h:235
SLAnimSkeleton * _skeleton
The skeleton this mesh is bound to.
Definition: SLMesh.h:256
SLVVec3f N
Vector for vertex normals (opt.) layout (location = 1)
Definition: SLMesh.h:204
SLVec3f minP
min. vertex in OS
Definition: SLMesh.h:220
virtual void deleteData()
SLMesh::deleteData deletes all mesh data and vbo's.
Definition: SLMesh.cpp:88
void calcTangents()
SLMesh::calcTangents computes the tangents per vertex for triangle meshes.
Definition: SLMesh.cpp:1229
SLVVec2f UV[2]
Array of 2 Vectors for tex. coords. (opt.) layout (location = 2)
Definition: SLMesh.h:205
SLVMat4f _jointMatrices
Joint matrix vector for this mesh.
Definition: SLMesh.h:257
SLVVec3f * _finalP
Pointer to final vertex position vector.
Definition: SLMesh.h:259
SLbool hitTriangleOS(SLRay *ray, SLNode *node, SLuint iT)
Definition: SLMesh.cpp:1345
void drawIntoDepthBuffer(SLSceneView *sv, SLNode *node, SLMaterial *depthMat)
Simplified drawing method for shadow map creation.
Definition: SLMesh.cpp:330
SLVVuchar Ji
2D Vector of per vertex joint ids (opt.) layout (location = 6)
Definition: SLMesh.h:208
SLCol4f _edgeColor
Color for hard edge drawing.
Definition: SLMesh.h:241
SLGLVertexArray & vao()
Definition: SLMesh.h:182
virtual void buildAABB(SLAABBox &aabb, const SLMat4f &wmNode)
Definition: SLMesh.cpp:1111
void deleteUnused()
Deletes unused vertices (= vertices that are not indexed in I16 or I32)
Definition: SLMesh.cpp:244
SLGLVertexArrayExt _vaoS
OpenGL VAO for optional selection drawing.
Definition: SLMesh.h:237
SLbool _accelStructIsOutOfDate
Flag if accel. struct needs update.
Definition: SLMesh.h:255
SLGLVertexArray _vao
Main OpenGL Vertex Array Object for drawing.
Definition: SLMesh.h:234
~SLMesh() override
The destructor deletes everything by calling deleteData.
Definition: SLMesh.cpp:82
SLVVec3f skinnedP
temp. vector for CPU skinned vertex positions
Definition: SLMesh.h:210
SLVVfloat Jw
2D Vector of per vertex joint weights (opt.) layout (location = 7)
Definition: SLMesh.h:209
SLVec3f finalN(SLuint i)
Definition: SLMesh.h:188
SLAccelStruct * _accelStruct
KD-tree or uniform grid.
Definition: SLMesh.h:254
SLVVec3f P
Vector for vertex positions layout (location = 0)
Definition: SLMesh.h:203
SLMaterial * _matOut
Pointer to the outside material.
Definition: SLMesh.h:233
SLuint numI() const
Definition: SLMesh.h:181
SLMaterial * mat() const
Definition: SLMesh.h:177
virtual void preShade(SLRay *ray)
Definition: SLMesh.cpp:1470
SLbool _isCPUSkinned
Flag if mesh has been skinned on CPU during update.
Definition: SLMesh.h:258
SLMaterial * _mat
Pointer to the inside material.
Definition: SLMesh.h:232
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
SLAABBox * aabb()
Definition: SLNode.h:301
SLbool drawBit(SLuint bit)
Definition: SLNode.h:300
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
void needAABBUpdate()
Definition: SLNode.cpp:665
void isSelected(bool isSelected)
Definition: SLNode.h:286
void levelForSM(SLubyte lfsm)
Definition: SLNode.h:288
Base class for all other classes.
Definition: SLObject.h:23
SLstring _name
name of an object
Definition: SLObject.h:42
Ray class with ray and intersection properties.
Definition: SLRay.h:40
SLint hitTriangle
Points to the intersected triangle.
Definition: SLRay.h:107
SLVec3f origin
Vector to the origin of ray in WS.
Definition: SLRay.h:75
static SLuint intersections
NO. of intersection.
Definition: SLRay.h:133
SLint srcTriangle
Points to the triangle at ray origin.
Definition: SLRay.h:99
static SLuint tests
NO. of intersection tests.
Definition: SLRay.h:132
SLMesh * hitMesh
Points to the intersected mesh.
Definition: SLRay.h:106
SLbool isOutside
Flag if ray is inside of a material.
Definition: SLRay.h:95
SLfloat hitAO
Ambient occlusion factor at intersection point.
Definition: SLRay.h:113
SLVec3f dir
Direction vector of ray in WS.
Definition: SLRay.h:76
SLMesh * srcMesh
Points to the mesh at ray origin.
Definition: SLRay.h:98
SLfloat length
length from origin to an intersection
Definition: SLRay.h:77
SLNode * hitNode
Points to the intersected node.
Definition: SLRay.h:105
SLVec3f hitPoint
Point of intersection.
Definition: SLRay.h:110
SLVec3f dirOS
Direction vector of ray in OS.
Definition: SLRay.h:81
SLCol4f hitTexColor
Color at intersection for texture or color attributes.
Definition: SLRay.h:112
SLVec3f originOS
Vector to the origin of ray in OS.
Definition: SLRay.h:80
SLVec3f hitNormal
Surface normal at intersection point.
Definition: SLRay.h:111
SLfloat hitV
barycentric coords in hit triangle
Definition: SLRay.h:104
SLfloat hitU
Definition: SLRay.h:104
T width
Definition: SLRect.h:29
T y
Definition: SLRect.h:29
SLbool isEmpty() const
Definition: SLRect.h:74
T x
Definition: SLRect.h:29
SLbool contains(T X, T Y)
Definition: SLRect.h:76
T height
Definition: SLRect.h:29
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
SLVMesh & selectedMeshes()
Definition: SLScene.h:125
SLVLight & lights()
Definition: SLScene.h:107
SLVNode & selectedNodes()
Definition: SLScene.h:124
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
SLRecti viewportRect() const
Definition: SLSceneView.h:176
void camera(SLCamera *camera)
Definition: SLSceneView.h:145
SLbool drawBit(SLuint bit)
Definition: SLSceneView.h:199
SLScene * s()
Definition: SLSceneView.h:167
Skybox node class with a SLBox mesh.
Definition: SLSkybox.h:29
T y
Definition: SLVec2.h:30
T x
Definition: SLVec2.h:30
T comp[3]
Definition: SLVec3.h:46
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
void set(const T X, const T Y, const T Z)
Definition: SLVec3.h:59
T dot(const SLVec3 &v) const
Definition: SLVec3.h:117
void sub(const SLVec3 &a, const SLVec3 &b)
Definition: SLVec3.h:113
T z
Definition: SLVec3.h:43
static SLVec3 ZERO
Definition: SLVec3.h:285
T maxXYZ()
Definition: SLVec3.h:150
T z
Definition: SLVec4.h:32
static SLVec4 WHITE
Definition: SLVec4.h:215
void set(const T X, const T Y, const T Z, const T W=1)
Definition: SLVec4.h:49
T y
Definition: SLVec4.h:32
static SLVec4 YELLOW
Definition: SLVec4.h:219
T x
Definition: SLVec4.h:32
static SLVec4 RED
Definition: SLVec4.h:216
static SLVec4 BLUE
Definition: SLVec4.h:218
void set(std::string path, const std::vector< char > &data)
Definition: SLIOMemory.cpp:29
static const float DEG2RAD
Definition: Utils.h:239
T abs(T a)
Definition: Utils.h:249
static const float PI
Definition: Utils.h:237
Struct for scene graph statistics.
Definition: SLNode.h:37
SLuint numMeshes
NO. of meshes in node.
Definition: SLNode.h:45
SLuint numTriangles
NO. of triangles in mesh.
Definition: SLNode.h:47
SLuint numLines
NO. of lines in mesh.
Definition: SLNode.h:48
SLuint numBytes
NO. of bytes allocated.
Definition: SLNode.h:39