diff --git a/CMakeExternals/VTK-8.1.0.patch b/CMakeExternals/VTK-8.1.0.patch new file mode 100644 index 0000000000..2082d02688 --- /dev/null +++ b/CMakeExternals/VTK-8.1.0.patch @@ -0,0 +1,80 @@ +diff --git a/Rendering/Core/vtkAssembly.cxx b/Rendering/Core/vtkAssembly.cxx +index 79e4d42b65..b17c74e659 100644 +--- a/Rendering/Core/vtkAssembly.cxx ++++ b/Rendering/Core/vtkAssembly.cxx +@@ -116,6 +116,7 @@ int vtkAssembly::RenderTranslucentPolygonalGeometry(vtkViewport *ren) + vtkProp3D* prop3D = static_cast(path->GetLastNode()->GetViewProp()); + if ( prop3D->GetVisibility() ) + { ++ prop3D->SetPropertyKeys(this->GetPropertyKeys()); + prop3D->SetAllocatedRenderTime(fraction, ren); + prop3D->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop3D->RenderTranslucentPolygonalGeometry(ren); +@@ -143,6 +144,7 @@ int vtkAssembly::HasTranslucentPolygonalGeometry() + vtkProp3D* prop3D = static_cast(path->GetLastNode()->GetViewProp()); + if ( prop3D->GetVisibility() ) + { ++ prop3D->SetPropertyKeys(this->GetPropertyKeys()); + result = prop3D->HasTranslucentPolygonalGeometry(); + } + } +@@ -175,6 +177,7 @@ int vtkAssembly::RenderVolumetricGeometry(vtkViewport *ren) + vtkProp3D* prop3D = static_cast(path->GetLastNode()->GetViewProp()); + if (prop3D->GetVisibility()) + { ++ prop3D->SetPropertyKeys(this->GetPropertyKeys()); + prop3D->SetAllocatedRenderTime(fraction, ren); + prop3D->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop3D->RenderVolumetricGeometry(ren); +@@ -210,6 +213,7 @@ int vtkAssembly::RenderOpaqueGeometry(vtkViewport *ren) + vtkProp3D* prop3D = static_cast(path->GetLastNode()->GetViewProp()); + if (prop3D->GetVisibility()) + { ++ prop3D->SetPropertyKeys(this->GetPropertyKeys()); + prop3D->PokeMatrix(path->GetLastNode()->GetMatrix()); + prop3D->SetAllocatedRenderTime(fraction, ren); + renderedSomething += prop3D->RenderOpaqueGeometry(ren); +diff --git a/Rendering/Core/vtkPropAssembly.cxx b/Rendering/Core/vtkPropAssembly.cxx +index 5033c3b66e..405b1a75ab 100644 +--- a/Rendering/Core/vtkPropAssembly.cxx ++++ b/Rendering/Core/vtkPropAssembly.cxx +@@ -97,6 +97,7 @@ int vtkPropAssembly::RenderTranslucentPolygonalGeometry(vtkViewport *ren) + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { ++ prop->SetPropertyKeys(this->GetPropertyKeys()); + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderTranslucentPolygonalGeometry(ren); +@@ -125,6 +126,7 @@ int vtkPropAssembly::HasTranslucentPolygonalGeometry() + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { ++ prop->SetPropertyKeys(this->GetPropertyKeys()); + result=prop->HasTranslucentPolygonalGeometry(); + } + } +@@ -154,6 +156,7 @@ int vtkPropAssembly::RenderVolumetricGeometry(vtkViewport *ren) + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { ++ prop->SetPropertyKeys(this->GetPropertyKeys()); + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderVolumetricGeometry(ren); +@@ -186,6 +189,7 @@ int vtkPropAssembly::RenderOpaqueGeometry(vtkViewport *ren) + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { ++ prop->SetPropertyKeys(this->GetPropertyKeys()); + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderOpaqueGeometry(ren); +@@ -217,6 +221,7 @@ int vtkPropAssembly::RenderOverlay(vtkViewport *ren) + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { ++ prop->SetPropertyKeys(this->GetPropertyKeys()); + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderOverlay(ren); diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index df6cffa27e..5000b167c7 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,85 +1,89 @@ #----------------------------------------------------------------------------- # VTK #----------------------------------------------------------------------------- if(WIN32) option(VTK_USE_SYSTEM_FREETYPE OFF) else() option(VTK_USE_SYSTEM_FREETYPE ON) endif() # Sanity checks if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR}) message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj VTK) set(proj_DEPENDENCIES ) set(VTK_DEPENDS ${proj}) if(MITK_USE_HDF5) list(APPEND proj_DEPENDENCIES HDF5) endif() if(NOT DEFINED VTK_DIR) set(additional_cmake_args ) # Optionally enable memory leak checks for any objects derived from vtkObject. This # will force unit tests to fail if they have any of these memory leaks. option(MITK_VTK_DEBUG_LEAKS OFF) mark_as_advanced(MITK_VTK_DEBUG_LEAKS) list(APPEND additional_cmake_args -DVTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS} -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF ) if(MITK_USE_Qt5) list(APPEND additional_cmake_args -DVTK_Group_Qt:BOOL=ON -DQt5_DIR:PATH=${Qt5_DIR} ) endif() if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() + + set (VTK_PATCH_OPTION + PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_LIST_DIR}/VTK-8.1.0.patch) mitk_query_custom_ep_vars() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-8.1.0.tar.gz URL_MD5 4fa5eadbc8723ba0b8d203f05376d932 + ${VTK_PATCH_OPTION} CMAKE_GENERATOR ${gen} CMAKE_GENERATOR_PLATFORM ${gen_platform} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE} -DVTK_LEGACY_REMOVE:BOOL=ON -DModule_vtkTestingRendering:BOOL=ON ${additional_cmake_args} ${${proj}_CUSTOM_CMAKE_ARGS} CMAKE_CACHE_ARGS ${ep_common_cache_args} ${${proj}_CUSTOM_CMAKE_CACHE_ARGS} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} ${${proj}_CUSTOM_CMAKE_CACHE_DEFAULT_ARGS} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h b/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h index 38831f3da4..a7e3f2db28 100644 --- a/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h +++ b/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h @@ -1,225 +1,225 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRenderingTestHelper_h #define mitkRenderingTestHelper_h #include #include #include #include #include class vtkRenderWindow; class vtkRenderer; namespace mitk { class MITKTESTINGHELPER_EXPORT RenderingTestHelper { public: /** @brief Generate a rendering test helper object including a render window of the size width * height (in pixel). @param argc Number of parameters. (here: Images) "Usage: [filename1 filenam2 -V referenceScreenshot (optional -T /directory/to/save/differenceImage)] @param argv Given parameters. If no data is inserted via commandline, you can add data later via AddNodeToDataStorage(). @param renderingMode The rendering mode. **/ RenderingTestHelper( int width, int height, int argc, char *argv[], - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::NoAntiAliasing); /** @brief Generate a rendering test helper object including a render window of the size width * height (in * pixel).*/ RenderingTestHelper( int width, int height, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::NoAntiAliasing); /** Default destructor */ ~RenderingTestHelper(); /** @brief Getter for the vtkRenderer. **/ vtkRenderer *GetVtkRenderer(); /** @brief Getter for the vtkRenderWindow which should be used to call vtkRegressionTestImage. **/ vtkRenderWindow *GetVtkRenderWindow(); /** @brief Method can be used to save a screenshot (e.g. reference screenshot as a .png file. @param fileName The filename of the new screenshot (including path). **/ void SaveAsPNG(std::string fileName); /** * @brief SetStopRenderWindow Convenience method to make the renderwindow hold after rendering. Usefull for * debugging. * @param flag Flag indicating whether the renderwindow should automatically close (false, default) or stay open * (true). Usefull for debugging. */ void SetAutomaticallyCloseRenderWindow(bool automaticallyCloseRenderWindow); /** @brief This method set the property of the member datastorage @param property Set a property for each image in the datastorage m_DataStorage. If you want to set the property for a single data node, use GetDataStorage() and set the property yourself for the destinct node. **/ void SetImageProperty(const char *propertyKey, mitk::BaseProperty *property); /** @brief Set the view direction of the renderwindow (e.g. sagittal, coronal, axial) **/ void SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection); /** @brief Reorient the slice (e.g. rotation and translation like the swivel mode). **/ void ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation); /** @brief Render everything into an mitkRenderWindow. Call SetViewDirection() and SetProperty() before this method. **/ void Render(); /** @brief Returns the datastorage, in order to modify the data inside a rendering test. **/ mitk::DataStorage::Pointer GetDataStorage(); /** * @brief SetMapperID Change between Standard2D and 3D mappers. * @param id Enum mitk::BaseRenderer::StandardMapperSlot which defines the mapper. */ void SetMapperID(mitk::BaseRenderer::StandardMapperSlot id); /** * @brief AddNodeToStorage Add a node to the datastorage and perform a reinit which is necessary for rendering. * @param node The data you want to add. */ void AddNodeToStorage(mitk::DataNode::Pointer node); /** * @brief SetMapperIDToRender3D Convenience method to render in a 3D renderwindow. * @warning Does not add helper objects like the image planes to render images in 3D. */ void SetMapperIDToRender3D(); /** * @brief SetMapperIDToRender2D Convenience method to render in a 2D renderwindow. */ void SetMapperIDToRender2D(); /** * @brief SaveReferenceScreenShot Convenience method to save a reference screen shot. * @param fileName Path/to/save/the/png/file. */ void SaveReferenceScreenShot(std::string fileName); /** * @brief CompareRenderWindowAgainstReference Convenience method to compare the image rendered in the internal renderwindow against a reference screen shot. * Usage of vtkTesting::Test: vtkTesting::Test( argc, argv, vtkRenderWindow, threshold ) Set a vtkRenderWindow containing the desired scene. This is automatically rendered. vtkTesting::Test() automatically searches in argc and argv[] for a path a valid image with -V. If the test failed with the first image (foo.png) it checks if there are images of the form foo_N.png (where N=1,2,3...) and compare against them. This allows for multiple valid images. * @param argc Number of arguments. * @param argv Arguments must(!) contain the term "-V Path/To/Valid/Image.png" * @param threshold Allowed difference between two images. Default = 10.0 and was taken from VTK. * @return True if the images are equal regarding the threshold. False in all other cases. */ bool CompareRenderWindowAgainstReference(int argc, char *argv[], double threshold = 10.0); /** @brief Returns true if the opengl context is compatible for advanced vtk effects **/ bool IsAdvancedOpenGL(); /** * @brief The ArgcHelperClass class is a convinience class to convert a vector * of strings to the standard c++ argv and argc arguments. This is necessary for * the vtkTesting::Test, since is requires the reference image (and other * optional parameters) via command line. */ class ArgcHelperClass { private: /** * Members for conversion. */ std::vector argv; std::vector> argvec; public: ArgcHelperClass(const std::vector &argstrings) : argv(argstrings.size() + 1), argvec(argstrings.size() + 1) { std::vector cmdArgs; cmdArgs.push_back(mitk::IOUtil::GetProgramPath()); cmdArgs.insert(cmdArgs.end(), argstrings.begin(), argstrings.end()); for (std::size_t i = 0; i < cmdArgs.size(); ++i) { argvec[i].assign(cmdArgs[i].begin(), cmdArgs[i].end()); argvec[i].push_back('\0'); argv[i] = &argvec[i][0]; } } char **GetArgv() { return &argv[0]; } int GetArgc() { return argv.size(); } }; protected: /** * @brief Initialize Internal method to initialize the renderwindow and set the datastorage. * @param width Height of renderwindow. * @param height Width of renderwindow. * @param renderingMode The rendering mode. */ void Initialize( int width, int height, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::NoAntiAliasing); /** @brief Prints the opengl information, e.g. version, vendor and extensions, * This function can only be called after an opengl context is active. * It only prints the context after the vtkRenderwindow is fully initialized. **/ void PrintGLInfo(); /** @brief This method tries to load the given file into a member datastorage, in order to render it. @param fileName The filename of the file to be loaded (including path). **/ void AddToStorage(const std::string &filename); /** @brief This method tries to parse the given argv for files (e.g. images) and load them into a member datastorage, in order to render it. @param argc Number of parameters. @param argv Given parameters. **/ void SetInputFileNames(int argc, char *argv[]); mitk::RenderWindow::Pointer m_RenderWindow; //<< Contains the mitkRenderWindow into which the test renders the data mitk::DataStorage::Pointer m_DataStorage; //<< Contains the mitkDataStorage which contains the data to be rendered bool m_AutomaticallyCloseRenderWindow; //<< Flag indicating whether the renderwindow should automatically close (true, // default) or stay open (false). Usefull for debugging. }; } // namespace mitk #endif diff --git a/Modules/Core/include/mitkBaseRenderer.h b/Modules/Core/include/mitkBaseRenderer.h index dd9ed0707a..d122e3c3fd 100644 --- a/Modules/Core/include/mitkBaseRenderer.h +++ b/Modules/Core/include/mitkBaseRenderer.h @@ -1,566 +1,568 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #define BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #include "mitkCameraRotationController.h" #include "mitkDataStorage.h" #include "mitkPlaneGeometry.h" #include "mitkPlaneGeometryData.h" #include "mitkSliceNavigationController.h" #include "mitkTimeGeometry.h" #include "mitkBindDispatcherInteractor.h" #include "mitkDispatcher.h" #include #include #include #include // DEPRECATED #include namespace mitk { class NavigationController; class SliceNavigationController; class CameraRotationController; class CameraController; class DataStorage; class Mapper; class BaseLocalStorageHandler; class KeyEvent; //##Documentation //## @brief Organizes the rendering process //## //## Organizes the rendering process. A Renderer contains a reference to a //## DataStorage and asks the mappers of the data objects to render //## the data into the renderwindow it is associated to. //## //## \#Render() checks if rendering is currently allowed by calling //## RenderWindow::PrepareRendering(). Initialization of a rendering context //## can also be performed in this method. //## //## The actual rendering code has been moved to \#Repaint() //## Both \#Repaint() and \#Update() are declared protected now. //## //## Note: Separation of the Repaint and Update processes (rendering vs //## creating a vtk prop tree) still needs to be worked on. The whole //## rendering process also should be reworked to use VTK based classes for //## both 2D and 3D rendering. //## @ingroup Renderer class MITKCORE_EXPORT BaseRenderer : public itk::Object { public: /** \brief This rendering mode enumeration is specified at various constructors * of the Renderer and RenderWindow classes, which autoconfigures the * respective VTK objects. This has to be done at construction time because later * configuring turns out to be not working on most platforms. */ struct RenderingMode { enum Type { - Standard = 0 + NoAntiAliasing = 0, + FastApproximateAntiAliasing = 1 // In contrast to MSAA, FXAA works with depth peeling as it is + // applied as a post-processing pass. }; }; typedef std::map BaseRendererMapType; static BaseRendererMapType baseRendererMap; static BaseRenderer *GetInstance(vtkRenderWindow *renWin); static void AddInstance(vtkRenderWindow *renWin, BaseRenderer *baseRenderer); static void RemoveInstance(vtkRenderWindow *renWin); static BaseRenderer *GetByName(const std::string &name); static vtkRenderWindow *GetRenderWindowByName(const std::string &name); #pragma GCC visibility push(default) itkEventMacro(RendererResetEvent, itk::AnyEvent); #pragma GCC visibility pop /** Standard class typedefs. */ mitkClassMacroItkParent(BaseRenderer, itk::Object); BaseRenderer(const char *name = nullptr, vtkRenderWindow *renWin = nullptr, mitk::RenderingManager *rm = nullptr, - RenderingMode::Type mode = RenderingMode::Standard); + RenderingMode::Type mode = RenderingMode::FastApproximateAntiAliasing); //##Documentation //## @brief MapperSlotId defines which kind of mapper (e.g. 2D or 3D) should be used. typedef int MapperSlotId; enum StandardMapperSlot { Standard2D = 1, Standard3D = 2 }; //##Documentation //## @brief Possible view directions for render windows. enum class ViewDirection { AXIAL = 0, SAGITTAL, CORONAL, THREE_D }; virtual void SetDataStorage(DataStorage *storage); ///< set the datastorage that will be used for rendering //##Documentation //## return the DataStorage that is used for rendering virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); } //##Documentation //## @brief Access the RenderWindow into which this renderer renders. vtkRenderWindow *GetRenderWindow() const { return m_RenderWindow; } vtkRenderer *GetVtkRenderer() const { return m_VtkRenderer; } //##Documentation //## @brief Returns the Dispatcher which handles Events for this BaseRenderer Dispatcher::Pointer GetDispatcher() const; //##Documentation //## @brief Default mapper id to use. static const MapperSlotId defaultMapper; //##Documentation //## @brief Do the rendering and flush the result. virtual void Paint(); //##Documentation //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. virtual void Initialize(); //##Documentation //## @brief Called to inform the renderer that the RenderWindow has been resized. virtual void Resize(int w, int h); //##Documentation //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). virtual void InitRenderer(vtkRenderWindow *renderwindow); //##Documentation //## @brief Set the initial size. Called by RenderWindow after it has become //## visible for the first time. virtual void InitSize(int w, int h); //##Documentation //## @brief Draws a point on the widget. //## Should be used during conferences to show the position of the remote mouse virtual void DrawOverlayMouse(Point2D &p2d); //##Documentation //## @brief Set/Get the WorldGeometry (m_WorldGeometry) for 3D and 2D rendering, that describing the //## (maximal) area to be rendered. //## //## Depending of the type of the passed BaseGeometry more or less information can be extracted: //## \li if it is a PlaneGeometry (which is a sub-class of BaseGeometry), m_CurrentWorldPlaneGeometry is //## also set to point to it. m_WorldTimeGeometry is set to nullptr. //## \li if it is a TimeGeometry, m_WorldTimeGeometry is also set to point to it. //## If m_WorldTimeGeometry contains instances of SlicedGeometry3D, m_CurrentWorldPlaneGeometry is set to //## one of geometries stored in the SlicedGeometry3D according to the value of m_Slice; otherwise //## a PlaneGeometry describing the top of the bounding-box of the BaseGeometry is set as the //## m_CurrentWorldPlaneGeometry. //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the BaseGeometry //## is set as the m_CurrentWorldPlaneGeometry. m_WorldTimeGeometry is set to nullptr. //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the BaseGeometry //## when the passed BaseGeometry is not sliced. //## \sa m_WorldGeometry //## \sa m_WorldTimeGeometry //## \sa m_CurrentWorldPlaneGeometry virtual void SetWorldGeometry3D(const BaseGeometry *geometry); virtual void SetWorldTimeGeometry(const mitk::TimeGeometry *geometry); /** * \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see * http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201 */ DEPRECATED(void SetWorldGeometry3D(TimeSlicedGeometry *geometry)); itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry) //##Documentation //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry) //##Documentation //## @brief Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry) /** * \deprecatedSince{2014_10} Please use GetCurrentWorldPlaneGeometry */ DEPRECATED(const PlaneGeometry *GetCurrentWorldGeometry2D()) { return GetCurrentWorldPlaneGeometry(); }; //##Documentation //## Calculates the bounds of the DataStorage (if it contains any valid data), //## creates a geometry from these bounds and sets it as world geometry of the renderer. //## //## Call this method to re-initialize the renderer to the current DataStorage //## (e.g. after loading an additional dataset), to ensure that the view is //## aligned correctly. //## \warn This is not implemented yet. virtual bool SetWorldGeometryToDataStorageBounds() { return false; } //##Documentation //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry //## //## \sa m_Slice virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int) //##Documentation //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry //## //## \sa m_TimeStep virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int) //##Documentation //## @brief Get the time-step of a BaseData object which //## exists at the time of the currently displayed content //## //## Returns -1 or mitk::BaseData::m_TimeSteps if there //## is no data at the current time. //## \sa GetTimeStep, m_TimeStep int GetTimeStep(const BaseData *data) const; //##Documentation //## @brief Get the time in ms of the currently displayed content //## //## \sa GetTimeStep, m_TimeStep ScalarType GetTime() const; //##Documentation //## @brief SetWorldGeometry is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySendEvent virtual void SetGeometry(const itk::EventObject &geometrySliceEvent); //##Documentation //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the //## slice navigation controller virtual void UpdateGeometry(const itk::EventObject &geometrySliceEvent); //##Documentation //## @brief SetSlice is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySliceEvent virtual void SetGeometrySlice(const itk::EventObject &geometrySliceEvent); //##Documentation //## @brief SetTimeStep is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometryTimeEvent virtual void SetGeometryTime(const itk::EventObject &geometryTimeEvent); //##Documentation //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry // m_CurrentWorldPlaneGeometry (for 2D rendering) itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode) /** * \deprecatedSince{2014_10} Please use GetCurrentWorldPlaneGeometryNode */ DEPRECATED(DataNode *GetCurrentWorldGeometry2DNode()) { return GetCurrentWorldPlaneGeometryNode(); }; //##Documentation //## @brief Sets timestamp of CurrentWorldPlaneGeometry and forces so reslicing in that renderwindow void SendUpdateSlice(); //##Documentation //## @brief Get timestamp of last call of SetCurrentWorldPlaneGeometry unsigned long GetCurrentWorldPlaneGeometryUpdateTime() { return m_CurrentWorldPlaneGeometryUpdateTime; } /** * \deprecatedSince{2014_10} Please use GetCurrentWorldPlaneGeometryUpdateTime */ DEPRECATED(unsigned long GetCurrentWorldGeometry2DUpdateTime()) { return GetCurrentWorldPlaneGeometryUpdateTime(); }; //##Documentation //## @brief Get timestamp of last change of current TimeStep unsigned long GetTimeStepUpdateTime() { return m_TimeStepUpdateTime; } //##Documentation //## @brief Perform a picking: find the x,y,z world coordinate of a //## display x,y coordinate. //## @warning Has to be overwritten in subclasses for the 3D-case. //## //## Implemented here only for 2D-rendering virtual void PickWorldPoint(const Point2D &diplayPosition, Point3D &worldPosition) const = 0; /** \brief Determines the object (mitk::DataNode) closest to the current * position by means of picking * * \warning Implementation currently empty for 2D rendering; intended to be * implemented for 3D renderers */ virtual DataNode *PickObject(const Point2D & /*displayPosition*/, Point3D & /*worldPosition*/) const { return nullptr; } //##Documentation //## @brief Get the MapperSlotId to use. itkGetMacro(MapperID, MapperSlotId) itkGetConstMacro(MapperID, MapperSlotId) //##Documentation //## @brief Set the MapperSlotId to use. itkSetMacro(MapperID, MapperSlotId) virtual int *GetSize() const; virtual int *GetViewportSize() const; void SetSliceNavigationController(SliceNavigationController *SlicenavigationController); itkGetObjectMacro(CameraController, CameraController) itkGetObjectMacro(SliceNavigationController, SliceNavigationController) itkGetObjectMacro(CameraRotationController, CameraRotationController) itkGetMacro(EmptyWorldGeometry, bool) //##Documentation //## @brief Tells if the displayed region is shifted and rescaled if the render window is resized. itkGetMacro(KeepDisplayedRegion, bool) //##Documentation //## @brief Tells if the displayed region should be shifted and rescaled if the render window is resized. itkSetMacro(KeepDisplayedRegion, bool) //##Documentation //## @brief get the name of the Renderer //## @note const char *GetName() const { return m_Name.c_str(); } //##Documentation //## @brief get the x_size of the RendererWindow //## @note int GetSizeX() const { return GetSize()[0]; } //##Documentation //## @brief get the y_size of the RendererWindow //## @note int GetSizeY() const { return GetSize()[1]; } const double *GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); /** Returns number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; ///** //* \brief Setter for the RenderingManager that handles this instance of BaseRenderer //*/ // void SetRenderingManager( mitk::RenderingManager* ); /** * \brief Getter for the RenderingManager that handles this instance of BaseRenderer */ virtual mitk::RenderingManager *GetRenderingManager() const; //##Documentation //## @brief This method converts a display point to the 3D world index //## using the geometry of the renderWindow. void DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const; //##Documentation //## @brief This method converts a display point to the 2D world index, mapped onto the display plane //## using the geometry of the renderWindow. void DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const; //##Documentation //## @brief This method converts a 3D world index to the display point //## using the geometry of the renderWindow. void WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const; //##Documentation //## @brief This method converts a 3D world index to the point on the viewport //## using the geometry of the renderWindow. void WorldToView(const Point3D &worldIndex, Point2D &viewPoint) const; //##Documentation //## @brief This method converts a 2D plane coordinate to the display point //## using the geometry of the renderWindow. void PlaneToDisplay(const Point2D &planePointInMM, Point2D &displayPoint) const; //##Documentation //## @brief This method converts a 2D plane coordinate to the point on the viewport //## using the geometry of the renderWindow. void PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const; double GetScaleFactorMMPerDisplayUnit() const; Point2D GetDisplaySizeInMM() const; Point2D GetViewportSizeInMM() const; Point2D GetOriginInMM() const; itkGetConstMacro(ConstrainZoomingAndPanning, bool) virtual void SetConstrainZoomingAndPanning(bool constrain); /** * \brief Provides (1) world coordinates for a given mouse position and (2) * translates mousePosition to Display coordinates * \deprecated Map2DRendererPositionTo3DWorldPosition is deprecated. Please use DisplayToWorld instead. */ DEPRECATED(virtual Point3D Map2DRendererPositionTo3DWorldPosition(const Point2D &mousePosition) const); protected: ~BaseRenderer() override; //##Documentation //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; vtkRenderWindow *m_RenderWindow; vtkRenderer *m_VtkRenderer; //##Documentation //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; //##Documentation //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; //##Documentation //## @brief The RenderingManager that manages this instance RenderingManager::Pointer m_RenderingManager; //##Documentation //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; //##Documentation //## @brief CameraController for 3D rendering //## @note preliminary. itk::SmartPointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; //##Documentation //## @brief Sets m_CurrentWorldPlaneGeometry virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry *geometry2d); /** * \deprecatedSince{2014_10} Please use SetCurrentWorldPlaneGeometry */ DEPRECATED(void SetCurrentWorldGeometry2D(PlaneGeometry *geometry2d)) { SetCurrentWorldPlaneGeometry(geometry2d); }; //##Documentation //## @brief Sets m_CurrentWorldGeometry virtual void SetCurrentWorldGeometry(const BaseGeometry *geometry); private: //##Documentation //## m_WorldTimeGeometry is set by SetWorldGeometry if the passed BaseGeometry is a //## TimeGeometry (or a sub-class of it). If it contains instances of SlicedGeometry3D, //## m_Slice and m_TimeStep (set via SetSlice and SetTimeStep, respectively) define //## which 2D geometry stored in m_WorldTimeGeometry (if available) //## is used as m_CurrentWorldPlaneGeometry. //## \sa m_CurrentWorldPlaneGeometry TimeGeometry::ConstPointer m_WorldTimeGeometry; //##Documentation //## Pointer to the current 3D-worldgeometry. BaseGeometry::ConstPointer m_CurrentWorldGeometry; //##Documentation //## Pointer to the current 2D-worldgeometry. The 2D-worldgeometry //## describes the maximal area (2D manifold) to be rendered in case we //## are doing 2D-rendering. //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). PlaneGeometry::Pointer m_CurrentWorldPlaneGeometry; //##Documentation //## Defines together with m_Slice which 2D geometry stored in m_WorldTimeGeometry //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep). //## \sa m_WorldTimeGeometry unsigned int m_Slice; //##Documentation //## Defines together with m_TimeStep which 2D geometry stored in m_WorldTimeGeometry //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep). //## \sa m_WorldTimeGeometry unsigned int m_TimeStep; //##Documentation //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime; //##Documentation //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; //##Documentation //## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage. BindDispatcherInteractor *m_BindDispatcherInteractor; //##Documentation //## @brief Tells if the displayed region should be shifted or rescaled if the render window is resized. bool m_KeepDisplayedRegion; protected: void PrintSelf(std::ostream &os, itk::Indent indent) const override; //##Documentation //## Data object containing the m_CurrentWorldPlaneGeometry defined above. PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData; //##Documentation //## DataNode objects containing the m_CurrentWorldPlaneGeometryData defined above. DataNode::Pointer m_CurrentWorldPlaneGeometryNode; //##Documentation //## @brief test only unsigned long m_CurrentWorldPlaneGeometryTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; typedef std::set LODEnabledMappersType; /** Number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int m_NumberOfVisibleLODEnabledMappers; // Local Storage Handling for mappers protected: std::list m_RegisteredLocalStorageHandlers; bool m_ConstrainZoomingAndPanning; public: void RemoveAllLocalStorages(); void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); }; } // namespace mitk #endif /* BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 */ diff --git a/Modules/Core/include/mitkRenderWindow.h b/Modules/Core/include/mitkRenderWindow.h index c7575e11f8..fe2522dfbd 100644 --- a/Modules/Core/include/mitkRenderWindow.h +++ b/Modules/Core/include/mitkRenderWindow.h @@ -1,100 +1,100 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66ASDF #define MITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66ASDF #include #include "mitkRenderWindowBase.h" namespace mitk { class vtkEventProvider; /** * \brief mitkRenderWindow integrates the MITK rendering mechanism into VTK and * is NOT QT dependent * * * \ingroup Renderer */ class MITKCORE_EXPORT RenderWindow : public mitk::RenderWindowBase, public itk::Object { public: mitkClassMacroItkParent(RenderWindow, itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, vtkRenderWindow *); mitkNewMacro2Param(Self, vtkRenderWindow *, const char *); mitkNewMacro3Param(Self, vtkRenderWindow *, const char *, mitk::RenderingManager *); mitkNewMacro4Param( Self, vtkRenderWindow *, const char *, mitk::RenderingManager *, mitk::BaseRenderer::RenderingMode::Type); ~RenderWindow() override; vtkRenderWindow *GetVtkRenderWindow() override; vtkRenderWindowInteractor *GetVtkRenderWindowInteractor() override; // Set Layout Index to define the Layout Type void SetLayoutIndex(unsigned int layoutIndex); // Get Layout Index to define the Layout Type unsigned int GetLayoutIndex(); // MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged(int layoutDesignIndex); void FullScreenMode(bool state); /** * \brief Convenience method to set the size of an mitkRenderWindow. * * This method sets the size of the vtkRenderWindow and tells the * rendering that the size has changed -> adapts displayGeometry, etc. */ void SetSize(int width, int height); /** * \brief Initializes the mitkVtkEventProvider to listen to the * currently used vtkInteractorStyle. * * This method makes sure that the internal mitkVtkEventProvider * listens to the correct vtkInteractorStyle. * This makes sure that VTK-Events are correctly translated into * MITK-Events. * * \warn This method needs to be called MANUALLY as soon as the MapperID * for this RenderWindow is changed or the vtkInteractorStyle is modified * somehow else! */ void ReinitEventProvider(); protected: RenderWindow(vtkRenderWindow *existingRenderWindow = nullptr, const char *name = "unnamed renderer", mitk::RenderingManager *rm = nullptr, - mitk::BaseRenderer::RenderingMode::Type rmtype = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type rmtype = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); void ResetView(); vtkRenderWindow *m_vtkRenderWindow; vtkRenderWindowInteractor *m_vtkRenderWindowInteractor; vtkEventProvider *m_vtkMitkEventProvider; private: }; } // namespace #endif /* MITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66ASDF */ diff --git a/Modules/Core/include/mitkRenderWindowBase.h b/Modules/Core/include/mitkRenderWindowBase.h index 8b9cb458e1..ef2a23e442 100644 --- a/Modules/Core/include/mitkRenderWindowBase.h +++ b/Modules/Core/include/mitkRenderWindowBase.h @@ -1,83 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKRENDERWINDOWBASE_H_HEADER_INCLUDED_C1C40D66ASDF #define MITKRENDERWINDOWBASE_H_HEADER_INCLUDED_C1C40D66ASDF #include #include "mitkCameraRotationController.h" #include "mitkSliceNavigationController.h" #include "mitkVtkPropRenderer.h" #include "vtkMitkRenderProp.h" #include "mitkInteractionEvent.h" namespace mitk { /** * \brief Base class of MITK RenderWindows * * This class sets up the MITK rendering mechanism and it's integration into VTK. * * Currently, there are two specific implementations of this abstract class: * QmitkRenderWindow, inerhits from the QVTKWidget and is the matured way for MITK rendering * mitkRenderWindow is a new, QT-independent RenderWindow implementation * * \ingroup Renderer */ class MITKCORE_EXPORT RenderWindowBase { public: // mitkClassMacroItkParent(RenderWindowBase,itk::Object); // itkFactorylessNewMacro(Self) // itkCloneMacro(Self) virtual ~RenderWindowBase(); void InitRenderer(); virtual mitk::SliceNavigationController *GetSliceNavigationController(); virtual mitk::CameraRotationController *GetCameraRotationController(); virtual mitk::BaseController *GetController(); virtual mitk::VtkPropRenderer *GetRenderer(); virtual vtkRenderWindow *GetVtkRenderWindow() = 0; virtual vtkRenderWindowInteractor *GetVtkRenderWindowInteractor() = 0; virtual bool HandleEvent(InteractionEvent *interactionEvent); protected: RenderWindowBase(); // helper functions: within constructors and destructors classes are not polymorph. void Initialize( mitk::RenderingManager *renderingManager = nullptr, const char *name = "unnamed renderer", - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); void Destroy(); mitk::VtkPropRenderer::Pointer m_Renderer; vtkMitkRenderProp *m_RenderProp; bool m_InResize; private: }; } #endif /* MITKRENDERWINDOWBASE_H_HEADER_INCLUDED_C1C40D66ASDF */ diff --git a/Modules/Core/include/mitkVtkPropRenderer.h b/Modules/Core/include/mitkVtkPropRenderer.h index 4375a6e558..5eeae29d8f 100644 --- a/Modules/Core/include/mitkVtkPropRenderer.h +++ b/Modules/Core/include/mitkVtkPropRenderer.h @@ -1,244 +1,258 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkVtkPropRenderer_h #define mitkVtkPropRenderer_h #include "mitkBaseRenderer.h" #include #include #include #include #include #include class vtkRenderWindow; class vtkLight; class vtkLightKit; class vtkWorldPointPicker; class vtkPointPicker; class vtkCellPicker; class vtkTextActor; class vtkTextProperty; class vtkAssemblyPath; #include #include namespace mitk { class Mapper; /*! \brief VtkPropRenderer VtkPropRenderer organizes the MITK rendering process. The MITK rendering process is completely integrated into the VTK rendering pipeline. The vtkMitkRenderProp is a custom vtkProp derived class, which implements the rendering interface between MITK and VTK. It redirects render() calls to the VtkPropRenderer, which is responsible for rendering of the datatreenodes. VtkPropRenderer replaces the old OpenGLRenderer. \sa rendering \ingroup rendering */ class MITKCORE_EXPORT VtkPropRenderer : public BaseRenderer { // Workaround for Displaylistbug private: bool didCount; void checkState(); // Workaround END public: mitkClassMacro(VtkPropRenderer, BaseRenderer); mitkNewMacro3Param(VtkPropRenderer, const char *, vtkRenderWindow *, mitk::RenderingManager *); mitkNewMacro4Param(VtkPropRenderer, const char *, vtkRenderWindow *, mitk::RenderingManager *, mitk::BaseRenderer::RenderingMode::Type); typedef std::map MappersMapType; // Render - called by vtkMitkRenderProp, returns the number of props rendered enum RenderType { Opaque, Translucent, Overlay, Volumetric }; + /** \brief Store/propagate vtkInformation during rendering */ + void SetPropertyKeys(vtkInformation *info); + int Render(RenderType type); /** \brief This methods contains all method neceassary before a VTK Render() call */ virtual void PrepareRender(); // Active current renderwindow virtual void MakeCurrent(); void SetDataStorage( mitk::DataStorage *storage) override; ///< set the datastorage that will be used for rendering void InitRenderer(vtkRenderWindow *renderwindow) override; virtual void Update(mitk::DataNode *datatreenode); void SetMapperID(const MapperSlotId mapperId) override; // Size void InitSize(int w, int h) override; void Resize(int w, int h) override; // Picking enum PickingMode { WorldPointPicking, PointPicking, CellPicking }; /** \brief Set the picking mode. This method is used to set the picking mode for 3D object picking. The user can select one of the three options WorldPointPicking, PointPicking and CellPicking. The first option uses the zBuffer from graphics rendering, the second uses the 3D points from the closest surface mesh, and the third option uses the cells of that mesh. The last option is the slowest, the first one the fastest. However, the first option cannot use transparent data object and the tolerance of the picked position to the selected point should be considered. PointPicking also need a tolerance around the picking position to select the closest point in the mesh. The CellPicker performs very well, if the foreground surface part (i.e. the surfacepart that is closest to the scene's cameras) needs to be picked. */ itkSetEnumMacro(PickingMode, PickingMode); itkGetEnumMacro(PickingMode, PickingMode); void PickWorldPoint(const Point2D &displayPoint, Point3D &worldPoint) const override; mitk::DataNode *PickObject(const Point2D &displayPosition, Point3D &worldPosition) const override; /** * @brief WriteSimpleText Write a text in a renderwindow. * * Writes some 2D text as overlay. Function returns an unique int Text_ID for each call, which can be used via the GetTextLabelProperty(int text_id) function in order to get a vtkTextProperty. This property enables the setup of font, font size, etc. * * @deprecatedSince{2015_05} Please use mitkTextOverlay2D instead. * See mitkTextOverlay2DRenderingTest for an example. */ DEPRECATED(int WriteSimpleText(std::string text, double posX, double posY, double color1 = 0.0, double color2 = 1.0, double color3 = 0.0, float opacity = 1.0)); /** * @brief CGetTextLabelProperty an be used in order to get a vtkTextProperty for * a specific text_id. This property enables the setup of font, font size, etc. * @param text_id the id of the text property. * @deprecatedSince{2015_05} Please use mitkTextOverlay2D instead. * See mitkTextOverlay2DRenderingTest for an example. */ DEPRECATED(vtkTextProperty *GetTextLabelProperty(int text_id)); /** This method calculates the bounds of the DataStorage (if it contains any * valid data), creates a geometry from these bounds and sets it as world * geometry of the renderer. * * Call this method to re-initialize the renderer to the current DataStorage * (e.g. after loading an additional dataset), to ensure that the view is * aligned correctly. */ bool SetWorldGeometryToDataStorageBounds() override; /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ void InitPathTraversal(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ vtkAssemblyPath *GetNextPath(); int GetNumberOfPaths(); const vtkWorldPointPicker *GetWorldPointPicker() const; const vtkPointPicker *GetPointPicker() const; const vtkCellPicker *GetCellPicker() const; /** * \brief Release vtk-based graphics resources. Called by * vtkMitkRenderProp::ReleaseGraphicsResources. */ virtual void ReleaseGraphicsResources(vtkWindow *renWin); MappersMapType GetMappersMap() const; static bool useImmediateModeRendering(); protected: VtkPropRenderer( const char *name = "VtkPropRenderer", vtkRenderWindow *renWin = nullptr, mitk::RenderingManager *rm = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); ~VtkPropRenderer() override; void Update() override; static void RenderingCallback(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata); virtual void UpdatePaths(); // apply transformations and properties recursively private: vtkSmartPointer m_Paths; vtkTimeStamp m_PathTime; // prepare all mitk::mappers for rendering void PrepareMapperQueue(); + /** \brief Propagate vtkInformation object to all VTK-based mappers */ + void PropagateRenderInfoToMappers(); + /** \brief Set parallel projection, remove the interactor and the lights of VTK. */ bool Initialize2DvtkCamera(); bool m_InitNeeded; bool m_ResizeNeeded; MapperSlotId m_CameraInitializedForMapperID; // Picking vtkWorldPointPicker *m_WorldPointPicker; vtkPointPicker *m_PointPicker; vtkCellPicker *m_CellPicker; PickingMode m_PickingMode; // Explicit use of SmartPointer to avoid circular #includes itk::SmartPointer m_CurrentWorldPlaneGeometryMapper; vtkLightKit *m_LightKit; // sorted list of mappers MappersMapType m_MappersMap; // rendering of text vtkRenderer *m_TextRenderer; typedef std::map TextMapType; TextMapType m_TextCollection; + + /** \brief Information passed from VTK's rendering to props. + + Used e.g. by vtkDualDepthPeelingPass to pass information. + Not passing this to all the MITK generated vktProps will + essentially break VTK's depth peeling / transparency. + */ + vtkInformation* m_VtkRenderInfo = nullptr; }; } // namespace mitk #endif /* mitkVtkPropRenderer_h */ diff --git a/Modules/Core/include/vtkMitkRenderProp.h b/Modules/Core/include/vtkMitkRenderProp.h index b4309fa5fb..02ed925fa3 100644 --- a/Modules/Core/include/vtkMitkRenderProp.h +++ b/Modules/Core/include/vtkMitkRenderProp.h @@ -1,75 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef VTKMITKRENDERPROP_H_HEADER_INCLUDED_C1C53723 #define VTKMITKRENDERPROP_H_HEADER_INCLUDED_C1C53723 #include "mitkVtkPropRenderer.h" #include "vtkProp.h" /*! \brief vtkMitkRenderProp The MITK rendering process is completely integrated into the VTK rendering pipeline. The vtkMitkRenderProp is a custom vtkProp derived class, which implements the rendering interface between MITK and VTK. -It redirects render() calls to the VtkPropRenderer, which is responsible for rendering of the datatreenodes. +It redirects VTK's various Render..Geometry() calls to mitk::VtkPropRenderer, which is responsible for rendering of mitk::DataNodes. \sa rendering \ingroup rendering */ class MITKCORE_EXPORT vtkMitkRenderProp : public vtkProp { public: static vtkMitkRenderProp *New(); vtkTypeMacro(vtkMitkRenderProp, vtkProp); void SetPropRenderer(mitk::VtkPropRenderer::Pointer propRenderer); + /** + * \brief Store a vtkInformation object + * + * This method will forward the vtkInformation object + * to the vtkProps of all mitk::VtkMapper + */ + void SetPropertyKeys(vtkInformation *keys) override; + int RenderOpaqueGeometry(vtkViewport *viewport) override; int RenderOverlay(vtkViewport *viewport) override; double *GetBounds() override; void ReleaseGraphicsResources(vtkWindow *window) override; /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ void InitPathTraversal() override; /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ vtkAssemblyPath *GetNextPath() override; int GetNumberOfPaths() override; - // BUG (#1551) added method for depth peeling support int HasTranslucentPolygonalGeometry() override; int RenderTranslucentPolygonalGeometry(vtkViewport *) override; int RenderVolumetricGeometry(vtkViewport *) override; protected: vtkMitkRenderProp(); ~vtkMitkRenderProp() override; mitk::VtkPropRenderer::Pointer m_VtkPropRenderer; }; #endif /* VTKMITKRENDERPROP_H_HEADER_INCLUDED_C1C53723 */ diff --git a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp index 6678a2ac2b..b7fec9d925 100644 --- a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp +++ b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp @@ -1,780 +1,787 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseRenderer.h" #include "mitkMapper.h" #include "mitkResliceMethodProperty.h" // Geometries #include "mitkPlaneGeometry.h" #include "mitkSlicedGeometry3D.h" // Controllers #include "mitkCameraController.h" #include "mitkCameraRotationController.h" #include "mitkSliceNavigationController.h" #include "mitkVtkLayerController.h" #include "mitkInteractionConst.h" #include "mitkProperties.h" #include "mitkWeakPointerProperty.h" // VTK #include #include #include #include #include #include #include mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap; mitk::BaseRenderer *mitk::BaseRenderer::GetInstance(vtkRenderWindow *renWin) { for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit) { if ((*mapit).first == renWin) return (*mapit).second; } return nullptr; } void mitk::BaseRenderer::AddInstance(vtkRenderWindow *renWin, BaseRenderer *baseRenderer) { if (renWin == nullptr || baseRenderer == nullptr) return; // ensure that no BaseRenderer is managed twice mitk::BaseRenderer::RemoveInstance(renWin); baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer)); } void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow *renWin) { auto mapit = baseRendererMap.find(renWin); if (mapit != baseRendererMap.end()) baseRendererMap.erase(mapit); } mitk::BaseRenderer *mitk::BaseRenderer::GetByName(const std::string &name) { for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit) { if ((*mapit).second->m_Name == name) return (*mapit).second; } return nullptr; } vtkRenderWindow *mitk::BaseRenderer::GetRenderWindowByName(const std::string &name) { for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit) { if ((*mapit).second->m_Name == name) return (*mapit).first; } return nullptr; } mitk::BaseRenderer::BaseRenderer(const char *name, vtkRenderWindow *renWin, mitk::RenderingManager *rm, - RenderingMode::Type) + RenderingMode::Type renderingMode) : m_RenderWindow(nullptr), m_VtkRenderer(nullptr), m_MapperID(defaultMapper), m_DataStorage(nullptr), m_RenderingManager(rm), m_LastUpdateTime(0), m_CameraController(nullptr), m_SliceNavigationController(nullptr), m_CameraRotationController(nullptr), m_WorldTimeGeometry(nullptr), m_CurrentWorldGeometry(nullptr), m_CurrentWorldPlaneGeometry(nullptr), m_Slice(0), m_TimeStep(), m_CurrentWorldPlaneGeometryUpdateTime(), m_TimeStepUpdateTime(), m_KeepDisplayedRegion(true), m_CurrentWorldPlaneGeometryData(nullptr), m_CurrentWorldPlaneGeometryNode(nullptr), m_CurrentWorldPlaneGeometryTransformTime(0), m_Name(name), m_EmptyWorldGeometry(true), m_NumberOfVisibleLODEnabledMappers(0) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; if (name != nullptr) { m_Name = name; } else { m_Name = "unnamed renderer"; itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name."); } if (renWin != nullptr) { m_RenderWindow = renWin; m_RenderWindow->Register(nullptr); } else { itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present."); } // instances.insert( this ); // adding this BaseRenderer to the List of all BaseRenderer m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor(GetName()); WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object *)this); m_CurrentWorldPlaneGeometry = mitk::PlaneGeometry::New(); m_CurrentWorldPlaneGeometryData = mitk::PlaneGeometryData::New(); m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry); m_CurrentWorldPlaneGeometryNode = mitk::DataNode::New(); m_CurrentWorldPlaneGeometryNode->SetData(m_CurrentWorldPlaneGeometryData); m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000)); m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New()); m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1)); m_CurrentWorldPlaneGeometryTransformTime = m_CurrentWorldPlaneGeometryNode->GetVtkTransform()->GetMTime(); mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::SliceNavigationController::New(); sliceNavigationController->SetRenderer(this); sliceNavigationController->ConnectGeometrySliceEvent(this); sliceNavigationController->ConnectGeometryUpdateEvent(this); sliceNavigationController->ConnectGeometryTimeEvent(this, false); m_SliceNavigationController = sliceNavigationController; m_CameraRotationController = mitk::CameraRotationController::New(); m_CameraRotationController->SetRenderWindow(m_RenderWindow); m_CameraRotationController->AcquireCamera(); m_CameraController = mitk::CameraController::New(); m_CameraController->SetRenderer(this); m_VtkRenderer = vtkRenderer::New(); - if (mitk::VtkLayerController::GetInstance(m_RenderWindow) == nullptr) - { + m_VtkRenderer->UseDepthPeelingOn(); + m_VtkRenderer->UseDepthPeelingForVolumesOn(); + m_VtkRenderer->SetMaximumNumberOfPeels(16); // This could be made adjustable in the Preferences + m_VtkRenderer->SetOcclusionRatio(0.0); + + if (RenderingMode::FastApproximateAntiAliasing == renderingMode) + m_VtkRenderer->UseFXAAOn(); + + if (nullptr == mitk::VtkLayerController::GetInstance(m_RenderWindow)) mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer); - } + mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } mitk::BaseRenderer::~BaseRenderer() { if (m_VtkRenderer != nullptr) { m_VtkRenderer->Delete(); m_VtkRenderer = nullptr; } if (m_CameraController.IsNotNull()) m_CameraController->SetRenderer(nullptr); mitk::VtkLayerController::RemoveInstance(m_RenderWindow); RemoveAllLocalStorages(); m_DataStorage = nullptr; if (m_BindDispatcherInteractor != nullptr) { delete m_BindDispatcherInteractor; } if (m_RenderWindow != nullptr) { m_RenderWindow->Delete(); m_RenderWindow = nullptr; } } void mitk::BaseRenderer::RemoveAllLocalStorages() { this->InvokeEvent(mitk::BaseRenderer::RendererResetEvent()); std::list::iterator it; for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); ++it) (*it)->ClearLocalStorage(this, false); m_RegisteredLocalStorageHandlers.clear(); } void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.push_back(lsh); } mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const { return m_BindDispatcherInteractor->GetDispatcher(); } void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.remove(lsh); } void mitk::BaseRenderer::SetDataStorage(DataStorage *storage) { if (storage != m_DataStorage && storage != nullptr) { m_DataStorage = storage; m_BindDispatcherInteractor->SetDataStorage(m_DataStorage); this->Modified(); } } const mitk::BaseRenderer::MapperSlotId mitk::BaseRenderer::defaultMapper = 1; void mitk::BaseRenderer::Paint() { } void mitk::BaseRenderer::Initialize() { } void mitk::BaseRenderer::Resize(int w, int h) { this->m_RenderWindow->SetSize(w, h); } void mitk::BaseRenderer::InitRenderer(vtkRenderWindow *renderwindow) { if (m_RenderWindow != renderwindow) { if (m_RenderWindow != nullptr) { m_RenderWindow->Delete(); } m_RenderWindow = renderwindow; if (m_RenderWindow != nullptr) { m_RenderWindow->Register(nullptr); } } RemoveAllLocalStorages(); if (m_CameraController.IsNotNull()) { m_CameraController->SetRenderer(this); } } void mitk::BaseRenderer::InitSize(int w, int h) { this->m_RenderWindow->SetSize(w, h); } void mitk::BaseRenderer::SetSlice(unsigned int slice) { if (m_Slice != slice) { m_Slice = slice; if (m_WorldTimeGeometry.IsNotNull()) { // get world geometry which may be rotated, for the current time step SlicedGeometry3D *slicedWorldGeometry = dynamic_cast(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); if (slicedWorldGeometry != nullptr) { // if slice position is part of the world geometry... if (m_Slice >= slicedWorldGeometry->GetSlices()) // set the current worldplanegeomety as the selected 2D slice of the world geometry m_Slice = slicedWorldGeometry->GetSlices() - 1; SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) { if (m_TimeStep != timeStep) { m_TimeStep = timeStep; m_TimeStepUpdateTime.Modified(); if (m_WorldTimeGeometry.IsNotNull()) { if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps()) m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1; SlicedGeometry3D *slicedWorldGeometry = dynamic_cast(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); if (slicedWorldGeometry != nullptr) { SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } int mitk::BaseRenderer::GetTimeStep(const mitk::BaseData *data) const { if ((data == nullptr) || (data->IsInitialized() == false)) { return -1; } return data->GetTimeGeometry()->TimePointToTimeStep(GetTime()); } mitk::ScalarType mitk::BaseRenderer::GetTime() const { if (m_WorldTimeGeometry.IsNull()) { return 0; } else { ScalarType timeInMS = m_WorldTimeGeometry->TimeStepToTimePoint(GetTimeStep()); if (timeInMS == itk::NumericTraits::NonpositiveMin()) return 0; else return timeInMS; } } void mitk::BaseRenderer::SetWorldTimeGeometry(const mitk::TimeGeometry *geometry) { assert(geometry != nullptr); itkDebugMacro("setting WorldTimeGeometry to " << geometry); if (m_WorldTimeGeometry != geometry) { if (geometry->GetBoundingBoxInWorld()->GetDiagonalLength2() == 0) return; m_WorldTimeGeometry = geometry; itkDebugMacro("setting WorldTimeGeometry to " << m_WorldTimeGeometry); if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps()) m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1; BaseGeometry *geometry3d; geometry3d = m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep); SetWorldGeometry3D(geometry3d); } } void mitk::BaseRenderer::SetWorldGeometry3D(const mitk::BaseGeometry *geometry) { itkDebugMacro("setting WorldGeometry3D to " << geometry); if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0) return; const SlicedGeometry3D *slicedWorldGeometry; slicedWorldGeometry = dynamic_cast(geometry); PlaneGeometry::ConstPointer geometry2d; if (slicedWorldGeometry != nullptr) { if (m_Slice >= slicedWorldGeometry->GetSlices() && (m_Slice != 0)) m_Slice = slicedWorldGeometry->GetSlices() - 1; geometry2d = slicedWorldGeometry->GetPlaneGeometry(m_Slice); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->InitializeStandardPlane(slicedWorldGeometry); geometry2d = plane; } SetCurrentWorldGeometry(slicedWorldGeometry); } else { geometry2d = dynamic_cast(geometry); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = PlaneGeometry::New(); plane->InitializeStandardPlane(geometry); geometry2d = plane; } SetCurrentWorldGeometry(geometry); } SetCurrentWorldPlaneGeometry(geometry2d); // calls Modified() if (m_CurrentWorldPlaneGeometry.IsNull()) itkWarningMacro("m_CurrentWorldPlaneGeometry is nullptr"); } void mitk::BaseRenderer::SetCurrentWorldPlaneGeometry(const mitk::PlaneGeometry *geometry2d) { if (m_CurrentWorldPlaneGeometry != geometry2d) { m_CurrentWorldPlaneGeometry = geometry2d->Clone(); m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry); m_CurrentWorldPlaneGeometryUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SendUpdateSlice() { m_CurrentWorldPlaneGeometryUpdateTime.Modified(); } int *mitk::BaseRenderer::GetSize() const { return this->m_RenderWindow->GetSize(); } int *mitk::BaseRenderer::GetViewportSize() const { return this->m_VtkRenderer->GetSize(); } void mitk::BaseRenderer::SetCurrentWorldGeometry(const mitk::BaseGeometry *geometry) { m_CurrentWorldGeometry = geometry; if (geometry == nullptr) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; m_EmptyWorldGeometry = true; return; } BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(nullptr); const BoundingBox::BoundsArrayType &worldBounds = boundingBox->GetBounds(); m_Bounds[0] = worldBounds[0]; m_Bounds[1] = worldBounds[1]; m_Bounds[2] = worldBounds[2]; m_Bounds[3] = worldBounds[3]; m_Bounds[4] = worldBounds[4]; m_Bounds[5] = worldBounds[5]; if (boundingBox->GetDiagonalLength2() <= mitk::eps) m_EmptyWorldGeometry = true; else m_EmptyWorldGeometry = false; } void mitk::BaseRenderer::SetGeometry(const itk::EventObject &geometrySendEvent) { const auto *sendEvent = dynamic_cast(&geometrySendEvent); assert(sendEvent != nullptr); SetWorldTimeGeometry(sendEvent->GetTimeGeometry()); } void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject &geometryUpdateEvent) { const auto *updateEvent = dynamic_cast(&geometryUpdateEvent); if (updateEvent == nullptr) return; if (m_CurrentWorldGeometry.IsNotNull()) { auto *slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); if (slicedWorldGeometry) { PlaneGeometry *geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice); SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified() } } } void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject &geometrySliceEvent) { const auto *sliceEvent = dynamic_cast(&geometrySliceEvent); assert(sliceEvent != nullptr); SetSlice(sliceEvent->GetPos()); } void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject &geometryTimeEvent) { const auto *timeEvent = dynamic_cast(&geometryTimeEvent); assert(timeEvent != nullptr); SetTimeStep(timeEvent->GetPos()); } const double *mitk::BaseRenderer::GetBounds() const { return m_Bounds; } void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D &itkNotUsed(p2d)) { MITK_INFO << "BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer." << std::endl; } void mitk::BaseRenderer::RequestUpdate() { SetConstrainZoomingAndPanning(true); m_RenderingManager->RequestUpdate(this->m_RenderWindow); } void mitk::BaseRenderer::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow); } unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const { return m_NumberOfVisibleLODEnabledMappers; } mitk::RenderingManager *mitk::BaseRenderer::GetRenderingManager() const { return m_RenderingManager.GetPointer(); } /*! Sets the new Navigation controller */ void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController) { if (SlicenavigationController == nullptr) return; // copy worldgeometry SlicenavigationController->SetInputWorldTimeGeometry(SlicenavigationController->GetCreatedWorldGeometry()); SlicenavigationController->Update(); // set new m_SliceNavigationController = SlicenavigationController; m_SliceNavigationController->SetRenderer(this); if (m_SliceNavigationController.IsNotNull()) { m_SliceNavigationController->ConnectGeometrySliceEvent(this); m_SliceNavigationController->ConnectGeometryUpdateEvent(this); m_SliceNavigationController->ConnectGeometryTimeEvent(this, false); } } void mitk::BaseRenderer::DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const { if (m_MapperID == BaseRenderer::Standard2D) { double display[3], *world; // For the rigth z-position in display coordinates, take the focal point, convert it to display and use it for // correct depth. double *displayCoord; double cameraFP[4]; // Get camera focal point and position. Convert to display (screen) // coordinates. We need a depth value for z-buffer. this->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint(cameraFP); cameraFP[3] = 0.0; this->GetVtkRenderer()->SetWorldPoint(cameraFP[0], cameraFP[1], cameraFP[2], cameraFP[3]); this->GetVtkRenderer()->WorldToDisplay(); displayCoord = this->GetVtkRenderer()->GetDisplayPoint(); // now convert the display point to world coordinates display[0] = displayPoint[0]; display[1] = displayPoint[1]; display[2] = displayCoord[2]; this->GetVtkRenderer()->SetDisplayPoint(display); this->GetVtkRenderer()->DisplayToWorld(); world = this->GetVtkRenderer()->GetWorldPoint(); for (int i = 0; i < 3; i++) { worldIndex[i] = world[i] / world[3]; } } else if (m_MapperID == BaseRenderer::Standard3D) { PickWorldPoint( displayPoint, worldIndex); // Seems to be the same code as above, but subclasses may contain different implementations. } return; } void mitk::BaseRenderer::DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const { if (m_MapperID == BaseRenderer::Standard2D) { Point3D worldPoint; this->DisplayToWorld(displayPoint, worldPoint); this->m_CurrentWorldPlaneGeometry->Map(worldPoint, planePointInMM); } else if (m_MapperID == BaseRenderer::Standard3D) { MITK_WARN << "No conversion possible with 3D mapper."; return; } return; } void mitk::BaseRenderer::WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const { double world[4], *display; world[0] = worldIndex[0]; world[1] = worldIndex[1]; world[2] = worldIndex[2]; world[3] = 1.0; this->GetVtkRenderer()->SetWorldPoint(world); this->GetVtkRenderer()->WorldToDisplay(); display = this->GetVtkRenderer()->GetDisplayPoint(); displayPoint[0] = display[0]; displayPoint[1] = display[1]; return; } void mitk::BaseRenderer::WorldToView(const mitk::Point3D &worldIndex, mitk::Point2D &viewPoint) const { double world[4], *view; world[0] = worldIndex[0]; world[1] = worldIndex[1]; world[2] = worldIndex[2]; world[3] = 1.0; this->GetVtkRenderer()->SetWorldPoint(world); this->GetVtkRenderer()->WorldToView(); view = this->GetVtkRenderer()->GetViewPoint(); this->GetVtkRenderer()->ViewToNormalizedViewport(view[0], view[1], view[2]); viewPoint[0] = view[0] * this->GetViewportSize()[0]; viewPoint[1] = view[1] * this->GetViewportSize()[1]; return; } void mitk::BaseRenderer::PlaneToDisplay(const Point2D &planePointInMM, Point2D &displayPoint) const { Point3D worldPoint; this->m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint); this->WorldToDisplay(worldPoint, displayPoint); return; } void mitk::BaseRenderer::PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const { Point3D worldPoint; this->m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint); this->WorldToView(worldPoint,viewPoint); return; } double mitk::BaseRenderer::GetScaleFactorMMPerDisplayUnit() const { if (this->GetMapperID() == BaseRenderer::Standard2D) { // GetParallelScale returns half of the height of the render window in mm. // Divided by the half size of the Display size in pixel givest the mm per pixel. return this->GetVtkRenderer()->GetActiveCamera()->GetParallelScale() * 2.0 / GetViewportSize()[1]; } else return 1.0; } mitk::Point2D mitk::BaseRenderer::GetDisplaySizeInMM() const { Point2D dispSizeInMM; dispSizeInMM[0] = GetSizeX() * GetScaleFactorMMPerDisplayUnit(); dispSizeInMM[1] = GetSizeY() * GetScaleFactorMMPerDisplayUnit(); return dispSizeInMM; } mitk::Point2D mitk::BaseRenderer::GetViewportSizeInMM() const { Point2D dispSizeInMM; dispSizeInMM[0] = GetViewportSize()[0] * GetScaleFactorMMPerDisplayUnit(); dispSizeInMM[1] = GetViewportSize()[1] * GetScaleFactorMMPerDisplayUnit(); return dispSizeInMM; } mitk::Point2D mitk::BaseRenderer::GetOriginInMM() const { Point2D originPx; originPx[0] = m_VtkRenderer->GetOrigin()[0]; originPx[1] = m_VtkRenderer->GetOrigin()[1]; Point2D displayGeometryOriginInMM; DisplayToPlane(originPx, displayGeometryOriginInMM); // top left of the render window (Origin) return displayGeometryOriginInMM; } void mitk::BaseRenderer::SetConstrainZoomingAndPanning(bool constrain) { m_ConstrainZoomingAndPanning = constrain; if (m_ConstrainZoomingAndPanning) { this->GetCameraController()->AdjustCameraToPlane(); } } mitk::Point3D mitk::BaseRenderer::Map2DRendererPositionTo3DWorldPosition(const Point2D &mousePosition) const { // DEPRECATED: Map2DRendererPositionTo3DWorldPosition is deprecated. use DisplayToWorldInstead Point3D position; DisplayToWorld(mousePosition, position); return position; } void mitk::BaseRenderer::PrintSelf(std::ostream &os, itk::Indent indent) const { os << indent << " MapperID: " << m_MapperID << std::endl; os << indent << " Slice: " << m_Slice << std::endl; os << indent << " TimeStep: " << m_TimeStep << std::endl; os << indent << " CurrentWorldPlaneGeometry: "; if (m_CurrentWorldPlaneGeometry.IsNull()) os << "nullptr" << std::endl; else m_CurrentWorldPlaneGeometry->Print(os, indent); os << indent << " CurrentWorldPlaneGeometryUpdateTime: " << m_CurrentWorldPlaneGeometryUpdateTime << std::endl; os << indent << " CurrentWorldPlaneGeometryTransformTime: " << m_CurrentWorldPlaneGeometryTransformTime << std::endl; Superclass::PrintSelf(os, indent); } diff --git a/Modules/Core/src/Rendering/mitkRenderWindow.cpp b/Modules/Core/src/Rendering/mitkRenderWindow.cpp index a6aa3eb77d..d223aa6350 100644 --- a/Modules/Core/src/Rendering/mitkRenderWindow.cpp +++ b/Modules/Core/src/Rendering/mitkRenderWindow.cpp @@ -1,85 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderWindow.h" #include "mitkRenderingManager.h" #include "mitkVtkEventProvider.h" #include "mitkVtkLayerController.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" mitk::RenderWindow::RenderWindow(vtkRenderWindow *renWin, const char *name, mitk::RenderingManager *rm, mitk::BaseRenderer::RenderingMode::Type rmtype) - : m_vtkRenderWindow(renWin), m_vtkRenderWindowInteractor(nullptr), m_vtkMitkEventProvider(nullptr) + : m_vtkRenderWindow(renWin), + m_vtkRenderWindowInteractor(nullptr), + m_vtkMitkEventProvider(nullptr) { - if (m_vtkRenderWindow == nullptr) + if (nullptr == m_vtkRenderWindow) { m_vtkRenderWindow = vtkRenderWindow::New(); - m_vtkRenderWindow->SetMultiSamples(0); - m_vtkRenderWindow->SetAlphaBitPlanes(0); + m_vtkRenderWindow->SetMultiSamples(0); // We do not support MSAA as it is incompatible with depth peeling + m_vtkRenderWindow->SetAlphaBitPlanes(1); // Necessary for depth peeling } if (m_vtkRenderWindow->GetSize()[0] <= 10) { m_vtkRenderWindow->SetSize(100, 100); } m_vtkRenderWindowInteractor = vtkRenderWindowInteractor::New(); m_vtkRenderWindowInteractor->SetRenderWindow(m_vtkRenderWindow); m_vtkRenderWindowInteractor->Initialize(); // initialize from RenderWindowBase - Initialize(rm, name, rmtype); + this->Initialize(rm, name, rmtype); m_vtkMitkEventProvider = vtkEventProvider::New(); m_vtkMitkEventProvider->SetInteractor(this->GetVtkRenderWindowInteractor()); m_vtkMitkEventProvider->SetMitkRenderWindow(this); m_vtkMitkEventProvider->SetEnabled(1); } mitk::RenderWindow::~RenderWindow() { Destroy(); m_vtkRenderWindow->Delete(); m_vtkRenderWindowInteractor->Delete(); m_vtkMitkEventProvider->Delete(); } vtkRenderWindow *mitk::RenderWindow::GetVtkRenderWindow() { return m_vtkRenderWindow; } vtkRenderWindowInteractor *mitk::RenderWindow::GetVtkRenderWindowInteractor() { return m_vtkRenderWindowInteractor; } void mitk::RenderWindow::SetSize(int width, int height) { this->GetVtkRenderWindow()->SetSize(width, height); } void mitk::RenderWindow::ReinitEventProvider() { m_vtkMitkEventProvider->SetEnabled(0); m_vtkMitkEventProvider->SetInteractor(this->GetVtkRenderWindowInteractor()); m_vtkMitkEventProvider->SetMitkRenderWindow(this); m_vtkMitkEventProvider->SetEnabled(1); } diff --git a/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp b/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp index d30ea1f15b..a405703343 100644 --- a/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp +++ b/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp @@ -1,121 +1,117 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderWindowBase.h" #include "mitkRenderingManager.h" #include "mitkVtkLayerController.h" #include "vtkRenderer.h" #include "mitkAnnotationUtils.h" mitk::RenderWindowBase::RenderWindowBase() : m_RenderProp(nullptr), m_InResize(false) { } /* * "Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a * virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from * a destructor, and the object to which the call applies is the object under construction or destruction, the function called is * the one defined in the constructor or destructor's own class or in one of its bases, but not a function overriding it in a class * derived from the constructor or destructor's class, or overriding it in one of the other base classes of the most derived object[..]" * or short: within constructors and destructors classes are not polymorph. */ void mitk::RenderWindowBase::Initialize(mitk::RenderingManager *renderingManager, const char *name, mitk::BaseRenderer::RenderingMode::Type renderingMode) { - if (renderingManager == nullptr) - { + if (nullptr == renderingManager) renderingManager = mitk::RenderingManager::GetInstance(); - } if (m_Renderer.IsNull()) - { m_Renderer = mitk::VtkPropRenderer::New(name, GetVtkRenderWindow(), renderingManager, renderingMode); - } m_Renderer->InitRenderer(this->GetVtkRenderWindow()); mitk::BaseRenderer::AddInstance(GetVtkRenderWindow(), m_Renderer); renderingManager->AddRenderWindow(GetVtkRenderWindow()); // Add previously created overlays to new BaseRenderer mitk::AnnotationUtils::BaseRendererChanged(m_Renderer); m_RenderProp = vtkMitkRenderProp::New(); m_RenderProp->SetPropRenderer(m_Renderer); m_Renderer->GetVtkRenderer()->AddViewProp(m_RenderProp); if ((this->GetVtkRenderWindow()->GetSize()[0] > 10) && (this->GetVtkRenderWindow()->GetSize()[1] > 10)) m_Renderer->InitSize(this->GetVtkRenderWindow()->GetSize()[0], this->GetVtkRenderWindow()->GetSize()[1]); m_InResize = false; } bool mitk::RenderWindowBase::HandleEvent(InteractionEvent *interactionEvent) { return m_Renderer->GetDispatcher()->ProcessEvent(interactionEvent); } void mitk::RenderWindowBase::Destroy() { m_Renderer->GetRenderingManager()->RemoveRenderWindow(GetVtkRenderWindow()); m_Renderer->GetVtkRenderer()->RemoveViewProp(m_RenderProp); m_RenderProp->Delete(); BaseRenderer::RemoveInstance(this->GetVtkRenderWindow()); } mitk::RenderWindowBase::~RenderWindowBase() { } mitk::SliceNavigationController *mitk::RenderWindowBase::GetSliceNavigationController() { return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetSliceNavigationController(); } mitk::CameraRotationController *mitk::RenderWindowBase::GetCameraRotationController() { return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetCameraRotationController(); } mitk::BaseController *mitk::RenderWindowBase::GetController() { mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(GetVtkRenderWindow()); switch (renderer->GetMapperID()) { case mitk::BaseRenderer::Standard2D: return GetSliceNavigationController(); case mitk::BaseRenderer::Standard3D: return GetCameraRotationController(); default: return GetSliceNavigationController(); } } mitk::VtkPropRenderer *mitk::RenderWindowBase::GetRenderer() { return m_Renderer; } diff --git a/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp b/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp index 391c28b73c..6f0986f708 100644 --- a/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp +++ b/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp @@ -1,682 +1,715 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVtkPropRenderer.h" // MAPPERS #include "mitkCameraController.h" #include "mitkImageVtkMapper2D.h" #include "mitkMapper.h" #include "mitkPlaneGeometryDataVtkMapper3D.h" #include "mitkVtkMapper.h" #include #include #include #include #include #include #include #include #include #include // VTK #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::VtkPropRenderer::VtkPropRenderer(const char *name, vtkRenderWindow *renWin, mitk::RenderingManager *rm, mitk::BaseRenderer::RenderingMode::Type renderingMode) : BaseRenderer(name, renWin, rm, renderingMode), m_CameraInitializedForMapperID(0) { didCount = false; m_WorldPointPicker = vtkWorldPointPicker::New(); m_PointPicker = vtkPointPicker::New(); m_PointPicker->SetTolerance(0.0025); m_CellPicker = vtkCellPicker::New(); m_CellPicker->SetTolerance(0.0025); mitk::PlaneGeometryDataVtkMapper3D::Pointer geometryMapper = mitk::PlaneGeometryDataVtkMapper3D::New(); m_CurrentWorldPlaneGeometryMapper = geometryMapper; m_CurrentWorldPlaneGeometryNode->SetMapper(2, geometryMapper); m_LightKit = vtkLightKit::New(); m_LightKit->AddLightsToRenderer(m_VtkRenderer); m_PickingMode = WorldPointPicking; m_TextRenderer = vtkRenderer::New(); m_TextRenderer->SetRenderWindow(renWin); m_TextRenderer->SetInteractive(0); m_TextRenderer->SetErase(0); } /*! \brief Destructs the VtkPropRenderer. */ mitk::VtkPropRenderer::~VtkPropRenderer() { // Workaround for GLDisplayList Bug { m_MapperID = 0; checkState(); } if (m_LightKit != nullptr) m_LightKit->Delete(); if (m_VtkRenderer != nullptr) { m_CameraController = nullptr; m_VtkRenderer->Delete(); m_VtkRenderer = nullptr; } else m_CameraController = nullptr; if (m_WorldPointPicker != nullptr) m_WorldPointPicker->Delete(); if (m_PointPicker != nullptr) m_PointPicker->Delete(); if (m_CellPicker != nullptr) m_CellPicker->Delete(); if (m_TextRenderer != nullptr) m_TextRenderer->Delete(); } void mitk::VtkPropRenderer::SetDataStorage(mitk::DataStorage *storage) { if (storage == nullptr || storage == m_DataStorage) return; BaseRenderer::SetDataStorage(storage); static_cast(m_CurrentWorldPlaneGeometryMapper.GetPointer()) ->SetDataStorageForTexture(m_DataStorage.GetPointer()); // Compute the geometry from the current data tree bounds and set it as world geometry this->SetWorldGeometryToDataStorageBounds(); } bool mitk::VtkPropRenderer::SetWorldGeometryToDataStorageBounds() { if (m_DataStorage.IsNull()) return false; // initialize world geometry auto geometry = m_DataStorage->ComputeVisibleBoundingGeometry3D(nullptr, "includeInBoundingBox"); if (geometry.IsNull()) return false; this->SetWorldTimeGeometry(geometry); this->GetVtkRenderer()->ResetCamera(); this->GetCameraController()->Fit(); this->Modified(); return true; } /*! \brief Called by the vtkMitkRenderProp in order to start MITK rendering process. */ int mitk::VtkPropRenderer::Render(mitk::VtkPropRenderer::RenderType type) { // Do we have objects to render? if (this->GetEmptyWorldGeometry()) return 0; if (m_DataStorage.IsNull()) return 0; // Update mappers and prepare mapper queue if (type == VtkPropRenderer::Opaque) + { this->PrepareMapperQueue(); + // Share vtkInformation, there might be new mappers + this->PropagateRenderInfoToMappers(); + } // go through the generated list and let the sorted mappers paint for (auto it = m_MappersMap.cbegin(); it != m_MappersMap.cend(); it++) { Mapper *mapper = (*it).second; mapper->MitkRender(this, type); } // Render text if (type == VtkPropRenderer::Overlay) { if (m_TextCollection.size() > 0) { m_TextRenderer->SetViewport(this->GetVtkRenderer()->GetViewport()); for (auto it = m_TextCollection.begin(); it != m_TextCollection.end(); ++it) m_TextRenderer->AddViewProp((*it).second); m_TextRenderer->Render(); } } return 1; } /*! \brief PrepareMapperQueue iterates the datatree PrepareMapperQueue iterates the datatree in order to find mappers which shall be rendered. Also, it sortes the mappers wrt to their layer. */ void mitk::VtkPropRenderer::PrepareMapperQueue() { // variable for counting LOD-enabled mappers m_NumberOfVisibleLODEnabledMappers = 0; // Do we have to update the mappers ? if (m_LastUpdateTime < GetMTime() || m_LastUpdateTime < this->GetCurrentWorldPlaneGeometry()->GetMTime()) { Update(); } else if (m_MapperID >= 1 && m_MapperID < 6) Update(); // remove all text properties before mappers will add new ones m_TextRenderer->RemoveAllViewProps(); for (unsigned int i = 0; i < m_TextCollection.size(); i++) { m_TextCollection[i]->Delete(); } m_TextCollection.clear(); // clear priority_queue m_MappersMap.clear(); int mapperNo = 0; // DataStorage if (m_DataStorage.IsNull()) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { const DataNode::Pointer node = it->Value(); if (node.IsNull()) continue; const mitk::Mapper::Pointer mapper = node->GetMapper(m_MapperID); if (mapper.IsNull()) continue; bool visible = true; node->GetVisibility(visible, this, "visible"); // The information about LOD-enabled mappers is required by RenderingManager if (mapper->IsLODEnabled(this) && visible) { ++m_NumberOfVisibleLODEnabledMappers; } // mapper without a layer property get layer number 1 int layer = 1; node->GetIntProperty("layer", layer, this); int nr = (layer << 16) + mapperNo; m_MappersMap.insert(std::pair(nr, mapper)); mapperNo++; } } +void mitk::VtkPropRenderer::SetPropertyKeys(vtkInformation *info) +{ + if (info == m_VtkRenderInfo) + return; + + m_VtkRenderInfo = info; + this->PropagateRenderInfoToMappers(); +} + +void mitk::VtkPropRenderer::PropagateRenderInfoToMappers() +{ + if (m_VtkRenderInfo == nullptr) + return; + + for (const auto &mapEntry : m_MappersMap) + { + auto vtkMapper = dynamic_cast(mapEntry.second); + + if (nullptr != vtkMapper) + { + auto prop = vtkMapper->GetVtkProp(this); + + if (nullptr != prop) + prop->SetPropertyKeys(m_VtkRenderInfo); + } + } +} + void mitk::VtkPropRenderer::Update(mitk::DataNode *datatreenode) { if (datatreenode != nullptr) { mitk::Mapper::Pointer mapper = datatreenode->GetMapper(m_MapperID); if (mapper.IsNotNull()) { if (GetCurrentWorldPlaneGeometry()->IsValid()) { mapper->Update(this); { auto *vtkmapper = dynamic_cast(mapper.GetPointer()); if (vtkmapper != nullptr) { vtkmapper->UpdateVtkTransform(this); } } } } } } void mitk::VtkPropRenderer::Update() { if (m_DataStorage.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetAll(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) Update(it->Value()); Modified(); m_LastUpdateTime = GetMTime(); } /*! \brief This method is called from the two Constructors */ void mitk::VtkPropRenderer::InitRenderer(vtkRenderWindow *renderWindow) { BaseRenderer::InitRenderer(renderWindow); vtkCallbackCommand *renderCallbackCommand = vtkCallbackCommand::New(); renderCallbackCommand->SetCallback(VtkPropRenderer::RenderingCallback); renderWindow->GetInteractor()->AddObserver(vtkCommand::RenderEvent, renderCallbackCommand); renderCallbackCommand->Delete(); if (renderWindow == nullptr) { m_InitNeeded = false; m_ResizeNeeded = false; return; } m_InitNeeded = true; m_ResizeNeeded = true; m_LastUpdateTime = 0; } void mitk::VtkPropRenderer::RenderingCallback(vtkObject *caller, unsigned long, void *, void *) { auto *renderWindowInteractor = dynamic_cast(caller); if (!renderWindowInteractor) return; mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(renderWindowInteractor->GetRenderWindow()); if (renderer) renderer->RequestUpdate(); } /*! \brief Resize the OpenGL Window */ void mitk::VtkPropRenderer::Resize(int w, int h) { BaseRenderer::Resize(w, h); m_RenderingManager->RequestUpdate(this->GetRenderWindow()); } void mitk::VtkPropRenderer::InitSize(int w, int h) { m_RenderWindow->SetSize(w, h); Superclass::InitSize(w, h); Modified(); Update(); if (m_VtkRenderer != nullptr) { int w = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); m_VtkRenderer->ResetCamera(); vtkObject::SetGlobalWarningDisplay(w); } this->GetCameraController()->Fit(); } int mitk::VtkPropRenderer::WriteSimpleText( std::string text, double posX, double posY, double color1, double color2, double color3, float opacity) { this->GetVtkRenderer()->ViewToDisplay(); if (!text.empty()) { Point2D p; vtkTextActor *textActor = vtkTextActor::New(); textActor->SetDisplayPosition(posX, posY); textActor->SetInput(text.c_str()); textActor->SetTextScaleModeToNone(); textActor->GetTextProperty()->SetColor(color1, color2, color3); // TODO: Read color from node property textActor->GetTextProperty()->SetOpacity(opacity); int text_id = m_TextCollection.size(); m_TextCollection.insert(TextMapType::value_type(text_id, textActor)); return text_id; } else { return -1; } } void mitk::VtkPropRenderer::SetMapperID(const MapperSlotId mapperId) { if (m_MapperID != mapperId) Superclass::SetMapperID(mapperId); // Workaround for GL Displaylist Bug checkState(); } /*! \brief Activates the current renderwindow. */ void mitk::VtkPropRenderer::MakeCurrent() { if (m_RenderWindow != nullptr) m_RenderWindow->MakeCurrent(); } void mitk::VtkPropRenderer::PickWorldPoint(const mitk::Point2D &displayPoint, mitk::Point3D &worldPoint) const { if (this->GetRenderWindow()->GetNeverRendered() != 0) return; // somebody called picking before we ever rendered; cannot have enough information yet switch (m_PickingMode) { case (WorldPointPicking): { m_WorldPointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_WorldPointPicker->GetPickPosition(), worldPoint); break; } case (PointPicking): { m_PointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_PointPicker->GetPickPosition(), worldPoint); break; } case (CellPicking): { m_CellPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_CellPicker->GetPickPosition(), worldPoint); break; } } // todo: is this picking in 2D renderwindows? // Superclass::PickWorldPoint(displayPoint, worldPoint); } mitk::DataNode *mitk::VtkPropRenderer::PickObject(const Point2D &displayPosition, Point3D &worldPosition) const { m_CellPicker->InitializePickList(); // Iterate over all DataStorage objects to determine all vtkProps intended // for picking DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { const DataNode *node = it->Value(); if (node == nullptr) continue; bool pickable = false; node->GetBoolProperty("pickable", pickable); if (!pickable) continue; auto *mapper = dynamic_cast(node->GetMapper(m_MapperID)); if (mapper == nullptr) continue; vtkProp *prop = mapper->GetVtkProp((mitk::BaseRenderer *)this); if (prop == nullptr) continue; m_CellPicker->AddPickList(prop); } // Do the picking and retrieve the picked vtkProp (if any) m_CellPicker->PickFromListOn(); m_CellPicker->Pick(displayPosition[0], displayPosition[1], 0.0, m_VtkRenderer); m_CellPicker->PickFromListOff(); vtk2itk(m_CellPicker->GetPickPosition(), worldPosition); vtkProp *prop = m_CellPicker->GetViewProp(); if (prop == nullptr) { return nullptr; } // Iterate over all DataStorage objects to determine if the retrieved // vtkProp is owned by any associated mapper. for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull()) continue; mitk::Mapper *mapper = node->GetMapper(m_MapperID); if (mapper == nullptr) continue; auto *vtkmapper = dynamic_cast(mapper); if (vtkmapper) { // if vtk-based, then ... if (vtkmapper->HasVtkProp(prop, const_cast(this))) { return node; } } } return nullptr; } // todo: is this 2D renderwindow picking? // return Superclass::PickObject( displayPosition, worldPosition ); vtkTextProperty *mitk::VtkPropRenderer::GetTextLabelProperty(int text_id) { return this->m_TextCollection[text_id]->GetTextProperty(); } void mitk::VtkPropRenderer::InitPathTraversal() { if (m_DataStorage.IsNotNull()) { this->UpdatePaths(); this->m_Paths->InitTraversal(); } } void mitk::VtkPropRenderer::UpdatePaths() { if (m_DataStorage.IsNull()) { return; } if (GetMTime() > m_PathTime || (m_Paths != nullptr && m_Paths->GetMTime() > m_PathTime)) { // Create the list to hold all the paths m_Paths = vtkSmartPointer::New(); DataStorage::SetOfObjects::ConstPointer objects = m_DataStorage->GetAll(); for (auto iter = objects->begin(); iter != objects->end(); ++iter) { vtkSmartPointer onePath = vtkSmartPointer::New(); Mapper *mapper = (*iter)->GetMapper(BaseRenderer::Standard3D); if (mapper) { auto *vtkmapper = dynamic_cast(mapper); if (nullptr != vtkmapper) { vtkProp *prop = vtkmapper->GetVtkProp(this); if (prop && prop->GetVisibility()) { // add to assembly path onePath->AddNode(prop, prop->GetMatrix()); m_Paths->AddItem(onePath); } } } } m_PathTime.Modified(); } } int mitk::VtkPropRenderer::GetNumberOfPaths() { UpdatePaths(); return m_Paths->GetNumberOfItems(); } vtkAssemblyPath *mitk::VtkPropRenderer::GetNextPath() { return m_Paths ? m_Paths->GetNextItem() : nullptr; } void mitk::VtkPropRenderer::ReleaseGraphicsResources(vtkWindow * /*renWin*/) { if (m_DataStorage.IsNull()) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (auto iter = allObjects->begin(); iter != allObjects->end(); ++iter) { DataNode::Pointer node = *iter; if (node.IsNull()) continue; Mapper *mapper = node->GetMapper(m_MapperID); if (mapper) { auto *vtkmapper = dynamic_cast(mapper); if (vtkmapper) vtkmapper->ReleaseGraphicsResources(this); } } } const vtkWorldPointPicker *mitk::VtkPropRenderer::GetWorldPointPicker() const { return m_WorldPointPicker; } const vtkPointPicker *mitk::VtkPropRenderer::GetPointPicker() const { return m_PointPicker; } const vtkCellPicker *mitk::VtkPropRenderer::GetCellPicker() const { return m_CellPicker; } mitk::VtkPropRenderer::MappersMapType mitk::VtkPropRenderer::GetMappersMap() const { return m_MappersMap; } // Workaround for GL Displaylist bug static int glWorkAroundGlobalCount = 0; bool mitk::VtkPropRenderer::useImmediateModeRendering() { return glWorkAroundGlobalCount > 1; } void mitk::VtkPropRenderer::checkState() { if (m_MapperID == Standard3D) { if (!didCount) { didCount = true; glWorkAroundGlobalCount++; if (glWorkAroundGlobalCount == 2) { MITK_INFO << "Multiple 3D Renderwindows active...: turning Immediate Rendering ON for legacy mappers"; // vtkMapper::GlobalImmediateModeRenderingOn(); } } } else { if (didCount) { didCount = false; glWorkAroundGlobalCount--; if (glWorkAroundGlobalCount == 1) { MITK_INFO << "Single 3D Renderwindow active...: turning Immediate Rendering OFF for legacy mappers"; // vtkMapper::GlobalImmediateModeRenderingOff(); } } } } //### Contains all methods which are neceassry before each VTK Render() call void mitk::VtkPropRenderer::PrepareRender() { if (this->GetMapperID() != m_CameraInitializedForMapperID) { Initialize2DvtkCamera(); // Set parallel projection etc. } GetCameraController()->AdjustCameraToPlane(); } bool mitk::VtkPropRenderer::Initialize2DvtkCamera() { if (this->GetMapperID() == Standard3D) { // activate parallel projection for 2D this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(false); vtkSmartPointer style = vtkSmartPointer::New(); this->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style); this->GetRenderWindow()->GetInteractor()->EnableRenderOff(); m_CameraInitializedForMapperID = Standard3D; } else if (this->GetMapperID() == Standard2D) { // activate parallel projection for 2D this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(true); // turn the light out in the scene in order to render correct grey values. // TODO Implement a property for light in the 2D render windows (in another method) this->GetVtkRenderer()->RemoveAllLights(); vtkSmartPointer style = vtkSmartPointer::New(); this->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style); this->GetRenderWindow()->GetInteractor()->EnableRenderOff(); m_CameraInitializedForMapperID = Standard2D; } return true; } diff --git a/Modules/Core/src/Rendering/vtkMitkRenderProp.cpp b/Modules/Core/src/Rendering/vtkMitkRenderProp.cpp index 2b3933c745..eaf97d9faf 100644 --- a/Modules/Core/src/Rendering/vtkMitkRenderProp.cpp +++ b/Modules/Core/src/Rendering/vtkMitkRenderProp.cpp @@ -1,110 +1,113 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "vtkMitkRenderProp.h" -#include #include #include +#include #include "mitkVtkMapper.h" -//#include "mitkGLMapper.h" vtkStandardNewMacro(vtkMitkRenderProp); vtkMitkRenderProp::vtkMitkRenderProp() { } vtkMitkRenderProp::~vtkMitkRenderProp() { } double *vtkMitkRenderProp::GetBounds() { return const_cast(m_VtkPropRenderer->GetBounds()); } void vtkMitkRenderProp::SetPropRenderer(mitk::VtkPropRenderer::Pointer propRenderer) { this->m_VtkPropRenderer = propRenderer; } +void vtkMitkRenderProp::SetPropertyKeys(vtkInformation *keys) +{ + Superclass::SetPropertyKeys(keys); + + if (nullptr != m_VtkPropRenderer) + m_VtkPropRenderer->SetPropertyKeys(keys); +} + int vtkMitkRenderProp::RenderOpaqueGeometry(vtkViewport * /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Opaque); } int vtkMitkRenderProp::RenderOverlay(vtkViewport * /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Overlay); } void vtkMitkRenderProp::ReleaseGraphicsResources(vtkWindow *window) { m_VtkPropRenderer->ReleaseGraphicsResources(window); } void vtkMitkRenderProp::InitPathTraversal() { m_VtkPropRenderer->InitPathTraversal(); } vtkAssemblyPath *vtkMitkRenderProp::GetNextPath() { return m_VtkPropRenderer->GetNextPath(); } int vtkMitkRenderProp::GetNumberOfPaths() { return m_VtkPropRenderer->GetNumberOfPaths(); } -// BUG (#1551) added method depth peeling int vtkMitkRenderProp::HasTranslucentPolygonalGeometry() { - typedef std::map MappersMapType; - const MappersMapType mappersMap = m_VtkPropRenderer->GetMappersMap(); - for (auto it = mappersMap.cbegin(); it != mappersMap.cend(); ++it) + for (const auto &mapEntry : m_VtkPropRenderer->GetMappersMap()) { - mitk::Mapper *mapper = (*it).second; + auto vtkMapper = dynamic_cast(mapEntry.second); - const mitk::VtkMapper::Pointer vtkMapper = dynamic_cast(mapper); - if (vtkMapper) + if (nullptr != vtkMapper) { // Due to VTK 5.2 bug, we need to initialize the Paths object in vtkPropAssembly // manually (see issue #8186 committed to VTK's Mantis issue tracker) // --> VTK bug resolved on 2008-12-01 - auto *propAssembly = dynamic_cast(vtkMapper->GetVtkProp(m_VtkPropRenderer)); - if (propAssembly) - { + auto propAssembly = dynamic_cast(vtkMapper->GetVtkProp(m_VtkPropRenderer)); + + if (nullptr != propAssembly) propAssembly->InitPathTraversal(); - } - if (vtkMapper->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry() == 1) + if (1 == vtkMapper->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()) return 1; } } + return 0; } int vtkMitkRenderProp::RenderTranslucentPolygonalGeometry(vtkViewport *) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Translucent); } int vtkMitkRenderProp::RenderVolumetricGeometry(vtkViewport *) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Volumetric); } diff --git a/Modules/QtWidgets/include/QmitkRenderWindow.h b/Modules/QtWidgets/include/QmitkRenderWindow.h index 012fd35019..8f4eb3be61 100644 --- a/Modules/QtWidgets/include/QmitkRenderWindow.h +++ b/Modules/QtWidgets/include/QmitkRenderWindow.h @@ -1,170 +1,170 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERWINDOW_H #define QMITKRENDERWINDOW_H #include "mitkRenderWindowBase.h" #include "QmitkRenderWindowMenu.h" #include #include #include #include "mitkBaseRenderer.h" #include "mitkInteractionEventConst.h" class QDragEnterEvent; class QDropEvent; class QInputEvent; /** * \ingroup QmitkModule * \brief MITK implementation of the QVTKWidget */ class MITKQTWIDGETS_EXPORT QmitkRenderWindow : public QVTKOpenGLWidget, public mitk::RenderWindowBase { Q_OBJECT public: QmitkRenderWindow( QWidget *parent = nullptr, const QString &name = "unnamed renderwindow", mitk::VtkPropRenderer *renderer = nullptr, mitk::RenderingManager *renderingManager = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard); + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); ~QmitkRenderWindow() override; /** * \brief Whether Qt events should be passed to parent (default: true) * * With introduction of the QVTKWidget the behaviour regarding Qt events changed. * QVTKWidget "accepts" Qt events like mouse clicks (i.e. set an "accepted" flag). * When this flag is set, Qt fininshed handling of this event -- otherwise it is * reached through to the widget's parent. * * This reaching through to the parent was implicitly required by QmitkMaterialWidget / QmitkMaterialShowCase. * * The default behaviour of QmitkRenderWindow is now to clear the "accepted" flag * of Qt events after they were handled by QVTKWidget. This way parents can also * handle events. * * If you don't want this behaviour, call SetResendQtEvents(true) on your render window. */ virtual void SetResendQtEvents(bool resend); // Set Layout Index to define the Layout Type void SetLayoutIndex(QmitkRenderWindowMenu::LayoutIndex layoutIndex); // Get Layout Index to define the Layout Type QmitkRenderWindowMenu::LayoutIndex GetLayoutIndex(); // MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged(QmitkRenderWindowMenu::LayoutDesign layoutDesign); // Activate or Deactivate MenuWidget. void ActivateMenuWidget(bool state); bool GetActivateMenuWidgetFlag() { return m_MenuWidgetActivated; } // Get it from the QVTKWidget parent vtkRenderWindow *GetVtkRenderWindow() override { return GetRenderWindow(); } vtkRenderWindowInteractor *GetVtkRenderWindowInteractor() override { return nullptr; } protected: // overloaded move handler void moveEvent(QMoveEvent *event) override; // overloaded show handler void showEvent(QShowEvent *event) override; // overloaded mouse press handler void mousePressEvent(QMouseEvent *event) override; // overloaded mouse double-click handler void mouseDoubleClickEvent(QMouseEvent *event) override; // overloaded mouse move handler void mouseMoveEvent(QMouseEvent *event) override; // overloaded mouse release handler void mouseReleaseEvent(QMouseEvent *event) override; // overloaded key press handler void keyPressEvent(QKeyEvent *event) override; // overloaded enter handler void enterEvent(QEvent *) override; // overloaded leave handler void leaveEvent(QEvent *) override; // Overloaded resize handler, see decs in QVTKOpenGLWidget. // Basically, we have to ensure the VTK rendering is updated for each change in window size. void resizeGL(int w, int h) Q_DECL_OVERRIDE; /// \brief Simply says we accept the event type. void dragEnterEvent(QDragEnterEvent *event) override; /// \brief If the dropped type is application/x-mitk-datanodes we process the request by converting to mitk::DataNode /// pointers and emitting the NodesDropped signal. void dropEvent(QDropEvent *event) override; #ifndef QT_NO_WHEELEVENT // overload wheel mouse event void wheelEvent(QWheelEvent *) override; #endif void AdjustRenderWindowMenuVisibility(const QPoint &pos); Q_SIGNALS: void LayoutDesignChanged(QmitkRenderWindowMenu::LayoutDesign); void ResetView(); void CrosshairRotationModeChanged(int); void CrosshairVisibilityChanged(bool); void moved(); /// \brief Emits a signal to say that this window has had the following nodes dropped on it. void NodesDropped(QmitkRenderWindow *thisWindow, std::vector nodes); private Q_SLOTS: void DeferredHideMenu(); private: // Helper Functions to Convert Qt-Events to Mitk-Events mitk::Point2D GetMousePosition(QMouseEvent *me) const; mitk::Point2D GetMousePosition(QWheelEvent *we) const; mitk::InteractionEvent::MouseButtons GetEventButton(QMouseEvent *me) const; mitk::InteractionEvent::MouseButtons GetButtonState(QMouseEvent *me) const; mitk::InteractionEvent::ModifierKeys GetModifiers(QInputEvent *me) const; mitk::InteractionEvent::MouseButtons GetButtonState(QWheelEvent *we) const; std::string GetKeyLetter(QKeyEvent *ke) const; int GetDelta(QWheelEvent *we) const; bool m_ResendQtEvents; QmitkRenderWindowMenu *m_MenuWidget; bool m_MenuWidgetActivated; QmitkRenderWindowMenu::LayoutIndex m_LayoutIndex; vtkSmartPointer m_InternalRenderWindow; }; #endif // QMITKRENDERWINDOW_H diff --git a/Modules/QtWidgets/include/QmitkStdMultiWidget.h b/Modules/QtWidgets/include/QmitkStdMultiWidget.h index 03966cdc5b..23b7b295ee 100644 --- a/Modules/QtWidgets/include/QmitkStdMultiWidget.h +++ b/Modules/QtWidgets/include/QmitkStdMultiWidget.h @@ -1,165 +1,165 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKSTDMULTIWIDGET_H #define QMITKSTDMULTIWIDGET_H // qt widgets module #include "MitkQtWidgetsExports.h" #include "QmitkAbstractMultiWidget.h" /** * @brief The 'QmitkStdMultiWidget' is a 'QmitkAbstractMultiWidget' that is used to display multiple render windows at once. * Render windows are predefined in a 2x2 design with 3 different 2D view planes and a 3D render window. */ class MITKQTWIDGETS_EXPORT QmitkStdMultiWidget : public QmitkAbstractMultiWidget { Q_OBJECT public: - - QmitkStdMultiWidget(QWidget *parent = nullptr, - Qt::WindowFlags f = 0, - mitk::RenderingManager *renderingManager = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, - const QString &name = "stdmulti"); + QmitkStdMultiWidget( + QWidget *parent = nullptr, + Qt::WindowFlags f = nullptr, + mitk::RenderingManager *renderingManager = nullptr, + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing, + const QString &name = "stdmulti"); ~QmitkStdMultiWidget() override; virtual void InitializeMultiWidget() override; virtual QmitkRenderWindow* GetRenderWindow(const QString& widgetName) const override; virtual QmitkRenderWindow* GetRenderWindow(const mitk::BaseRenderer::ViewDirection& viewDirection) const override; virtual void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) override; virtual const mitk::Point3D GetSelectedPosition(const QString& widgetName) const override; virtual void SetCrosshairVisibility(bool) override; virtual bool GetCrosshairVisibility() const override; virtual void ResetCrosshair() override; virtual void SetWidgetPlaneMode(int mode) override; mitk::SliceNavigationController* GetTimeNavigationController(); void AddPlanesToDataStorage(); void RemovePlanesFromDataStorage(); /** \brief Listener to the CrosshairPositionEvent Ensures the CrosshairPositionEvent is handled only once and at the end of the Qt-Event loop */ void HandleCrosshairPositionEvent(); /** * @brief Convenience method to get a render window widget. * @param Number of the widget (0-3) * @return The render window widget */ QmitkRenderWindow* GetRenderWindow(unsigned int number) const; QmitkRenderWindow* GetRenderWindow1() const; QmitkRenderWindow* GetRenderWindow2() const; QmitkRenderWindow* GetRenderWindow3() const; QmitkRenderWindow* GetRenderWindow4() const; /** * @brief Convenience method to get a widget plane. * @param Number of the widget plane (1-3) * @return The widget plane as data node */ mitk::DataNode::Pointer GetWidgetPlane(unsigned int number) const; mitk::DataNode::Pointer GetWidgetPlane1() const; mitk::DataNode::Pointer GetWidgetPlane2() const; mitk::DataNode::Pointer GetWidgetPlane3() const; /** * @brief SetDecorationColor Set the color of the decoration of the 4 widgets. * * This is used to color the frame of the renderwindow and the corner annatation. * For the first 3 widgets, this color is a property of the helper object nodes * which contain the respective plane geometry. For widget 4, this is a member, * since there is no data node for this widget. */ void SetDecorationColor(unsigned int widgetNumber, mitk::Color color); /** * @brief GetDecorationColorForWidget Get the color for annotation, crosshair and rectangle. * @param widgetNumber Number of the renderwindow (0-3). * @return Color in mitk format. */ mitk::Color GetDecorationColor(unsigned int widgetNumber); public Q_SLOTS: // mouse events virtual void mousePressEvent(QMouseEvent*) override; virtual void moveEvent(QMoveEvent* e) override; virtual void wheelEvent(QWheelEvent* e) override; /// Receives the signal from HandleCrosshairPositionEvent, executes the StatusBar update void HandleCrosshairPositionEventDelayed(); void Fit(); void AddDisplayPlaneSubTree(); void EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p); void SetWidgetPlaneVisibility(const char *widgetName, bool visible, mitk::BaseRenderer *renderer = nullptr); void SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer = nullptr); Q_SIGNALS: void WheelMoved(QWheelEvent *); void Moved(); private: virtual void SetLayoutImpl() override; virtual void SynchronizeImpl() override { } virtual void SetInteractionSchemeImpl() override { } void CreateRenderWindowWidgets(); mitk::SliceNavigationController* m_TimeNavigationController; /** * @brief The 3 helper objects which contain the plane geometry. */ mitk::DataNode::Pointer m_PlaneNode1; mitk::DataNode::Pointer m_PlaneNode2; mitk::DataNode::Pointer m_PlaneNode3; /** * @brief m_ParentNodeForGeometryPlanes This helper object is added to the datastorage * and contains the 3 planes for displaying the image geometry (crosshair and 3D planes). */ mitk::DataNode::Pointer m_ParentNodeForGeometryPlanes; /** * @brief m_DecorationColorWidget4 color for annotation and rectangle of widget 4. * * For other widgets1-3, the color is a property of the respective data node. * There is no node for widget 4, hence, we need an extra member. */ mitk::Color m_DecorationColorWidget4; bool m_PendingCrosshairPositionEvent; }; #endif // QMITKSTDMULTIWIDGET_H diff --git a/Modules/QtWidgetsExt/src/QmitkSelectableGLWidget.cpp b/Modules/QtWidgetsExt/src/QmitkSelectableGLWidget.cpp index 0406f772a6..ab310990b4 100644 --- a/Modules/QtWidgetsExt/src/QmitkSelectableGLWidget.cpp +++ b/Modules/QtWidgetsExt/src/QmitkSelectableGLWidget.cpp @@ -1,106 +1,106 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkSelectableGLWidget.h" #include "QmitkRenderWindow.h" #include QmitkSelectableGLWidget::QmitkSelectableGLWidget(QWidget *parent) : QWidget(parent), m_Ui(new Ui::QmitkSelectableGLWidget) { m_Ui->setupUi(this); QLayout *hlayout; hlayout = m_Ui->hboxLayout; hlayout->setMargin(3); QString rendererName("Renderer::"); rendererName += objectName(); // create Renderer m_Renderer = mitk::VtkPropRenderer::New( - qPrintable(rendererName), nullptr, mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::RenderingMode::Standard); + qPrintable(rendererName), nullptr, mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); // create widget QString composedName("QSGLWt::"); if (!objectName().isEmpty()) composedName += objectName(); else composedName += "QmitkGLWidget"; /* * here is the place to define QT-Flags to enable and disable certain OpenGL elements, like StencilBuffer, RGBA and so * on. * See QGLFormat for futher informations * QGL::AlphaChannel: Enable Alpha in Framebuffer * QGL::Rgba enable use of rgba rather than color_index * QGL::StencilBuffer for use of stencilbuffer in OpenGL */ m_RenderWindow = new QmitkRenderWindow(this, composedName, m_Renderer); hlayout->addWidget(m_RenderWindow); } QmitkSelectableGLWidget::~QmitkSelectableGLWidget() { delete m_Ui; } mitk::VtkPropRenderer *QmitkSelectableGLWidget::GetRenderer() { return m_Renderer.GetPointer(); } QmitkRenderWindow *QmitkSelectableGLWidget::GetRenderWindow() const { return m_RenderWindow; } void QmitkSelectableGLWidget::wheelEvent(QWheelEvent *e) { if (m_RenderWindow->GetSliceNavigationController()->GetSliceLocked()) return; mitk::Stepper *stepper = m_RenderWindow->GetSliceNavigationController()->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = m_RenderWindow->GetSliceNavigationController()->GetTime(); } if (e->orientation() * e->delta() > 0) { stepper->Next(); } else { stepper->Previous(); } } mitk::SliceNavigationController *QmitkSelectableGLWidget::GetSliceNavigationController() const { return m_RenderWindow->GetSliceNavigationController(); } mitk::CameraRotationController *QmitkSelectableGLWidget::GetCameraRotationController() const { return m_RenderWindow->GetCameraRotationController(); } mitk::BaseController *QmitkSelectableGLWidget::GetController() const { return m_RenderWindow->GetController(); } diff --git a/Modules/Segmentation/Testing/mitkContourMapper2DTest.cpp b/Modules/Segmentation/Testing/mitkContourMapper2DTest.cpp index ca945671be..8506ace53e 100644 --- a/Modules/Segmentation/Testing/mitkContourMapper2DTest.cpp +++ b/Modules/Segmentation/Testing/mitkContourMapper2DTest.cpp @@ -1,80 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCommon.h" #include "mitkContour.h" #include "mitkContourMapper2D.h" #include "mitkDataNode.h" #include "mitkStandaloneDataStorage.h" #include "mitkVtkPropRenderer.h" #include int mitkContourMapper2DTest(int /*argc*/, char * /*argv*/ []) { mitk::Contour::Pointer contour; mitk::ContourMapper2D::Pointer contourMapper; mitk::DataNode::Pointer node; contourMapper = mitk::ContourMapper2D::New(); node = mitk::DataNode::New(); std::cout << "Testing mitk::ContourMapper2D::New(): "; contour = mitk::Contour::New(); node->SetData(contour); if (contour.IsNull()) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } else { std::cout << "[PASSED]" << std::endl; } contourMapper->SetDataNode(node); contourMapper->Update(nullptr); auto *testContour = (mitk::Contour *)contourMapper->GetInput(); std::cout << testContour << std::endl; mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); ds->Add(node); mitk::BoundingBox::Pointer bounds = ds->ComputeBoundingBox(); std::cout << "bounds: " << bounds << std::endl; bounds = ds->ComputeVisibleBoundingBox(); std::cout << "visible bounds: " << bounds << std::endl; vtkRenderWindow *renWin = vtkRenderWindow::New(); mitk::VtkPropRenderer::Pointer renderer = mitk::VtkPropRenderer::New( - "ContourRenderer", renWin, mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::RenderingMode::Standard); + "ContourRenderer", renWin, mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::RenderingMode::NoAntiAliasing); std::cout << "Testing mitk::BaseRenderer::SetData()" << std::endl; renderer->SetDataStorage(ds); std::cout << "[TEST DONE]" << std::endl; renWin->Delete(); return EXIT_SUCCESS; } diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/plugin.xml b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/plugin.xml index aac0c76d78..596b89bd5c 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/plugin.xml +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/plugin.xml @@ -1,29 +1,29 @@ - + diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp index fc8faedc73..3f3ce8590f 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp @@ -1,263 +1,267 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "QmitkStdMultiWidgetEditorPreferencePage.h" #include #include #include #include QmitkStdMultiWidgetEditorPreferencePage::QmitkStdMultiWidgetEditorPreferencePage() : m_Preferences(nullptr), m_Ui(new Ui::QmitkStdMultiWidgetEditorPreferencePage), m_Control(nullptr) { } QmitkStdMultiWidgetEditorPreferencePage::~QmitkStdMultiWidgetEditorPreferencePage() { } void QmitkStdMultiWidgetEditorPreferencePage::CreateQtControl(QWidget* parent) { m_Control = new QWidget(parent); m_Ui->setupUi(m_Control); berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); Q_ASSERT(prefService); m_Preferences = prefService->GetSystemPreferences()->Node(QmitkStdMultiWidgetEditor::EDITOR_ID); QObject::connect( m_Ui->m_ColorButton1, SIGNAL( clicked() ) , this, SLOT( ColorChooserButtonClicked() ) ); QObject::connect( m_Ui->m_ColorButton2, SIGNAL( clicked() ) , this, SLOT( ColorChooserButtonClicked() ) ); QObject::connect( m_Ui->m_ResetButton, SIGNAL( clicked() ) , this, SLOT( ResetPreferencesAndGUI() ) ); QObject::connect( m_Ui->m_RenderingMode, SIGNAL(activated(int) ) , this, SLOT( ChangeRenderingMode(int) ) ); QObject::connect( m_Ui->m_RenderWindowDecorationColor, SIGNAL( clicked() ) , this, SLOT( ColorChooserButtonClicked() ) ); QObject::connect( m_Ui->m_RenderWindowChooser, SIGNAL(activated(int) ) , this, SLOT( OnWidgetComboBoxChanged(int) ) ); QObject::connect( m_Ui->m_RenderWindowDecorationText, SIGNAL(textChanged(QString) ) , this, SLOT( AnnotationTextChanged(QString) ) ); this->Update(); } QWidget* QmitkStdMultiWidgetEditorPreferencePage::GetQtControl() const { return m_Control; } void QmitkStdMultiWidgetEditorPreferencePage::Init(berry::IWorkbench::Pointer) { } void QmitkStdMultiWidgetEditorPreferencePage::PerformCancel() { } bool QmitkStdMultiWidgetEditorPreferencePage::PerformOk() { m_Preferences->Put("stdmulti.widget0 corner annotation", m_WidgetAnnotation[0]); m_Preferences->Put("stdmulti.widget1 corner annotation", m_WidgetAnnotation[1]); m_Preferences->Put("stdmulti.widget2 corner annotation", m_WidgetAnnotation[2]); m_Preferences->Put("stdmulti.widget3 corner annotation", m_WidgetAnnotation[3]); m_Preferences->Put("stdmulti.widget0 decoration color", m_WidgetDecorationColor[0]); m_Preferences->Put("stdmulti.widget1 decoration color", m_WidgetDecorationColor[1]); m_Preferences->Put("stdmulti.widget2 decoration color", m_WidgetDecorationColor[2]); m_Preferences->Put("stdmulti.widget3 decoration color", m_WidgetDecorationColor[3]); m_Preferences->Put("stdmulti.widget0 first background color", m_WidgetBackgroundColor1[0]); m_Preferences->Put("stdmulti.widget1 first background color", m_WidgetBackgroundColor1[1]); m_Preferences->Put("stdmulti.widget2 first background color", m_WidgetBackgroundColor1[2]); m_Preferences->Put("stdmulti.widget3 first background color", m_WidgetBackgroundColor1[3]); m_Preferences->Put("stdmulti.widget0 second background color", m_WidgetBackgroundColor2[0]); m_Preferences->Put("stdmulti.widget1 second background color", m_WidgetBackgroundColor2[1]); m_Preferences->Put("stdmulti.widget2 second background color", m_WidgetBackgroundColor2[2]); m_Preferences->Put("stdmulti.widget3 second background color", m_WidgetBackgroundColor2[3]); m_Preferences->PutInt("crosshair gap size", m_Ui->m_CrosshairGapSize->value()); m_Preferences->PutBool("Use constrained zooming and panning" , m_Ui->m_EnableFlexibleZooming->isChecked()); m_Preferences->PutBool("Show level/window widget", m_Ui->m_ShowLevelWindowWidget->isChecked()); m_Preferences->PutBool("PACS like mouse interaction", m_Ui->m_PACSLikeMouseMode->isChecked()); m_Preferences->PutInt("Rendering Mode", m_Ui->m_RenderingMode->currentIndex()); return true; } void QmitkStdMultiWidgetEditorPreferencePage::Update() { //Note: there should be default preferences already defined in the //QmitkStdMultiWidgetEditor::InitializePreferences(). Therefore, //all default values here are not relevant. //gradient background colors m_WidgetBackgroundColor1[0] = m_Preferences->Get("stdmulti.widget0 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[0] = m_Preferences->Get("stdmulti.widget0 second background color", "#1d1d1c"); m_WidgetBackgroundColor1[1] = m_Preferences->Get("stdmulti.widget1 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[1] = m_Preferences->Get("stdmulti.widget1 second background color", "#1d1d1c"); m_WidgetBackgroundColor1[2] = m_Preferences->Get("stdmulti.widget2 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[2] = m_Preferences->Get("stdmulti.widget2 second background color", "#1d1d1c"); m_WidgetBackgroundColor1[3] = m_Preferences->Get("stdmulti.widget3 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[3] = m_Preferences->Get("stdmulti.widget3 second background color", "#adb1b6"); //decoration colors m_WidgetDecorationColor[0] = m_Preferences->Get("stdmulti.widget0 decoration color", "#c00000"); m_WidgetDecorationColor[1] = m_Preferences->Get("stdmulti.widget1 decoration color", "#0fad00"); m_WidgetDecorationColor[2] = m_Preferences->Get("stdmulti.widget2 decoration color", "#0080ff"); m_WidgetDecorationColor[3] = m_Preferences->Get("stdmulti.widget3 decoration color", "#fec500"); //annotation text m_WidgetAnnotation[0] = m_Preferences->Get("stdmulti.widget0 corner annotation", "Axial"); m_WidgetAnnotation[1] = m_Preferences->Get("stdmulti.widget1 corner annotation", "Sagittal"); m_WidgetAnnotation[2] = m_Preferences->Get("stdmulti.widget2 corner annotation", "Coronal"); m_WidgetAnnotation[3] = m_Preferences->Get("stdmulti.widget3 corner annotation", "3D"); //Ui stuff int index = m_Ui->m_RenderWindowChooser->currentIndex(); QColor firstBackgroundColor(m_WidgetBackgroundColor1[index]); QColor secondBackgroundColor(m_WidgetBackgroundColor2[index]); QColor widgetColor(m_WidgetDecorationColor[index]); this->SetStyleSheetToColorChooserButton(firstBackgroundColor, m_Ui->m_ColorButton1); this->SetStyleSheetToColorChooserButton(secondBackgroundColor, m_Ui->m_ColorButton2); this->SetStyleSheetToColorChooserButton(widgetColor, m_Ui->m_RenderWindowDecorationColor); m_Ui->m_RenderWindowDecorationText->setText(m_WidgetAnnotation[index]); m_Ui->m_EnableFlexibleZooming->setChecked(m_Preferences->GetBool("Use constrained zooming and panning", true)); m_Ui->m_ShowLevelWindowWidget->setChecked(m_Preferences->GetBool("Show level/window widget", true)); m_Ui->m_PACSLikeMouseMode->setChecked(m_Preferences->GetBool("PACS like mouse interaction", false)); - int mode= m_Preferences->GetInt("Rendering Mode",0); + int mode = m_Preferences->GetInt("Rendering Mode", 1); m_Ui->m_RenderingMode->setCurrentIndex(mode); m_Ui->m_CrosshairGapSize->setValue(m_Preferences->GetInt("crosshair gap size", 32)); } void QmitkStdMultiWidgetEditorPreferencePage::ColorChooserButtonClicked() { unsigned int widgetIndex = m_Ui->m_RenderWindowChooser->currentIndex(); if(widgetIndex > 3) { MITK_ERROR << "Selected index for unknown."; return; } QObject *senderObj = sender(); // This will give Sender button //find out last used color and set it QColor initialColor; if( senderObj->objectName() == m_Ui->m_ColorButton1->objectName()) { initialColor = QColor(m_WidgetBackgroundColor1[widgetIndex]); }else if( senderObj->objectName() == m_Ui->m_ColorButton2->objectName()) { initialColor = QColor(m_WidgetBackgroundColor2[widgetIndex]); }else if( senderObj->objectName() == m_Ui->m_RenderWindowDecorationColor->objectName()) { initialColor = QColor(m_WidgetDecorationColor[widgetIndex]); } //get the new color QColor newcolor = QColorDialog::getColor(initialColor); if(!newcolor.isValid()) { newcolor = initialColor; } this->SetStyleSheetToColorChooserButton(newcolor, static_cast(senderObj)); //convert it to std string and apply it if( senderObj->objectName() == m_Ui->m_ColorButton1->objectName()) { m_WidgetBackgroundColor1[widgetIndex] = newcolor.name(); } else if( senderObj->objectName() == m_Ui->m_ColorButton2->objectName()) { m_WidgetBackgroundColor2[widgetIndex] = newcolor.name(); } else if( senderObj->objectName() == m_Ui->m_RenderWindowDecorationColor->objectName()) { m_WidgetDecorationColor[widgetIndex] = newcolor.name(); } } void QmitkStdMultiWidgetEditorPreferencePage::SetStyleSheetToColorChooserButton(QColor backgroundcolor, QPushButton* button) { button->setAutoFillBackground(true); QString styleSheet = "background-color:rgb("; styleSheet.append(QString::number(backgroundcolor.red())); styleSheet.append(","); styleSheet.append(QString::number(backgroundcolor.green())); styleSheet.append(","); styleSheet.append(QString::number(backgroundcolor.blue())); styleSheet.append(")"); button->setStyleSheet(styleSheet); } void QmitkStdMultiWidgetEditorPreferencePage::AnnotationTextChanged(QString text) { unsigned int widgetIndex = m_Ui->m_RenderWindowChooser->currentIndex(); if( widgetIndex > 3) { MITK_INFO << "Selected index for unknown widget."; return; } m_WidgetAnnotation[widgetIndex] = text; } void QmitkStdMultiWidgetEditorPreferencePage::ResetPreferencesAndGUI() { m_Preferences->Clear(); this->Update(); } void QmitkStdMultiWidgetEditorPreferencePage::OnWidgetComboBoxChanged(int i) { if( i > 3) { MITK_ERROR << "Selected unknown widget."; return; } QColor widgetColor(m_WidgetDecorationColor[i]); QColor gradientBackground1(m_WidgetBackgroundColor1[i]); QColor gradientBackground2(m_WidgetBackgroundColor2[i]); this->SetStyleSheetToColorChooserButton(widgetColor, m_Ui->m_RenderWindowDecorationColor); this->SetStyleSheetToColorChooserButton(gradientBackground1, m_Ui->m_ColorButton1); this->SetStyleSheetToColorChooserButton(gradientBackground2, m_Ui->m_ColorButton2); m_Ui->m_RenderWindowDecorationText->setText(m_WidgetAnnotation[i]); } -void QmitkStdMultiWidgetEditorPreferencePage::ChangeRenderingMode(int ) +void QmitkStdMultiWidgetEditorPreferencePage::ChangeRenderingMode(int i) { - //if( i == 0 ) - //{ - m_CurrentRenderingMode = "Standard"; - //} + if (0 == i) + { + m_CurrentRenderingMode = "No Anti-aliasing"; + } + else if (1 == i) + { + m_CurrentRenderingMode = "Fast Approximate Anti-Aliasing (FXAA)"; + } } diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui index 540c3223c6..e0a9d50f14 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui @@ -1,212 +1,217 @@ QmitkStdMultiWidgetEditorPreferencePage 0 0 518 431 External Programs stdmulti.widget1 stdmulti.widget2 stdmulti.widget3 stdmulti.widget4 <html><head/><body><p>If two colors are set, a gradient background is generated.</p></body></html> Background color Reset preferences - Standard Rendering + No anti-aliasing + + + + + Fast Approximate Anti-Aliasing (FXAA) * Changes require restart of MITK. 32 Qt::Horizontal The small text on the button left of each renderwindow. Corner annotation <html><head/><body><p>The gap in the middle of the crosshair in pixels.</p></body></html> Crosshair gap size <html><head/><body><p>The color is used for the following decorations (of each renderwindow):</p><p>Rectangle border</p><p>Corner annotation</p><p>Crosshair</p><p>Plane geometry helper objects (3D Planes)</p><p>Image navigator borders</p><p><br/></p></body></html> Decoration color <html><head/><body><p>Choose the renderwindow from the multi widget.</p></body></html> Render windows Qt::LeftToRight Show level/window widget true Qt::LeftToRight Use PACS like mouse interaction (select left mouse button action) false Qt::Horizontal Rendering Mode* <html><head/><body><p>If activated, zooming and panning is limited to a certain space arround each image.</p></body></html> Qt::LeftToRight Use constraint zooming and panning true