diff --git a/Modules/Core/include/mitkRenderingManager.h b/Modules/Core/include/mitkRenderingManager.h index 200814ea2e..4245adfa70 100644 --- a/Modules/Core/include/mitkRenderingManager.h +++ b/Modules/Core/include/mitkRenderingManager.h @@ -1,429 +1,403 @@ /*=================================================================== 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 MITKRENDERINGMANAGER_H_HEADER_INCLUDED_C135A197 #define MITKRENDERINGMANAGER_H_HEADER_INCLUDED_C135A197 #include #include #include #include #include #include #include #include "mitkPropertyList.h" #include "mitkProperties.h" #include "mitkTimeGeometry.h" class vtkRenderWindow; class vtkObject; namespace mitk { class RenderingManager; class RenderingManagerFactory; class BaseGeometry; class SliceNavigationController; class BaseRenderer; class DataStorage; /** * \brief Manager for coordinating the rendering process. * * RenderingManager is a central instance retrieving and executing * RenderWindow update requests. Its main purpose is to coordinate * distributed requests which cannot be aware of each other - lacking the * knowledge of whether they are really necessary or not. For example, two * objects might determine that a specific RenderWindow needs to be updated. * This would result in one unnecessary update, if both executed the update * on their own. * * The RenderingManager addresses this by letting each such object * request an update, and waiting for other objects to possibly * issue the same request. The actual update will then only be executed at a * well-defined point in the main event loop (this may be each time after * event processing is done). * * Convinience methods for updating all RenderWindows which have been * registered with the RenderingManager exist. If theses methods are not * used, it is not required to register (add) RenderWindows prior to using * the RenderingManager. * * The methods #ForceImmediateUpdate() and #ForceImmediateUpdateAll() can * be used to force the RenderWindow update execution without any delay, * bypassing the request functionality. * * The interface of RenderingManager is platform independent. Platform * specific subclasses have to be implemented, though, to supply an * appropriate event issueing for controlling the update execution process. * See method documentation for a description of how this can be done. * * \sa TestingRenderingManager An "empty" RenderingManager implementation which * can be used in tests etc. * */ class MITKCORE_EXPORT RenderingManager : public itk::Object { public: mitkClassMacroItkParent(RenderingManager,itk::Object); typedef std::vector< vtkRenderWindow* > RenderWindowVector; typedef std::vector< float > FloatVector; typedef std::vector< bool > BoolVector; typedef itk::SmartPointer< DataStorage > DataStoragePointer; enum RequestType { REQUEST_UPDATE_ALL = 0, REQUEST_UPDATE_2DWINDOWS, REQUEST_UPDATE_3DWINDOWS }; static Pointer New(); /** Set the object factory which produces the desired platform specific * RenderingManager singleton instance. */ static void SetFactory( RenderingManagerFactory *factory ); /** Get the object factory which produces the platform specific * RenderingManager instances. */ static const RenderingManagerFactory *GetFactory(); /** Returns true if a factory has already been set. */ static bool HasFactory(); /** Get the RenderingManager singleton instance. */ static RenderingManager *GetInstance(); /** Returns true if the singleton instance does already exist. */ static bool IsInstantiated(); /** Adds a RenderWindow. This is required if the methods #RequestUpdateAll * or #ForceImmediateUpdate are to be used. */ void AddRenderWindow( vtkRenderWindow *renderWindow ); /** Removes a RenderWindow. */ void RemoveRenderWindow( vtkRenderWindow *renderWindow ); /** Get a list of all registered RenderWindows */ const RenderWindowVector &GetAllRegisteredRenderWindows(); /** Requests an update for the specified RenderWindow, to be executed as * soon as the main loop is ready for rendering. */ void RequestUpdate( vtkRenderWindow *renderWindow ); /** Immediately executes an update of the specified RenderWindow. */ void ForceImmediateUpdate( vtkRenderWindow *renderWindow ); /** Requests all currently registered RenderWindows to be updated. * If only 2D or 3D windows should be updated, this can be specified * via the parameter requestType. */ void RequestUpdateAll( RequestType type = REQUEST_UPDATE_ALL ); /** Immediately executes an update of all registered RenderWindows. * If only 2D or 3D windows should be updated, this can be specified * via the parameter requestType. */ void ForceImmediateUpdateAll( RequestType type = REQUEST_UPDATE_ALL ); /** Initializes the windows specified by requestType to the geometry of the * given DataStorage. */ //virtual bool InitializeViews( const DataStorage *storage, const DataNode* node = NULL, // RequestType type = REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace = false ); /** Initializes the windows specified by requestType to the given * geometry. PLATFORM SPECIFIC. TODO: HOW IS THIS PLATFORM SPECIFIC? * Throws an exception if bounding box has 0 extent due to exceeding * double precision range. */ virtual bool InitializeViews( const BaseGeometry *geometry, RequestType type = REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace = false ); virtual bool InitializeViews( const TimeGeometry *geometry, RequestType type = REQUEST_UPDATE_ALL, bool preserveRoughOrientationInWorldSpace = false ); /** Initializes the windows to the default viewing direction * (geomtry information is NOT changed). PLATFORM SPECIFIC. */ virtual bool InitializeViews( RequestType type = REQUEST_UPDATE_ALL ); /** Initializes the specified window to the geometry of the given * DataNode. Set "initializeGlobalTimeSNC" to true in order to use this * geometry as global TimeGeometry. PLATFORM SPECIFIC. */ //virtual bool InitializeView( vtkRenderWindow *renderWindow, const DataStorage* ds, const DataNode* node = NULL, bool initializeGlobalTimeSNC = false ); /** Initializes the specified window to the given geometry. Set * "initializeGlobalTimeSNC" to true in order to use this geometry as * global TimeGeometry. PLATFORM SPECIFIC. */ virtual bool InitializeView( vtkRenderWindow *renderWindow, const BaseGeometry *geometry, bool initializeGlobalTimeSNC = false); virtual bool InitializeView( vtkRenderWindow *renderWindow, const TimeGeometry *geometry, bool initializeGlobalTimeSNC = false); /** Initializes the specified window to the default viewing direction * (geomtry information is NOT changed). PLATFORM SPECIFIC. */ virtual bool InitializeView( vtkRenderWindow *renderWindow ); /** * @brief Initializes the renderwindows by the aggregated geometry of * all objects that are held in the data storage. * This is basically a global reinit * @param The data storage from which the bounding object can be retrieved */ virtual void InitializeViewsByBoundingObjects(const DataStorage * ); /** Gets the (global) SliceNavigationController responsible for * time-slicing. */ const SliceNavigationController *GetTimeNavigationController() const; /** Gets the (global) SliceNavigationController responsible for * time-slicing. */ SliceNavigationController *GetTimeNavigationController(); virtual ~RenderingManager(); /** Executes all pending requests. This method has to be called by the * system whenever a RenderingManager induced request event occurs in * the system pipeline (see concrete RenderingManager implementations). */ virtual void ExecutePendingRequests(); bool IsRendering() const; void AbortRendering(); /** En-/Disable LOD increase globally. */ itkSetMacro( LODIncreaseBlocked, bool ); /** En-/Disable LOD increase globally. */ itkGetMacro( LODIncreaseBlocked, bool ); /** En-/Disable LOD increase globally. */ itkBooleanMacro( LODIncreaseBlocked ); /** En-/Disable LOD abort mechanism. */ itkSetMacro( LODAbortMechanismEnabled, bool ); /** En-/Disable LOD abort mechanism. */ itkGetMacro( LODAbortMechanismEnabled, bool ); /** En-/Disable LOD abort mechanism. */ itkBooleanMacro( LODAbortMechanismEnabled ); /** Force a sub-class to start a timer for a pending hires-rendering request */ virtual void StartOrResetTimer() {}; /** To be called by a sub-class from a timer callback */ void ExecutePendingHighResRenderingRequest(); virtual void DoStartRendering() {}; virtual void DoMonitorRendering() {}; virtual void DoFinishAbortRendering() {}; int GetNextLOD( BaseRenderer* renderer ); /** Set current LOD (NULL means all renderers)*/ void SetMaximumLOD( unsigned int max ); void SetShading( bool state, unsigned int lod ); bool GetShading( unsigned int lod ); void SetClippingPlaneStatus( bool status ); bool GetClippingPlaneStatus(); void SetShadingValues( float ambient, float diffuse, float specular, float specpower ); FloatVector &GetShadingValues(); /** Returns a property list */ PropertyList::Pointer GetPropertyList() const; /** Returns a property from m_PropertyList */ BaseProperty* GetProperty(const char *propertyKey) const; /** Sets or adds (if not present) a property in m_PropertyList */ void SetProperty(const char *propertyKey, BaseProperty* propertyValue); /** * \brief Setter / Getter for internal DataStorage * * Sets / returns the mitk::DataStorage that is used internally. This instance holds all mitk::DataNodes that are * rendered by the registered BaseRenderers. * * If this DataStorage is changed at runtime by calling SetDataStorage(), * all currently registered BaseRenderers are automatically given the correct instance. * When a new BaseRenderer is added, it is automatically initialized with the currently active DataStorage. */ void SetDataStorage( mitk::DataStorage* storage ); /** * \brief Setter / Getter for internal DataStorage * * Sets / returns the mitk::DataStorage that is used internally. This instance holds all mitk::DataNodes that are * rendered by the registered BaseRenderers. * * If this DataStorage is changed at runtime by calling SetDataStorage(), * all currently registered BaseRenderers are automatically given the correct instance. * When a new BaseRenderer is added, it is automatically initialized with the currently active DataStorage. */ mitk::DataStorage* GetDataStorage(); /** * @brief Sets a flag to the given renderwindow to indicated that it has the focus e.g. has been clicked recently. * @param focusWindow */ void SetRenderWindowFocus(vtkRenderWindow* focusWindow); itkGetMacro(FocusedRenderWindow, vtkRenderWindow*) itkSetMacro(ConstrainedPanningZooming, bool); protected: enum { RENDERING_INACTIVE = 0, RENDERING_REQUESTED, RENDERING_INPROGRESS }; RenderingManager(); /** Abstract method for generating a system specific event for rendering * request. This method is called whenever an update is requested */ virtual void GenerateRenderingRequestEvent() = 0; virtual void InitializePropertyList(); bool m_UpdatePending; typedef std::map< BaseRenderer *, unsigned int > RendererIntMap; typedef std::map< BaseRenderer *, bool > RendererBoolMap; RendererBoolMap m_RenderingAbortedMap; RendererIntMap m_NextLODMap; unsigned int m_MaxLOD; bool m_LODIncreaseBlocked; bool m_LODAbortMechanismEnabled; BoolVector m_ShadingEnabled; bool m_ClippingPlaneEnabled; FloatVector m_ShadingValues; static void RenderingStartCallback( vtkObject *caller, unsigned long eid, void *clientdata, void *calldata ); static void RenderingProgressCallback( vtkObject *caller, unsigned long eid, void *clientdata, void *calldata ); static void RenderingEndCallback( vtkObject *caller, unsigned long eid, void *clientdata, void *calldata ); typedef std::map< vtkRenderWindow *, int > RenderWindowList; RenderWindowList m_RenderWindowList; RenderWindowVector m_AllRenderWindows; struct RenderWindowCallbacks { vtkCallbackCommand* commands[3u]; }; typedef std::map RenderWindowCallbacksList; RenderWindowCallbacksList m_RenderWindowCallbacksList; itk::SmartPointer m_TimeNavigationController; static RenderingManager::Pointer s_Instance; static RenderingManagerFactory *s_RenderingManagerFactory; PropertyList::Pointer m_PropertyList; DataStoragePointer m_DataStorage; bool m_ConstrainedPanningZooming; private: void InternalViewInitialization( mitk::BaseRenderer *baseRenderer, const mitk::TimeGeometry *geometry, bool boundingBoxInitialized, int mapperID ); vtkRenderWindow* m_FocusedRenderWindow; }; #pragma GCC visibility push(default) itkEventMacro( RenderingManagerEvent, itk::AnyEvent ); itkEventMacro( RenderingManagerViewsInitializedEvent, RenderingManagerEvent ); #pragma GCC visibility pop +itkEventMacroDeclaration(FocusChangedEvent, itk::AnyEvent) + /** * Generic RenderingManager implementation for "non-rendering-plattform", * e.g. for tests. Its factory (TestingRenderingManagerFactory) is * automatically on start-up and is used by default if not other * RenderingManagerFactory is instantiated explicitly thereafter. * (see mitkRenderingManager.cpp) */ class MITKCORE_EXPORT TestingRenderingManager : public RenderingManager { public: mitkClassMacro(TestingRenderingManager,RenderingManager); itkFactorylessNewMacro(Self) itkCloneMacro(Self) protected: virtual void GenerateRenderingRequestEvent() override { // ForceImmediateUpdateAll(); }; }; -class ITKEvent_EXPORT FocusChangedEvent : public itk::AnyEvent -{ -public: - typedef FocusChangedEvent Self; - typedef itk::AnyEvent Superclass; - - FocusChangedEvent( vtkRenderWindow* renderwindow = nullptr ); - - virtual ~FocusChangedEvent(); - - virtual const char * GetEventName() const override; - - virtual bool CheckEvent(const ::itk::EventObject* e) const override; - - virtual ::itk::EventObject* MakeObject() const override; - - vtkRenderWindow* GetFocusedRenderWindow() const; - - FocusChangedEvent(const Self& s); - -protected: - vtkWeakPointer m_RenderWindow; - -private: - void operator=(const Self&); - -}; - } // namespace mitk #endif /* MITKRenderingManager_H_HEADER_INCLUDED_C135A197 */ diff --git a/Modules/Core/src/Controllers/mitkRenderingManager.cpp b/Modules/Core/src/Controllers/mitkRenderingManager.cpp index 6a5aa41645..78331d6fb6 100644 --- a/Modules/Core/src/Controllers/mitkRenderingManager.cpp +++ b/Modules/Core/src/Controllers/mitkRenderingManager.cpp @@ -1,873 +1,837 @@ /*=================================================================== 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 "mitkRenderingManager.h" #include "mitkRenderingManagerFactory.h" #include "mitkBaseRenderer.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" #include "mitkProportionalTimeGeometry.h" #include "mitkCameraController.h" #include #include #include "mitkNumericTypes.h" #include #include #include #include namespace mitk { + itkEventMacroDefinition(FocusChangedEvent, itk::AnyEvent) + RenderingManager::Pointer RenderingManager::s_Instance = 0; RenderingManagerFactory *RenderingManager::s_RenderingManagerFactory = 0; RenderingManager ::RenderingManager() : m_UpdatePending(false), m_MaxLOD(1), m_LODIncreaseBlocked(false), m_LODAbortMechanismEnabled(false), m_ClippingPlaneEnabled(false), m_TimeNavigationController(SliceNavigationController::New()), m_DataStorage(NULL), m_ConstrainedPanningZooming(true), m_FocusedRenderWindow(nullptr) { m_ShadingEnabled.assign(3, false); m_ShadingValues.assign(4, 0.0); InitializePropertyList(); } RenderingManager ::~RenderingManager() { // Decrease reference counts of all registered vtkRenderWindows for // proper destruction RenderWindowVector::iterator it; for (it = m_AllRenderWindows.begin(); it != m_AllRenderWindows.end(); ++it) { (*it)->UnRegister(NULL); RenderWindowCallbacksList::iterator callbacks_it = this->m_RenderWindowCallbacksList.find(*it); if (callbacks_it != this->m_RenderWindowCallbacksList.end()) { (*it)->RemoveObserver(callbacks_it->second.commands[0u]); (*it)->RemoveObserver(callbacks_it->second.commands[1u]); (*it)->RemoveObserver(callbacks_it->second.commands[2u]); } } } void RenderingManager ::SetFactory(RenderingManagerFactory *factory) { s_RenderingManagerFactory = factory; } const RenderingManagerFactory * RenderingManager ::GetFactory() { return s_RenderingManagerFactory; } bool RenderingManager ::HasFactory() { if (RenderingManager::s_RenderingManagerFactory) { return true; } else { return false; } } RenderingManager::Pointer RenderingManager ::New() { const RenderingManagerFactory* factory = GetFactory(); if (factory == NULL) return NULL; return factory->CreateRenderingManager(); } RenderingManager * RenderingManager ::GetInstance() { if (!RenderingManager::s_Instance) { if (s_RenderingManagerFactory) { s_Instance = s_RenderingManagerFactory->CreateRenderingManager(); } } return s_Instance; } bool RenderingManager ::IsInstantiated() { if (RenderingManager::s_Instance) return true; else return false; } void RenderingManager ::AddRenderWindow(vtkRenderWindow *renderWindow) { if (renderWindow && (m_RenderWindowList.find(renderWindow) == m_RenderWindowList.end())) { m_RenderWindowList[renderWindow] = RENDERING_INACTIVE; m_AllRenderWindows.push_back(renderWindow); if (m_DataStorage.IsNotNull()) mitk::BaseRenderer::GetInstance(renderWindow)->SetDataStorage(m_DataStorage.GetPointer()); // Register vtkRenderWindow instance renderWindow->Register(NULL); // Add callbacks for rendering abort mechanism //BaseRenderer *renderer = BaseRenderer::GetInstance( renderWindow ); vtkCallbackCommand *startCallbackCommand = vtkCallbackCommand::New(); startCallbackCommand->SetCallback( RenderingManager::RenderingStartCallback); renderWindow->AddObserver(vtkCommand::StartEvent, startCallbackCommand); vtkCallbackCommand *progressCallbackCommand = vtkCallbackCommand::New(); progressCallbackCommand->SetCallback( RenderingManager::RenderingProgressCallback); renderWindow->AddObserver(vtkCommand::AbortCheckEvent, progressCallbackCommand); vtkCallbackCommand *endCallbackCommand = vtkCallbackCommand::New(); endCallbackCommand->SetCallback( RenderingManager::RenderingEndCallback); renderWindow->AddObserver(vtkCommand::EndEvent, endCallbackCommand); RenderWindowCallbacks callbacks; callbacks.commands[0u] = startCallbackCommand; callbacks.commands[1u] = progressCallbackCommand; callbacks.commands[2u] = endCallbackCommand; this->m_RenderWindowCallbacksList[renderWindow] = callbacks; //Delete vtk variables correctly startCallbackCommand->Delete(); progressCallbackCommand->Delete(); endCallbackCommand->Delete(); } } void RenderingManager ::RemoveRenderWindow(vtkRenderWindow *renderWindow) { if (m_RenderWindowList.erase(renderWindow)) { RenderWindowCallbacksList::iterator callbacks_it = this->m_RenderWindowCallbacksList.find(renderWindow); if (callbacks_it != this->m_RenderWindowCallbacksList.end()) { renderWindow->RemoveObserver(callbacks_it->second.commands[0u]); renderWindow->RemoveObserver(callbacks_it->second.commands[1u]); renderWindow->RemoveObserver(callbacks_it->second.commands[2u]); this->m_RenderWindowCallbacksList.erase(callbacks_it); } RenderWindowVector::iterator rw_it = std::find(m_AllRenderWindows.begin(), m_AllRenderWindows.end(), renderWindow); if (rw_it != m_AllRenderWindows.cend()) { // Decrease reference count for proper destruction (*rw_it)->UnRegister(NULL); m_AllRenderWindows.erase(rw_it); } } } const RenderingManager::RenderWindowVector& RenderingManager ::GetAllRegisteredRenderWindows() { return m_AllRenderWindows; } void RenderingManager ::RequestUpdate(vtkRenderWindow *renderWindow) { // If the renderWindow is not valid, we do not want to inadvertantly create // an entry in the m_RenderWindowList map. It is possible if the user is // regularly calling AddRenderer and RemoveRenderer for a rendering update // to come into this method with a renderWindow pointer that is valid in the // sense that the window does exist within the application, but that // renderWindow has been temporarily removed from this RenderingManager for // performance reasons. if (m_RenderWindowList.find(renderWindow) == m_RenderWindowList.cend()) { return; } m_RenderWindowList[renderWindow] = RENDERING_REQUESTED; if (!m_UpdatePending) { m_UpdatePending = true; this->GenerateRenderingRequestEvent(); } } void RenderingManager ::ForceImmediateUpdate(vtkRenderWindow *renderWindow) { // If the renderWindow is not valid, we do not want to inadvertantly create // an entry in the m_RenderWindowList map. It is possible if the user is // regularly calling AddRenderer and RemoveRenderer for a rendering update // to come into this method with a renderWindow pointer that is valid in the // sense that the window does exist within the application, but that // renderWindow has been temporarily removed from this RenderingManager for // performance reasons. if (m_RenderWindowList.find(renderWindow) == m_RenderWindowList.cend()) { return; } // Erase potentially pending requests for this window m_RenderWindowList[renderWindow] = RENDERING_INACTIVE; m_UpdatePending = false; // Immediately repaint this window (implementation platform specific) // If the size is 0 it crashes int *size = renderWindow->GetSize(); if (0 != size[0] && 0 != size[1]) { //prepare the camera etc. before rendering //Note: this is a very important step which should be called before the VTK render! //If you modify the camera anywhere else or after the render call, the scene cannot be seen. mitk::VtkPropRenderer *vPR = dynamic_cast(mitk::BaseRenderer::GetInstance(renderWindow)); if (vPR) vPR->PrepareRender(); // Execute rendering renderWindow->Render(); } } void RenderingManager ::RequestUpdateAll(RequestType type) { RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { int id = BaseRenderer::GetInstance(it->first)->GetMapperID(); if ((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2))) { this->RequestUpdate(it->first); } } } void RenderingManager ::ForceImmediateUpdateAll(RequestType type) { RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { int id = BaseRenderer::GetInstance(it->first)->GetMapperID(); if ((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2))) { // Immediately repaint this window (implementation platform specific) // If the size is 0, it crashes this->ForceImmediateUpdate(it->first); } } } void RenderingManager::InitializeViewsByBoundingObjects(const DataStorage *ds) { if (!ds) return; // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox" , mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = ds->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = ds->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry this->InitializeViews(bounds); } //TODO_GOETZ // Remove old function, so only this one is working. bool RenderingManager ::InitializeViews(const BaseGeometry * dataGeometry, RequestType type, bool preserveRoughOrientationInWorldSpace) { ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New(); propTimeGeometry->Initialize(dynamic_cast(dataGeometry->Clone().GetPointer()), 1); return InitializeViews(propTimeGeometry, type, preserveRoughOrientationInWorldSpace); } bool RenderingManager ::InitializeViews(const TimeGeometry * dataGeometry, RequestType type, bool /*preserveRoughOrientationInWorldSpace*/) { MITK_DEBUG << "initializing views"; bool boundingBoxInitialized = false; TimeGeometry::ConstPointer timeGeometry = dataGeometry; TimeGeometry::Pointer modifiedGeometry = NULL; if (dataGeometry != NULL) { modifiedGeometry = dataGeometry->Clone(); } int warningLevel = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); if ((timeGeometry.IsNotNull()) && (const_cast( timeGeometry->GetBoundingBoxInWorld())->GetDiagonalLength2() > mitk::eps)) { boundingBoxInitialized = true; } if (timeGeometry.IsNotNull()) {// make sure bounding box has an extent bigger than zero in any direction // clone the input geometry //Old Geometry3D::Pointer modifiedGeometry = dynamic_cast( dataGeometry->Clone().GetPointer() ); assert(modifiedGeometry.IsNotNull()); for (TimeStepType step = 0; step < modifiedGeometry->CountTimeSteps(); ++step) { BaseGeometry::BoundsArrayType newBounds = modifiedGeometry->GetGeometryForTimeStep(step)->GetBounds(); for (unsigned int dimension = 0; (2 * dimension) < newBounds.Size(); dimension++) { //check for equality but for an epsilon if (Equal(newBounds[2 * dimension], newBounds[2 * dimension + 1])) { newBounds[2 * dimension + 1] += 1; if( Equal( newBounds[ 2 * dimension ], newBounds[ 2 * dimension + 1 ] ) ) // newBounds will still be equal if values are beyond double precision { mitkThrow()<< "One dimension of object data has zero length, please make sure you're not using numbers beyond double precision as coordinates."; } } } modifiedGeometry->GetGeometryForTimeStep(step)->SetBounds(newBounds); } } timeGeometry = modifiedGeometry; RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance(it->first); baseRenderer->SetConstrainZoomingAndPanning(m_ConstrainedPanningZooming); int id = baseRenderer->GetMapperID(); if (((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2))) ) { this->InternalViewInitialization(baseRenderer, timeGeometry, boundingBoxInitialized, id); } } if (boundingBoxInitialized) { m_TimeNavigationController->SetInputWorldTimeGeometry(timeGeometry); } m_TimeNavigationController->Update(); this->RequestUpdateAll(type); vtkObject::SetGlobalWarningDisplay(warningLevel); // Inform listeners that views have been initialized this->InvokeEvent(mitk::RenderingManagerViewsInitializedEvent()); return boundingBoxInitialized; } bool RenderingManager ::InitializeViews(RequestType type) { RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance(it->first); int id = baseRenderer->GetMapperID(); if ((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2))) { mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController(); // Re-initialize view direction nc->SetViewDirectionToDefault(); // Update the SNC nc->Update(); } } this->RequestUpdateAll(type); return true; } bool RenderingManager::InitializeView(vtkRenderWindow * renderWindow, const BaseGeometry * geometry, bool initializeGlobalTimeSNC) { ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New(); propTimeGeometry->Initialize(dynamic_cast(geometry->Clone().GetPointer()), 1); return InitializeView(renderWindow, propTimeGeometry, initializeGlobalTimeSNC); } bool RenderingManager::InitializeView(vtkRenderWindow * renderWindow, const TimeGeometry * geometry, bool initializeGlobalTimeSNC) { bool boundingBoxInitialized = false; int warningLevel = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); if ((geometry != NULL) && (const_cast( geometry->GetBoundingBoxInWorld())->GetDiagonalLength2() > mitk::eps)) { boundingBoxInitialized = true; } mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance(renderWindow); int id = baseRenderer->GetMapperID(); this->InternalViewInitialization(baseRenderer, geometry, boundingBoxInitialized, id); if (boundingBoxInitialized && initializeGlobalTimeSNC) { m_TimeNavigationController->SetInputWorldTimeGeometry(geometry); } m_TimeNavigationController->Update(); this->RequestUpdate(renderWindow); vtkObject::SetGlobalWarningDisplay(warningLevel); return boundingBoxInitialized; } bool RenderingManager::InitializeView(vtkRenderWindow * renderWindow) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance(renderWindow); mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController(); // Re-initialize view direction nc->SetViewDirectionToDefault(); // Update the SNC nc->Update(); this->RequestUpdate(renderWindow); return true; } void RenderingManager::InternalViewInitialization(mitk::BaseRenderer *baseRenderer, const mitk::TimeGeometry *geometry, bool boundingBoxInitialized, int mapperID) { mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController(); // Re-initialize view direction nc->SetViewDirectionToDefault(); if (boundingBoxInitialized) { // Set geometry for NC nc->SetInputWorldTimeGeometry(geometry); nc->Update(); if (mapperID == BaseRenderer::Standard2D) { // For 2D SNCs, steppers are set so that the cross is centered // in the image nc->GetSlice()->SetPos(nc->GetSlice()->GetSteps() / 2); } baseRenderer->GetCameraController()->SetViewToAnterior(); baseRenderer->GetCameraController()->Fit(); } else { nc->Update(); } } const SliceNavigationController* RenderingManager::GetTimeNavigationController() const { return m_TimeNavigationController.GetPointer(); } SliceNavigationController* RenderingManager::GetTimeNavigationController() { return m_TimeNavigationController.GetPointer(); } void RenderingManager::ExecutePendingRequests() { m_UpdatePending = false; // Satisfy all pending update requests RenderWindowList::const_iterator it; int i = 0; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it, ++i) { if (it->second == RENDERING_REQUESTED) { this->ForceImmediateUpdate(it->first); } } } void RenderingManager::RenderingStartCallback(vtkObject *caller, unsigned long, void *, void *) { vtkRenderWindow *renderWindow = dynamic_cast(caller); mitk::RenderingManager* renman = mitk::BaseRenderer::GetInstance(renderWindow)->GetRenderingManager(); RenderWindowList &renderWindowList = renman->m_RenderWindowList; if (renderWindow) { renderWindowList[renderWindow] = RENDERING_INPROGRESS; } renman->m_UpdatePending = false; } void RenderingManager ::RenderingProgressCallback(vtkObject *caller, unsigned long, void *, void *) { vtkRenderWindow *renderWindow = dynamic_cast(caller); mitk::RenderingManager* renman = mitk::BaseRenderer::GetInstance(renderWindow)->GetRenderingManager(); if (renman->m_LODAbortMechanismEnabled) { vtkRenderWindow *renderWindow = dynamic_cast(caller); if (renderWindow) { BaseRenderer *renderer = BaseRenderer::GetInstance(renderWindow); if (renderer && (renderer->GetNumberOfVisibleLODEnabledMappers() > 0)) { renman->DoMonitorRendering(); } } } } void RenderingManager ::RenderingEndCallback(vtkObject *caller, unsigned long, void *, void *) { vtkRenderWindow *renderWindow = dynamic_cast(caller); mitk::RenderingManager* renman = mitk::BaseRenderer::GetInstance(renderWindow)->GetRenderingManager(); RenderWindowList &renderWindowList = renman->m_RenderWindowList; RendererIntMap &nextLODMap = renman->m_NextLODMap; if (renderWindow) { BaseRenderer *renderer = BaseRenderer::GetInstance(renderWindow); if (renderer) { renderWindowList[renderer->GetRenderWindow()] = RENDERING_INACTIVE; // Level-of-Detail handling if (renderer->GetNumberOfVisibleLODEnabledMappers() > 0) { if (nextLODMap[renderer] == 0) renman->StartOrResetTimer(); else nextLODMap[renderer] = 0; } } } } bool RenderingManager ::IsRendering() const { RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { if (it->second == RENDERING_INPROGRESS) { return true; } } return false; } void RenderingManager ::AbortRendering() { RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { if (it->second == RENDERING_INPROGRESS) { it->first->SetAbortRender(true); m_RenderingAbortedMap[BaseRenderer::GetInstance(it->first)] = true; } } } int RenderingManager ::GetNextLOD(BaseRenderer *renderer) { if (renderer != NULL) { return m_NextLODMap[renderer]; } else { return 0; } } void RenderingManager ::ExecutePendingHighResRenderingRequest() { RenderWindowList::const_iterator it; for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it) { BaseRenderer *renderer = BaseRenderer::GetInstance(it->first); if (renderer->GetNumberOfVisibleLODEnabledMappers() > 0) { if (m_NextLODMap[renderer] == 0) { m_NextLODMap[renderer] = 1; RequestUpdate(it->first); } } } } void RenderingManager ::SetMaximumLOD(unsigned int max) { m_MaxLOD = max; } //enable/disable shading void RenderingManager ::SetShading(bool state, unsigned int lod) { if (lod > m_MaxLOD) { itkWarningMacro(<< "LOD out of range requested: " << lod << " maxLOD: " << m_MaxLOD); return; } m_ShadingEnabled[lod] = state; } bool RenderingManager ::GetShading(unsigned int lod) { if (lod > m_MaxLOD) { itkWarningMacro(<< "LOD out of range requested: " << lod << " maxLOD: " << m_MaxLOD); return false; } return m_ShadingEnabled[lod]; } //enable/disable the clipping plane void RenderingManager ::SetClippingPlaneStatus(bool status) { m_ClippingPlaneEnabled = status; } bool RenderingManager ::GetClippingPlaneStatus() { return m_ClippingPlaneEnabled; } void RenderingManager ::SetShadingValues(float ambient, float diffuse, float specular, float specpower) { m_ShadingValues[0] = ambient; m_ShadingValues[1] = diffuse; m_ShadingValues[2] = specular; m_ShadingValues[3] = specpower; } RenderingManager::FloatVector & RenderingManager ::GetShadingValues() { return m_ShadingValues; } void RenderingManager::InitializePropertyList() { if (m_PropertyList.IsNull()) { m_PropertyList = PropertyList::New(); } this->SetProperty("coupled-zoom", BoolProperty::New(false)); this->SetProperty("coupled-plane-rotation", BoolProperty::New(false)); this->SetProperty("MIP-slice-rendering", BoolProperty::New(false)); } PropertyList::Pointer RenderingManager::GetPropertyList() const { return m_PropertyList; } BaseProperty* RenderingManager::GetProperty(const char *propertyKey) const { return m_PropertyList->GetProperty(propertyKey); } void RenderingManager::SetProperty(const char *propertyKey, BaseProperty* propertyValue) { m_PropertyList->SetProperty(propertyKey, propertyValue); } void RenderingManager::SetDataStorage(DataStorage* storage) { if (storage != NULL) { m_DataStorage = storage; RenderingManager::RenderWindowVector::const_iterator iter; for (iter = m_AllRenderWindows.cbegin(); iter < m_AllRenderWindows.cend(); iter++) { mitk::BaseRenderer::GetInstance((*iter))->SetDataStorage(m_DataStorage.GetPointer()); } } } mitk::DataStorage* RenderingManager::GetDataStorage() { return m_DataStorage; } void RenderingManager::SetRenderWindowFocus(vtkRenderWindow *focusWindow) { if (!focusWindow || (m_RenderWindowList.find(focusWindow) != m_RenderWindowList.cend())) { m_FocusedRenderWindow = focusWindow; - this->InvokeEvent(FocusChangedEvent(focusWindow)); + this->InvokeEvent(FocusChangedEvent()); return; } MITK_ERROR << "Tried to set a RenderWindow that does not exist."; } // Create and register generic RenderingManagerFactory. TestingRenderingManagerFactory renderingManagerFactory; - - FocusChangedEvent::FocusChangedEvent(vtkRenderWindow *renderwindow) : m_RenderWindow(renderwindow) - { - MITK_INFO << "FocusChangedEvent"; - if(renderwindow) MITK_INFO << renderwindow->GetWindowName(); - } - - FocusChangedEvent::~FocusChangedEvent() - { - - } - - const char *FocusChangedEvent::GetEventName() const - { - return "FocusChangedEvent"; - } - - bool FocusChangedEvent::CheckEvent(const itk::EventObject *e) const - { - return dynamic_cast(e); - } - - itk::EventObject *FocusChangedEvent::MakeObject() const - { - return new Self( m_RenderWindow ); - } - - vtkRenderWindow *FocusChangedEvent::GetFocusedRenderWindow() const - { - return m_RenderWindow.GetPointer(); - } - - FocusChangedEvent::FocusChangedEvent(const FocusChangedEvent::Self &s) - : itk::AnyEvent(s), m_RenderWindow(s.m_RenderWindow) - { - - } - } // namespace