iMSTK
Interactive Medical Simulation Toolkit
imstkVTKFluidRenderDelegate.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 "imstkVTKFluidRenderDelegate.h"
8 #include "imstkPointSet.h"
9 #include "imstkVisualModel.h"
10 #include "imstkRenderMaterial.h"
11 #include "imstkGeometryUtilities.h"
12 
13 #include <vtkOpenGLFluidMapper.h>
14 #include <vtkVertexGlyphFilter.h>
15 #include <vtkDoubleArray.h>
16 #include <vtkVolume.h>
17 
18 namespace imstk
19 {
20 VTKFluidRenderDelegate::VTKFluidRenderDelegate() :
21  m_polydata(vtkSmartPointer<vtkPolyData>::New()),
22  m_mappedVertexArray(vtkSmartPointer<vtkDoubleArray>::New())
23 {
24 }
25 
26 void
27 VTKFluidRenderDelegate::init()
28 {
29  auto geometry = std::dynamic_pointer_cast<PointSet>(m_visualModel->getGeometry());
30  CHECK(geometry != nullptr) << "VTKFluidRenderDelegate only works with PointSet geometry";
31  m_vertices = geometry->getVertexPositions();
32 
33  // Map vertices
34  if (m_vertices != nullptr)
35  {
36  m_mappedVertexArray = vtkDoubleArray::SafeDownCast(GeometryUtils::coupleVtkDataArray(m_vertices));
37  auto points = vtkSmartPointer<vtkPoints>::New();
38  points->SetNumberOfPoints(geometry->getNumVertices());
39  points->SetData(m_mappedVertexArray);
40  m_polydata->SetPoints(points);
41  }
42 
43  // When geometry is modified, update data source, mostly for when an entirely new array/buffer was set
44  queueConnect<Event>(geometry, &Geometry::modified,
45  std::static_pointer_cast<VTKFluidRenderDelegate>(shared_from_this()),
47 
48  // When the vertex buffer internals are modified, ie: a single or N elements
49  queueConnect<Event>(geometry->getVertexPositions(), &VecDataArray<double, 3>::modified,
50  std::static_pointer_cast<VTKFluidRenderDelegate>(shared_from_this()),
52 
53  // Setup mapper
54  {
55  vtkNew<vtkOpenGLFluidMapper> mapper;
56  mapper->SetInputData(m_polydata);
57  vtkNew<vtkVolume> volume;
58  volume->SetMapper(mapper);
59  m_mapper = mapper;
60  m_actor = volume;
61  }
62 
63  update();
65 }
66 
67 void
69 {
70  // Custom handling of events
71  std::shared_ptr<PointSet> geom = std::dynamic_pointer_cast<PointSet>(m_visualModel->getGeometry());
72  std::shared_ptr<VecDataArray<double, 3>> vertices = geom->getVertexPositions();
73 
74  // Only use the most recent event from respective sender
75  std::list<Command> cmds;
76  bool contains[4] = { false, false, false, false };
77  rforeachEvent([&](Command cmd)
78  {
79  if (cmd.m_event->m_sender == m_visualModel.get() && !contains[0])
80  {
81  cmds.push_back(cmd);
82  contains[0] = true;
83  }
84  else if (cmd.m_event->m_sender == m_material.get() && !contains[1])
85  {
86  cmds.push_back(cmd);
87  contains[1] = true;
88  }
89  else if (cmd.m_event->m_sender == geom.get() && !contains[2])
90  {
91  cmds.push_back(cmd);
92  contains[2] = true;
93  }
94  else if (cmd.m_event->m_sender == vertices.get() && !contains[3])
95  {
96  cmds.push_back(cmd);
97  contains[3] = true;
98  }
99  });
100 
101  // Now do each event in order recieved
102  for (std::list<Command>::reverse_iterator i = cmds.rbegin(); i != cmds.rend(); i++)
103  {
104  i->invoke();
105  }
106 }
107 
108 void
110 {
111  // Called when the geometry posts modified
112  auto geometry = std::static_pointer_cast<PointSet>(m_visualModel->getGeometry());
113 
114  // Test if the vertex buffer changed
115  if (m_vertices != geometry->getVertexPositions())
116  {
117  //printf("Vertex data swapped\n");
118  m_vertices = geometry->getVertexPositions();
119  {
120  // Update the pointer of the coupled array
121  m_mappedVertexArray->SetNumberOfComponents(3);
122  m_mappedVertexArray->SetArray(reinterpret_cast<double*>(m_vertices->getPointer()), m_vertices->size() * 3, 1);
123  }
124  }
125  m_mappedVertexArray->Modified();
126 }
127 
128 void
130 {
131  auto geometry = std::static_pointer_cast<PointSet>(m_visualModel->getGeometry());
132  m_vertices = geometry->getVertexPositions();
133  if (m_vertices->getVoidPointer() != m_mappedVertexArray->GetVoidPointer(0))
134  {
135  m_mappedVertexArray->SetNumberOfComponents(3);
136  m_mappedVertexArray->SetArray(reinterpret_cast<double*>(m_vertices->getPointer()), m_vertices->size() * 3, 1);
137  }
138  m_mappedVertexArray->Modified();
139 }
140 
141 void
143 {
144  vtkSmartPointer<vtkOpenGLFluidMapper> mapper = vtkOpenGLFluidMapper::SafeDownCast(m_mapper);
145 
146  // todo: Expose in RenderMaterial or subclass
147  mapper->SetParticleRadius(m_material->getPointSize());
148  mapper->SetSurfaceFilterIterations(3);
149  mapper->SetSurfaceFilterRadius(5);
150  mapper->SetSurfaceFilterMethod(vtkOpenGLFluidMapper::FluidSurfaceFilterMethod::NarrowRange);
151  mapper->SetDisplayMode(vtkOpenGLFluidMapper::FluidDisplayMode::TransparentFluidVolume);
152  mapper->SetAttenuationColor(0.1f, 0.9f, 0.9f);
153  mapper->SetAttenuationScale(16.0f);
154  mapper->SetOpaqueColor(0.9f, 0.1f, 0.1f);
155  mapper->SetParticleColorPower(0.1f);
156  mapper->SetParticleColorScale(0.57f);
157  mapper->SetAdditionalReflection(0.0f);
158  mapper->SetRefractiveIndex(1.5f);
159  mapper->SetRefractionScale(0.07f);
160 }
161 } // 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.
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
Definition: imstkPointSet.h:25
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...
void processEvents() override
Update polydata source based on the mesh geometry.
Compound Geometry.
void geometryModified(Event *e)
Callback for when geometry changes.
void updateRenderProperties() override
Updates the actor and mapper properties from the currently set VisualModel.
void updateRenderProperties() override
Updates the actor and mapper properties from the currently set VisualModel.
std::shared_ptr< VecDataArray< double, 3 > > getVertexPositions(DataType type=DataType::PostTransform) const
Returns the vector of current positions of the mesh vertices.
void vertexDataModified(Event *e)
Callback for when vertices change.
Stores everything needed to invoke an event A call may not be present, in which case invoke doesn&#39;t d...