iMSTK
Interactive Medical Simulation Toolkit
imstkVTKSurfaceMeshRenderDelegate.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkVTKSurfaceMeshRenderDelegate.h"
8 #include "imstkGeometryUtilities.h"
9 #include "imstkRenderMaterial.h"
10 #include "imstkSurfaceMesh.h"
11 #include "imstkTextureDelegate.h"
12 #include "imstkTextureManager.h"
13 #include "imstkVisualModel.h"
14 
15 #include <vtkActor.h>
16 #include <vtkCellData.h>
17 #include <vtkDoubleArray.h>
18 #include <vtkFloatArray.h>
19 #include <vtkOpenGLPolyDataMapper.h>
20 #include <vtkOpenGLVertexBufferObject.h>
21 #include <vtkPointData.h>
22 #include <vtkPolyData.h>
23 #include <vtkProperty.h>
24 #include <vtkTexture.h>
25 #include <vtkTransform.h>
26 
27 namespace imstk
28 {
29 VTKSurfaceMeshRenderDelegate::VTKSurfaceMeshRenderDelegate() :
30  m_polydata(vtkSmartPointer<vtkPolyData>::New()),
31  m_mappedVertexArray(vtkSmartPointer<vtkDoubleArray>::New()),
32  m_mappedNormalArray(vtkSmartPointer<vtkDoubleArray>::New())
33 {
34 }
35 
36 void
37 VTKSurfaceMeshRenderDelegate::init()
38 {
39  m_geometry = std::dynamic_pointer_cast<SurfaceMesh>(m_visualModel->getGeometry());
40  CHECK(m_geometry != nullptr) << "VTKSurfaceMeshRenderDelegate only works with SurfaceMesh geometry";
41  m_geometry->computeVertexToCellMap();
42 
43  m_isDynamicMesh = m_visualModel->getRenderMaterial()->getIsDynamicMesh();
44 
45  // Get our own handles to these in case the geometry changes them
46  m_vertices = m_isDynamicMesh ? m_geometry->getVertexPositions() : m_geometry->getInitialVertexPositions();
47  m_indices = m_geometry->getCells();
48 
49  // Map vertices to VTK point data
50  if (m_vertices != nullptr)
51  {
52  m_mappedVertexArray = vtkDoubleArray::SafeDownCast(GeometryUtils::coupleVtkDataArray(m_vertices));
53  auto points = vtkSmartPointer<vtkPoints>::New();
54  points->SetNumberOfPoints(m_vertices->size());
55  points->SetData(m_mappedVertexArray);
56  m_polydata->SetPoints(points);
57  }
58 
59  // Map indices to VTK cell data (copied)
60  if (m_indices != nullptr)
61  {
62  m_cellArray = vtkSmartPointer<vtkCellArray>::New();
63  vtkIdType cell[3];
64  for (const auto& t : *m_indices)
65  {
66  for (size_t i = 0; i < 3; i++)
67  {
68  cell[i] = t[i];
69  }
70  m_cellArray->InsertNextCell(3, cell);
71  }
72  m_polydata->SetPolys(m_cellArray);
73  }
74 
75  // Map vertex scalars if it has them
76  if (m_geometry->getVertexScalars() != nullptr)
77  {
78  setVertexScalarBuffer(m_geometry->getVertexScalars());
79  }
80 
81  // Map cell scalars if it has them
82  if (m_geometry->getCellScalars() != nullptr)
83  {
84  setCellScalarBuffer(m_geometry->getCellScalars());
85  }
86 
87  // Map normals, if none provided compute per vertex normals
88  if (m_geometry->getVertexNormals() == nullptr)
89  {
90  m_geometry->computeVertexNormals();
91  }
92  m_mappedNormalArray = vtkDoubleArray::SafeDownCast(GeometryUtils::coupleVtkDataArray(m_geometry->getVertexNormals()));
93  m_polydata->GetPointData()->SetNormals(m_mappedNormalArray);
94 
95  // Map TCoords
96  if (m_geometry->getVertexTCoords() != nullptr)
97  {
98  setTextureCoordinateBuffer(m_geometry->getVertexTCoords());
99  }
100 
101  // When geometry is modified, update data source, mostly for when an entirely new array/buffer was set
102  queueConnect<Event>(m_geometry, &Geometry::modified,
103  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
105 
106  // When the vertex buffer internals are modified, ie: a single or N elements
107  queueConnect<Event>(m_vertices, &VecDataArray<double, 3>::modified,
108  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
110 
111  // When index buffer internals are modified
112  queueConnect<Event>(m_indices, &VecDataArray<int, 3>::modified,
113  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
114  &VTKSurfaceMeshRenderDelegate::indexDataModified);
115 
116  // When vertex normals are modified
117  queueConnect<Event>(m_geometry->getVertexNormals(), &VecDataArray<double, 3>::modified,
118  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
119  &VTKSurfaceMeshRenderDelegate::normalDataModified);
120 
121  connect<Event>(m_material, &RenderMaterial::texturesModified,
122  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
124 
125  // Setup mapper
126  {
127  vtkNew<vtkPolyDataMapper> mapper;
128  mapper->SetInputData(m_polydata);
129  vtkNew<vtkActor> actor;
130  actor->SetMapper(mapper);
131  m_mapper = mapper;
132  m_actor = actor;
133  if (!m_isDynamicMesh)
134  {
135  actor->SetUserTransform(m_transform);
136  }
137  if (auto glMapper = vtkOpenGLPolyDataMapper::SafeDownCast(m_mapper))
138  {
139  glMapper->SetVBOShiftScaleMethod(vtkOpenGLVertexBufferObject::DISABLE_SHIFT_SCALE);
140  }
141  }
142 
143  update();
145 }
146 
147 void
149 {
150  if (!m_isDynamicMesh)
151  {
152  // Update the transform
153  const Mat4d& mImstk = m_geometry->getTransform();
154  vtkNew<vtkMatrix4x4> mVtk;
155  for (int y = 0; y < 4; y++)
156  {
157  for (int x = 0; x < 4; x++)
158  {
159  mVtk->SetElement(x, y, mImstk(x, y));
160  }
161  }
162  m_transform->SetMatrix(mVtk);
163  }
164 
165  // Custom handling of events
166  std::shared_ptr<VecDataArray<double, 3>> verticesPtr =
167  m_isDynamicMesh ? m_geometry->getVertexPositions() : m_geometry->getInitialVertexPositions();
168  std::shared_ptr<VecDataArray<int, 3>> indicesPtr = m_geometry->getCells();
169  std::shared_ptr<AbstractDataArray> cellScalarsPtr = m_geometry->getCellScalars();
170  std::shared_ptr<AbstractDataArray> vertexScalarsPtr = m_geometry->getVertexScalars();
171  std::shared_ptr<AbstractDataArray> textureCoordinatesPtr = m_geometry->getVertexTCoords();
172 
173  std::shared_ptr<VecDataArray<double, 3>> normalsPtr = m_geometry->getVertexNormals();
174 
175  // Only use the most recent event from respective sender
176  std::array<Command, 9> cmds;
177  std::array<bool, 9> contains = { false, false, false, false, false, false, false, false, false };
178  rforeachEvent([&](Command cmd)
179  {
180  if (cmd.m_event->m_sender == m_visualModel.get() && !contains[0])
181  {
182  cmds[0] = cmd;
183  contains[0] = true;
184  }
185  else if (cmd.m_event->m_sender == m_material.get() && !contains[1])
186  {
187  cmds[1] = cmd;
188  contains[1] = true;
189  }
190  else if (cmd.m_event->m_sender == m_geometry.get() && !contains[2])
191  {
192  cmds[2] = cmd;
193  contains[2] = true;
194  }
195  else if (cmd.m_event->m_sender == verticesPtr.get() && !contains[3])
196  {
197  cmds[3] = cmd;
198  contains[3] = true;
199  }
200  else if (cmd.m_event->m_sender == cellScalarsPtr.get() && !contains[4])
201  {
202  cmds[4] = cmd;
203  contains[4] = true;
204  }
205  else if (cmd.m_event->m_sender == vertexScalarsPtr.get() && !contains[5])
206  {
207  cmds[5] = cmd;
208  contains[5] = true;
209  }
210  else if (cmd.m_event->m_sender == indicesPtr.get() && !contains[6])
211  {
212  cmds[6] = cmd;
213  contains[6] = true;
214  }
215  else if (cmd.m_event->m_sender == textureCoordinatesPtr.get() && !contains[7])
216  {
217  cmds[7] = cmd;
218  contains[7] = true;
219  }
220  else if (cmd.m_event->m_sender == normalsPtr.get() && !contains[8])
221  {
222  cmds[8] = cmd;
223  contains[8] = true;
224  }
225  });
226 
227  // Now do all the commands
228  cmds[0].invoke(); // Update VisualModel
229  cmds[1].invoke(); // Update RenderMaterial
230  cmds[3].invoke(); // Update vertices
231  cmds[4].invoke(); // Update cell scalars
232  cmds[5].invoke(); // Update vertex scalars
233  cmds[8].invoke(); // Update vertex normals
234  cmds[6].invoke(); // Update indices
235  cmds[7].invoke(); // Update texture coordinates
236  cmds[2].invoke(); // Update geometry as a whole
237 }
238 
239 void
241 {
242  setVertexBuffer(m_isDynamicMesh ? m_geometry->getVertexPositions() :
243  m_geometry->getInitialVertexPositions());
244 
245  if (m_isDynamicMesh)
246  {
247  // If the material says we should recompute normals
248  if (m_visualModel->getRenderMaterial()->getRecomputeVertexNormals())
249  {
250  m_geometry->computeVertexNormals();
251  setNormalBuffer(m_geometry->getVertexNormals());
252  }
253  }
254 }
255 
256 void
257 VTKSurfaceMeshRenderDelegate::indexDataModified(Event* imstkNotUsed(e))
258 {
259  setIndexBuffer(m_geometry->getCells());
260 }
261 
262 void
263 VTKSurfaceMeshRenderDelegate::normalDataModified(Event* imstkNotUsed(e))
264 {
265  setNormalBuffer(m_geometry->getVertexNormals());
266 }
267 
268 void
269 VTKSurfaceMeshRenderDelegate::vertexScalarsModified(Event* imstkNotUsed(e))
270 {
271  setVertexScalarBuffer(m_geometry->getVertexScalars());
272 }
273 
274 void
275 VTKSurfaceMeshRenderDelegate::cellScalarsModified(Event* imstkNotUsed(e))
276 {
277  setCellScalarBuffer(m_geometry->getCellScalars());
278 }
279 
280 void
281 VTKSurfaceMeshRenderDelegate::textureCoordinatesModified(Event* imstkNotUsed(e))
282 {
283  setTextureCoordinateBuffer(m_geometry->getVertexTCoords());
284 }
285 
286 void
288 {
289  // If the mesh is dynamic check for buffer size changes & consistently reupload
290  // the vertex buffer. Recompute normals dynamically.
291  if (m_isDynamicMesh)
292  {
293  // If the vertices were reallocated
294  if (m_vertices != m_geometry->getVertexPositions())
295  {
296  setVertexBuffer(m_geometry->getVertexPositions());
297  }
298 
299  // Consistently reupload the vertex buffer
300  m_mappedVertexArray->Modified();
301 
302  // Only update index buffer when reallocated
303  if (m_indices != m_geometry->getCells())
304  {
305  setIndexBuffer(m_geometry->getCells());
306  }
307 
308  if (m_normals != m_geometry->getVertexNormals())
309  {
310  setNormalBuffer(m_geometry->getVertexNormals());
311  }
312 
313  if (m_visualModel->getRenderMaterial()->getRecomputeVertexNormals())
314  {
315  m_geometry->computeVertexNormals();
316  setNormalBuffer(m_geometry->getVertexNormals());
317  }
318  }
319  // If the mesh is not dynamic, avoid reuploading & recomputing any buffers
320  // vertices & normals can be changed rigidly by a transform in the shader
321  else
322  {
323  // If the vertices were reallocated
324  bool normalsOutdated = false;
325  if (m_vertices != m_geometry->getInitialVertexPositions())
326  {
327  setVertexBuffer(m_geometry->getInitialVertexPositions());
328  normalsOutdated = true;
329  }
330 
331  // Only update index buffer when reallocated
332  if (m_indices != m_geometry->getCells())
333  {
334  setIndexBuffer(m_geometry->getCells());
335  normalsOutdated = true;
336  }
337 
338  if (m_normals != m_geometry->getVertexNormals())
339  {
340  setNormalBuffer(m_geometry->getVertexNormals());
341  normalsOutdated = false;
342  }
343 
344  if (normalsOutdated && m_visualModel->getRenderMaterial()->getRecomputeVertexNormals())
345  {
346  m_geometry->computeVertexNormals();
347  setNormalBuffer(m_geometry->getVertexNormals());
348  }
349  }
350 
351  if (m_vertexScalars != m_geometry->getVertexScalars())
352  {
353  setVertexScalarBuffer(m_geometry->getVertexScalars());
354  }
355 
356  if (m_cellScalars != m_geometry->getCellScalars())
357  {
358  setCellScalarBuffer(m_geometry->getCellScalars());
359  }
360 
361  if (m_textureCoordinates != m_geometry->getVertexTCoords())
362  {
363  setTextureCoordinateBuffer(m_geometry->getVertexTCoords());
364  }
365 }
366 
367 void
369 {
370  // If a texture is set/swapped reinit all textures
371  RenderMaterial* material = static_cast<RenderMaterial*>(e->m_sender);
372  if (material != nullptr)
373  {
374  // Reload all textures
375  // If texture already present, don't do anything unless name changed
376  initializeTextures();
377  }
378 }
379 
380 void
381 VTKSurfaceMeshRenderDelegate::setVertexBuffer(std::shared_ptr<VecDataArray<double, 3>> vertices)
382 {
383  // If the buffer changed
384  if (m_vertices != vertices)
385  {
386  // If previous buffer exist
387  if (m_vertices != nullptr)
388  {
389  // stop observing its changes
390  disconnect(m_vertices,
391  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
393  }
394  // Set new buffer and observe
395  m_vertices = vertices;
396  queueConnect<Event>(m_vertices, &VecDataArray<double, 3>::modified,
397  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
399  }
400 
401  // Couple the buffer
402  m_mappedVertexArray->SetNumberOfComponents(3);
403  m_mappedVertexArray->SetArray(reinterpret_cast<double*>(m_vertices->getPointer()), m_vertices->size() * 3, 1);
404  m_mappedVertexArray->Modified();
405  m_polydata->GetPoints()->SetNumberOfPoints(m_vertices->size());
406 }
407 
408 void
409 VTKSurfaceMeshRenderDelegate::setNormalBuffer(std::shared_ptr<VecDataArray<double, 3>> normals)
410 {
411  // If the buffer changed
412  if (m_normals != normals)
413  {
414  // If previous buffer exist
415  if (m_normals != nullptr)
416  {
417  // stop observing its changes
418  disconnect(m_normals,
419  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
421  }
422  // Set new buffer and observe
423  m_normals = normals;
424  queueConnect<Event>(m_normals, &VecDataArray<double, 3>::modified,
425  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
426  &VTKSurfaceMeshRenderDelegate::normalDataModified);
427  }
428 
429  // Couple the buffer
430  m_mappedNormalArray->SetNumberOfComponents(3);
431  m_mappedNormalArray->SetArray(reinterpret_cast<double*>(m_normals->getPointer()), m_normals->size() * 3, 1);
432  m_mappedNormalArray->Modified();
433 }
434 
435 void
436 VTKSurfaceMeshRenderDelegate::setIndexBuffer(std::shared_ptr<VecDataArray<int, 3>> indices)
437 {
438  // If the buffer changed
439  if (m_indices != indices)
440  {
441  // If previous buffer exist
442  if (m_indices != nullptr)
443  {
444  // stop observing its changes
445  disconnect(m_indices,
446  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
448  }
449  // Set new buffer and observe
450  m_indices = indices;
451  queueConnect<Event>(m_indices, &VecDataArray<int, 3>::modified,
452  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
453  &VTKSurfaceMeshRenderDelegate::indexDataModified);
454  }
455 
456  // Copy the buffer
457  // Copy cells
458  m_cellArray->Reset();
459  vtkIdType cell[3];
460  for (const auto& t : *m_indices)
461  {
462  for (size_t i = 0; i < 3; i++)
463  {
464  cell[i] = t[i];
465  }
466  m_cellArray->InsertNextCell(3, cell);
467  }
468  m_cellArray->Modified();
469 }
470 
471 void
472 VTKSurfaceMeshRenderDelegate::setVertexScalarBuffer(std::shared_ptr<AbstractDataArray> scalars)
473 {
474  // If the buffer changed
475  if (m_vertexScalars != scalars)
476  {
477  // If previous buffer exist
478  if (m_vertexScalars != nullptr)
479  {
480  // stop observing its changes
481  disconnect(m_vertexScalars,
482  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
483  &AbstractDataArray::modified);
484  }
485  // Set new buffer and observe
486  m_vertexScalars = scalars;
487  queueConnect<Event>(m_vertexScalars, &AbstractDataArray::modified,
488  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
489  &VTKSurfaceMeshRenderDelegate::vertexScalarsModified);
490  m_mappedVertexScalarArray = GeometryUtils::coupleVtkDataArray(m_vertexScalars);
491  m_polydata->GetPointData()->SetScalars(m_mappedVertexScalarArray);
492  }
493  m_mappedVertexScalarArray->SetNumberOfComponents(m_vertexScalars->getNumberOfComponents());
494  m_mappedVertexScalarArray->SetVoidArray(m_vertexScalars->getVoidPointer(),
495  static_cast<vtkIdType>(m_vertexScalars->size()), 1);
496  m_mappedVertexScalarArray->Modified();
497 }
498 
499 void
500 VTKSurfaceMeshRenderDelegate::setCellScalarBuffer(std::shared_ptr<AbstractDataArray> scalars)
501 {
502  // If the buffer changed
503  if (m_cellScalars != scalars)
504  {
505  // If previous buffer exist
506  if (m_cellScalars != nullptr)
507  {
508  // stop observing its changes
509  disconnect(m_cellScalars,
510  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
511  &AbstractDataArray::modified);
512  }
513  // Set new buffer and observe
514  m_cellScalars = scalars;
515  queueConnect<Event>(m_cellScalars, &AbstractDataArray::modified,
516  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
517  &VTKSurfaceMeshRenderDelegate::cellScalarsModified);
518  m_mappedCellScalarArray = GeometryUtils::coupleVtkDataArray(m_cellScalars);
519  m_polydata->GetCellData()->SetScalars(m_mappedCellScalarArray);
520  }
521  m_mappedCellScalarArray->SetNumberOfComponents(m_cellScalars->getNumberOfComponents());
522  m_mappedCellScalarArray->SetVoidArray(m_cellScalars->getVoidPointer(),
523  static_cast<vtkIdType>(m_cellScalars->size()), 1);
524  m_mappedCellScalarArray->Modified();
525 }
526 
527 void
528 VTKSurfaceMeshRenderDelegate::setTextureCoordinateBuffer(std::shared_ptr<AbstractDataArray> textureCoordinates)
529 {
530  // If the buffer changed
531  if (m_textureCoordinates != textureCoordinates)
532  {
533  // If previous buffer exist
534  if (m_textureCoordinates != nullptr)
535  {
536  // stop observing its changes
537  disconnect(m_textureCoordinates,
538  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
539  &AbstractDataArray::modified);
540  }
541  // Set new buffer and observe
542  m_textureCoordinates = textureCoordinates;
543  queueConnect<Event>(m_textureCoordinates, &AbstractDataArray::modified,
544  std::static_pointer_cast<VTKSurfaceMeshRenderDelegate>(shared_from_this()),
545  &VTKSurfaceMeshRenderDelegate::textureCoordinatesModified);
546  m_mappedTCoordsArray = vtkFloatArray::SafeDownCast(GeometryUtils::coupleVtkDataArray(textureCoordinates));
547  m_mappedTCoordsArray->SetName(m_geometry->getActiveVertexTCoords().c_str());
548  m_polydata->GetPointData()->SetTCoords(m_mappedTCoordsArray);
549  }
550 
551  m_mappedTCoordsArray->SetNumberOfComponents(m_textureCoordinates->getNumberOfComponents());
552  m_mappedTCoordsArray->SetVoidArray(m_textureCoordinates->getVoidPointer(), static_cast<vtkIdType>(m_textureCoordinates->size()), 1);
553  m_mappedTCoordsArray->Modified();
554 
555  // Map Tangents
556  if (m_geometry->getVertexTangents() == nullptr)
557  {
558  m_geometry->computeVertexTangents();
559  }
560  // These need to be float for PBR
561  m_mappedTangentArray = vtkFloatArray::SafeDownCast(GeometryUtils::coupleVtkDataArray(m_geometry->getVertexTangents()));
562  m_polydata->GetPointData()->SetTangents(m_mappedTangentArray);
563  m_mappedTangentArray->Modified();
564 }
565 
566 void
568 {
569  auto material = m_visualModel->getRenderMaterial();
570  if (material == nullptr)
571  {
572  return;
573  }
574 
575  unsigned int currentUnit = 0;
576 
577  // Go through all of the textures
578  vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(m_actor);
579  actor->GetProperty()->RemoveAllTextures();
580  for (int unit = 0; unit < (int)Texture::Type::None; unit++)
581  {
582  // Get imstk texture
583  auto texture = material->getTexture((Texture::Type)unit);
584  // If neither of these are provided, the texture is not filled out
585  if (texture->getImageData() == nullptr && texture->getPath() == "")
586  {
587  continue;
588  }
589 
590  // Get vtk texture
591  std::shared_ptr<TextureManager<VTKTextureDelegate>> textureManager = m_textureManager.lock();
592  auto textureDelegate = textureManager->getTextureDelegate(texture);
593 
594  /* /!\ VTKTextureWrapMode not yet supported in VTK 7
595  * See here for some work that needs to be imported back to upstream:
596  * https://gitlab.kitware.com/iMSTK/vtk/commit/62a7ecd8a5f54e243c26960de22d5d1d23ef932b
597  *
598  texture->SetWrapMode(vtkTexture::VTKTextureWrapMode::ClampToBorder);
599 
600  * /!\ MultiTextureAttribute not yet supported in VTK 7
601  * See here for some work that needs to be imported back to upstream:
602  * https://gitlab.kitware.com/iMSTK/vtk/commit/ae373026755db42b6fdce5093109ef1a39a76340
603  *
604  // Link texture unit to texture attribute
605  m_mapper->MapDataArrayToMultiTextureAttribute(unit, tCoordsName.c_str(),
606  vtkDataObject::FIELD_ASSOCIATION_POINTS);
607  */
608 
609  // Set texture
610  vtkSmartPointer<vtkTexture> currentTexture = textureDelegate->getVtkTexture();
611  if (material->getShadingModel() == RenderMaterial::ShadingModel::PBR)
612  {
613  switch (texture->getType())
614  {
615  case Texture::Type::Diffuse:
616  {
617  actor->GetProperty()->SetBaseColorTexture(currentTexture);
618  break;
619  }
620  case Texture::Type::Normal:
621  {
622  actor->GetProperty()->SetNormalTexture(currentTexture);
623  break;
624  }
625  case Texture::Type::AmbientOcclusion:
626  case Texture::Type::ORM:
627  {
628  actor->GetProperty()->SetORMTexture(currentTexture);
629  break;
630  }
631  case Texture::Type::Anistropy:
632  {
633  actor->GetProperty()->SetAnisotropyTexture(currentTexture);
634  break;
635  }
636  case Texture::Type::CoatNormal:
637  {
638  actor->GetProperty()->SetCoatNormalTexture(currentTexture);
639  break;
640  }
641  default:
642  {
643  }
644  }
645  }
646  else if (texture->getType() == Texture::Type::Diffuse)
647  {
648  actor->SetTexture(currentTexture);
649  }
650 
651  currentUnit++;
652  }
653 }
654 } // namespace imstk
void rforeachEvent(std::function< void(Command cmd)> func)
thread safe reverse loop over all event commands, one can implement a custom handler ...
void update()
Update render delegate.
friend void disconnect(std::shared_ptr< EventObject >, std::shared_ptr< EventObject >, std::string(*)())
Remove an observer from the sender.
vtkSmartPointer< vtkDataArray > coupleVtkDataArray(std::shared_ptr< AbstractDataArray > imstkArray)
Coupling functions, these create vtk data objects that point to our data objects thus no copying is d...
std::shared_ptr< VisualModel > m_visualModel
imstk visual model (contains data (geometry) and render specification (render material)) ...
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
Type
Texture type - determines filtering.
Definition: imstkTexture.h:30
Compound Geometry.
void geometryModified(Event *e)
Callback for when geometry is modified.
void updateRenderProperties() override
Updates the actor and mapper properties from the currently set VisualModel.
Delegates rendering of SurfaceMesh to VTK from VisualModel.
void vertexDataModified(Event *e)
Callback for when vertex values are modified.
Serves no function, just a database for render properties, emits events for others to observe its cha...
void texturesModified(Event *e)
Callback for when RenderMaterial textures are modified.
Physically based rendering.
Stores everything needed to invoke an event A call may not be present, in which case invoke doesn&#39;t d...