From 7dffdcbc80e9723c5b2161134d87e37baabd6132 Mon Sep 17 00:00:00 2001
From: Alexis Girault <alexis.girault@kitware.com>
Date: Thu, 7 Apr 2016 14:47:20 -0400
Subject: [PATCH] ENH: add Render mode option

- SIMULATION adds the object actors and set the
interactor style to no interactions.
- DEBUG adds additional actors to visualize
lights, the camera, axis, and set the interactor
style to trackball to interact with the scene.
---
 Base/Rendering/CMakeLists.txt                 |   2 +
 Base/Rendering/imstkRenderer.cpp              | 149 ++++++++++++++++++
 Base/Rendering/imstkRenderer.h                |  70 ++++++++
 Base/Rendering/imstkViewer.cpp                | 121 +++++++-------
 Base/Rendering/imstkViewer.h                  |  25 +--
 .../imstkSimulationManager.cpp                |  10 +-
 .../imstkSimulationManager.h                  |   3 +-
 Examples/Sandbox/main.cpp                     |   4 +-
 8 files changed, 298 insertions(+), 86 deletions(-)
 create mode 100644 Base/Rendering/imstkRenderer.cpp
 create mode 100644 Base/Rendering/imstkRenderer.h

diff --git a/Base/Rendering/CMakeLists.txt b/Base/Rendering/CMakeLists.txt
index 489aa5c56..f9e62a9e3 100644
--- a/Base/Rendering/CMakeLists.txt
+++ b/Base/Rendering/CMakeLists.txt
@@ -5,12 +5,14 @@ include(imstkAddLibrary)
 imstk_add_library( Rendering
   H_FILES
     imstkViewer.h
+    imstkRenderer.h
     imstkRenderDelegate.h
     imstkPlaneRenderDelegate.h
     imstkSphereRenderDelegate.h
     imstkCubeRenderDelegate.h
   CPP_FILES
     imstkViewer.cpp
+    imstkRenderer.cpp
     imstkRenderDelegate.cpp
     imstkPlaneRenderDelegate.cpp
     imstkSphereRenderDelegate.cpp
diff --git a/Base/Rendering/imstkRenderer.cpp b/Base/Rendering/imstkRenderer.cpp
new file mode 100644
index 000000000..39537e516
--- /dev/null
+++ b/Base/Rendering/imstkRenderer.cpp
@@ -0,0 +1,149 @@
+/*=========================================================================
+
+   Library: iMSTK
+
+   Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+   & Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+   =========================================================================*/
+
+#include "imstkRenderer.h"
+
+#include "imstkRenderDelegate.h"
+
+#include "vtkLight.h"
+#include "vtkLightActor.h"
+#include "vtkCamera.h"
+#include "vtkCameraActor.h"
+#include "vtkAxesActor.h"
+
+#include "g3log/g3log.hpp"
+
+
+namespace imstk {
+Renderer::Renderer(std::shared_ptr<Scene> scene)
+{
+    // Object actors
+    for ( const auto& obj : scene->getSceneObjects() )
+    {
+        auto geom     = obj->getVisualGeometry();
+        auto delegate = RenderDelegate::make_delegate( geom );
+        m_objectVtkActors.push_back( delegate->getVtkActor() );
+    }
+
+    // Lights and light actors
+    for ( const auto& light : scene->getLights() )
+    {
+        m_vtkLights.push_back( light->getVtkLight() );
+        if( light->isPositional() )
+        {
+            auto lightActor = vtkSmartPointer<vtkLightActor>::New();
+            lightActor->SetLight( light->getVtkLight() );
+            m_debugVtkActors.push_back( lightActor );
+        }
+    }
+
+    // Camera and camera actor
+    m_sceneVtkCamera = scene->getCamera()->getVtkCamera();
+    auto camActor = vtkSmartPointer<vtkCameraActor>::New();
+    camActor->SetCamera(  m_sceneVtkCamera );
+    m_debugVtkActors.push_back( camActor );
+
+    // Global Axis
+    auto axes = vtkSmartPointer<vtkAxesActor>::New();
+    m_debugVtkActors.push_back( axes );
+
+    ///TODO : based on scene properties
+    // Customize background colors
+    m_vtkRenderer->SetBackground(0.66,0.66,0.66);
+    m_vtkRenderer->SetBackground2(157.0/255.0*0.66,186/255.0*0.66,192.0/255.0*0.66);
+    m_vtkRenderer->GradientBackgroundOn();
+}
+
+vtkSmartPointer<vtkRenderer>
+Renderer::getVtkRenderer() const
+{
+    return m_vtkRenderer;
+}
+
+void
+Renderer::setup(Mode mode)
+{
+    if( mode == Mode::EMPTY && m_currentMode != Mode::EMPTY )
+    {
+        m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
+
+        this->removeActors(m_objectVtkActors);
+        m_vtkRenderer->RemoveAllLights();
+
+        if( m_currentMode == Mode::DEBUG )
+        {
+            this->removeActors(m_debugVtkActors);
+        }
+    }
+    else if( mode == Mode::DEBUG && m_currentMode != Mode::DEBUG )
+    {
+        m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
+
+        this->addActors(m_debugVtkActors);
+
+        if( m_currentMode == Mode::EMPTY )
+        {
+            this->addActors(m_objectVtkActors);
+            for ( const auto& light : m_vtkLights )
+            {
+                m_vtkRenderer->AddLight(light);
+            }
+        }
+    }
+    else if ( mode == Mode::SIMULATION && m_currentMode != Mode::SIMULATION )
+    {
+        m_vtkRenderer->SetActiveCamera(m_sceneVtkCamera);
+
+        if( m_currentMode == Mode::EMPTY )
+        {
+            this->addActors(m_objectVtkActors);
+            for ( const auto& light : m_vtkLights )
+            {
+                m_vtkRenderer->AddLight(light);
+            }
+        }
+        else if( m_currentMode == Mode::DEBUG )
+        {
+            this->removeActors(m_debugVtkActors);
+        }
+    }
+
+    m_currentMode = mode;
+}
+
+void
+Renderer::removeActors(const std::vector<vtkSmartPointer<vtkProp>>& actorList)
+{
+    for ( const auto& actor : actorList )
+    {
+        m_vtkRenderer->RemoveActor(actor);
+    }
+}
+
+void
+Renderer::addActors(const std::vector<vtkSmartPointer<vtkProp>>& actorList)
+{
+    for ( const auto& actor : actorList )
+    {
+        m_vtkRenderer->AddActor(actor);
+    }
+}
+}
diff --git a/Base/Rendering/imstkRenderer.h b/Base/Rendering/imstkRenderer.h
new file mode 100644
index 000000000..8804cfea6
--- /dev/null
+++ b/Base/Rendering/imstkRenderer.h
@@ -0,0 +1,70 @@
+/*=========================================================================
+
+   Library: iMSTK
+
+   Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+   & Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+   =========================================================================*/
+
+#ifndef imstkRenderer_h
+#define imstkRenderer_h
+
+#include <memory>
+#include <vector>
+
+#include "imstkScene.h"
+
+#include "vtkSmartPointer.h"
+#include "vtkRenderer.h"
+#include "vtkProp.h"
+
+namespace imstk {
+
+class Renderer
+{
+public:
+
+    enum Mode
+    {
+        EMPTY,
+        DEBUG,
+        SIMULATION
+    };
+
+    Renderer(std::shared_ptr<Scene> scene);
+    ~ Renderer() = default;
+
+    void setup(Mode mode);
+
+    vtkSmartPointer<vtkRenderer> getVtkRenderer() const;
+
+protected:
+
+    void removeActors(const std::vector<vtkSmartPointer<vtkProp>>& actorList);
+    void addActors(const std::vector<vtkSmartPointer<vtkProp>>& actorList);
+
+    vtkSmartPointer<vtkRenderer> m_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
+    vtkSmartPointer<vtkCamera> m_defaultVtkCamera = vtkSmartPointer<vtkCamera>::New();
+    vtkSmartPointer<vtkCamera> m_sceneVtkCamera;
+    std::vector<vtkSmartPointer<vtkLight>> m_vtkLights;
+    std::vector<vtkSmartPointer<vtkProp>> m_objectVtkActors;
+    std::vector<vtkSmartPointer<vtkProp>> m_debugVtkActors;
+
+    Mode m_currentMode = Mode::EMPTY;
+};
+}
+
+#endif // ifndef imstkRenderer_h
diff --git a/Base/Rendering/imstkViewer.cpp b/Base/Rendering/imstkViewer.cpp
index a12eb89a6..10e3458a4 100644
--- a/Base/Rendering/imstkViewer.cpp
+++ b/Base/Rendering/imstkViewer.cpp
@@ -21,12 +21,6 @@
 
 #include "imstkViewer.h"
 
-#include "vtkRenderer.h"
-#include "vtkLight.h"
-#include "vtkLightActor.h"
-#include "vtkCamera.h"
-#include "vtkCameraActor.h"
-#include "vtkAxesActor.h"
 #include "vtkInteractorStyleTrackballCamera.h"
 
 #include "g3log/g3log.hpp"
@@ -34,96 +28,87 @@
 #include "imstkRenderDelegate.h"
 
 namespace imstk {
+std::shared_ptr<Scene>
+Viewer::getCurrentScene() const
+{
+    return m_currentScene;
+}
+
 void
-Viewer::initRenderer()
+Viewer::setCurrentScene(std::shared_ptr<Scene>scene)
 {
-    // Check current Scene
-    if (m_currentScene == nullptr)
+    // If already current scene
+    if( scene == m_currentScene )
     {
-        LOG(WARNING) << "No scene specified, nothing to render.";
+        LOG(WARNING) << scene->getName() << " already is the viewer current scene.";
         return;
     }
 
-    // Create and add renderer
-    auto renderer = vtkSmartPointer<vtkRenderer>::New();
-    //renderer->UseShadowsOn();
-    m_renderWindow->AddRenderer(renderer);
-
-    // Create and add actors
-    for (const auto& obj : m_currentScene->getSceneObjects())
-    {
-        auto geom     = obj->getVisualGeometry();
-        auto delegate = RenderDelegate::make_delegate(geom);
-        renderer->AddActor(delegate->getVtkActor());
-    }
-
-    // Add lights
-    for (const auto& light : m_currentScene->getLights())
+    // If the current scene has a renderer, remove it
+    if( m_currentScene )
     {
-        renderer->AddLight( light->getVtkLight() );
-        if( light->isPositional() )
+        auto vtkRenderer = m_rendererMap.at(m_currentScene)->getVtkRenderer();
+        if(m_vtkRenderWindow->HasRenderer(vtkRenderer))
         {
-            auto lightActor = vtkSmartPointer<vtkLightActor>::New();
-            lightActor->SetLight( light->getVtkLight() );
-            renderer->AddActor( lightActor );
+            m_vtkRenderWindow->RemoveRenderer(vtkRenderer);
         }
     }
 
-    // Add camera
-    //auto camActor = vtkSmartPointer<vtkCameraActor>::New();
-    //camActor->SetCamera(  m_currentScene->getCamera()->getVtkCamera() );
-    //renderer->AddActor( camActor );
-    //renderer->GetActiveCamera()->SetFocalPoint(0,0,0);
-    renderer->SetActiveCamera( m_currentScene->getCamera()->getVtkCamera() );
-    renderer->ResetCameraClippingRange();
-
+    // Update current scene
+    m_currentScene = scene;
 
-    // Global Axis
-    auto axes = vtkSmartPointer<vtkAxesActor>::New();
-    renderer->AddActor(axes);
+    // Create renderer if it doesn't exist
+    if (!m_rendererMap.count(m_currentScene))
+    {
+        m_rendererMap[m_currentScene] = std::make_shared<Renderer>(m_currentScene);
+    }
 
-    // Customize background colors
-    renderer->SetBackground(0.66,0.66,0.66);
-    renderer->SetBackground2(157.0/255.0*0.66,186/255.0*0.66,192.0/255.0*0.66);
-    renderer->GradientBackgroundOn();
+    // Set renderer to renderWindow
+    m_vtkRenderWindow->AddRenderer(m_rendererMap.at(m_currentScene)->getVtkRenderer());
 }
 
 void
-Viewer::startRenderingLoop()
+Viewer::setRenderingMode(Renderer::Mode mode)
 {
-    auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
-    m_interactor->SetInteractorStyle( style );
-    m_interactor->SetRenderWindow( m_renderWindow );
-    m_interactor->Start();
-}
+    if( !m_currentScene )
+    {
+        LOG(WARNING) << "Missing scene, can not set rendering mode.\n"
+                     << "Use Viewer::setCurrentScene to setup scene.";
+        return;
+    }
 
-void
-Viewer::endRenderingLoop()
-{
-    m_interactor->TerminateApp();
-}
+    // Setup renderer
+    m_rendererMap.at(m_currentScene)->setup(mode);
 
-vtkSmartPointer<vtkRenderWindow>
-Viewer::getRenderWindow() const
-{
-    return m_renderWindow;
+    // Setup interactor style
+    if( mode == Renderer::Mode::DEBUG )
+    {
+        auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
+        m_vtkInteractor->SetInteractorStyle( style );
+    }
+    else if( mode == Renderer::Mode::SIMULATION )
+    {
+        auto style = vtkSmartPointer<vtkInteractorStyle>::New();
+        m_vtkInteractor->SetInteractorStyle( style );
+    }
 }
 
 void
-Viewer::setRenderWindow(vtkSmartPointer<vtkRenderWindow>renWin)
+Viewer::startRenderingLoop()
 {
-    m_renderWindow = renWin;
+    // Start interaction loop
+    m_vtkInteractor->Start();
 }
 
-std::shared_ptr<Scene>
-Viewer::getCurrentScene() const
+void
+Viewer::endRenderingLoop()
 {
-    return m_currentScene;
+    m_vtkInteractor->TerminateApp();
 }
 
-void
-Viewer::setCurrentScene(std::shared_ptr<Scene>scene)
+vtkSmartPointer<vtkRenderWindow>
+Viewer::getVtkRenderWindow() const
 {
-    m_currentScene = scene;
+    return m_vtkRenderWindow;
 }
 }
diff --git a/Base/Rendering/imstkViewer.h b/Base/Rendering/imstkViewer.h
index 574f089ef..ad892398b 100644
--- a/Base/Rendering/imstkViewer.h
+++ b/Base/Rendering/imstkViewer.h
@@ -23,8 +23,10 @@
 #define imstkViewer_h
 
 #include <memory>
+#include <unordered_map>
 
 #include "imstkScene.h"
+#include "imstkRenderer.h"
 
 #include "vtkSmartPointer.h"
 #include "vtkRenderWindow.h"
@@ -37,27 +39,28 @@ public:
 
     Viewer(std::string name = "iMSTK Viewer")
     {
-        m_renderWindow->SetWindowName(name.data());
-        m_renderWindow->SetSize(1000,800);
+        m_vtkInteractor->SetRenderWindow( m_vtkRenderWindow );
+        m_vtkRenderWindow->SetWindowName(name.data());
+        m_vtkRenderWindow->SetSize(1000,800);
     }
 
     ~Viewer() = default;
 
-    void                            initRenderer();
-    void                            startRenderingLoop();
-    void                            endRenderingLoop();
+    std::shared_ptr<Scene> getCurrentScene() const;
+    void setCurrentScene(std::shared_ptr<Scene>scene);
+    void setRenderingMode(Renderer::Mode mode);
+    void startRenderingLoop();
+    void endRenderingLoop();
 
-    vtkSmartPointer<vtkRenderWindow>getRenderWindow() const;
-    void                            setRenderWindow(vtkSmartPointer<vtkRenderWindow>renWin);
+    vtkSmartPointer<vtkRenderWindow>getVtkRenderWindow() const;
 
-    std::shared_ptr<Scene>          getCurrentScene() const;
-    void                            setCurrentScene(std::shared_ptr<Scene>scene);
 
 protected:
 
-    vtkSmartPointer<vtkRenderWindow> m_renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
-    vtkSmartPointer<vtkRenderWindowInteractor> m_interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
+    vtkSmartPointer<vtkRenderWindow> m_vtkRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
+    vtkSmartPointer<vtkRenderWindowInteractor> m_vtkInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
     std::shared_ptr<Scene> m_currentScene;
+    std::unordered_map<std::shared_ptr<Scene>, std::shared_ptr<Renderer>> m_rendererMap;
 };
 }
 
