3 VTK is the primary rendering backend for iMSTK, though it can be used without rendering/standalone. This also allows one to utilize any rendering backend they wish.
5 A VTKViewer is used to render an iMSTK Scene. Setup as:
8 auto viewer = std::make_shared<VTKViewer>();
9 viewer->setActiveScene(myScene);
12 Given the scene it sets up RenderDelegates for every VisualModel. While a VisualModel model gives what is to be rendered. The RenderDelegate implements it. Keeping rendering backend separate from iMSTK. Typically the VTKViewer is given to the SimulationManager to update. But if one would instead like to invoke render themselves. Just call update on the viewer.
15 viewer->update(); // Renders now
20 Cameras in iMSTK are used for rendering. They must be given to the scene and set as active. There are default cameras with the iMSTK scene. Camera's allow control with (position, focal point, up) or by view matrix directly.
23 // Often the default active camera from the scene is used
24 scene->getActiveCamera()->setFocalPoint(0.0, 0.0, 0.0);
25 scene->getActiveCamera()->setPosition(-0.0237419, 0.0368787, 0.338374);
26 scene->getActiveCamera()->setViewUp(0.0, 1.0, 0.0);
32 // Camera transition over time t
34 Mat4d finalView = ...;
35 getActiveCamera()->setView(t * (finalView - initView) + initView);
38 Additionally the fov can change.
41 camera->setFieldOfView(90.0); // Degrees
44 A camera also has a near and far. That is how close and far it can render. These are not adjusted automatically at any point in iMSTK.
46 camera->setNearZ(0.01);
47 camera->setFarZ(1000.0);
50 Quickly get the forward direction with `Camera::getForward`
52 Ask the `Camera` for a ray direction emanating from where the user has clicked:
55 // Get mouse position (0, 1) with origin at bot left of screen
56 const Vec2d mousePos = viewer->getMouseDevice()->getPos();
58 const Vec3d normalizedMousePos = Vec2d(mousePos[0] * 2.0 - 1.0, mousePos[1] * 2.0 - 1.0);
59 const Vec3d rayDir = scene->getActiveCamera()->getEyeRayDir(normalizedMousePos);
60 const Vec3d rayStart = scene->getActiveCamera()->getPosition();
65 RenderMaterials give properties of VisualModel to be rendered. Importantly we have a DisplayMode
67 - Surface: Renders only the surface of the geometry.
68 - Wireframe: Renders only the wireframe of the geometry, edges of the cells.
69 - Points: Renders only the vertices of the geometry.
70 - WireframeSurface: Renders both the surface of the cells
72 As well as a choice between ShadingModels:
73 - Phong: Computes lighting with normals per every fragments/pixels.
74 - Gourand: Computes lighting with normals per vertex then interpolates over fragments/pixels.
75 - Flat: Computes lighting per cell and uses it for every fragment/pixel of that cell.
76 - PBR: Uses phong shading but has a very specific model based on realistic parameters.
78 To setup a basic material we can do:
82 mat.setDisplayMode(RenderMaterial::DisplayMode::WireframeSurface);
83 mat.setLineWidth(2.0);
84 mat.setEdgeColor(Color::Orange);
87 This gives us orange edges, gray default surface color, and edges that are displayed with size 2. The typical phong model allows us to specify specular, diffuse, and ambient lighting. We give scales and colors for each.
89 ### Physically Based Rendering (PBR)
91 Alternatively utilize PBR which is parameterized differently based on realistic parameters such as "roughness" or "metalness". There are also a number of other features. Here is how to use that with textures for diffuse, normals, and ambient occlusion.
94 auto material = std::make_shared<RenderMaterial>();
95 material->setDisplayMode(RenderMaterial::DisplayMode::Surface);
96 material->setShadingModel(RenderMaterial::ShadingModel::PBR);
97 auto headDiffuseTexture = std::make_shared<Texture>(iMSTK_DATA_ROOT "head/HeadTexture_BaseColor.png", Texture::Type::Diffuse);
98 auto headNormalTexture = std::make_shared<Texture>(iMSTK_DATA_ROOT "head/HeadTexture_Normal.png", Texture::Type::Normal);
99 auto headAoTexture = std::make_shared<Texture>(iMSTK_DATA_ROOT "head/HeadTexture_AO.png", Texture::Type::AmbientOcclusion;
101 material->setRoughness(10.0);
102 material->setMetalness(0.0);
103 material->addTexture(headDiffuseTexture);
104 material->addTexture(headNormalTexture);
105 material->addTexture(headAoTexture);
109 <img src="media/pbr.jpg" alt="Physically based rendering" width="600"/>
115 Two important flags of this material that are by default on.
117 - RenderMaterial::setRecomputeVertexNormals: When on the vertex buffer is continuously updated.
118 - RenderMaterial::setIsDynamicMesh: When off buffers aren't not even checked for changes. A transform can still be applied through the shader.
120 ### DisplayMode::SurfaceNormals
122 This display mode can be used to quickly render face windings.
125 <img src="media/surfaceNormals.jpg" alt="Physically based rendering" width="600"/>
128 ### DisplayMode::Fluid
130 This display mode uses screen-space fluids to render.
133 <img src="media/PbdModel/blood.png" alt="Physically based rendering" width="600"/>
136 ## DebugGeometryModel
138 The `DebugGeometryModel` can be used to quickly render primitives.
141 auto debugGeomVisuals = mySceneObject->addComponent<DebugGeometryModel>();
142 debugGeomVisuals->addPoint(myVertex, myColor);
143 debugGeomVisuals->addLine(...);
144 debugGeomVisuals->addTriangle(...);
147 ## CollisionDataDebugModel
149 The `CollisionDataDebugModel` extends the `DebugGeometryModel` providing quick rendering of `CollisionData` from a `CollisionDetectionAlgorithm`.
152 SpheretoSphereCD detector;
156 auto cdDebugModel = mySceneObject->addComponent<CollisionDataDebugModel>();
157 cdDebugModel->setInputCD(detector.getCollisionData());
162 `TextVisualModel` can be used in iMSTK to render text to the corners or center of the screen:
165 auto txtVisuals = mySceneObject->addComponent<TextVisualModel>();
166 txtVisuals->setPosition(TextVisualModel::DisplayPosition::UpperLeft);
167 txtVisuals->setFontSize(30.0);
168 txtVisuals->setTextColor(Color::Orange);
173 Given a `PbdObjectController` one can quickly render the ghost of the controller with `ObjectControllerGhost` as follows:
176 // Add extra component to tool for the ghost
177 auto controllerGhost = lapTool->addComponent<ObjectControllerGhost>();
178 controllerGhost->setUseForceFade(true);
179 controllerGhost->setController(controller);
183 <img src="media/rbd1.gif" alt="Virtual coupling in action" width="800"/>
186 ## Force Text Rendering
188 It can often be useful to see the forces experienced by the user. This can be done easily by adding a `ControllerForceText` component.
191 auto controllerForceTxt = mySceneObject->addComponent<ControllerForceText>();
192 controllerForceTxt->setController(controller);
195 ## Per Vertex Labelings
197 The `VertexLabelVisualModel` was introduce to allow quick debugging and numbering of vertex indices/numberings. It can be configured like so:
200 auto vertexLabelModel = mySceneObject->addComponent<VertexLabelVisualModel>();
201 vertexLabelModel->setGeometry(myMeshToRender);
205 <img src="media/vertexLabels.png" alt="Vertex labeling" width="600"/>
210 The AxesModel can be used to quickly render a axes basis.
213 auto axesModel = mySceneObject->addComponent<AxesModel>();
214 axesModel->setPosition(Vec3d(0.0, 20.0, 4.0));
215 axesModel->setPosition(Quatd::FromTwoVectors(Vec3d(0.0, 1.0, 0.0), Vec3d(1.0, 1.0, 0.0)));
218 ## VolumeRenderMaterial
220 The VolumeRenderMaterial exposes VTK objects for rendering, it can be used as:
223 auto material = std::make_shared<VolumeRenderMaterial>();
224 vtkNew<vtkColorTransferFunction> colorFunc;
225 colorFunc->AddRGBPoint(0.0, 1.0, 0.0, 0.0);
226 colorFunc->AddRGBPoint(8.0, 0.0, 0.0, 1.0);
227 volumeMaterial->getVolumeProperty()->SetColor(colorFunc);
228 vtkNew<vtkPiecewiseFunction> opacityFunc;
229 opacityFunc->AddPoint(0.0, 0.0);
230 opacityFunc->AddPoint(1.0, 1.0);
231 volumeMaterial->getVolumeProperty()->SetScalarOpacity(opacityFunc);
234 Here set both a color and opacity function. As we render the volume (by marching along a ray shot from the screen) we sample the image we are rendering and lookup a color and opacity. These functions specify this. AddRGBPoint(intensity, r, g, b) and AddPoint(intensity, opacity).
236 A number of presets (which may or may not fit your image/volume) are also available which can be used as below:
239 std::shared_ptr<VolumeRenderMaterial> volumeMaterial = VolumeRenderMaterialPresets::getPreset(currMatId);
243 <img src="media/vhp.png" alt="Femur Signed Distance Function" width="600"/>
246 ## Custom RenderDelegates & VisualModels
248 If one needs to implement their own rendering capabilities the VisualModel's and RenderDelegates can be extended. Extending the VisualModel the delegate hint can be provided.
251 class ChartVisualModel : public VisualModel
256 // Setup delegate hint here
257 setDelegateHint("Chart");
259 ~ChartVisualModel() override = default;
262 If iMSTK is provided a delegate hint in a VisualModel it will first look to construct the corresponding RenderDelegate using this hint. iMSTK, by default, has many registrations. One can add a registration in their own code by defining a `VTKChartRenderDelegate` and adding:
265 RenderDelegateRegistrar<VTKChartRenderDelegate> registerChartDelegate("Chart");
270 iMSTK provides three types of lights.
271 - PointLight: Specified with a position, intensity, color.
272 - DirectionalLight: Specified with a direction, intensity, color.
273 - SpotLight: Specified with a position, focal point, cone angle, intensity, color.
277 auto light = std::make_shared<SpotLight>();
278 light->setFocalPoint(Vec3d(0.0, 0.0, 0.0));
279 light->setPosition(Vec3d(0.0, 10.0, 0.0));
280 light->setIntensity(1.0);
281 light->setSpotAngle(10.0);
282 scene->addLight("light0", light);
285 All lights can also work with constant, linear, and quadratic falloff.
288 light->setAttenuationValues(0.0, 0.0, 1.0); // Constant a
289 light->setAttenuationValues(0.0, 0.5, 0.0); // Linear falloff a + bx
290 light->setAttenuationValues(50.0, 0.0, 0.0); // Quadratic a + bx + cx^2
293 