7 #include "imstkVTKRenderer.h" 8 #include "imstkCamera.h" 9 #include "imstkDirectionalLight.h" 10 #include "imstkPointLight.h" 11 #include "imstkSpotLight.h" 12 #include "imstkLogger.h" 13 #include "imstkScene.h" 14 #include "imstkSceneObject.h" 15 #include "imstkTextureManager.h" 16 #include "imstkVisualModel.h" 17 #include "imstkVTKSurfaceMeshRenderDelegate.h" 19 #include <vtkCameraActor.h> 20 #include <vtkCullerCollection.h> 22 #include <vtkLightActor.h> 25 #include <vtkChartXY.h> 26 #include <vtkContextActor.h> 27 #include <vtkContextScene.h> 28 #include <vtkDoubleArray.h> 29 #include <vtkPlotBar.h> 30 #include <vtkStringArray.h> 32 #include <vtkTextProperty.h> 34 #include <vtkCameraPass.h> 35 #include <vtkOpenVRCamera.h> 36 #include <vtkOpenVRRenderer.h> 37 #include <vtkRenderPassCollection.h> 38 #include <vtkRenderStepsPass.h> 39 #include <vtkSequencePass.h> 40 #include <vtkSSAOPass.h> 41 #include <vtkProperty.h> 48 m_ssaoPass(vtkSmartPointer<vtkSSAOPass>::New()),
49 m_renderStepsPass(vtkSmartPointer<vtkRenderStepsPass>::New())
52 m_VrEnabled = enableVR;
55 m_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
59 m_vtkRenderer = vtkSmartPointer<vtkOpenVRRenderer>::New();
60 vtkOpenVRRenderer::SafeDownCast(m_vtkRenderer)->SetAutomaticLightCreation(
false);
61 vtkOpenVRRenderer::SafeDownCast(m_vtkRenderer)->SetLightFollowCamera(
false);
73 for (
const auto& light : m_scene->getLights())
75 std::string name = light->getTypeName();
76 if (name == DirectionalLight::getStaticTypeName())
78 auto lightVtk = vtkSmartPointer<vtkLight>::New();
79 lightVtk->SetPositional(
false);
80 const Color& color = light->getColor();
81 lightVtk->SetColor(color.r, color.g, color.b);
82 lightVtk->SetIntensity(light->getIntensity());
83 lightVtk->SetFocalPoint(light->getFocalPoint().data());
84 lightVtk->SetPosition(0.0, 0.0, 0.0);
85 lightVtk->SetAttenuationValues(light->getAttenuationValues().data());
87 m_vtkLights.push_back(VtkLightPair(light, lightVtk));
89 else if (name == SpotLight::getStaticTypeName())
91 auto lightVtk = vtkSmartPointer<vtkLight>::New();
92 lightVtk->SetPositional(
true);
93 const Color& color = light->getColor();
94 lightVtk->SetColor(color.r, color.g, color.b);
95 lightVtk->SetIntensity(light->getIntensity());
96 lightVtk->SetFocalPoint(light->getFocalPoint().data());
98 auto spotLight = std::dynamic_pointer_cast<
SpotLight>(light);
99 lightVtk->SetPosition(spotLight->getPosition().data());
100 lightVtk->SetConeAngle(spotLight->getSpotAngle());
101 lightVtk->SetAttenuationValues(light->getAttenuationValues().data());
103 m_vtkLights.push_back(VtkLightPair(light, lightVtk));
105 auto lightActorSpot = vtkSmartPointer<vtkLightActor>::New();
106 lightActorSpot->SetLight(lightVtk);
107 m_debugVtkActors.push_back(lightActorSpot);
109 else if (name == PointLight::getStaticTypeName())
111 auto lightVtk = vtkSmartPointer<vtkLight>::New();
112 lightVtk->SetPositional(
true);
113 const Color& color = light->getColor();
114 lightVtk->SetColor(color.r, color.g, color.b);
115 lightVtk->SetIntensity(light->getIntensity());
116 lightVtk->SetFocalPoint(light->getFocalPoint().data());
117 lightVtk->SetAttenuationValues(light->getAttenuationValues().data());
119 auto pointLight = std::dynamic_pointer_cast<
PointLight>(light);
120 lightVtk->SetPosition(pointLight->getPosition().data());
122 m_vtkLights.push_back(VtkLightPair(light, lightVtk));
124 auto lightActorPoint = vtkSmartPointer<vtkLightActor>::New();
125 lightActorPoint->SetLight(lightVtk);
126 m_debugVtkActors.push_back(lightActorPoint);
130 LOG(WARNING) <<
"Light type undefined!";
134 for (
const auto& light : m_vtkLights)
136 m_vtkRenderer->AddLight(light.second);
142 m_camera = vtkSmartPointer<vtkCamera>::New();
146 m_camera = vtkSmartPointer<vtkOpenVRCamera>::New();
150 vtkNew<vtkCameraActor> camActor;
151 camActor->SetCamera(m_camera);
152 m_debugVtkActors.push_back(camActor);
155 m_vtkRenderer->SetBackground(m_config->m_BGColor1.r, m_config->m_BGColor1.g, m_config->m_BGColor1.b);
156 m_vtkRenderer->SetBackground2(m_config->m_BGColor2.r, m_config->m_BGColor2.g, m_config->m_BGColor2.b);
158 m_vtkRenderer->GradientBackgroundOn();
162 if (
auto culler = m_vtkRenderer->GetCullers()->GetLastItem())
164 m_vtkRenderer->RemoveCuller(culler);
168 connect<Event>(m_scene, &Scene::modified,
173 m_timeTableChart = vtkSmartPointer<vtkChartXY>::New();
174 vtkSmartPointer<vtkContextScene> m_benchmarkChartScene = vtkSmartPointer<vtkContextScene>::New();
175 m_timeTableChartActor = vtkSmartPointer<vtkContextActor>::New();
176 m_vtkRenderer->AddActor(m_timeTableChartActor);
177 m_benchmarkChartScene->SetRenderer(m_vtkRenderer);
179 m_timeTableChart->SetAutoSize(
true);
180 m_timeTableChart->SetSize(vtkRectf(0.0, 0.0, 600.0, 600.0));
182 m_benchmarkChartScene->AddItem(m_timeTableChart);
183 m_timeTableChartActor->SetScene(m_benchmarkChartScene);
184 m_timeTableChartActor->SetVisibility(
false);
186 m_timeTablePlot = vtkPlotBar::SafeDownCast(m_timeTableChart->AddPlot(vtkChart::BAR));
187 m_timeTablePlot->SetColor(0.6, 0.1, 0.1);
188 m_timeTablePlot->SetOrientation(vtkPlotBar::HORIZONTAL);
189 m_timeTableChart->GetAxis(vtkAxis::BOTTOM)->SetTitle(
"ms");
190 m_timeTableChart->GetAxis(vtkAxis::LEFT)->SetTitle(
"");
191 m_timeTableChart->GetAxis(vtkAxis::LEFT)->GetLabelProperties()->SetVerticalJustification(VTK_TEXT_CENTERED);
192 m_timeTableChart->GetAxis(vtkAxis::LEFT)->GetLabelProperties()->SetJustification(VTK_TEXT_RIGHT);
194 m_timeTable = vtkSmartPointer<vtkTable>::New();
195 vtkSmartPointer<vtkDoubleArray> xIndices = vtkSmartPointer<vtkDoubleArray>::New();
196 xIndices->SetName(
"Indices");
197 xIndices->SetNumberOfValues(0);
198 vtkSmartPointer<vtkDoubleArray> yElapsedTimes = vtkSmartPointer<vtkDoubleArray>::New();
199 yElapsedTimes->SetName(
"Elapsed Times");
200 yElapsedTimes->SetNumberOfValues(0);
201 vtkSmartPointer<vtkStringArray> labels = vtkSmartPointer<vtkStringArray>::New();
202 labels->SetName(
"Labels");
203 labels->SetNumberOfValues(0);
204 m_timeTable->AddColumn(xIndices);
205 m_timeTable->AddColumn(yElapsedTimes);
206 m_timeTable->AddColumn(labels);
207 m_timeTablePlot->SetInputData(m_timeTable, 0, 1);
209 m_timeTableChart->GetAxis(vtkAxis::BOTTOM)->GetLabelProperties()->SetColor(1.0, 1.0, 1.0);
210 vtkAxis* axisY = m_timeTableChart->GetAxis(vtkAxis::LEFT);
211 axisY->GetLabelProperties()->SetColor(1.0, 1.0, 1.0);
212 axisY->SetGridVisible(
false);
213 axisY->SetCustomTickPositions(xIndices, labels);
217 m_ssaoPass->SetDelegatePass(m_renderStepsPass);
221 m_isInitialized =
true;
231 if (mode == Mode::Empty && m_currentMode != Mode::Empty)
234 m_vtkRenderer->RemoveAllLights();
236 if (m_currentMode == Mode::Debug)
241 else if (mode == Mode::Debug && m_currentMode != Mode::Debug)
245 if (m_currentMode == Mode::Empty)
248 for (
const auto& light : m_vtkLights)
250 m_vtkRenderer->AddLight(light.second);
254 else if (mode == Mode::Simulation && m_currentMode != Mode::Simulation)
256 if (m_currentMode == Mode::Empty)
259 for (
const auto& light : m_vtkLights)
261 m_vtkRenderer->AddLight(light.second);
264 else if (m_currentMode == Mode::Debug)
271 m_camera = vtkSmartPointer<vtkCamera>::New();
280 std::vector<std::pair<std::string, double>> nameToTimesVec(timeTable.begin(), timeTable.end());
281 std::sort(nameToTimesVec.begin(), nameToTimesVec.end(),
282 [](
const std::pair<std::string, double>& a,
const std::pair<std::string, double>& b) {
return a.second < b.second; });
285 vtkSmartPointer<vtkDoubleArray> xIndices = vtkDoubleArray::SafeDownCast(m_timeTable->GetColumn(0));
286 vtkSmartPointer<vtkDoubleArray> yElapsedTimes = vtkDoubleArray::SafeDownCast(m_timeTable->GetColumn(1));
287 vtkSmartPointer<vtkStringArray> labels = vtkStringArray::SafeDownCast(m_timeTable->GetColumn(2));
289 labels->SetNumberOfValues(nameToTimesVec.size());
290 xIndices->SetNumberOfValues(nameToTimesVec.size());
291 yElapsedTimes->SetNumberOfValues(nameToTimesVec.size());
292 for (
size_t i = 0; i < nameToTimesVec.size(); i++)
294 labels->SetValue(i, nameToTimesVec[i].first.c_str());
295 xIndices->SetValue(i, i + 1);
296 yElapsedTimes->SetValue(i, nameToTimesVec[i].second);
300 vtkAxis* botAxis = m_timeTableChart->GetAxis(vtkAxis::BOTTOM);
303 double newMaxElapsed = yElapsedTimes->GetRange()[1];
304 yElapsedTimes->Modified();
305 double currMaxElapsed = botAxis->GetMaximum();
308 if (newMaxElapsed > currMaxElapsed)
310 botAxis->SetRange(0.0, newMaxElapsed);
316 if (m_timeTableIter % 400 == 0)
318 botAxis->SetRange(0.0, newMaxElapsed);
322 botAxis->SetRange(0.0, currMaxElapsed);
328 vtkAxis* leftAxis = m_timeTableChart->GetAxis(vtkAxis::LEFT);
329 leftAxis->SetRange(xIndices->GetRange());
330 leftAxis->SetCustomTickPositions(xIndices, labels);
332 m_timeTable->Modified();
338 m_timeTableChartActor->SetVisibility(visible);
342 VTKRenderer::getTimeTableVisibility()
const 344 return m_timeTableChartActor->GetVisibility();
350 std::shared_ptr<Camera> cam = m_scene->getActiveCamera();
354 if (
auto vtkVRCam = vtkOpenVRCamera::SafeDownCast(m_camera))
357 vtkMatrix4x4* finalView = m_camera->GetModelViewTransformMatrix();
358 for (
int i = 0; i < 4; i++)
360 for (
int j = 0; j < 4; j++)
362 cam->m_hmdView(i, j) = finalView->GetElement(j, i);
372 const Mat4d& invView = cam->getInvView();
374 const double eyePos[3] = { invView(0, 3), invView(1, 3), invView(2, 3) };
375 const double forward[3] = { invView(0, 2), invView(1, 2), invView(2, 2) };
376 const double up[3] = { invView(0, 1), invView(1, 1), invView(2, 1) };
378 m_camera->SetPosition(eyePos);
379 m_camera->SetFocalPoint(eyePos[0] - forward[0], eyePos[1] - forward[1], eyePos[2] - forward[2]);
380 m_camera->SetViewUp(up[0], up[1], up[2]);
381 m_camera->SetViewAngle(cam->getFieldOfView());
383 m_camera->SetClippingRange(cam->getNearZ(), cam->getFarZ());
386 auto projVtk = vtkSmartPointer<vtkMatrix4x4>::Take(m_camera->GetProjectionTransformMatrix(m_vtkRenderer));
387 for (
int i = 0; i < 4; i++)
389 for (
int j = 0; j < 4; j++)
391 cam->m_proj(i, j) = projVtk->GetElement(j, i);
400 for (
auto delegate : m_renderDelegates)
402 delegate.second->update();
407 for (
auto light : m_vtkLights)
409 std::shared_ptr<Light> lightImstk = light.first;
410 vtkSmartPointer<vtkLight> lightVtk = light.second;
411 std::string lightName = lightImstk->getTypeName();
412 if (lightName ==
"DirectionalLight")
414 const Color& color = lightImstk->getColor();
415 lightVtk->SetColor(color.r, color.g, color.b);
416 lightVtk->SetIntensity(lightImstk->getIntensity());
417 lightVtk->SetFocalPoint(lightImstk->getFocalPoint().data());
418 lightVtk->SetPosition(0.0, 0.0, 0.0);
419 lightVtk->SetAttenuationValues(lightImstk->getAttenuationValues().data());
421 else if (lightName ==
"SpotLight")
423 const Color& color = lightImstk->getColor();
424 lightVtk->SetColor(color.r, color.g, color.b);
425 lightVtk->SetIntensity(lightImstk->getIntensity());
426 lightVtk->SetFocalPoint(lightImstk->getFocalPoint().data());
428 auto spotLight = std::dynamic_pointer_cast<
SpotLight>(lightImstk);
429 lightVtk->SetPosition(spotLight->getPosition().data());
430 lightVtk->SetConeAngle(spotLight->getSpotAngle());
431 lightVtk->SetAttenuationValues(lightImstk->getAttenuationValues().data());
433 else if (lightName ==
"PointLight")
435 const Color& color = lightImstk->getColor();
436 lightVtk->SetColor(color.r, color.g, color.b);
437 lightVtk->SetIntensity(lightImstk->getIntensity());
438 lightVtk->SetFocalPoint(lightImstk->getFocalPoint().data());
439 lightVtk->SetAttenuationValues(lightImstk->getAttenuationValues().data());
441 auto pointLight = std::dynamic_pointer_cast<
PointLight>(lightImstk);
442 lightVtk->SetPosition(pointLight->getPosition().data());
450 for (
const auto& actor : actorList)
452 m_vtkRenderer->RemoveActor(actor);
459 for (
const auto& actor : actorList)
461 m_vtkRenderer->AddActor(actor);
468 m_renderedObjects.insert(entity);
469 m_renderedVisualModels[entity] = std::unordered_set<std::shared_ptr<VisualModel>>();
472 connect<Event>(entity, &Entity::modified,
473 std::static_pointer_cast<
VTKRenderer>(shared_from_this()),
482 renderDelegate->initialize(visualModel);
483 if (renderDelegate ==
nullptr)
485 LOG(WARNING) <<
"error: Could not create render delegate for '" 486 << sceneObject->getName() <<
"'.";
489 renderDelegate->setTextureManager(m_textureManager);
491 m_renderedVisualModels[sceneObject].insert(visualModel);
492 m_objectVtkActors.push_back(renderDelegate->getVtkActor());
493 m_vtkRenderer->AddActor(renderDelegate->getVtkActor());
495 if (
auto smRenderDelegate = std::dynamic_pointer_cast<VTKSurfaceMeshRenderDelegate>(renderDelegate))
497 smRenderDelegate->initializeTextures();
500 visualModel->setRenderDelegateCreated(
this,
true);
503 std::unordered_set<std::shared_ptr<VisualModel>>::iterator
506 auto renderDelegate = m_renderDelegates[visualModel];
507 auto iter = std::find(m_objectVtkActors.begin(), m_objectVtkActors.end(), renderDelegate->getVtkActor());
508 if (iter != m_objectVtkActors.end())
510 m_objectVtkActors.erase(iter);
512 m_vtkRenderer->RemoveActor(renderDelegate->getVtkActor());
514 m_renderDelegates.erase(visualModel);
515 return m_renderedVisualModels[sceneObject].erase(m_renderedVisualModels[sceneObject].find(visualModel));
518 std::unordered_set<std::shared_ptr<Entity>>::iterator
521 auto iter = m_renderedObjects.erase(m_renderedObjects.find(entity));
524 for (
auto visualModel : entity->getComponents<
VisualModel>())
529 m_renderedVisualModels.erase(entity);
532 disconnect(entity, std::static_pointer_cast<VTKRenderer>(shared_from_this()),
533 &SceneObject::modified);
541 for (
auto ent : m_scene->getSceneObjects())
543 if (m_renderedObjects.count(ent) == 0)
549 for (
auto i = m_renderedObjects.begin(); i != m_renderedObjects.end();)
551 auto sos = m_scene->getSceneObjects();
552 if (sos.find(*i) == sos.end())
566 Entity* sceneObject =
static_cast<Entity*
>(e->m_sender);
567 if (sceneObject !=
nullptr)
570 auto iter = std::find_if(m_renderedObjects.begin(), m_renderedObjects.end(),
571 [sceneObject](
const std::shared_ptr<Entity>& i) {
return i.get() == sceneObject; });
572 if (iter != m_renderedObjects.end())
583 if (m_renderedObjects.count(sceneObject) == 0 || m_renderedVisualModels.count(sceneObject) == 0)
591 const auto& visualModels = sceneObject->getComponents<
VisualModel>();
592 for (
auto visualModel : visualModels)
594 if (m_renderedVisualModels[sceneObject].count(visualModel) == 0)
600 for (
auto i = m_renderedVisualModels[sceneObject].begin(); i != m_renderedVisualModels[sceneObject].end(); i++)
602 auto iter = std::find(visualModels.begin(), visualModels.end(), *i);
603 if (iter == visualModels.end())
613 m_vtkRenderer->SetBackground(backgroundOne.x(), backgroundOne.y(), backgroundOne.z());
614 if (gradientBackground)
616 m_vtkRenderer->SetBackground2(backgroundTwo.x(), backgroundTwo.y(), backgroundTwo.z());
617 m_vtkRenderer->GradientBackgroundOn();
621 m_vtkRenderer->GradientBackgroundOff();
631 if (m_config->m_ssaoConfig.m_enableSSAO)
633 m_config->m_ssaoConfig.m_SSAOBlur ? m_ssaoPass->BlurOn() : m_ssaoPass->BlurOff();
634 m_ssaoPass->SetRadius(m_config->m_ssaoConfig.m_SSAORadius);
635 m_ssaoPass->SetBias(m_config->m_ssaoConfig.m_SSAOBias);
636 m_ssaoPass->SetKernelSize(m_config->m_ssaoConfig.m_KernelSize);
638 m_ssaoPass->SetDelegatePass(m_renderStepsPass);
639 m_vtkRenderer->SetPass(m_ssaoPass);
643 m_vtkRenderer->SetPass(
nullptr);
647 m_vtkRenderer->SetBackground(m_config->m_BGColor1.r, m_config->m_BGColor1.g, m_config->m_BGColor1.b);
648 m_vtkRenderer->SetBackground2(m_config->m_BGColor2.r, m_config->m_BGColor2.g, m_config->m_BGColor2.b);
652 VTKRenderer::setDebugActorsVisible(
const bool debugActorsVisible)
654 m_debugActorsVisible = debugActorsVisible;
655 for (
auto debugActors : m_debugVtkActors)
657 debugActors->SetVisibility(debugActorsVisible);
void updateBackground(const Vec3d color1, const Vec3d color2=Vec3d::Zero(), const bool gradientBackground=false)
Update background colors.
void sceneModifed(Event *e)
Callback for when the scene this renderer renders is modified This involves adding/removing scene obj...
void setTimeTableVisibility(const bool visible) override
Get/Set the visibility of the benchmark graph.
friend void disconnect(std::shared_ptr< EventObject >, std::shared_ptr< EventObject >, std::string(*)())
Remove an observer from the sender.
void addVisualModel(std::shared_ptr< Entity > sceneObject, std::shared_ptr< VisualModel > visualModel)
Add a VisualModel to be rendered, creates a delegate for it.
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
void updateCamera()
Updates the camera.
void addEntity(std::shared_ptr< Entity > sceneObject)
Adds an entity to be rendered.
void setTimeTable(const std::unordered_map< std::string, double > &timeTable) override
Sets the benchmarking table using unordered_map.
void addActors(const std::vector< vtkSmartPointer< vtkProp >> &actorList)
Add actors (also called props) from the scene.
std::unordered_set< std::shared_ptr< Entity > >::iterator removeEntity(std::shared_ptr< Entity > sceneObject)
Removes a SceneObject to be rendered.
void setConfig(std::shared_ptr< RendererConfig > config) override
Apply configuration changes.
virtual void setMode(const Renderer::Mode mode, const bool enableVR)
Set rendering mode.
static std::shared_ptr< VTKRenderDelegate > makeDelegate(std::shared_ptr< VisualModel > visualModel)
Instantiate proper render delegate.
void setMode(const Mode mode, const bool enableVR) override
Set the rendering mode to display debug actors or not.
void entityModified(Event *e)
Callback for when a SceneObject is modified This involves adding/removing visual models to render lis...
vtkSmartPointer< vtkRenderer > getVtkRenderer() const
Returns VTK renderer.
std::unordered_set< std::shared_ptr< VisualModel > >::iterator removeVisualModel(std::shared_ptr< Entity > sceneObject, std::shared_ptr< VisualModel > visualModel)
Remove a VisualModel from rendering.
Top-level class for entities. Entities contain a collection of components which define how to be used...
The TextureManager provides delegates for textures, it will create new ones and cache old ones...
couples a imstk texture to a VTK texture
A point light has a position, and it's range is determined by it's intensity.
Mode
Enumerations for the render mode.
VTKRenderer(std::shared_ptr< Scene > scene, const bool enableVR)
Scene is tied to this renderer.
void removeActors(const std::vector< vtkSmartPointer< vtkProp >> &actorList)
Remove actors (also called props) from the scene.
Contains geometric, material, and render information.
void initialize() override
Create the rendering delegates and related VTK objects according to the scene.
void updateRenderDelegates()
Updates the render delegates.