diff --git a/Base/SimulationManager/imstkSimulationManager.cpp b/Base/SimulationManager/imstkSimulationManager.cpp
index 835e06583..770fb4f88 100644
--- a/Base/SimulationManager/imstkSimulationManager.cpp
+++ b/Base/SimulationManager/imstkSimulationManager.cpp
@@ -114,7 +114,7 @@ SimulationManager::getViewer() const
 }
 
 void
-SimulationManager::startSimulation(std::string sceneName)
+SimulationManager::startSimulation(std::string sceneName, Renderer::Mode renderMode)
 {
     LOG(INFO) << "Starting simulation.";
 
@@ -139,9 +139,9 @@ SimulationManager::startSimulation(std::string sceneName)
         return;
     }
 
-    // Init viewer renderer
+    // Init viewer
     m_viewer->setCurrentScene(startingScene);
-    m_viewer->initRenderer();
+    m_viewer->setRenderingMode(renderMode);
 
     // Start scene
     this->startModuleInNewThread(startingScene);
@@ -181,7 +181,9 @@ SimulationManager::switchScene(std::string newSceneName, bool unloadCurrentScene
         return;
     }
 
-    // TODO : update viewer
+    // Update viewer
+    m_viewer->setCurrentScene(newScene);
+    m_viewer->setRenderingMode(Renderer::Mode::SIMULATION);
 
     if (unloadCurrentScene)
     {
diff --git a/Base/SimulationManager/imstkSimulationManager.h b/Base/SimulationManager/imstkSimulationManager.h
index 1efdc3c54..4a03c8e36 100644
--- a/Base/SimulationManager/imstkSimulationManager.h
+++ b/Base/SimulationManager/imstkSimulationManager.h
@@ -60,7 +60,8 @@ public:
     std::shared_ptr<Viewer> getViewer() const;
 
     // Simulation
-    void                    startSimulation(std::string sceneName);
+    void                    startSimulation(std::string sceneName,
+                                            Renderer::Mode renderMode = Renderer::Mode::SIMULATION);
     void                    switchScene(std::string newSceneName,
                                         bool        unloadCurrentScene);
     void                    runSimulation();
diff --git a/Examples/Sandbox/main.cpp b/Examples/Sandbox/main.cpp
index 7468d1d90..ebf83c03f 100644
--- a/Examples/Sandbox/main.cpp
+++ b/Examples/Sandbox/main.cpp
@@ -34,7 +34,7 @@ int main()
 
     auto planeGeom = std::make_shared<imstk::Plane>();
 
-    planeGeom->scale(8);
+    planeGeom->scale(10);
     auto planeObj = std::make_shared<imstk::VisualObject>("VisualPlane");
     planeObj->setVisualGeometry(planeGeom);
 
@@ -75,7 +75,7 @@ int main()
     cam1->setPosition(imstk::Vec3d(-5.5, 2.5, 32));
     cam1->setFocalPoint(imstk::Vec3d(1, 1, 0));
 
-    sdk->startSimulation("SceneTest");
+    sdk->startSimulation("SceneTest", imstk::Renderer::Mode::DEBUG );
 
 
     /*
-- 
GitLab