diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/Properties.dox b/Documentation/Doxygen/3-DeveloperManual/Concepts/Properties.dox index ac62e82201..e40b17a393 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Concepts/Properties.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Concepts/Properties.dox @@ -1,257 +1,236 @@ /** \page PropertiesPage Properties \tableofcontents \section PropertyConcept The Concept Behind MITK Properties Properties belong to a datanode and contain information relevant to the handling of the node by MITK. They provide a place to store additional information which is not part of the actual data, and as such have no reason to be contained within the data/file itself, but might be needed for such things as rendering (e.g. transfer functions) or interaction (e.g. the name of the node). Propteries can be read and set: \code //1: Read a property mitk::Property::Pointer readProperty = node->GetProperty("color"); //read the property "color" from the data node mitk::ColorProperty::Pointer colorProperty = dynamic_cast(readProperty); //cast this property to the subtype ColorProperty //2: Write a property mitk::BoolProperty::Pointer newProperty = mitk::BoolProperty::New( true ); //create a new property, in this case a boolean property node->SetProperty( "IsTensorVolume", newProperty ); //add this property to node with the key "IsTensorVolume" \endcode \section PropertiesPage_PropertyServices Property Services Property services enable you to extend the capabilities of the basic property system of MITK. Currently there are four property services, i.e., aliases, descriptions, extensions, and filters. All of them are briefly described in the following. More detailed information can be found in the corresponding API documentation, as all of the services are completely documented. All property services are provided through the functionalities of the \ref MicroServices_UserDocs "C++ Micro Services". Hence, you can use property services from all of your modules and plugins. \subsection PropertiesPage_PropertyAliases Property Aliases You can add an alias to a certain property name which is displayed by the Property View instead of the genuine property name. A property name can have more than one alias in which case the property is displayed multiple times in the Properties View. In addition, aliases can be easily restricted to certain data node types. Property aliases are provided through the service interface mitk::IPropertyAliases. \subsection PropertiesPage_PropertyDescriptions Property Descriptions The Property View will display a description of the currently selected property at its bottom if the property has an associated description. Descriptions are parsed and displayed as rich text. Property descriptions are provided through the service interface mitk::IPropertyDescriptions. \subsection PropertiesPage_PropertyExtensions Property Extensions Property extensions are a very generic approach to attach meta data to properties. They have the sole requirement of inheriting from mitk::PropertyExtension. The Property View searches for known property extensions like mitk::IntPropertyExtension and mitk::FloatPropertyExtension to configure the editors of the properties, e.g., you can specify the valid range for a numeric property. Property extensions are provided through the service interface mitk::IPropertyExtensions. \subsection PropertiesPage_PropertyFilters Property Filters Property filters are a rather powerful tool to filter shown properties by the Property View. There is a single global filter and the possibility to add filters on top of it for specific data node types. Filters consist of blacklist entries and whitelist entries, i.e., blacklisted entries are filtered out and whitelisted entries are the only properties which remain after filtering. If both lists contain entries only whitelisted entries are displayed that are not blacklisted. Property filters are provided through the service interface mitk::IPropertyFilters. \section ListOfIndependentProperty A List Of Module Independent Properties This section lists most of the known properties in MITK according to where they are used. Not every node needs each (or even close to) of these properties. \subsection FileManagement File Management \subsection GenericRenderingProperty Generic Rendering Properties \subsection SurfaceRenderingProperties Surface Rendering Properties \subsection VolumeRenderingProperties Volume Rendering Properties - -\remark -Uselod can be active with usegpu, usemip, useray, but any of the latter can not -be used with another one of them. - \subsection PointSetProperties Point Set Properties \subsection Geometry2DProperties Geometry2D Properties Information on properties not in this list can be found in the appropriate module. \subsection PropertiesPageSeeAlso See Also */ diff --git a/Modules/Core/files.cmake b/Modules/Core/files.cmake index 3637647f25..869340a1c3 100644 --- a/Modules/Core/files.cmake +++ b/Modules/Core/files.cmake @@ -1,328 +1,327 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkCoreActivator.cpp mitkCoreObjectFactoryBase.cpp mitkCoreObjectFactory.cpp mitkCoreServices.cpp mitkException.cpp Algorithms/mitkBaseDataSource.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkCompareImageDataFilter.cpp Algorithms/mitkCompositePixelValueToString.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkExtractSliceFilter.cpp Algorithms/mitkExtractSliceFilter2.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkImageToSurfaceFilter.cpp Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToImageFilter.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkTemporalJoinImagesFilter.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAnatomicalStructureColorPresets.cpp DataManagement/mitkArbitraryTimeGeometry.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkApplyTransformMatrixOperation.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseGeometry.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataStorage.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkFloatPropertyExtension.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGeometryTransformHolder.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkGenericIDRelationRule.cpp DataManagement/mitkIdentifiable.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageReadAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageVtkReadAccessor.cpp DataManagement/mitkImageVtkWriteAccessor.cpp DataManagement/mitkImageWriteAccessor.cpp DataManagement/mitkIntPropertyExtension.cpp DataManagement/mitkIPersistenceService.cpp DataManagement/mitkIPropertyAliases.cpp DataManagement/mitkIPropertyDescriptions.cpp DataManagement/mitkIPropertyExtensions.cpp DataManagement/mitkIPropertyFilters.cpp DataManagement/mitkIPropertyOwner.cpp DataManagement/mitkIPropertyPersistence.cpp DataManagement/mitkIPropertyProvider.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLine.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTableProperty.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMaterial.cpp DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModifiedLock.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDataUID.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateFunction.cpp DataManagement/mitkNodePredicateGeometry.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateDataProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkNodePredicateSubGeometry.cpp DataManagement/mitkNumericConstants.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneGeometryData.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkPointSetShapeProperty.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyAliases.cpp DataManagement/mitkPropertyDescriptions.cpp DataManagement/mitkPropertyExtension.cpp DataManagement/mitkPropertyExtensions.cpp DataManagement/mitkPropertyFilter.cpp DataManagement/mitkPropertyFilters.cpp DataManagement/mitkPropertyKeyPath.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkPropertyListReplacedObserver.cpp DataManagement/mitkPropertyNameHelper.cpp DataManagement/mitkPropertyObserver.cpp DataManagement/mitkPropertyPersistence.cpp DataManagement/mitkPropertyPersistenceInfo.cpp DataManagement/mitkPropertyRelationRuleBase.cpp DataManagement/mitkProportionalTimeGeometry.cpp DataManagement/mitkRenderingModeProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkScaleOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkSourceImageRelationRule.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTemporoSpatialStringProperty.cpp DataManagement/mitkUIDManipulator.cpp DataManagement/mitkVector.cpp DataManagement/mitkVectorProperty.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp - DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkIPropertyRelations.cpp DataManagement/mitkPropertyRelations.cpp Interactions/mitkAction.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkCrosshairPositionEvent.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayActionEventBroadcast.cpp Interactions/mitkDisplayActionEventFunctions.cpp Interactions/mitkDisplayActionEventHandler.cpp Interactions/mitkDisplayActionEventHandlerDesynchronized.cpp Interactions/mitkDisplayActionEventHandlerStd.cpp Interactions/mitkDisplayActionEventHandlerSynchronized.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventFactory.cpp Interactions/mitkEventRecorder.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkInteractionEventConst.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionEventHandler.cpp Interactions/mitkInteractionEventObserver.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInteractionSchemeSwitcher.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkMouseDoubleClickEvent.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkSinglePointDataInteractor.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineCondition.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkXML2EventParser.cpp IO/mitkAbstractFileIO.cpp IO/mitkAbstractFileReader.cpp IO/mitkAbstractFileWriter.cpp IO/mitkCustomMimeType.cpp IO/mitkFileReader.cpp IO/mitkFileReaderRegistry.cpp IO/mitkFileReaderSelector.cpp IO/mitkFileReaderWriterBase.cpp IO/mitkFileWriter.cpp IO/mitkFileWriterRegistry.cpp IO/mitkFileWriterSelector.cpp IO/mitkGeometry3DToXML.cpp IO/mitkIFileIO.cpp IO/mitkIFileReader.cpp IO/mitkIFileWriter.cpp IO/mitkGeometryDataReaderService.cpp IO/mitkGeometryDataWriterService.cpp IO/mitkImageGenerator.cpp IO/mitkImageVtkLegacyIO.cpp IO/mitkImageVtkXmlIO.cpp IO/mitkIMimeTypeProvider.cpp IO/mitkIOConstants.cpp IO/mitkIOMimeTypes.cpp IO/mitkIOUtil.cpp IO/mitkItkImageIO.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkLegacyFileReaderService.cpp IO/mitkLegacyFileWriterService.cpp IO/mitkLocaleSwitch.cpp IO/mitkLog.cpp IO/mitkMimeType.cpp IO/mitkMimeTypeProvider.cpp IO/mitkOperation.cpp IO/mitkPixelType.cpp IO/mitkPointSetReaderService.cpp IO/mitkPointSetWriterService.cpp IO/mitkProportionalTimeGeometryToXML.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSurfaceStlIO.cpp IO/mitkSurfaceVtkIO.cpp IO/mitkSurfaceVtkLegacyIO.cpp IO/mitkSurfaceVtkXmlIO.cpp IO/mitkUtf8Util.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkPreferenceListReaderOptionsFunctor.cpp IO/mitkIOMetaInformationPropertyConstants.cpp Rendering/mitkAbstractAnnotationRenderer.cpp Rendering/mitkAnnotationUtils.cpp Rendering/mitkBaseRenderer.cpp #Rendering/mitkGLMapper.cpp Moved to deprecated LegacyGL Module Rendering/mitkGradientBackground.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/mitkMapper.cpp Rendering/mitkAnnotation.cpp Rendering/mitkPlaneGeometryDataMapper2D.cpp Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp Rendering/mitkPointSetVtkMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowFrame.cpp #Rendering/mitkSurfaceGLMapper2D.cpp Moved to deprecated LegacyGL Module Rendering/mitkSurfaceVtkMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkVtkMapper.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp ) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfig.xml Interactions/DisplayConfigMITKBase.xml Interactions/DisplayConfigPACSBase.xml Interactions/DisplayConfigCrosshair.xml Interactions/DisplayConfigRotation.xml Interactions/DisplayConfigActivateCoupling.xml Interactions/DisplayConfigSwivel.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigMITKLimited.xml Interactions/DisplayConfigBlockLMB.xml Interactions/PointSet.xml Interactions/Legacy/StateMachine.xml Interactions/Legacy/DisplayConfigMITKTools.xml Interactions/PointSetConfig.xml mitkLevelWindowPresets.xml mitkAnatomicalStructureColorPresets.xml ) diff --git a/Modules/Core/include/mitkVtkVolumeRenderingProperty.h b/Modules/Core/include/mitkVtkVolumeRenderingProperty.h deleted file mode 100644 index 7d9c8df434..0000000000 --- a/Modules/Core/include/mitkVtkVolumeRenderingProperty.h +++ /dev/null @@ -1,104 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef _MITK_VTK_VOLUME_RENDERING_PROPERTY__H_ -#define _MITK_VTK_VOLUME_RENDERING_PROPERTY__H_ - -#include "mitkEnumerationProperty.h" - -#define VTK_RAY_CAST_COMPOSITE_FUNCTION 1 -#define VTK_VOLUME_RAY_CAST_MIP_FUNCTION 2 -namespace mitk -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4522) -#endif - - /** - * Encapsulates the enumeration for volume rendering. Valid values are - * (VTK constant/Id/string representation): - * VTK_VOLUME_RAY_CAST_MIP_FUNCTION - * VTK_RAY_CAST_COMPOSITE_FUNCTION - * Default is nullptr - */ - class MITKCORE_EXPORT VtkVolumeRenderingProperty : public EnumerationProperty - { - public: - mitkClassMacro(VtkVolumeRenderingProperty, EnumerationProperty); - - itkFactorylessNewMacro(Self); - - itkCloneMacro(Self); - - mitkNewMacro1Param(VtkVolumeRenderingProperty, const IdType &); - - mitkNewMacro1Param(VtkVolumeRenderingProperty, const std::string &); - - /** - * Returns the current volume rendering type - */ - virtual int GetRenderingType(); - - /** - * Sets the rendering type to VTK_VOLUME_RAY_CAST_MIP_FUNCTION - */ - virtual void SetRenderingTypeToMIP(); - - /** - * Sets the rendering type to VTK_RAY_CAST_COMPOSITE_FUNCTION - */ - virtual void SetRenderingTypeToComposite(); - - using BaseProperty::operator=; - - protected: - /** Sets rendering type to default (VTK_RAY_CAST_COMPOSITE_FUNCTION). - */ - VtkVolumeRenderingProperty(); - - /** - * Constructor. Sets rendering type to the given value. - */ - VtkVolumeRenderingProperty(const IdType &value); - - /** - * Constructor. Sets rendering type to the given value. - */ - VtkVolumeRenderingProperty(const std::string &value); - - /** - * this function is overridden as protected, so that the user may not add - * additional invalid rendering types. - */ - bool AddEnum(const std::string &name, const IdType &id) override; - - /** - * Adds the enumeration types as defined by vtk to the list of known - * enumeration values. - */ - virtual void AddRenderingTypes(); - - private: - // purposely not implemented - VtkVolumeRenderingProperty &operator=(const VtkVolumeRenderingProperty &); - - itk::LightObject::Pointer InternalClone() const override; - }; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -} // end of namespace mitk - -#endif diff --git a/Modules/Core/src/DataManagement/mitkVtkVolumeRenderingProperty.cpp b/Modules/Core/src/DataManagement/mitkVtkVolumeRenderingProperty.cpp deleted file mode 100644 index 6d69eb3849..0000000000 --- a/Modules/Core/src/DataManagement/mitkVtkVolumeRenderingProperty.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkVtkVolumeRenderingProperty.h" -#include - -mitk::VtkVolumeRenderingProperty::VtkVolumeRenderingProperty() -{ - this->AddRenderingTypes(); - this->SetValue(static_cast(VTK_RAY_CAST_COMPOSITE_FUNCTION)); -} - -mitk::VtkVolumeRenderingProperty::VtkVolumeRenderingProperty(const IdType &value) -{ - this->AddRenderingTypes(); - if (IsValidEnumerationValue(value)) - { - this->SetValue(value); - } - else - MITK_INFO << "Warning: invalid rendering configuration" << std::endl; -} - -mitk::VtkVolumeRenderingProperty::VtkVolumeRenderingProperty(const std::string &value) -{ - this->AddRenderingTypes(); - if (IsValidEnumerationValue(value)) - { - this->SetValue(value); - } - else - MITK_INFO << "Warning: invalid rendering configuration" << std::endl; -} - -int mitk::VtkVolumeRenderingProperty::GetRenderingType() -{ - return static_cast(this->GetValueAsId()); -} - -void mitk::VtkVolumeRenderingProperty::SetRenderingTypeToMIP() -{ - this->SetValue(static_cast(VTK_VOLUME_RAY_CAST_MIP_FUNCTION)); -} - -void mitk::VtkVolumeRenderingProperty::SetRenderingTypeToComposite() -{ - this->SetValue(static_cast(VTK_RAY_CAST_COMPOSITE_FUNCTION)); -} - -void mitk::VtkVolumeRenderingProperty::AddRenderingTypes() -{ - AddEnum("MIP", static_cast(VTK_VOLUME_RAY_CAST_MIP_FUNCTION)); - AddEnum("COMPOSITE", static_cast(VTK_RAY_CAST_COMPOSITE_FUNCTION)); -} - -bool mitk::VtkVolumeRenderingProperty::AddEnum(const std::string &name, const IdType &id) -{ - return Superclass::AddEnum(name, id); -} - -itk::LightObject::Pointer mitk::VtkVolumeRenderingProperty::InternalClone() const -{ - itk::LightObject::Pointer result(new Self(*this)); - result->UnRegister(); - return result; -} diff --git a/Modules/MapperExt/files.cmake b/Modules/MapperExt/files.cmake index 01778f6a7a..0c8592ec5a 100644 --- a/Modules/MapperExt/files.cmake +++ b/Modules/MapperExt/files.cmake @@ -1,18 +1,16 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkEnhancedPointSetVtkMapper3D.cpp - mitkGPUVolumeMapper3D.cpp mitkSplineVtkMapper3D.cpp mitkUnstructuredGridMapper2D.cpp mitkUnstructuredGridVtkMapper3D.cpp mitkVectorImageMapper2D.cpp mitkVolumeMapperVtkSmart3D.cpp vtkMaskedGlyph2D.cpp vtkMaskedGlyph3D.cpp - vtkMitkGPUVolumeRayCastMapper.cpp vtkUnstructuredGridMapper.cpp vtkPointSetSlicer.cxx ) diff --git a/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h b/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h deleted file mode 100644 index 46fff93757..0000000000 --- a/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h +++ /dev/null @@ -1,162 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef MITKGPUVOLUMEMAPPER3D_H_HEADER_INCLUDED -#define MITKGPUVOLUMEMAPPER3D_H_HEADER_INCLUDED - -// MITK -#include "MitkMapperExtExports.h" -#include "mitkBaseRenderer.h" -#include "mitkCommon.h" -#include "mitkImage.h" -#include "mitkVtkMapper.h" - -// VTK -#include -#include -#include -#include -#include -#include - -#include "vtkMitkGPUVolumeRayCastMapper.h" - -namespace mitk -{ - /************************************************************************/ - /* Properties that influence the mapper are: - * - * - \b "level window": for the level window of the volume data - * - \b "LookupTable" : for the lookup table of the volume data - * - \b "TransferFunction" (mitk::TransferFunctionProperty): for the used transfer function of the volume data - ************************************************************************/ - - //##Documentation - //## @brief Vtk-based mapper for VolumeData - //## - //## @ingroup Mapper - class MITKMAPPEREXT_EXPORT GPUVolumeMapper3D : public VtkMapper - { - public: - mitkClassMacro(GPUVolumeMapper3D, VtkMapper); - - itkFactorylessNewMacro(Self); - - itkCloneMacro(Self); - - virtual const mitk::Image *GetInput(); - - vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; - - void ApplyProperties(vtkActor *actor, mitk::BaseRenderer *renderer) override; - static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); - - /** Returns true if this Mapper currently allows for Level-of-Detail rendering. - * This reflects whether this Mapper currently invokes StartEvent, EndEvent, and - * ProgressEvent on BaseRenderer. */ - bool IsLODEnabled(BaseRenderer *renderer = nullptr) const override; - bool IsMIPEnabled(BaseRenderer *renderer = nullptr); - bool IsGPUEnabled(BaseRenderer *renderer = nullptr); - bool IsRAYEnabled(BaseRenderer *renderer = nullptr); - - void MitkRenderVolumetricGeometry(mitk::BaseRenderer *renderer) override; - - protected: - GPUVolumeMapper3D(); - ~GPUVolumeMapper3D() override; - - bool IsRenderable(mitk::BaseRenderer *renderer); - - void InitCommon(); - void DeinitCommon(); - - void InitCPU(mitk::BaseRenderer *renderer); - void DeinitCPU(mitk::BaseRenderer *renderer); - void GenerateDataCPU(mitk::BaseRenderer *renderer); - - bool InitGPU(mitk::BaseRenderer *renderer); - void DeinitGPU(mitk::BaseRenderer *); - void GenerateDataGPU(mitk::BaseRenderer *); - - bool InitRAY(mitk::BaseRenderer *renderer); - void DeinitRAY(mitk::BaseRenderer *renderer); - void GenerateDataRAY(mitk::BaseRenderer *renderer); - - void InitVtkMapper(mitk::BaseRenderer *renderer); - - void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; - - void CreateDefaultTransferFunctions(); - void UpdateTransferFunctions(mitk::BaseRenderer *renderer); - - vtkSmartPointer m_Volumenullptr; - - bool m_commonInitialized; - vtkSmartPointer m_UnitSpacingImageFilter; - vtkSmartPointer m_DefaultOpacityTransferFunction; - vtkSmartPointer m_DefaultGradientTransferFunction; - vtkSmartPointer m_DefaultColorTransferFunction; - vtkSmartPointer m_BinaryOpacityTransferFunction; - vtkSmartPointer m_BinaryGradientTransferFunction; - vtkSmartPointer m_BinaryColorTransferFunction; - - class LocalStorage : public mitk::Mapper::BaseLocalStorage - { - public: - // NO SMARTPOINTER HERE - vtkRenderWindow *m_VtkRenderWindow; - - bool m_cpuInitialized; - vtkSmartPointer m_VolumeCPU; - vtkSmartPointer m_MapperCPU; - vtkSmartPointer m_VolumePropertyCPU; - - bool m_gpuSupported; - bool m_gpuInitialized; - vtkSmartPointer m_VolumeGPU; - vtkSmartPointer m_VolumePropertyGPU; - - bool m_raySupported; - bool m_rayInitialized; - vtkSmartPointer m_VolumeRAY; - vtkSmartPointer m_MapperRAY; - vtkSmartPointer m_VolumePropertyRAY; - - LocalStorage() - { - m_VtkRenderWindow = nullptr; - - m_cpuInitialized = false; - - m_gpuInitialized = false; - m_gpuSupported = true; // assume initially gpu slicing is supported - - m_rayInitialized = false; - m_raySupported = true; // assume initially gpu raycasting is supported - } - - ~LocalStorage() override - { - if (m_cpuInitialized && m_MapperCPU && m_VtkRenderWindow) - m_MapperCPU->ReleaseGraphicsResources(m_VtkRenderWindow); - - if (m_rayInitialized && m_MapperRAY && m_VtkRenderWindow) - m_MapperRAY->ReleaseGraphicsResources(m_VtkRenderWindow); - } - }; - - mitk::LocalStorageHandler m_LSH; - }; - -} // namespace mitk - -#endif /* MITKVOLUMEDATAVTKMAPPER3D_H_HEADER_INCLUDED */ diff --git a/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h b/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h deleted file mode 100644 index 7d1bf53711..0000000000 --- a/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h +++ /dev/null @@ -1,290 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ -/*========================================================================= - - Program: Visualization Toolkit - Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.h,v $ - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ -// .NAME vtkMitkGPUVolumeRayCastMapper - Ray casting performed on the GPU. -// .SECTION Description -// vtkMitkGPUVolumeRayCastMapper is a volume mapper that performs ray casting on -// the GPU using fragment programs. -// - -#ifndef __vtkMitkGPUVolumeRayCastMapper_h -#define __vtkMitkGPUVolumeRayCastMapper_h - -#include "MitkMapperExtExports.h" -#include "mitkCommon.h" -#include "vtkVersionMacros.h" -#include "vtkVolumeMapper.h" - -class vtkVolumeProperty; -class vtkRenderWindow; - -// class vtkKWAMRVolumeMapper; // friend class. - -class MITKMAPPEREXT_EXPORT vtkMitkGPUVolumeRayCastMapper : public vtkVolumeMapper -{ -public: - vtkTypeMacro(vtkMitkGPUVolumeRayCastMapper, vtkVolumeMapper); - void PrintSelf(ostream &os, vtkIndent indent) override; - - // Description: - // If AutoAdjustSampleDistances is on, the the ImageSampleDistance - // will be varied to achieve the allocated render time of this - // prop (controlled by the desired update rate and any culling in - // use). - vtkSetClampMacro(AutoAdjustSampleDistances, int, 0, 1); - vtkGetMacro(AutoAdjustSampleDistances, int); - vtkBooleanMacro(AutoAdjustSampleDistances, int); - - // Description: - // Set/Get the distance between samples used for rendering - // when AutoAdjustSampleDistances is off, or when this mapper - // has more than 1 second allocated to it for rendering. - // Initial value is 1.0. - vtkSetMacro(SampleDistance, float); - vtkGetMacro(SampleDistance, float); - - // Description: - // Sampling distance in the XY image dimensions. Default value of 1 meaning - // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If - // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value - // will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances - // is on. - vtkSetClampMacro(ImageSampleDistance, float, 0.1f, 100.0f); - vtkGetMacro(ImageSampleDistance, float); - - // Description: - // This is the minimum image sample distance allow when the image - // sample distance is being automatically adjusted. - vtkSetClampMacro(MinimumImageSampleDistance, float, 0.1f, 100.0f); - vtkGetMacro(MinimumImageSampleDistance, float); - - // Description: - // This is the maximum image sample distance allow when the image - // sample distance is being automatically adjusted. - vtkSetClampMacro(MaximumImageSampleDistance, float, 0.1f, 100.0f); - vtkGetMacro(MaximumImageSampleDistance, float); - - // Description: - // Set/Get the window / level applied to the final color. - // This allows brightness / contrast adjustments on the - // final image. - // window is the width of the window. - // level is the center of the window. - // Initial window value is 1.0 - // Initial level value is 0.5 - // window cannot be null but can be negative, this way - // values will be reversed. - // |window| can be larger than 1.0 - // level can be any real value. - vtkSetMacro(FinalColorWindow, float); - vtkGetMacro(FinalColorWindow, float); - vtkSetMacro(FinalColorLevel, float); - vtkGetMacro(FinalColorLevel, float); - - // Description: - // Maximum size of the 3D texture in GPU memory. - // Will default to the size computed from the graphics - // card. Can be adjusted by the user. - vtkSetMacro(MaxMemoryInBytes, vtkIdType); - vtkGetMacro(MaxMemoryInBytes, vtkIdType); - - // Description: - // Maximum fraction of the MaxMemoryInBytes that should - // be used to hold the texture. Valid values are 0.1 to - // 1.0. - vtkSetClampMacro(MaxMemoryFraction, float, 0.1f, 1.0f); - vtkGetMacro(MaxMemoryFraction, float); - - // Description: - // Tells if the mapper will report intermediate progress. - // Initial value is true. As the progress works with a GL blocking - // call (glFinish()), this can be useful for huge dataset but can - // slow down rendering of small dataset. It should be set to true - // for big dataset or complex shading and streaming but to false for - // small datasets. - vtkSetMacro(ReportProgress, bool); - vtkGetMacro(ReportProgress, bool); - - // Description: - // Based on hardware and properties, we may or may not be able to - // render using 3D texture mapping. This indicates if 3D texture - // mapping is supported by the hardware, and if the other extensions - // necessary to support the specific properties are available. - virtual int IsRenderSupported(vtkRenderWindow *vtkNotUsed(window), vtkVolumeProperty *vtkNotUsed(property)) - { - return 0; - } - - void CreateCanonicalView(vtkRenderer *ren, - vtkVolume *volume, - vtkImageData *image, - int blend_mode, - double viewDirection[3], - double viewUp[3]); - - void SetMaskInput(vtkImageData *mask); - vtkGetObjectMacro(MaskInput, vtkImageData); - - // Description: - // Tells how much mask color transfer function is used compared to the - // standard color transfer function when the mask is true. - // 0.0 means only standard color transfer function. - // 1.0 means only mask color tranfer function. - // Initial value is 1.0. - vtkSetClampMacro(MaskBlendFactor, float, 0.0f, 1.0f); - vtkGetMacro(MaskBlendFactor, float); - - // BTX - // Description: - // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE - // Initialize rendering for this volume. - void Render(vtkRenderer *, vtkVolume *) override; - - // Description: - // Handled in the subclass - the actual render method - // \pre input is up-to-date. - virtual void GPURender(vtkRenderer *, vtkVolume *) {} - // Description: - // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE - // Release any graphics resources that are being consumed by this mapper. - // The parameter window could be used to determine which graphic - // resources to release. - // \deprecatedSince{2013_12} - DEPRECATED(void ReleaseGraphicsResources(vtkWindow *) override){}; - - // Description: - // Return how much the dataset has to be reduced in each dimension to - // fit on the GPU. If the value is 1.0, there is no need to reduce the - // dataset. - // \pre the calling thread has a current OpenGL context. - // \pre mapper_supported: IsRenderSupported(renderer->GetRenderWindow(),0) - // The computation is based on hardware limits (3D texture indexable size) - // and MaxMemoryInBytes. - // \post valid_i_ratio: ratio[0]>0 && ratio[0]<=1.0 - // \post valid_j_ratio: ratio[1]>0 && ratio[1]<=1.0 - // \post valid_k_ratio: ratio[2]>0 && ratio[2]<=1.0 - virtual void GetReductionRatio(double ratio[3]) = 0; - - // ETX - -protected: - vtkMitkGPUVolumeRayCastMapper(); - ~vtkMitkGPUVolumeRayCastMapper() override; - - // Check to see that the render will be OK - int ValidateRender(vtkRenderer *, vtkVolume *); - - // Special version of render called during the creation - // of a canonical view. - void CanonicalViewRender(vtkRenderer *, vtkVolume *); - - // Methods called by the AMR Volume Mapper. - virtual void PreRender(vtkRenderer *ren, - vtkVolume *vol, - double datasetBounds[6], - double scalarRange[2], - int numberOfScalarComponents, - unsigned int numberOfLevels) = 0; - - // \pre input is up-to-date - virtual void RenderBlock(vtkRenderer *ren, vtkVolume *vol, unsigned int level) = 0; - - virtual void PostRender(vtkRenderer *ren, int numberOfScalarComponents) = 0; - - // Description: - // Called by the AMR Volume Mapper. - // Set the flag that tells if the scalars are on point data (0) or - // cell data (1). - void SetCellFlag(int cellFlag); - - // The distance between sample points along the ray - float SampleDistance; - - float ImageSampleDistance; - float MinimumImageSampleDistance; - float MaximumImageSampleDistance; - int AutoAdjustSampleDistances; - - int SmallVolumeRender; - double BigTimeToDraw; - double SmallTimeToDraw; - - float FinalColorWindow; - float FinalColorLevel; - - vtkIdType MaxMemoryInBytes; - float MaxMemoryFraction; - - // 1 if we are generating the canonical image, 0 otherwise - int GeneratingCanonicalView; - vtkImageData *CanonicalViewImageData; - - // Description: - // Set the mapper in AMR Mode or not. Initial value is false. - // Called only by the vtkKWAMRVolumeMapper - vtkSetClampMacro(AMRMode, int, 0, 1); - vtkGetMacro(AMRMode, int); - vtkBooleanMacro(AMRMode, int); - - int AMRMode; - int CellFlag; // point data or cell data (or field data, not handled) ? - - // Description: - // Compute the cropping planes clipped by the bounds of the volume. - // The result is put into this->ClippedCroppingRegionPlanes. - // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage - // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes - // members instead of CroppingRegionPlanes. - // \pre volume_exists: this->GetInput()!=0 - // \pre valid_cropping: this->Cropping && - // this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && - // this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && - // this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) - virtual void ClipCroppingRegionPlanes(); - - double ClippedCroppingRegionPlanes[6]; - - bool ReportProgress; - - vtkImageData *MaskInput; - - float MaskBlendFactor; - - vtkGetObjectMacro(TransformedInput, vtkImageData); - void SetTransformedInput(vtkImageData *); - - vtkImageData *TransformedInput; - - // Description: - // This is needed only to check if the input data has been changed since the last - // Render() call. - vtkImageData *LastInput; - -private: - vtkMitkGPUVolumeRayCastMapper(const vtkMitkGPUVolumeRayCastMapper &); // Not implemented. - void operator=(const vtkMitkGPUVolumeRayCastMapper &); // Not implemented. -}; - -#endif diff --git a/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp b/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp deleted file mode 100644 index b339cc0dfc..0000000000 --- a/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp +++ /dev/null @@ -1,586 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#define GPU_INFO MITK_INFO("mapper.vr") -#define GPU_WARN MITK_WARN("mapper.vr") -#define GPU_ERROR MITK_ERROR("mapper.vr") - -#include "mitkGPUVolumeMapper3D.h" - -#include "mitkDataNode.h" - -#include "mitkColorProperty.h" -#include "mitkColorProperty.h" -#include "mitkLevelWindow.h" -#include "mitkLevelWindowProperty.h" -#include "mitkLookupTableProperty.h" -#include "mitkProperties.h" -#include "mitkRenderingManager.h" -#include "mitkTransferFunctionInitializer.h" -#include "mitkTransferFunctionProperty.h" -#include "mitkVtkPropRenderer.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "vtkMitkGPUVolumeRayCastMapper.h" - -#include "vtkOpenGLGPUVolumeRayCastMapper.h" - -const mitk::Image *mitk::GPUVolumeMapper3D::GetInput() -{ - return static_cast(GetDataNode()->GetData()); -} - -void mitk::GPUVolumeMapper3D::MitkRenderVolumetricGeometry(mitk::BaseRenderer *renderer) -{ - VtkMapper::MitkRenderVolumetricGeometry(renderer); - - // if(ls->m_gpuInitialized) - // ls->m_MapperGPU->UpdateMTime(); -} - -bool mitk::GPUVolumeMapper3D::InitGPU(mitk::BaseRenderer * /*renderer*/) -{ - return false; -} - -void mitk::GPUVolumeMapper3D::InitCPU(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_cpuInitialized) - return; - - ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); - - ls->m_MapperCPU = vtkSmartPointer::New(); - int numThreads = ls->m_MapperCPU->GetNumberOfThreads(); - - GPU_INFO << "initializing cpu-raycast-vr (vtkFixedPointVolumeRayCastMapper) (" << numThreads << " threads)"; - - ls->m_MapperCPU->SetSampleDistance(1.0); - // ls->m_MapperCPU->LockSampleDistanceToInputSpacingOn(); - ls->m_MapperCPU->SetImageSampleDistance(1.0); - ls->m_MapperCPU->IntermixIntersectingGeometryOn(); - ls->m_MapperCPU->SetAutoAdjustSampleDistances(0); - - ls->m_VolumePropertyCPU = vtkSmartPointer::New(); - ls->m_VolumePropertyCPU->ShadeOn(); - ls->m_VolumePropertyCPU->SetAmbient(0.10f); // 0.05f - ls->m_VolumePropertyCPU->SetDiffuse(0.50f); // 0.45f - ls->m_VolumePropertyCPU->SetSpecular(0.40f); // 0.50f - ls->m_VolumePropertyCPU->SetSpecularPower(16.0f); - ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); - - ls->m_VolumeCPU = vtkSmartPointer::New(); - ls->m_VolumeCPU->SetMapper(ls->m_MapperCPU); - ls->m_VolumeCPU->SetProperty(ls->m_VolumePropertyCPU); - ls->m_VolumeCPU->VisibilityOn(); - - ls->m_MapperCPU->SetInputConnection(m_UnitSpacingImageFilter->GetOutputPort()); // m_Resampler->GetOutput()); - - ls->m_cpuInitialized = true; -} - -void mitk::GPUVolumeMapper3D::DeinitCPU(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (!ls->m_cpuInitialized) - return; - - GPU_INFO << "deinitializing cpu-raycast-vr"; - - ls->m_VolumePropertyCPU = nullptr; - ls->m_MapperCPU = nullptr; - ls->m_VolumeCPU = nullptr; - ls->m_cpuInitialized = false; -} - -mitk::GPUVolumeMapper3D::GPUVolumeMapper3D() -{ - m_Volumenullptr = nullptr; - m_commonInitialized = false; -} - -mitk::GPUVolumeMapper3D::~GPUVolumeMapper3D() -{ - DeinitCommon(); -} - -void mitk::GPUVolumeMapper3D::InitCommon() -{ - if (m_commonInitialized) - return; - - m_UnitSpacingImageFilter = vtkSmartPointer::New(); - m_UnitSpacingImageFilter->SetOutputSpacing(1.0, 1.0, 1.0); - - CreateDefaultTransferFunctions(); - - m_commonInitialized = true; -} - -void mitk::GPUVolumeMapper3D::DeinitCommon() -{ - if (!m_commonInitialized) - return; - - m_commonInitialized = false; -} - -bool mitk::GPUVolumeMapper3D::IsRenderable(mitk::BaseRenderer *renderer) -{ - if (!GetDataNode()) - return false; - - DataNode *node = GetDataNode(); - - bool visible = true; - node->GetVisibility(visible, renderer, "visible"); - - if (!visible) - return false; - - bool value = false; - if (!node->GetBoolProperty("volumerendering", value, renderer)) - return false; - - if (!value) - return false; - - auto *input = const_cast(this->GetInput()); - - if (!input || !input->IsInitialized()) - return false; - - vtkImageData *inputData = input->GetVtkImageData(this->GetTimestep()); - - if (inputData == nullptr) - return false; - - return true; -} - -void mitk::GPUVolumeMapper3D::InitVtkMapper(mitk::BaseRenderer *renderer) -{ - if (IsRAYEnabled(renderer)) - { - DeinitCPU(renderer); - if (!InitRAY(renderer)) - { - GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; - goto fallback; - } - } - else if (IsGPUEnabled(renderer)) - { - DeinitCPU(renderer); - DeinitRAY(renderer); - if (!InitGPU(renderer)) - { - GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; - goto fallback; - } - } - else - { - fallback: - DeinitRAY(renderer); - InitCPU(renderer); - } -} - -vtkProp *mitk::GPUVolumeMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) -{ - if (!IsRenderable(renderer)) - { - if (!m_Volumenullptr) - { - m_Volumenullptr = vtkSmartPointer::New(); - m_Volumenullptr->VisibilityOff(); - } - return m_Volumenullptr; - } - - InitCommon(); - InitVtkMapper(renderer); - - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_rayInitialized) - return ls->m_VolumeRAY; - - if (ls->m_gpuInitialized) - return ls->m_VolumeGPU; - - return ls->m_VolumeCPU; -} - -void mitk::GPUVolumeMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) -{ - if (!IsRenderable(renderer)) - return; - - InitCommon(); - InitVtkMapper(renderer); - - auto *input = const_cast(this->GetInput()); - vtkImageData *inputData = input->GetVtkImageData(this->GetTimestep()); - m_UnitSpacingImageFilter->SetInputData(inputData); - - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_rayInitialized) - { - GenerateDataRAY(renderer); - } - else - - if (ls->m_gpuInitialized) - { - GenerateDataGPU(renderer); - } - else - { - GenerateDataCPU(renderer); - } - - // UpdateTransferFunctions - UpdateTransferFunctions(renderer); -} - -void mitk::GPUVolumeMapper3D::GenerateDataGPU(mitk::BaseRenderer * /*renderer*/) -{ -} - -void mitk::GPUVolumeMapper3D::GenerateDataCPU(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - int nextLod = mitk::RenderingManager::GetInstance()->GetNextLOD(renderer); - - if (IsLODEnabled(renderer) && nextLod == 0) - { - ls->m_MapperCPU->SetImageSampleDistance(3.5); - ls->m_MapperCPU->SetSampleDistance(1.25); - ls->m_VolumePropertyCPU->SetInterpolationTypeToNearest(); - } - else - { - ls->m_MapperCPU->SetImageSampleDistance(1.0); - ls->m_MapperCPU->SetSampleDistance(1.0); - ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); - } - - // Check raycasting mode - if (IsMIPEnabled(renderer)) - ls->m_MapperCPU->SetBlendModeToMaximumIntensity(); - else - ls->m_MapperCPU->SetBlendModeToComposite(); - - // Updating shadings - { - float value = 0; - if (GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient", value, renderer)) - ls->m_VolumePropertyCPU->SetAmbient(value); - if (GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse", value, renderer)) - ls->m_VolumePropertyCPU->SetDiffuse(value); - if (GetDataNode()->GetFloatProperty("volumerendering.cpu.specular", value, renderer)) - ls->m_VolumePropertyCPU->SetSpecular(value); - if (GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power", value, renderer)) - ls->m_VolumePropertyCPU->SetSpecularPower(value); - } -} - -void mitk::GPUVolumeMapper3D::CreateDefaultTransferFunctions() -{ - m_DefaultOpacityTransferFunction = vtkSmartPointer::New(); - m_DefaultOpacityTransferFunction->AddPoint(0.0, 0.0); - m_DefaultOpacityTransferFunction->AddPoint(255.0, 0.8); - m_DefaultOpacityTransferFunction->ClampingOn(); - - m_DefaultGradientTransferFunction = vtkSmartPointer::New(); - m_DefaultGradientTransferFunction->AddPoint(0.0, 0.0); - m_DefaultGradientTransferFunction->AddPoint(255.0, 0.8); - m_DefaultGradientTransferFunction->ClampingOn(); - - m_DefaultColorTransferFunction = vtkSmartPointer::New(); - m_DefaultColorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0); - m_DefaultColorTransferFunction->AddRGBPoint(127.5, 1, 1, 0.0); - m_DefaultColorTransferFunction->AddRGBPoint(255.0, 0.8, 0.2, 0); - m_DefaultColorTransferFunction->ClampingOn(); - - m_BinaryOpacityTransferFunction = vtkSmartPointer::New(); - m_BinaryOpacityTransferFunction->AddPoint(0, 0.0); - m_BinaryOpacityTransferFunction->AddPoint(1, 1.0); - - m_BinaryGradientTransferFunction = vtkSmartPointer::New(); - m_BinaryGradientTransferFunction->AddPoint(0.0, 1.0); - - m_BinaryColorTransferFunction = vtkSmartPointer::New(); -} - -void mitk::GPUVolumeMapper3D::UpdateTransferFunctions(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - vtkPiecewiseFunction *opacityTransferFunction = m_DefaultOpacityTransferFunction; - vtkPiecewiseFunction *gradientTransferFunction = m_DefaultGradientTransferFunction; - vtkColorTransferFunction *colorTransferFunction = m_DefaultColorTransferFunction; - - bool isBinary = false; - - GetDataNode()->GetBoolProperty("binary", isBinary, renderer); - - if (isBinary) - { - opacityTransferFunction = m_BinaryOpacityTransferFunction; - gradientTransferFunction = m_BinaryGradientTransferFunction; - colorTransferFunction = m_BinaryColorTransferFunction; - - colorTransferFunction->RemoveAllPoints(); - float rgb[3]; - if (!GetDataNode()->GetColor(rgb, renderer)) - rgb[0] = rgb[1] = rgb[2] = 1; - colorTransferFunction->AddRGBPoint(0, rgb[0], rgb[1], rgb[2]); - colorTransferFunction->Modified(); - } - else - { - auto *transferFunctionProp = - dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction", renderer)); - - if (transferFunctionProp) - { - opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); - gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); - colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); - } - } - - if (ls->m_gpuInitialized) - { - ls->m_VolumePropertyGPU->SetColor(colorTransferFunction); - ls->m_VolumePropertyGPU->SetScalarOpacity(opacityTransferFunction); - ls->m_VolumePropertyGPU->SetGradientOpacity(gradientTransferFunction); - } - - if (ls->m_rayInitialized) - { - ls->m_VolumePropertyRAY->SetColor(colorTransferFunction); - ls->m_VolumePropertyRAY->SetScalarOpacity(opacityTransferFunction); - ls->m_VolumePropertyRAY->SetGradientOpacity(gradientTransferFunction); - } - - if (ls->m_cpuInitialized) - { - ls->m_VolumePropertyCPU->SetColor(colorTransferFunction); - ls->m_VolumePropertyCPU->SetScalarOpacity(opacityTransferFunction); - ls->m_VolumePropertyCPU->SetGradientOpacity(gradientTransferFunction); - } -} - -void mitk::GPUVolumeMapper3D::ApplyProperties(vtkActor * /*actor*/, mitk::BaseRenderer * /*renderer*/) -{ - // GPU_INFO << "ApplyProperties"; -} - -void mitk::GPUVolumeMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) -{ - // GPU_INFO << "SetDefaultProperties"; - - node->AddProperty("volumerendering", mitk::BoolProperty::New(false), renderer, overwrite); - node->AddProperty("volumerendering.usemip", mitk::BoolProperty::New(false), renderer, overwrite); - node->AddProperty("volumerendering.uselod", mitk::BoolProperty::New(false), renderer, overwrite); - - node->AddProperty("volumerendering.cpu.ambient", mitk::FloatProperty::New(0.10f), renderer, overwrite); - node->AddProperty("volumerendering.cpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); - node->AddProperty("volumerendering.cpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); - node->AddProperty("volumerendering.cpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); - bool usegpu = true; -#ifdef __APPLE__ - usegpu = false; - node->AddProperty("volumerendering.uselod", mitk::BoolProperty::New(true), renderer, overwrite); -#endif - node->AddProperty("volumerendering.usegpu", mitk::BoolProperty::New(usegpu), renderer, overwrite); - - node->AddProperty("volumerendering.useray", mitk::BoolProperty::New(false), renderer, overwrite); - - node->AddProperty("volumerendering.ray.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); - node->AddProperty("volumerendering.ray.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); - node->AddProperty("volumerendering.ray.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); - node->AddProperty("volumerendering.ray.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); - - node->AddProperty("volumerendering.gpu.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.usetexturecompression", mitk::BoolProperty::New(false), renderer, overwrite); - node->AddProperty("volumerendering.gpu.reducesliceartifacts", mitk::BoolProperty::New(false), renderer, overwrite); - - node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); - - mitk::Image::Pointer image = dynamic_cast(node->GetData()); - if (image.IsNotNull() && image->IsInitialized()) - { - if ((overwrite) || (node->GetProperty("levelwindow", renderer) == nullptr)) - { - mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); - mitk::LevelWindow levelwindow; - levelwindow.SetAuto(image); - levWinProp->SetLevelWindow(levelwindow); - node->SetProperty("levelwindow", levWinProp, renderer); - } - - if ((overwrite) || (node->GetProperty("TransferFunction", renderer) == nullptr)) - { - // add a default transfer function - mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); - mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); - tfInit->SetTransferFunctionMode(0); - node->SetProperty("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); - } - } - - Superclass::SetDefaultProperties(node, renderer, overwrite); -} - -bool mitk::GPUVolumeMapper3D::IsLODEnabled(mitk::BaseRenderer *renderer) const -{ - bool value = false; - return GetDataNode()->GetBoolProperty("volumerendering.uselod", value, renderer) && value; -} - -bool mitk::GPUVolumeMapper3D::IsMIPEnabled(mitk::BaseRenderer *renderer) -{ - bool value = false; - return GetDataNode()->GetBoolProperty("volumerendering.usemip", value, renderer) && value; -} - -bool mitk::GPUVolumeMapper3D::IsGPUEnabled(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - bool value = false; - return ls->m_gpuSupported && GetDataNode()->GetBoolProperty("volumerendering.usegpu", value, renderer) && value; -} - -bool mitk::GPUVolumeMapper3D::InitRAY(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_rayInitialized) - return ls->m_raySupported; - - ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); - - GPU_INFO << "initializing gpu-raycast-vr (vtkOpenGLGPUVolumeRayCastMapper)"; - - ls->m_MapperRAY = vtkSmartPointer::New(); - ls->m_MapperRAY->SetAutoAdjustSampleDistances(0); - ls->m_MapperRAY->SetSampleDistance(1.0); - - ls->m_VolumePropertyRAY = vtkSmartPointer::New(); - ls->m_VolumePropertyRAY->ShadeOn(); - ls->m_VolumePropertyRAY->SetAmbient(0.25f); // 0.05f - ls->m_VolumePropertyRAY->SetDiffuse(0.50f); // 0.45f - ls->m_VolumePropertyRAY->SetSpecular(0.40f); // 0.50f - ls->m_VolumePropertyRAY->SetSpecularPower(16.0f); - ls->m_VolumePropertyRAY->SetInterpolationTypeToLinear(); - - ls->m_VolumeRAY = vtkSmartPointer::New(); - ls->m_VolumeRAY->SetMapper(ls->m_MapperRAY); - ls->m_VolumeRAY->SetProperty(ls->m_VolumePropertyRAY); - ls->m_VolumeRAY->VisibilityOn(); - - ls->m_MapperRAY->SetInputConnection(this->m_UnitSpacingImageFilter->GetOutputPort()); - - ls->m_raySupported = ls->m_MapperRAY->IsRenderSupported(renderer->GetRenderWindow(), ls->m_VolumePropertyRAY); - - ls->m_rayInitialized = true; - return ls->m_raySupported; -} - -void mitk::GPUVolumeMapper3D::DeinitRAY(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_rayInitialized) - { - GPU_INFO << "deinitializing gpu-raycast-vr"; - - ls->m_MapperRAY = nullptr; - ls->m_VolumePropertyRAY = nullptr; - // Here ReleaseGraphicsResources has to be called to avoid VTK error messages. - // This seems like a VTK bug, because ReleaseGraphicsResources() is ment for internal use, - // but you cannot just delete the object (last smartpointer reference) without getting the - // VTK error. - ls->m_VolumeRAY->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetRenderWindow()); - ls->m_VolumeRAY = nullptr; - ls->m_rayInitialized = false; - } -} - -void mitk::GPUVolumeMapper3D::GenerateDataRAY(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD(renderer) == 0) - ls->m_MapperRAY->SetImageSampleDistance(4.0); - else - ls->m_MapperRAY->SetImageSampleDistance(1.0); - - // Check raycasting mode - if (IsMIPEnabled(renderer)) - ls->m_MapperRAY->SetBlendModeToMaximumIntensity(); - else - ls->m_MapperRAY->SetBlendModeToComposite(); - - // Updating shadings - { - float value = 0; - if (GetDataNode()->GetFloatProperty("volumerendering.ray.ambient", value, renderer)) - ls->m_VolumePropertyRAY->SetAmbient(value); - if (GetDataNode()->GetFloatProperty("volumerendering.ray.diffuse", value, renderer)) - ls->m_VolumePropertyRAY->SetDiffuse(value); - if (GetDataNode()->GetFloatProperty("volumerendering.ray.specular", value, renderer)) - ls->m_VolumePropertyRAY->SetSpecular(value); - if (GetDataNode()->GetFloatProperty("volumerendering.ray.specular.power", value, renderer)) - ls->m_VolumePropertyRAY->SetSpecularPower(value); - } -} - -bool mitk::GPUVolumeMapper3D::IsRAYEnabled(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - bool value = false; - return ls->m_raySupported && GetDataNode()->GetBoolProperty("volumerendering.useray", value, renderer) && value; -} diff --git a/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp b/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp index 03cd67e759..d1b12197ee 100644 --- a/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp +++ b/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp @@ -1,236 +1,201 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkVolumeMapperVtkSmart3D.h" #include "mitkTransferFunctionProperty.h" #include "mitkTransferFunctionInitializer.h" #include "mitkLevelWindowProperty.h" #include #include #include #include void mitk::VolumeMapperVtkSmart3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { bool value; this->GetDataNode()->GetBoolProperty("volumerendering", value, renderer); if (!value) { m_Volume->VisibilityOff(); return; } else { createMapper(GetInputImage()); m_Volume->VisibilityOn(); } UpdateTransferFunctions(renderer); UpdateRenderMode(renderer); this->Modified(); } vtkProp* mitk::VolumeMapperVtkSmart3D::GetVtkProp(mitk::BaseRenderer *) { if (!m_Volume->GetMapper()) { createMapper(GetInputImage()); createVolume(); createVolumeProperty(); } return m_Volume; } void mitk::VolumeMapperVtkSmart3D::ApplyProperties(vtkActor *, mitk::BaseRenderer *) { } void mitk::VolumeMapperVtkSmart3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { // GPU_INFO << "SetDefaultProperties"; node->AddProperty("volumerendering", mitk::BoolProperty::New(false), renderer, overwrite); - node->AddProperty("volumerendering.usemip", mitk::BoolProperty::New(false), renderer, overwrite); - node->AddProperty("volumerendering.cpu.ambient", mitk::FloatProperty::New(0.10f), renderer, overwrite); - node->AddProperty("volumerendering.cpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); - node->AddProperty("volumerendering.cpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); - node->AddProperty("volumerendering.cpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); - node->AddProperty("volumerendering.usegpu", mitk::BoolProperty::New(false), renderer, overwrite); - node->AddProperty("volumerendering.useray", mitk::BoolProperty::New(false), renderer, overwrite); - - node->AddProperty("volumerendering.gpu.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); - node->AddProperty("volumerendering.gpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); + node->AddProperty("volumerendering.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); + node->AddProperty("volumerendering.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); + node->AddProperty("volumerendering.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); + node->AddProperty("volumerendering.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { if ((overwrite) || (node->GetProperty("TransferFunction", renderer) == nullptr)) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); tfInit->SetTransferFunctionMode(0); node->SetProperty("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkImageData* mitk::VolumeMapperVtkSmart3D::GetInputImage() { auto input = dynamic_cast(this->GetDataNode()->GetData()); return input->GetVtkImageData(this->GetTimestep()); } void mitk::VolumeMapperVtkSmart3D::createMapper(vtkImageData* imageData) { Vector3D spacing; FillVector3D(spacing, 1.0, 1.0, 1.0); m_ImageChangeInformation->SetInputData(imageData); m_ImageChangeInformation->SetOutputSpacing(spacing.GetDataPointer()); m_SmartVolumeMapper->SetBlendModeToComposite(); m_SmartVolumeMapper->SetInputConnection(m_ImageChangeInformation->GetOutputPort()); } void mitk::VolumeMapperVtkSmart3D::createVolume() { m_Volume->SetMapper(m_SmartVolumeMapper); m_Volume->SetProperty(m_VolumeProperty); } void mitk::VolumeMapperVtkSmart3D::createVolumeProperty() { m_VolumeProperty->ShadeOn(); - m_VolumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION); + m_VolumeProperty->SetInterpolationType(VTK_CUBIC_INTERPOLATION); } void mitk::VolumeMapperVtkSmart3D::UpdateTransferFunctions(mitk::BaseRenderer *renderer) { vtkSmartPointer opacityTransferFunction; vtkSmartPointer gradientTransferFunction; vtkSmartPointer colorTransferFunction; bool isBinary = false; this->GetDataNode()->GetBoolProperty("binary", isBinary, renderer); if (isBinary) { colorTransferFunction = vtkSmartPointer::New(); float rgb[3]; if (!GetDataNode()->GetColor(rgb, renderer)) rgb[0] = rgb[1] = rgb[2] = 1; colorTransferFunction->AddRGBPoint(0, rgb[0], rgb[1], rgb[2]); colorTransferFunction->Modified(); opacityTransferFunction = vtkSmartPointer::New(); gradientTransferFunction = vtkSmartPointer::New(); } else { auto *transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction", renderer)); if (transferFunctionProp) { opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); } else { opacityTransferFunction = vtkSmartPointer::New(); gradientTransferFunction = vtkSmartPointer::New(); colorTransferFunction = vtkSmartPointer::New(); } } m_VolumeProperty->SetColor(colorTransferFunction); m_VolumeProperty->SetScalarOpacity(opacityTransferFunction); m_VolumeProperty->SetGradientOpacity(gradientTransferFunction); } void mitk::VolumeMapperVtkSmart3D::UpdateRenderMode(mitk::BaseRenderer *renderer) { - bool usegpu = false; - bool useray = false; - bool usemip = false; - this->GetDataNode()->GetBoolProperty("volumerendering.usegpu", usegpu); - this->GetDataNode()->GetBoolProperty("volumerendering.useray", useray); - this->GetDataNode()->GetBoolProperty("volumerendering.usemip", usemip); - - if (usegpu) - m_SmartVolumeMapper->SetRequestedRenderModeToGPU(); - else if (useray) - m_SmartVolumeMapper->SetRequestedRenderModeToRayCast(); - else - m_SmartVolumeMapper->SetRequestedRenderModeToDefault(); + m_SmartVolumeMapper->SetRequestedRenderModeToGPU(); int blendMode; if (this->GetDataNode()->GetIntProperty("volumerendering.blendmode", blendMode)) + { m_SmartVolumeMapper->SetBlendMode(blendMode); - else if (usemip) - m_SmartVolumeMapper->SetBlendMode(vtkSmartVolumeMapper::MAXIMUM_INTENSITY_BLEND); + } // shading parameter - if (m_SmartVolumeMapper->GetRequestedRenderMode() == vtkSmartVolumeMapper::GPURenderMode) - { - float value = 0; - if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.ambient", value, renderer)) - m_VolumeProperty->SetAmbient(value); - if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.diffuse", value, renderer)) - m_VolumeProperty->SetDiffuse(value); - if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.specular", value, renderer)) - m_VolumeProperty->SetSpecular(value); - if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.specular.power", value, renderer)) - m_VolumeProperty->SetSpecularPower(value); - } - else - { - float value = 0; - if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient", value, renderer)) - m_VolumeProperty->SetAmbient(value); - if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse", value, renderer)) - m_VolumeProperty->SetDiffuse(value); - if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.specular", value, renderer)) - m_VolumeProperty->SetSpecular(value); - if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power", value, renderer)) - m_VolumeProperty->SetSpecularPower(value); - } + float value = 0; + if (this->GetDataNode()->GetFloatProperty("volumerendering.ambient", value, renderer)) + m_VolumeProperty->SetAmbient(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.diffuse", value, renderer)) + m_VolumeProperty->SetDiffuse(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.specular", value, renderer)) + m_VolumeProperty->SetSpecular(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.specular.power", value, renderer)) + m_VolumeProperty->SetSpecularPower(value); } mitk::VolumeMapperVtkSmart3D::VolumeMapperVtkSmart3D() { m_SmartVolumeMapper = vtkSmartPointer::New(); m_SmartVolumeMapper->SetBlendModeToComposite(); m_ImageChangeInformation = vtkSmartPointer::New(); m_VolumeProperty = vtkSmartPointer::New(); m_Volume = vtkSmartPointer::New(); } mitk::VolumeMapperVtkSmart3D::~VolumeMapperVtkSmart3D() { } diff --git a/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp b/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp deleted file mode 100644 index d2db1547f4..0000000000 --- a/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ -/*========================================================================= - - Program: Visualization Toolkit - Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.cxx,v $ - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ - -#include "vtkMitkGPUVolumeRayCastMapper.h" -#include "vtkCamera.h" -#include "vtkCellData.h" -#include "vtkCommand.h" // for VolumeMapperRender{Start|End|Progress}Event -#include "vtkDataArray.h" -#include "vtkGPUInfo.h" -#include "vtkGPUInfoList.h" -#include "vtkImageData.h" -#include "vtkImageResample.h" -#include "vtkMultiThreader.h" -#include "vtkPointData.h" -#include "vtkRenderWindow.h" -#include "vtkRenderer.h" -#include "vtkRendererCollection.h" -#include "vtkTimerLog.h" -#include "vtkVolume.h" -#include "vtkVolumeProperty.h" -#include - -vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, MaskInput, vtkImageData); -vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, TransformedInput, vtkImageData); - -vtkMitkGPUVolumeRayCastMapper::vtkMitkGPUVolumeRayCastMapper() -{ - this->AutoAdjustSampleDistances = 1; - this->ImageSampleDistance = 1.0; - this->MinimumImageSampleDistance = 1.0; - this->MaximumImageSampleDistance = 10.0; - this->SampleDistance = 1.0; - this->SmallVolumeRender = 0; - this->BigTimeToDraw = 0.0; - this->SmallTimeToDraw = 0.0; - this->FinalColorWindow = 1.0; - this->FinalColorLevel = 0.5; - this->GeneratingCanonicalView = 0; - this->CanonicalViewImageData = nullptr; - - this->MaskInput = nullptr; - this->MaskBlendFactor = 1.0f; - - this->AMRMode = 0; - this->ClippedCroppingRegionPlanes[0] = VTK_DOUBLE_MAX; - this->ClippedCroppingRegionPlanes[1] = VTK_DOUBLE_MIN; - this->ClippedCroppingRegionPlanes[2] = VTK_DOUBLE_MAX; - this->ClippedCroppingRegionPlanes[3] = VTK_DOUBLE_MIN; - this->ClippedCroppingRegionPlanes[4] = VTK_DOUBLE_MAX; - this->ClippedCroppingRegionPlanes[5] = VTK_DOUBLE_MIN; - - this->MaxMemoryInBytes = 0; - vtkGPUInfoList *l = vtkGPUInfoList::New(); - l->Probe(); - if (l->GetNumberOfGPUs() > 0) - { - vtkGPUInfo *info = l->GetGPUInfo(0); - this->MaxMemoryInBytes = info->GetDedicatedVideoMemory(); - if (this->MaxMemoryInBytes == 0) - { - this->MaxMemoryInBytes = info->GetDedicatedSystemMemory(); - } - // we ignore info->GetSharedSystemMemory(); as this is very slow. - } - l->Delete(); - - if (this->MaxMemoryInBytes == 0) // use some default value: 128MB. - { - this->MaxMemoryInBytes = 128 * 1024 * 1024; - } - - this->MaxMemoryFraction = 0.75; - - this->ReportProgress = true; - - this->TransformedInput = nullptr; - this->LastInput = nullptr; -} - -// ---------------------------------------------------------------------------- -vtkMitkGPUVolumeRayCastMapper::~vtkMitkGPUVolumeRayCastMapper() -{ - this->SetMaskInput(nullptr); - this->SetTransformedInput(nullptr); - this->LastInput = nullptr; -} - -// ---------------------------------------------------------------------------- -// The render method that is called from the volume. If this is a canonical -// view render, a specialized version of this method will be called instead. -// Otherwise we will -// - Invoke a start event -// - Start timing -// - Check that everything is OK for rendering -// - Render -// - Stop the timer and record results -// - Invoke an end event -// ---------------------------------------------------------------------------- -void vtkMitkGPUVolumeRayCastMapper::Render(vtkRenderer *ren, vtkVolume *vol) -{ - // Catch renders that are happening due to a canonical view render and - // handle them separately. - if (this->GeneratingCanonicalView) - { - this->CanonicalViewRender(ren, vol); - return; - } - - // Invoke a VolumeMapperRenderStartEvent - this->InvokeEvent(vtkCommand::VolumeMapperRenderStartEvent, nullptr); - - // Start the timer to time the length of this render - vtkTimerLog *timer = vtkTimerLog::New(); - timer->StartTimer(); - - // Make sure everything about this render is OK. - // This is where the input is updated. - if (this->ValidateRender(ren, vol)) - { - // Everything is OK - so go ahead and really do the render - this->GPURender(ren, vol); - } - - // Stop the timer - timer->StopTimer(); - double t = timer->GetElapsedTime(); - - // cout << "Render Timer " << t << " seconds, " << 1.0/t << " frames per second" << endl; - - this->TimeToDraw = t; - timer->Delete(); - - if (vol->GetAllocatedRenderTime() < 1.0) - { - this->SmallTimeToDraw = t; - } - else - { - this->BigTimeToDraw = t; - } - - // Invoke a VolumeMapperRenderEndEvent - this->InvokeEvent(vtkCommand::VolumeMapperRenderEndEvent, nullptr); -} - -// ---------------------------------------------------------------------------- -// Special version for rendering a canonical view - we don't do things like -// invoke start or end events, and we don't capture the render time. -// ---------------------------------------------------------------------------- -void vtkMitkGPUVolumeRayCastMapper::CanonicalViewRender(vtkRenderer *ren, vtkVolume *vol) -{ - // Make sure everything about this render is OK - if (this->ValidateRender(ren, vol)) - { - // Everything is OK - so go ahead and really do the render - this->GPURender(ren, vol); - } -} - -// ---------------------------------------------------------------------------- -// This method us used by the render method to validate everything before -// attempting to render. This method returns 0 if something is not right - -// such as missing input, a null renderer or a null volume, no scalars, etc. -// In some cases it will produce a vtkErrorMacro message, and in others -// (for example, in the case of cropping planes that define a region with -// a volume or 0 or less) it will fail silently. If everything is OK, it will -// return with a value of 1. -// ---------------------------------------------------------------------------- -int vtkMitkGPUVolumeRayCastMapper::ValidateRender(vtkRenderer *ren, vtkVolume *vol) -{ - // Check that we have everything we need to render. - int goodSoFar = 1; - - // Check for a renderer - we MUST have one - if (!ren) - { - goodSoFar = 0; - vtkErrorMacro("Renderer cannot be null."); - } - - // Check for the volume - we MUST have one - if (goodSoFar && !vol) - { - goodSoFar = 0; - vtkErrorMacro("Volume cannot be null."); - } - - // Don't need to check if we have a volume property - // since the volume will create one if we don't. Also - // don't need to check for the scalar opacity function - // or the RGB transfer function since the property will - // create them if they do not yet exist. - - // However we must currently check that the number of - // color channels is 3 - // TODO: lift this restriction - should work with - // gray functions as well. Right now turning off test - // because otherwise 4 component rendering isn't working. - // Will revisit. - if (goodSoFar && vol->GetProperty()->GetColorChannels() != 3) - { - // goodSoFar = 0; - // vtkErrorMacro("Must have a color transfer function."); - } - - // Check the cropping planes. If they are invalid, just silently - // fail. This will happen when an interactive widget is dragged - // such that it defines 0 or negative volume - this can happen - // and should just not render the volume. - // Check the cropping planes - if (goodSoFar && this->Cropping && (this->CroppingRegionPlanes[0] >= this->CroppingRegionPlanes[1] || - this->CroppingRegionPlanes[2] >= this->CroppingRegionPlanes[3] || - this->CroppingRegionPlanes[4] >= this->CroppingRegionPlanes[5])) - { - // No error message here - we want to be silent - goodSoFar = 0; - } - - // Check that we have input data - auto *input = dynamic_cast(this->GetInput()); - - // If we have a timestamp change or data change then create a new clone. - if (input != this->LastInput || input->GetMTime() > this->TransformedInput->GetMTime()) - { - this->LastInput = input; - - vtkImageData *clone; - if (!this->TransformedInput) - { - clone = vtkImageData::New(); - this->SetTransformedInput(clone); - clone->Delete(); - } - else - { - clone = this->TransformedInput; - } - - clone->ShallowCopy(input); - - // @TODO: This is the workaround to deal with GPUVolumeRayCastMapper - // not able to handle extents starting from non zero values. - // There is not a easy fix in the GPU volume ray cast mapper hence - // this fix has been introduced. - - // Get the current extents. - int extents[6], real_extents[6]; - clone->GetExtent(extents); - clone->GetExtent(real_extents); - - // Get the current origin and spacing. - double origin[3], spacing[3]; - clone->GetOrigin(origin); - clone->GetSpacing(spacing); - - for (int cc = 0; cc < 3; cc++) - { - // Transform the origin and the extents. - origin[cc] = origin[cc] + extents[2 * cc] * spacing[cc]; - extents[2 * cc + 1] -= extents[2 * cc]; - extents[2 * cc] -= extents[2 * cc]; - } - - clone->SetOrigin(origin); - clone->SetExtent(extents); - } - - if (goodSoFar && !this->TransformedInput) - { - vtkErrorMacro("Input is nullptr but is required"); - goodSoFar = 0; - } - - // Update the date then make sure we have scalars. Note - // that we must have point or cell scalars because field - // scalars are not supported. - vtkDataArray *scalars = nullptr; - if (goodSoFar) - { - // Here is where we update the input - // this->TransformedInput->UpdateInformation(); //VTK6_TODO - // this->TransformedInput->SetUpdateExtentToWholeExtent(); - // this->TransformedInput->Update(); - - // Now make sure we can find scalars - scalars = this->GetScalars( - this->TransformedInput, this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag); - - // We couldn't find scalars - if (!scalars) - { - vtkErrorMacro("No scalars found on input."); - goodSoFar = 0; - } - // Even if we found scalars, if they are field data scalars that isn't good - else if (this->CellFlag == 2) - { - vtkErrorMacro("Only point or cell scalar support - found field scalars instead."); - goodSoFar = 0; - } - } - - // Make sure the scalar type is actually supported. This mappers supports - // almost all standard scalar types. - if (goodSoFar) - { - switch (scalars->GetDataType()) - { - case VTK_CHAR: - vtkErrorMacro(<< "scalar of type VTK_CHAR is not supported " - << "because this type is platform dependent. " - << "Use VTK_SIGNED_CHAR or VTK_UNSIGNED_CHAR instead."); - goodSoFar = 0; - break; - case VTK_BIT: - vtkErrorMacro("scalar of type VTK_BIT is not supported by this mapper."); - goodSoFar = 0; - break; - case VTK_ID_TYPE: - vtkErrorMacro("scalar of type VTK_ID_TYPE is not supported by this mapper."); - goodSoFar = 0; - break; - case VTK_STRING: - vtkErrorMacro("scalar of type VTK_STRING is not supported by this mapper."); - goodSoFar = 0; - break; - default: - // Don't need to do anything here - break; - } - } - - // Check on the blending type - we support composite and min / max intensity - if (goodSoFar) - { - if (this->BlendMode != vtkVolumeMapper::COMPOSITE_BLEND && - this->BlendMode != vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND && - this->BlendMode != vtkVolumeMapper::MINIMUM_INTENSITY_BLEND) - { - goodSoFar = 0; - vtkErrorMacro(<< "Selected blend mode not supported. " - << "Only Composite and MIP and MinIP modes " - << "are supported by the current implementation."); - } - } - - // This mapper supports 1 component data, or 4 component if it is not independent - // component (i.e. the four components define RGBA) - int numberOfComponents = 0; - if (goodSoFar) - { - numberOfComponents = scalars->GetNumberOfComponents(); - if (!(numberOfComponents == 1 || (numberOfComponents == 4 && vol->GetProperty()->GetIndependentComponents() == 0))) - { - goodSoFar = 0; - vtkErrorMacro(<< "Only one component scalars, or four " - << "component with non-independent components, " - << "are supported by this mapper."); - } - } - - // If this is four component data, then it better be unsigned char (RGBA). - if (goodSoFar && numberOfComponents == 4 && scalars->GetDataType() != VTK_UNSIGNED_CHAR) - { - goodSoFar = 0; - vtkErrorMacro("Only unsigned char is supported for 4-component scalars!"); - } - - // return our status - return goodSoFar; -} - -// ---------------------------------------------------------------------------- -// Description: -// Called by the AMR Volume Mapper. -// Set the flag that tells if the scalars are on point data (0) or -// cell data (1). -void vtkMitkGPUVolumeRayCastMapper::SetCellFlag(int cellFlag) -{ - this->CellFlag = cellFlag; -} - -// ---------------------------------------------------------------------------- -void vtkMitkGPUVolumeRayCastMapper::CreateCanonicalView(vtkRenderer *ren, - vtkVolume *volume, - vtkImageData *image, - int vtkNotUsed(blend_mode), - double viewDirection[3], - double viewUp[3]) -{ - this->GeneratingCanonicalView = 1; - int oldSwap = ren->GetRenderWindow()->GetSwapBuffers(); - ren->GetRenderWindow()->SwapBuffersOff(); - - int dim[3]; - image->GetDimensions(dim); - int *size = ren->GetRenderWindow()->GetSize(); - - vtkImageData *bigImage = vtkImageData::New(); - bigImage->SetDimensions(size[0], size[1], 1); - bigImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3); - - this->CanonicalViewImageData = bigImage; - - double scale[2]; - scale[0] = dim[0] / static_cast(size[0]); - scale[1] = dim[1] / static_cast(size[1]); - - // Save the visibility flags of the renderers and set all to false except - // for the ren. - vtkRendererCollection *renderers = ren->GetRenderWindow()->GetRenderers(); - int numberOfRenderers = renderers->GetNumberOfItems(); - - auto rendererVisibilities = new bool[numberOfRenderers]; - renderers->InitTraversal(); - int i = 0; - while (i < numberOfRenderers) - { - vtkRenderer *r = renderers->GetNextItem(); - rendererVisibilities[i] = r->GetDraw() == 1; - if (r != ren) - { - r->SetDraw(false); - } - ++i; - } - - // Save the visibility flags of the props and set all to false except - // for the volume. - - vtkPropCollection *props = ren->GetViewProps(); - int numberOfProps = props->GetNumberOfItems(); - - auto propVisibilities = new bool[numberOfProps]; - props->InitTraversal(); - i = 0; - while (i < numberOfProps) - { - vtkProp *p = props->GetNextProp(); - propVisibilities[i] = p->GetVisibility() == 1; - if (p != volume) - { - p->SetVisibility(false); - } - ++i; - } - - vtkCamera *savedCamera = ren->GetActiveCamera(); - savedCamera->Modified(); - vtkCamera *canonicalViewCamera = vtkCamera::New(); - - // Code from vtkFixedPointVolumeRayCastMapper: - double *center = volume->GetCenter(); - double bounds[6]; - volume->GetBounds(bounds); - double d = - sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) + (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) + - (bounds[5] - bounds[4]) * (bounds[5] - bounds[4])); - - // For now use x distance - need to change this - d = bounds[1] - bounds[0]; - - // Set up the camera in parallel - canonicalViewCamera->SetFocalPoint(center); - canonicalViewCamera->ParallelProjectionOn(); - canonicalViewCamera->SetPosition( - center[0] - d * viewDirection[0], center[1] - d * viewDirection[1], center[2] - d * viewDirection[2]); - canonicalViewCamera->SetViewUp(viewUp); - canonicalViewCamera->SetParallelScale(d / 2); - - ren->SetActiveCamera(canonicalViewCamera); - ren->GetRenderWindow()->Render(); - - ren->SetActiveCamera(savedCamera); - canonicalViewCamera->Delete(); - - // Shrink to image to the desired size - vtkImageResample *resample = vtkImageResample::New(); - resample->SetInputData(bigImage); - resample->SetAxisMagnificationFactor(0, scale[0]); - resample->SetAxisMagnificationFactor(1, scale[1]); - resample->SetAxisMagnificationFactor(2, 1); - resample->UpdateWholeExtent(); - - // Copy the pixels over - image->DeepCopy(resample->GetOutput()); - - bigImage->Delete(); - resample->Delete(); - - // Restore the visibility flags of the props - props->InitTraversal(); - i = 0; - while (i < numberOfProps) - { - vtkProp *p = props->GetNextProp(); - p->SetVisibility(propVisibilities[i]); - ++i; - } - - delete[] propVisibilities; - - // Restore the visibility flags of the renderers - renderers->InitTraversal(); - i = 0; - while (i < numberOfRenderers) - { - vtkRenderer *r = renderers->GetNextItem(); - r->SetDraw(rendererVisibilities[i]); - ++i; - } - - delete[] rendererVisibilities; - - ren->GetRenderWindow()->SetSwapBuffers(oldSwap); - this->CanonicalViewImageData = nullptr; - this->GeneratingCanonicalView = 0; -} - -// ---------------------------------------------------------------------------- -// Print method for vtkMitkGPUVolumeRayCastMapper -void vtkMitkGPUVolumeRayCastMapper::PrintSelf(ostream &os, vtkIndent indent) -{ - this->Superclass::PrintSelf(os, indent); - - os << indent << "AutoAdjustSampleDistances: " << this->AutoAdjustSampleDistances << endl; - os << indent << "MinimumImageSampleDistance: " << this->MinimumImageSampleDistance << endl; - os << indent << "MaximumImageSampleDistance: " << this->MaximumImageSampleDistance << endl; - os << indent << "ImageSampleDistance: " << this->ImageSampleDistance << endl; - os << indent << "SampleDistance: " << this->SampleDistance << endl; - os << indent << "FinalColorWindow: " << this->FinalColorWindow << endl; - os << indent << "FinalColorLevel: " << this->FinalColorLevel << endl; - os << indent << "MaskInput: " << this->MaskInput << endl; - os << indent << "MaskBlendFactor: " << this->MaskBlendFactor << endl; - os << indent << "MaxMemoryInBytes: " << this->MaxMemoryInBytes << endl; - os << indent << "MaxMemoryFraction: " << this->MaxMemoryFraction << endl; - os << indent << "ReportProgress: " << this->ReportProgress << endl; -} - -// ---------------------------------------------------------------------------- -// Description: -// Compute the cropping planes clipped by the bounds of the volume. -// The result is put into this->ClippedCroppingRegionPlanes. -// NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage -// in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes -// members instead of CroppingRegionPlanes. -// \pre volume_exists: this->GetInput()!=0 -// \pre valid_cropping: this->Cropping && -// this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && -// this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && -// this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) -void vtkMitkGPUVolumeRayCastMapper::ClipCroppingRegionPlanes() -{ - assert("pre: volume_exists" && this->GetInput() != nullptr); - assert("pre: valid_cropping" && this->Cropping && this->CroppingRegionPlanes[0] < this->CroppingRegionPlanes[1] && - this->CroppingRegionPlanes[2] < this->CroppingRegionPlanes[3] && - this->CroppingRegionPlanes[4] < this->CroppingRegionPlanes[5]); - - // vtkVolumeMapper::Render() will have something like: - // if(this->Cropping && (this->CroppingRegionPlanes[0]>=this->CroppingRegionPlanes[1] || - // this->CroppingRegionPlanes[2]>=this->CroppingRegionPlanes[3] || - // this->CroppingRegionPlanes[4]>=this->CroppingRegionPlanes[5])) - // { - // // silentely stop because the cropping is not valid. - // return; - // } - - double volBounds[6]; - this->GetInput()->GetBounds(volBounds); - - int i = 0; - while (i < 6) - { - // max of the mins - if (this->CroppingRegionPlanes[i] < volBounds[i]) - { - this->ClippedCroppingRegionPlanes[i] = volBounds[i]; - } - else - { - this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i]; - } - ++i; - // min of the maxs - if (this->CroppingRegionPlanes[i] > volBounds[i]) - { - this->ClippedCroppingRegionPlanes[i] = volBounds[i]; - } - - else - { - this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i]; - } - ++i; - } -} diff --git a/Modules/MapperExt/src/vtkMitkOpenGLVolumeTextureMapper3D.cpp b/Modules/MapperExt/src/vtkMitkOpenGLVolumeTextureMapper3D.cpp deleted file mode 100644 index aaa400fbbf..0000000000 --- a/Modules/MapperExt/src/vtkMitkOpenGLVolumeTextureMapper3D.cpp +++ /dev/null @@ -1,2443 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifdef _OPENMP -#include -#endif - -#include "vtkWindows.h" -#include "mitkCommon.h" -#include "vtkMitkOpenGLVolumeTextureMapper3D.h" - -#define GPU_INFO MITK_INFO("mapper.vr") -#define GPU_WARN MITK_WARN("mapper.vr") - -#include "vtkCamera.h" -#include "vtkDataArray.h" -#include "vtkImageData.h" -#include "vtkLight.h" -#include "vtkLightCollection.h" -#include "vtkMath.h" -#include "vtkMatrix4x4.h" -#include "vtkObjectFactory.h" -#include "vtkOpenGLExtensionManager.h" -#include "vtkPlane.h" -#include "vtkPlaneCollection.h" -#include "vtkPointData.h" -#include "vtkRenderWindow.h" -#include "vtkRenderer.h" -#include "vtkTimerLog.h" -#include "vtkTransform.h" -#include "vtkVolumeProperty.h" -#include "vtkgl.h" - -#include "vtkOpenGLRenderWindow.h" - -#define myGL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define myGL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 -#define myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - -const char *vtkMitkVolumeTextureMapper3D_FourDependentShadeFP = "!!ARBfp1.0\n" - - //# We need some temporary variables - "TEMP index, normal, finalColor;\n" - "TEMP temp,temp1, temp2, temp3,temp4; \n" - "TEMP sampleColor;\n" - "TEMP ndotl, ndoth, ndotv; \n" - "TEMP lightInfo, lightResult;\n" - - //# We are going to use the first - //# texture coordinate - "ATTRIB tex0 = fragment.texcoord[0];\n" - - //# This is the lighting information - "PARAM lightDirection = program.local[0];\n" - "PARAM halfwayVector = program.local[1];\n" - "PARAM coefficient = program.local[2];\n" - "PARAM lightDiffColor = program.local[3]; \n" - "PARAM lightSpecColor = program.local[4]; \n" - "PARAM viewVector = program.local[5];\n" - "PARAM constants = program.local[6];\n" - - //# This is our output color - "OUTPUT out = result.color;\n" - - //# Look up the gradient direction - //# in the third volume - "TEX temp2, tex0, texture[0], 3D;\n" - - //# This normal is stored 0 to 1, change to -1 to 1 - //# by multiplying by 2.0 then adding -1.0. - "MAD normal, temp2, constants.x, constants.y;\n" - - "DP3 temp4, normal, normal;\n" - "RSQ temp, temp4.x;\n" - "MUL normal, normal, temp;\n" - - //"RCP temp4,temp.x;\n" - - //"MUL temp2.w,temp2.w,temp4.x;\n" - - //"MUL_SAT temp2.w,temp2.w,6.0;\n" - - "TEX sampleColor, tex0, texture[1], 3D;\n" - - //# Take the dot product of the light - //# direction and the normal - "DP3 ndotl, normal, lightDirection;\n" - - //# Take the dot product of the halfway - //# vector and the normal - "DP3 ndoth, normal, halfwayVector;\n" - - "DP3 ndotv, normal, viewVector;\n" - - //# flip if necessary for two sided lighting - "MUL temp3, ndotl, constants.y; \n" - "CMP ndotl, ndotv, ndotl, temp3;\n" - "MUL temp3, ndoth, constants.y; \n" - "CMP ndoth, ndotv, ndoth, temp3;\n" - - //# put the pieces together for a LIT operation - "MOV lightInfo.x, ndotl.x; \n" - "MOV lightInfo.y, ndoth.x; \n" - "MOV lightInfo.w, coefficient.w; \n" - - //# compute the lighting - "LIT lightResult, lightInfo;\n" - - //# COLOR FIX - "MUL lightResult, lightResult, 4.0;\n" - - //# This is the ambient contribution - "MUL finalColor, coefficient.x, sampleColor;\n" - - //# This is the diffuse contribution - "MUL temp3, lightDiffColor, sampleColor;\n" - "MUL temp3, temp3, lightResult.y;\n" - "ADD finalColor, finalColor, temp3;\n" - - //# This is th specular contribution - "MUL temp3, lightSpecColor, lightResult.z; \n" - - //# Add specular into result so far, and replace - //# with the original alpha. - "ADD out, finalColor, temp3;\n" - "MOV out.w, temp2.w;\n" - - "END\n"; - -const char *vtkMitkVolumeTextureMapper3D_OneComponentShadeFP = "!!ARBfp1.0\n" - - //# This is the fragment program for one - //# component data with shading - - //# We need some temporary variables - "TEMP index, normal, finalColor;\n" - "TEMP temp,temp1, temp2, temp3,temp4; \n" - "TEMP sampleColor;\n" - "TEMP ndotl, ndoth, ndotv; \n" - "TEMP lightInfo, lightResult;\n" - - //# We are going to use the first - //# texture coordinate - "ATTRIB tex0 = fragment.texcoord[0];\n" - - //# This is the lighting information - "PARAM lightDirection = program.local[0];\n" - "PARAM halfwayVector = program.local[1];\n" - "PARAM coefficient = program.local[2];\n" - "PARAM lightDiffColor = program.local[3]; \n" - "PARAM lightSpecColor = program.local[4]; \n" - "PARAM viewVector = program.local[5];\n" - "PARAM constants = program.local[6];\n" - - //# This is our output color - "OUTPUT out = result.color;\n" - - //# Look up the gradient direction - //# in the third volume - "TEX temp2, tex0, texture[0], 3D;\n" - - // Gradient Compution - - //# Look up the scalar value / gradient - //# magnitude in the first volume - //"TEX temp1, tex0, texture[0], 3D;\n" - - /* - - "ADD temp3,tex0,{-0.005,0,0};\n" - "TEX temp2,temp3, texture[0], 3D;\n" - - //"ADD temp3,tex0,{ 0.005,0,0};\n" - //"TEX temp1,temp3, texture[0], 3D;\n" - - "SUB normal.x,temp2.y,temp1.y;\n" - - "ADD temp3,tex0,{0,-0.005,0};\n" - "TEX temp2,temp3, texture[0], 3D;\n" - - //"ADD temp3,tex0,{0, 0.005,0};\n" - //"TEX temp1,temp3, texture[0], 3D;\n" - - "SUB normal.y,temp2.y,temp1.y;\n" - - "ADD temp3,tex0,{0,0,-0.005};\n" - "TEX temp2,temp3, texture[0], 3D;\n" - - //"ADD temp3,tex0,{0,0, 0.005};\n" - //"TEX temp1,temp3, texture[0], 3D;\n" - - "SUB normal.z,temp2.y,temp1.y;\n" - - */ - - //"MOV normal,{1,1,1};\n" - - "MOV index.x,temp2.a;\n" - - //# This normal is stored 0 to 1, change to -1 to 1 - //# by multiplying by 2.0 then adding -1.0. - "MAD normal, temp2, constants.x, constants.y;\n" - - //# Swizzle this to use (a,r) as texture - //# coordinates - //"SWZ index, temp1, a, r, 1, 1;\n" - - //# Use this coordinate to look up a - //# final color in the third texture - //# (this is a 2D texture) - - "DP3 temp4, normal, normal;\n" - - "RSQ temp, temp4.x;\n" - - "RCP temp4,temp.x;\n" - - "MUL normal, normal, temp;\n" - - "MOV index.y, temp4.x;\n" - - "TEX sampleColor, index, texture[1], 2D;\n" - - //"MUL sampleColor.w,sampleColor.w,temp4.x;\n" - - //# Take the dot product of the light - //# direction and the normal - "DP3 ndotl, normal, lightDirection;\n" - - //# Take the dot product of the halfway - //# vector and the normal - "DP3 ndoth, normal, halfwayVector;\n" - - "DP3 ndotv, normal, viewVector;\n" - - //# flip if necessary for two sided lighting - "MUL temp3, ndotl, constants.y; \n" - "CMP ndotl, ndotv, ndotl, temp3;\n" - "MUL temp3, ndoth, constants.y; \n" - "CMP ndoth, ndotv, ndoth, temp3;\n" - - //# put the pieces together for a LIT operation - "MOV lightInfo.x, ndotl.x; \n" - "MOV lightInfo.y, ndoth.x; \n" - "MOV lightInfo.w, coefficient.w; \n" - - //# compute the lighting - "LIT lightResult, lightInfo;\n" - - //# COLOR FIX - "MUL lightResult, lightResult, 4.0;\n" - - //# This is the ambient contribution - "MUL finalColor, coefficient.x, sampleColor;\n" - - //# This is the diffuse contribution - "MUL temp3, lightDiffColor, sampleColor;\n" - "MUL temp3, temp3, lightResult.y;\n" - "ADD finalColor, finalColor, temp3;\n" - - //# This is th specular contribution - "MUL temp3, lightSpecColor, lightResult.z; \n" - - //# Add specular into result so far, and replace - //# with the original alpha. - "ADD out, finalColor, temp3;\n" - "MOV out.w, sampleColor.w;\n" - - "END\n"; - -//#ifndef VTK_IMPLEMENT_MESA_CXX -vtkStandardNewMacro(vtkMitkOpenGLVolumeTextureMapper3D); -//#endif - -vtkMitkOpenGLVolumeTextureMapper3D::vtkMitkOpenGLVolumeTextureMapper3D() -{ - // GPU_INFO << "vtkMitkOpenGLVolumeTextureMapper3D"; - - this->Initialized = 0; - this->Volume1Index = 0; - this->Volume2Index = 0; - this->Volume3Index = 0; - this->ColorLookupIndex = 0; - this->AlphaLookupIndex = 0; - this->RenderWindow = nullptr; - this->SupportsCompressedTexture = false; - - prgOneComponentShade = 0; - prgRGBAShade = 0; -} - -vtkMitkOpenGLVolumeTextureMapper3D::~vtkMitkOpenGLVolumeTextureMapper3D() -{ - // GPU_INFO << "~vtkMitkOpenGLVolumeTextureMapper3D"; - if (prgOneComponentShade) - vtkgl::DeleteProgramsARB(1, &prgOneComponentShade); - - if (prgRGBAShade) - vtkgl::DeleteProgramsARB(1, &prgRGBAShade); -} - -// Release the graphics resources used by this texture. -void vtkMitkOpenGLVolumeTextureMapper3D::ReleaseGraphicsResources(vtkWindow *renWin) -{ - // GPU_INFO << "ReleaseGraphicsResources"; - - if ((this->Volume1Index || this->Volume2Index || this->Volume3Index || this->ColorLookupIndex) && renWin) - { - static_cast(renWin)->MakeCurrent(); -#ifdef GL_VERSION_1_1 - // free any textures - this->DeleteTextureIndex(&this->Volume1Index); - this->DeleteTextureIndex(&this->Volume2Index); - this->DeleteTextureIndex(&this->Volume3Index); - this->DeleteTextureIndex(&this->ColorLookupIndex); - this->DeleteTextureIndex(&this->AlphaLookupIndex); -#endif - } - this->Volume1Index = 0; - this->Volume2Index = 0; - this->Volume3Index = 0; - this->ColorLookupIndex = 0; - this->RenderWindow = nullptr; - this->SupportsCompressedTexture = false; - this->SupportsNonPowerOfTwoTextures = false; - - this->Modified(); -} - -// Release the graphics resources used by this texture. -void vtkMitkOpenGLVolumeTextureMapper3D::ReleaseGraphicsResources(mitk::BaseRenderer *renderer) -{ - // GPU_INFO << "ReleaseGraphicsResources"; - - vtkWindow *renWin = renderer->GetVtkRenderer()->GetRenderWindow(); - - if ((this->Volume1Index || this->Volume2Index || this->Volume3Index || this->ColorLookupIndex) && renWin) - { - static_cast(renWin)->MakeCurrent(); -#ifdef GL_VERSION_1_1 - // free any textures - this->DeleteTextureIndex(&this->Volume1Index); - this->DeleteTextureIndex(&this->Volume2Index); - this->DeleteTextureIndex(&this->Volume3Index); - this->DeleteTextureIndex(&this->ColorLookupIndex); - this->DeleteTextureIndex(&this->AlphaLookupIndex); -#endif - } - this->Volume1Index = 0; - this->Volume2Index = 0; - this->Volume3Index = 0; - this->ColorLookupIndex = 0; - this->RenderWindow = nullptr; - this->SupportsCompressedTexture = false; - this->SupportsNonPowerOfTwoTextures = false; - - this->Modified(); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::Render(vtkRenderer *ren, vtkVolume *vol) -{ - // GPU_INFO << "Render"; - - ren->GetRenderWindow()->MakeCurrent(); - - if (!this->Initialized) - { - // this->Initialize(); - this->Initialize(ren); - } - - if (!this->RenderPossible) - { - vtkErrorMacro("required extensions not supported"); - return; - } - - vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); - vtkPlaneCollection *clipPlanes; - vtkPlane *plane; - int numClipPlanes = 0; - double planeEquation[4]; - - // build transformation - vol->GetMatrix(matrix); - matrix->Transpose(); - - glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_POLYGON_BIT | - GL_TEXTURE_BIT); - - int i; - - // Use the OpenGL clip planes - clipPlanes = this->ClippingPlanes; - if (clipPlanes) - { - numClipPlanes = clipPlanes->GetNumberOfItems(); - if (numClipPlanes > 6) - { - vtkErrorMacro(<< "OpenGL guarantees only 6 additional clipping planes"); - } - - for (i = 0; i < numClipPlanes; i++) - { - glEnable(static_cast(GL_CLIP_PLANE0 + i)); - - plane = static_cast(clipPlanes->GetItemAsObject(i)); - - planeEquation[0] = plane->GetNormal()[0]; - planeEquation[1] = plane->GetNormal()[1]; - planeEquation[2] = plane->GetNormal()[2]; - planeEquation[3] = -(planeEquation[0] * plane->GetOrigin()[0] + planeEquation[1] * plane->GetOrigin()[1] + - planeEquation[2] * plane->GetOrigin()[2]); - glClipPlane(static_cast(GL_CLIP_PLANE0 + i), planeEquation); - } - } - - // insert model transformation - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMultMatrixd(matrix->Element[0]); - - glColor4f(1.0, 1.0, 1.0, 1.0); - - // Turn lighting off - the polygon textures already have illumination - glDisable(GL_LIGHTING); - - // vtkGraphicErrorMacro(ren->GetRenderWindow(),"Before actual render method"); - - this->RenderFP(ren, vol); - - // pop transformation matrix - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - matrix->Delete(); - glPopAttrib(); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::RenderFP(vtkRenderer *ren, vtkVolume *vol) -{ - // GPU_INFO << "RenderFP"; - - /* - glAlphaFunc (GL_GREATER, static_cast(1.0/255.0)); - glEnable (GL_ALPHA_TEST); - */ - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - int components = this->GetInput()->GetNumberOfScalarComponents(); - switch (components) - { - case 1: - this->RenderOneIndependentShadeFP(ren, vol); - break; - - case 4: - this->RenderRGBAShadeFP(ren, vol); - break; - } - - vtkgl::ActiveTexture(vtkgl::TEXTURE2); - glDisable(GL_TEXTURE_2D); - glDisable(vtkgl::TEXTURE_3D); - - vtkgl::ActiveTexture(vtkgl::TEXTURE1); - glDisable(GL_TEXTURE_2D); - glDisable(vtkgl::TEXTURE_3D); - - vtkgl::ActiveTexture(vtkgl::TEXTURE0); - glDisable(GL_TEXTURE_2D); - glDisable(vtkgl::TEXTURE_3D); - - glDisable(GL_BLEND); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::DeleteTextureIndex(GLuint *index) -{ - // GPU_INFO << "DeleteTextureIndex"; - - if (glIsTexture(*index)) - { - GLuint tempIndex; - tempIndex = *index; - glDeleteTextures(1, &tempIndex); - *index = 0; - } -} - -void vtkMitkOpenGLVolumeTextureMapper3D::CreateTextureIndex(GLuint *index) -{ - // GPU_INFO << "CreateTextureIndex"; - - GLuint tempIndex = 0; - glGenTextures(1, &tempIndex); - *index = static_cast(tempIndex); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::RenderPolygons(vtkRenderer *ren, vtkVolume *vol, int stages[4]) -{ - // GPU_INFO << "RenderPolygons"; - - vtkRenderWindow *renWin = ren->GetRenderWindow(); - - if (renWin->CheckAbortStatus()) - { - return; - } - - double bounds[27][6]; - float distance2[27]; - - int numIterations; - int i, j, k; - - // No cropping case - render the whole thing - if (!this->Cropping) - { - // Use the input data bounds - we'll take care of the volume's - // matrix during rendering - this->GetInput()->GetBounds(bounds[0]); - numIterations = 1; - } - // Simple cropping case - render the subvolume - else if (this->CroppingRegionFlags == 0x2000) - { - this->GetCroppingRegionPlanes(bounds[0]); - numIterations = 1; - } - // Complex cropping case - render each region in back-to-front order - else - { - // Get the camera position - double camPos[4]; - ren->GetActiveCamera()->GetPosition(camPos); - - double volBounds[6]; - this->GetInput()->GetBounds(volBounds); - - // Pass camera through inverse volume matrix - // so that we are in the same coordinate system - vtkMatrix4x4 *volMatrix = vtkMatrix4x4::New(); - vol->GetMatrix(volMatrix); - camPos[3] = 1.0; - volMatrix->Invert(); - volMatrix->MultiplyPoint(camPos, camPos); - volMatrix->Delete(); - if (camPos[3]) - { - camPos[0] /= camPos[3]; - camPos[1] /= camPos[3]; - camPos[2] /= camPos[3]; - } - - // These are the region limits for x (first four), y (next four) and - // z (last four). The first region limit is the lower bound for - // that axis, the next two are the region planes along that axis, and - // the final one in the upper bound for that axis. - float limit[12]; - for (i = 0; i < 3; i++) - { - limit[i * 4] = volBounds[i * 2]; - limit[i * 4 + 1] = this->CroppingRegionPlanes[i * 2]; - limit[i * 4 + 2] = this->CroppingRegionPlanes[i * 2 + 1]; - limit[i * 4 + 3] = volBounds[i * 2 + 1]; - } - - // For each of the 27 possible regions, find out if it is enabled, - // and if so, compute the bounds and the distance from the camera - // to the center of the region. - int numRegions = 0; - int region; - for (region = 0; region < 27; region++) - { - int regionFlag = 1 << region; - - if (this->CroppingRegionFlags & regionFlag) - { - // what is the coordinate in the 3x3x3 grid - int loc[3]; - loc[0] = region % 3; - loc[1] = (region / 3) % 3; - loc[2] = (region / 9) % 3; - - // compute the bounds and center - float center[3]; - for (i = 0; i < 3; i++) - { - bounds[numRegions][i * 2] = limit[4 * i + loc[i]]; - bounds[numRegions][i * 2 + 1] = limit[4 * i + loc[i] + 1]; - center[i] = (bounds[numRegions][i * 2] + bounds[numRegions][i * 2 + 1]) / 2.0; - } - - // compute the distance squared to the center - distance2[numRegions] = (camPos[0] - center[0]) * (camPos[0] - center[0]) + - (camPos[1] - center[1]) * (camPos[1] - center[1]) + - (camPos[2] - center[2]) * (camPos[2] - center[2]); - - // we've added one region - numRegions++; - } - } - - // Do a quick bubble sort on distance - for (i = 1; i < numRegions; i++) - { - for (j = i; j > 0 && distance2[j] > distance2[j - 1]; j--) - { - float tmpBounds[6]; - float tmpDistance2; - - for (k = 0; k < 6; k++) - { - tmpBounds[k] = bounds[j][k]; - } - tmpDistance2 = distance2[j]; - - for (k = 0; k < 6; k++) - { - bounds[j][k] = bounds[j - 1][k]; - } - distance2[j] = distance2[j - 1]; - - for (k = 0; k < 6; k++) - { - bounds[j - 1][k] = tmpBounds[k]; - } - distance2[j - 1] = tmpDistance2; - } - } - - numIterations = numRegions; - } - - // loop over all regions we need to render - for (int loop = 0; loop < numIterations; loop++) - { - // Compute the set of polygons for this region - // according to the bounds - this->ComputePolygons(ren, vol, bounds[loop]); - - // Loop over the polygons - for (i = 0; i < this->NumberOfPolygons; i++) - { - if (renWin->CheckAbortStatus()) - { - return; - } - - float *ptr = this->PolygonBuffer + 36 * i; - - glBegin(GL_TRIANGLE_FAN); - - for (j = 0; j < 6; j++) - { - if (ptr[0] < 0.0) - { - break; - } - - for (k = 0; k < 4; k++) - { - if (stages[k]) - { - vtkgl::MultiTexCoord3fv(vtkgl::TEXTURE0 + k, ptr); - } - } - glVertex3fv(ptr + 3); - - ptr += 6; - } - glEnd(); - } - } -} - -// This method moves the scalars from the input volume into volume1 (and -// possibly volume2) which are the 3D texture maps used for rendering. -// -// In the case where our volume is a power of two, the copy is done -// directly. If we need to resample, then trilinear interpolation is used. -// -// A shift/scale is applied to the input scalar value to produce an 8 bit -// value for the texture volume. -// -// When the input data is one component, the scalar value is placed in the -// second component of the two component volume1. The first component is -// filled in later with the gradient magnitude. -// -// When the input data is two component non-independent, the first component -// of the input data is placed in the first component of volume1, and the -// second component of the input data is placed in the third component of -// volume1. Volume1 has three components - the second is filled in later with -// the gradient magnitude. -// -// When the input data is four component non-independent, the first three -// components of the input data are placed in volume1 (which has three -// components), and the fourth component is placed in the second component -// of volume2. The first component of volume2 is later filled in with the -// gradient magnitude. - -template -class ScalarGradientCompute -{ - T *dataPtr; - unsigned char *tmpPtr; - unsigned char *tmpPtr2; - int sizeX; - int sizeY; - int sizeZ; - int sizeXY; - int sizeXm1; - int sizeYm1; - int sizeZm1; - int fullX; - int fullY; - int fullZ; - int fullXY; - int currentChunkStart; - int currentChunkEnd; - - int offZ; - - float offset; - float scale; - -public: - ScalarGradientCompute(T *_dataPtr, - unsigned char *_tmpPtr, - unsigned char *_tmpPtr2, - int _sizeX, - int _sizeY, - int _sizeZ, - int _fullX, - int _fullY, - int _fullZ, - float _offset, - float _scale) - { - dataPtr = _dataPtr; - tmpPtr = _tmpPtr; - tmpPtr2 = _tmpPtr2; - sizeX = _sizeX; - sizeY = _sizeY; - sizeZ = _sizeZ; - fullX = _fullX; - fullY = _fullY; - fullZ = _fullZ; - offset = _offset; - scale = _scale; - - sizeXY = sizeX * sizeY; - sizeXm1 = sizeX - 1; - sizeYm1 = sizeY - 1; - sizeZm1 = sizeZ - 1; - - fullXY = fullX * fullY; - currentChunkStart = 0; - currentChunkEnd = 0; - offZ = 0; - } - - inline float sample(int x, int y, int z) { return float(dataPtr[x + y * sizeX + z * sizeXY]); } - inline void fill(int x, int y, int z) - { - int doff = x + y * fullX + (z - offZ) * fullXY; - - tmpPtr[doff * 4 + 0] = 0; - tmpPtr[doff * 4 + 1] = 0; - tmpPtr[doff * 4 + 2] = 0; - tmpPtr[doff * 4 + 3] = 0; - /* -tmpPtr2[doff*3+0]= 0; -tmpPtr2[doff*3+1]= 0; -tmpPtr2[doff*3+2]= 0; -*/ - } - - inline int clamp(int x) - { - if (x < 0) - x = 0; - else if (x > 255) - x = 255; - return x; - } - - inline void write(int x, int y, int z, float grayValue, float gx, float gy, float gz) - { - /* - gx /= aspect[0]; - gy /= aspect[1]; - gz /= aspect[2]; - */ - // Compute the gradient magnitude - - int iGrayValue = static_cast((grayValue + offset) * scale + 0.5f); - - gx *= scale; - gy *= scale; - gz *= scale; - - float t = sqrtf(gx * gx + gy * gy + gz * gz); - - if (t > 0.01f) - { - if (t < 2.0f) - { - float fac = 2.0f / t; - gx *= fac; - gy *= fac; - gz *= fac; - } - else if (t > 255.0f) - { - float fac = 255.0f / t; - gx *= fac; - gy *= fac; - gz *= fac; - } - } - else - { - gx = gy = gz = 0.0f; - } - - int nx = static_cast(0.5f * gx + 127.5f); - int ny = static_cast(0.5f * gy + 127.5f); - int nz = static_cast(0.5f * gz + 127.5f); - - int doff = x + y * fullX + (z - offZ) * fullXY; - - // tmpPtr[doff*2+0]= 0; - - tmpPtr[doff * 4 + 0] = clamp(nx); - tmpPtr[doff * 4 + 1] = clamp(ny); - tmpPtr[doff * 4 + 2] = clamp(nz); - tmpPtr[doff * 4 + 3] = clamp(iGrayValue); - - /* - if( z == fullZ/2 ) - if( y == fullY/2 ) - MITK_INFO << x << " " << y << " " << z << " : " << iGrayValue << " : " << iGradient; - */ - } - - inline void compute(int x, int y, int z) - { - float grayValue = sample(x, y, z); - float gx, gy, gz; - - gx = sample(x + 1, y, z) - sample(x - 1, y, z); - gy = sample(x, y + 1, z) - sample(x, y - 1, z); - gz = sample(x, y, z + 1) - sample(x, y, z - 1); - - write(x, y, z, grayValue, gx, gy, gz); - } - - inline void computeClamp(int x, int y, int z) - { - float grayValue = sample(x, y, z); - float gx, gy, gz; - - if (x == 0) - gx = 2.0f * (sample(x + 1, y, z) - grayValue); - else if (x == sizeXm1) - gx = 2.0f * (grayValue - sample(x - 1, y, z)); - else - gx = sample(x + 1, y, z) - sample(x - 1, y, z); - - if (y == 0) - gy = 2.0f * (sample(x, y + 1, z) - grayValue); - else if (y == sizeYm1) - gy = 2.0f * (grayValue - sample(x, y - 1, z)); - else - gy = sample(x, y + 1, z) - sample(x, y - 1, z); - - if (z == 0) - gz = 2.0f * (sample(x, y, z + 1) - grayValue); - else if (z == sizeZm1) - gz = 2.0f * (grayValue - sample(x, y, z - 1)); - else - gz = sample(x, y, z + 1) - sample(x, y, z - 1); - - write(x, y, z, grayValue, gx, gy, gz); - } - - inline void compute1D(int y, int z) - { - int x; - - x = 0; - computeClamp(x, y, z); - x++; - - while (x < sizeX - 1) - { - compute(x, y, z); - x++; - } - - if (x < sizeX) - { - computeClamp(x, y, z); - x++; - } - - while (x < fullX) - { - fill(x, y, z); - x++; - } - } - - inline void fill1D(int y, int z) - { - int x; - - x = 0; - while (x < fullX) - { - fill(x, y, z); - x++; - } - } - - inline void computeClamp1D(int y, int z) - { - int x; - - x = 0; - - while (x < sizeX) - { - computeClamp(x, y, z); - x++; - } - - while (x < fullX) - { - fill(x, y, z); - x++; - } - } - - inline void computeClamp2D(int z) - { - int y; - - y = 0; - - while (y < sizeY) - { - computeClamp1D(y, z); - y++; - } - - while (y < fullY) - { - fill1D(y, z); - y++; - } - } - - inline void compute2D(int z) - { - int y; - - y = 0; - computeClamp1D(y, z); - y++; - - while (y < sizeY - 1) - { - compute1D(y, z); - y++; - } - - if (y < sizeY) - { - computeClamp1D(y, z); - y++; - } - - while (y < fullY) - { - fill1D(y, z); - y++; - } - } - - inline void fill2D(int z) - { - int y; - - y = 0; - while (y < fullY) - { - fill1D(y, z); - y++; - } - } - - inline void fillSlices(int currentChunkStart, int currentChunkEnd) - { - offZ = currentChunkStart; - -/* - int num = omp_get_num_procs(); - MITK_INFO << "omp uses " << num << " processors"; -*/ - -#pragma omp parallel for - for (int z = currentChunkStart; z <= currentChunkEnd; z++) - { - if (z == 0 || z == sizeZ - 1) - computeClamp2D(z); - else if (z >= sizeZ) - fill2D(z); - else - compute2D(z); - } - } -}; - -template -void vtkVolumeTextureMapper3DComputeScalars( - T *dataPtr, vtkMitkVolumeTextureMapper3D *me, float offset, float scale, GLuint volume1, GLuint /*volume2*/) -{ - // T *inPtr; - // unsigned char *outPtr, *outPtr2; - // int i, j, k; - // int idx; - - int inputDimensions[3]; - double inputSpacing[3]; - vtkImageData *input = me->GetInput(); - - input->GetDimensions(inputDimensions); - input->GetSpacing(inputSpacing); - - int outputDimensions[3]; - float outputSpacing[3]; - me->GetVolumeDimensions(outputDimensions); - me->GetVolumeSpacing(outputSpacing); - - // int components = input->GetNumberOfScalarComponents(); - - // double wx, wy, wz; - // double fx, fy, fz; - // int x, y, z; - - // double sampleRate[3]; - // sampleRate[0] = outputSpacing[0] / static_cast(inputSpacing[0]); - // sampleRate[1] = outputSpacing[1] / static_cast(inputSpacing[1]); - // sampleRate[2] = outputSpacing[2] / static_cast(inputSpacing[2]); - - int fullX = outputDimensions[0]; - int fullY = outputDimensions[1]; - int fullZ = outputDimensions[2]; - - int sizeX = inputDimensions[0]; - int sizeY = inputDimensions[1]; - int sizeZ = inputDimensions[2]; - - int chunkSize = 64; - - if (fullZ < chunkSize) - chunkSize = fullZ; - - int numChunks = (fullZ + (chunkSize - 1)) / chunkSize; - - // inPtr = dataPtr; - - unsigned char *tmpPtr = new unsigned char[fullX * fullY * chunkSize * 4]; - unsigned char *tmpPtr2 = 0; // new unsigned char[fullX*fullY*chunkSize*3]; - - // For each Chunk - { - ScalarGradientCompute sgc(dataPtr, tmpPtr, tmpPtr2, sizeX, sizeY, sizeZ, fullX, fullY, fullZ, offset, scale); - - int currentChunk = 0; - - while (currentChunk < numChunks) - { - int currentChunkStart = currentChunk * chunkSize; - int currentChunkEnd = currentChunkStart + chunkSize - 1; - - if (currentChunkEnd > (fullZ - 1)) - currentChunkEnd = (fullZ - 1); - - int currentChunkSize = currentChunkEnd - currentChunkStart + 1; - - sgc.fillSlices(currentChunkStart, currentChunkEnd); - - glBindTexture(vtkgl::TEXTURE_3D, volume1); - vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D, - 0, - 0, - 0, - currentChunkStart, - fullX, - fullY, - currentChunkSize, - GL_RGBA, - GL_UNSIGNED_BYTE, - tmpPtr); - currentChunk++; - } - } - - delete[] tmpPtr; -} - -class RGBACompute -{ - unsigned char *dataPtr; - unsigned char *tmpPtr; - unsigned char *tmpPtr2; - int sizeX; - int sizeY; - int sizeZ; - int sizeXY; - int sizeXm1; - int sizeYm1; - int sizeZm1; - int fullX; - int fullY; - int fullZ; - int fullXY; - // int currentChunkStart; - // int currentChunkEnd; - - int offZ; - -public: - RGBACompute(unsigned char *_dataPtr, - unsigned char *_tmpPtr, - unsigned char *_tmpPtr2, - int _sizeX, - int _sizeY, - int _sizeZ, - int _fullX, - int _fullY, - int _fullZ) - { - dataPtr = _dataPtr; - tmpPtr = _tmpPtr; - tmpPtr2 = _tmpPtr2; - sizeX = _sizeX; - sizeY = _sizeY; - sizeZ = _sizeZ; - fullX = _fullX; - fullY = _fullY; - fullZ = _fullZ; - - sizeXY = sizeX * sizeY; - sizeXm1 = sizeX - 1; - sizeYm1 = sizeY - 1; - sizeZm1 = sizeZ - 1; - - fullXY = fullX * fullY; - offZ = 0; - } - - inline int sample(int x, int y, int z) { return dataPtr[(x + y * sizeX + z * sizeXY) * 4 + 3]; } - inline void fill(int x, int y, int z) - { - int doff = x + y * fullX + (z - offZ) * fullXY; - - tmpPtr[doff * 4 + 0] = 0; - tmpPtr[doff * 4 + 1] = 0; - tmpPtr[doff * 4 + 2] = 0; - tmpPtr[doff * 4 + 3] = 0; - - tmpPtr2[doff * 3 + 0] = 0; - tmpPtr2[doff * 3 + 1] = 0; - tmpPtr2[doff * 3 + 2] = 0; - } - - inline int clamp(int x) - { - if (x < 0) - x = 0; - else if (x > 255) - x = 255; - return x; - } - - inline void write(int x, int y, int z, int iGrayValue, int gx, int gy, int gz) - { - /* - gx /= aspect[0]; - gy /= aspect[1]; - gz /= aspect[2]; - */ - int nx = static_cast(0.5f * gx + 127.5f); - int ny = static_cast(0.5f * gy + 127.5f); - int nz = static_cast(0.5f * gz + 127.5f); - - int doff = x + y * fullX + (z - offZ) * fullXY; - - // tmpPtr[doff*2+0]= 0; - - tmpPtr[doff * 4 + 0] = clamp(nx); - tmpPtr[doff * 4 + 1] = clamp(ny); - tmpPtr[doff * 4 + 2] = clamp(nz); - tmpPtr[doff * 4 + 3] = clamp(iGrayValue); - - int soff = x + y * sizeX + z * sizeXY; - - tmpPtr2[doff * 3 + 0] = dataPtr[soff * 4 + 0]; - tmpPtr2[doff * 3 + 1] = dataPtr[soff * 4 + 1]; - tmpPtr2[doff * 3 + 2] = dataPtr[soff * 4 + 2]; - - /* - if( z == fullZ/2 ) - if( y == fullY/2 ) - MITK_INFO << x << " " << y << " " << z << " : " << iGrayValue << " : " << iGradient; - */ - } - - inline void compute(int x, int y, int z) - { - int grayValue = sample(x, y, z); - int gx, gy, gz; - - gx = sample(x + 1, y, z) - sample(x - 1, y, z); - gy = sample(x, y + 1, z) - sample(x, y - 1, z); - gz = sample(x, y, z + 1) - sample(x, y, z - 1); - - write(x, y, z, grayValue, gx, gy, gz); - } - - inline void computeClamp(int x, int y, int z) - { - int grayValue = sample(x, y, z); - int gx, gy, gz; - - if (x == 0) - gx = 2 * (sample(x + 1, y, z) - grayValue); - else if (x == sizeXm1) - gx = 2 * (grayValue - sample(x - 1, y, z)); - else - gx = sample(x + 1, y, z) - sample(x - 1, y, z); - - if (y == 0) - gy = 2 * (sample(x, y + 1, z) - grayValue); - else if (y == sizeYm1) - gy = 2 * (grayValue - sample(x, y - 1, z)); - else - gy = sample(x, y + 1, z) - sample(x, y - 1, z); - - if (z == 0) - gz = 2 * (sample(x, y, z + 1) - grayValue); - else if (z == sizeZm1) - gz = 2 * (grayValue - sample(x, y, z - 1)); - else - gz = sample(x, y, z + 1) - sample(x, y, z - 1); - - write(x, y, z, grayValue, gx, gy, gz); - } - - inline void compute1D(int y, int z) - { - int x = 0; - - computeClamp(x, y, z); - x++; - - while (x < sizeX - 1) - { - compute(x, y, z); - x++; - } - - if (x < sizeX) - { - computeClamp(x, y, z); - x++; - } - - while (x < fullX) - { - fill(x, y, z); - x++; - } - } - - inline void fill1D(int y, int z) - { - int x = 0; - - while (x < fullX) - { - fill(x, y, z); - x++; - } - } - - inline void computeClamp1D(int y, int z) - { - int x = 0; - - while (x < sizeX) - { - computeClamp(x, y, z); - x++; - } - - while (x < fullX) - { - fill(x, y, z); - x++; - } - } - - inline void computeClamp2D(int z) - { - int y = 0; - - while (y < sizeY) - { - computeClamp1D(y, z); - y++; - } - - while (y < fullY) - { - fill1D(y, z); - y++; - } - } - - inline void compute2D(int z) - { - int y = 0; - - computeClamp1D(y, z); - y++; - - while (y < sizeY - 1) - { - compute1D(y, z); - y++; - } - - if (y < sizeY) - { - computeClamp1D(y, z); - y++; - } - - while (y < fullY) - { - fill1D(y, z); - y++; - } - } - - inline void fill2D(int z) - { - int y = 0; - - while (y < fullY) - { - fill1D(y, z); - y++; - } - } - - inline void fillSlices(int currentChunkStart, int currentChunkEnd) - { - offZ = currentChunkStart; - -#pragma omp parallel for - for (int z = currentChunkStart; z <= currentChunkEnd; z++) - { - if (z == 0 || z == sizeZ - 1) - computeClamp2D(z); - else if (z >= sizeZ) - fill2D(z); - else - compute2D(z); - } - } -}; - -void vtkVolumeTextureMapper3DComputeRGBA(unsigned char *dataPtr, - vtkMitkVolumeTextureMapper3D *me, - GLuint volume1, - GLuint volume2) -{ - // unsigned char *inPtr; - // unsigned char *outPtr, *outPtr2; - // int i, j, k; - // int idx; - - int inputDimensions[3]; - double inputSpacing[3]; - vtkImageData *input = me->GetInput(); - - input->GetDimensions(inputDimensions); - input->GetSpacing(inputSpacing); - - int outputDimensions[3]; - float outputSpacing[3]; - me->GetVolumeDimensions(outputDimensions); - me->GetVolumeSpacing(outputSpacing); - - int components = input->GetNumberOfScalarComponents(); - - MITK_INFO << "components are " << components; - - // double wx, wy, wz; - // double fx, fy, fz; - // int x, y, z; - - // double sampleRate[3]; - // sampleRate[0] = outputSpacing[0] / static_cast(inputSpacing[0]); - // sampleRate[1] = outputSpacing[1] / static_cast(inputSpacing[1]); - // sampleRate[2] = outputSpacing[2] / static_cast(inputSpacing[2]); - - int fullX = outputDimensions[0]; - int fullY = outputDimensions[1]; - int fullZ = outputDimensions[2]; - - int sizeX = inputDimensions[0]; - int sizeY = inputDimensions[1]; - int sizeZ = inputDimensions[2]; - - int chunkSize = 64; - - if (fullZ < chunkSize) - chunkSize = fullZ; - - int numChunks = (fullZ + (chunkSize - 1)) / chunkSize; - - // inPtr = dataPtr; - - unsigned char *tmpPtr = new unsigned char[fullX * fullY * chunkSize * 4]; - unsigned char *tmpPtr2 = new unsigned char[fullX * fullY * chunkSize * 3]; - - // For each Chunk - { - RGBACompute sgc(dataPtr, tmpPtr, tmpPtr2, sizeX, sizeY, sizeZ, fullX, fullY, fullZ); - - int currentChunk = 0; - - while (currentChunk < numChunks) - { - // MITK_INFO << "processing chunk " << currentChunk; - - int currentChunkStart = currentChunk * chunkSize; - int currentChunkEnd = currentChunkStart + chunkSize - 1; - - if (currentChunkEnd > (fullZ - 1)) - currentChunkEnd = (fullZ - 1); - - int currentChunkSize = currentChunkEnd - currentChunkStart + 1; - - sgc.fillSlices(currentChunkStart, currentChunkEnd); - - glBindTexture(vtkgl::TEXTURE_3D, volume1); - vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D, - 0, - 0, - 0, - currentChunkStart, - fullX, - fullY, - currentChunkSize, - GL_RGBA, - GL_UNSIGNED_BYTE, - tmpPtr); - - glBindTexture(vtkgl::TEXTURE_3D, volume2); - vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D, - 0, - 0, - 0, - currentChunkStart, - fullX, - fullY, - currentChunkSize, - GL_RGB, - GL_UNSIGNED_BYTE, - tmpPtr2); - - currentChunk++; - } - } - - delete[] tmpPtr; - delete[] tmpPtr2; -} - -//----------------------------------------------------------------------------- -void vtkMitkOpenGLVolumeTextureMapper3D::ComputeVolumeDimensions() -{ - // Get the image data - vtkImageData *input = this->GetInput(); - - // How big does the Volume need to be? - int dim[3]; - input->GetDimensions(dim); - - int powerOfTwoDim[3]; - - if (this->SupportsNonPowerOfTwoTextures) - { - for (int i = 0; i < 3; i++) - powerOfTwoDim[i] = (dim[i] + 1) & ~1; - - // MITK_INFO << "using non-power-two even textures (" << - // (1.0-double(dim[0]*dim[1]*dim[2])/double(powerOfTwoDim[0]*powerOfTwoDim[1]*powerOfTwoDim[2])) * 100.0 << "% - // memory wasted)"; - } - else - { - for (int i = 0; i < 3; i++) - { - powerOfTwoDim[i] = 4; - while (powerOfTwoDim[i] < dim[i]) - powerOfTwoDim[i] *= 2; - } - - MITK_WARN << "using power-two textures (" - << (1.0 - - double(dim[0] * dim[1] * dim[2]) / double(powerOfTwoDim[0] * powerOfTwoDim[1] * powerOfTwoDim[2])) * - 100.0 - << "% memory wasted)"; - } - - // Save the volume size - this->VolumeDimensions[0] = powerOfTwoDim[0]; - this->VolumeDimensions[1] = powerOfTwoDim[1]; - this->VolumeDimensions[2] = powerOfTwoDim[2]; - - // What is the spacing? - double spacing[3]; - input->GetSpacing(spacing); - - // Compute the new spacing - this->VolumeSpacing[0] = (dim[0] - 1.01) * spacing[0] / static_cast(this->VolumeDimensions[0] - 1); - this->VolumeSpacing[1] = (dim[1] - 1.01) * spacing[1] / static_cast(this->VolumeDimensions[1] - 1); - this->VolumeSpacing[2] = ((dim[2]) - 1.01) * spacing[2] / static_cast(this->VolumeDimensions[2] - 1); -} - -//----------------------------------------------------------------------------- -bool vtkMitkOpenGLVolumeTextureMapper3D::UpdateVolumes(vtkVolume *vtkNotUsed(vol)) -{ - // Get the image data - vtkImageData *input = this->GetInput(); - // input->Update(); //VTK6_TODO - - bool needUpdate = false; - - // Has the volume changed in some way? - if (this->SavedTextureInput != input || this->SavedTextureMTime.GetMTime() < input->GetMTime()) - needUpdate = true; - - // Do we have any volume on the gpu already? - if (!this->Volume1Index) - needUpdate = true; - - if (!needUpdate) - return true; - - ComputeVolumeDimensions(); - - int components = input->GetNumberOfScalarComponents(); - - // Find the scalar range - double scalarRange[2]; - input->GetPointData()->GetScalars()->GetRange(scalarRange, components - 1); - - // Is the difference between max and min less than 4096? If so, and if - // the data is not of float or double type, use a simple offset mapping. - // If the difference between max and min is 4096 or greater, or the data - // is of type float or double, we must use an offset / scaling mapping. - // In this case, the array size will be 4096 - we need to figure out the - // offset and scale factor. - float offset; - float scale; - - int arraySizeNeeded; - - int scalarType = input->GetScalarType(); - - if (scalarType == VTK_FLOAT || scalarType == VTK_DOUBLE || scalarRange[1] - scalarRange[0] > 255) - { - arraySizeNeeded = 256; - offset = -scalarRange[0]; - scale = 255.0 / (scalarRange[1] - scalarRange[0]); - } - else - { - arraySizeNeeded = static_cast(scalarRange[1] - scalarRange[0] + 1); - offset = -scalarRange[0]; - scale = 1.0; - } - - this->ColorTableSize = arraySizeNeeded; - this->ColorTableOffset = offset; - this->ColorTableScale = scale; - - // Allocating volume on gpu - { - // Deleting old textures - this->DeleteTextureIndex(&this->Volume1Index); - this->DeleteTextureIndex(&this->Volume2Index); - this->DeleteTextureIndex(&this->Volume3Index); - - this->CreateTextureIndex(&this->Volume1Index); - // this->CreateTextureIndex(&this->Volume2Index); - - int dim[3]; - this->GetVolumeDimensions(dim); - - vtkgl::ActiveTexture(vtkgl::TEXTURE0); - - MITK_INFO << "allocating volume on gpu"; - - GLint gradientScalarTextureFormat = GL_RGBA8; - - if (this->UseCompressedTexture && SupportsCompressedTexture) - gradientScalarTextureFormat = myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - - glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); - vtkgl::TexImage3D( - vtkgl::TEXTURE_3D, 0, gradientScalarTextureFormat, dim[0], dim[1], dim[2], 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - this->Setup3DTextureParameters(true); - } - - // Transfer the input volume to the RGBA volume - void *dataPtr = input->GetScalarPointer(); - - switch (scalarType) - { - vtkTemplateMacro(vtkVolumeTextureMapper3DComputeScalars( - static_cast(dataPtr), this, offset, scale, this->Volume1Index, this->Volume2Index)); - } - - this->SavedTextureInput = input; - this->SavedTextureMTime.Modified(); - - return true; -} - -//----------------------------------------------------------------------------- -bool vtkMitkOpenGLVolumeTextureMapper3D::UpdateVolumesRGBA(vtkVolume *vtkNotUsed(vol)) -{ - // Get the image data - vtkImageData *input = this->GetInput(); - // input->Update(); //VTK6_TODO - - bool needUpdate = false; - - // Has the volume changed in some way? - if (this->SavedTextureInput != input || this->SavedTextureMTime.GetMTime() < input->GetMTime()) - needUpdate = true; - - // Do we have any volume on the gpu already? - if (!this->Volume1Index) - needUpdate = true; - - if (!needUpdate) - return true; - - MITK_INFO << "updating rgba volume"; - - ComputeVolumeDimensions(); - - // Allocating volume on gpu - { - // Deleting old textures - this->DeleteTextureIndex(&this->Volume1Index); - this->DeleteTextureIndex(&this->Volume2Index); - this->DeleteTextureIndex(&this->Volume3Index); - - this->CreateTextureIndex(&this->Volume1Index); - this->CreateTextureIndex(&this->Volume2Index); - - int dim[3]; - this->GetVolumeDimensions(dim); - - MITK_INFO << "allocating volume on gpu"; - - GLint gradientScalarTextureFormat = GL_RGBA8; - GLint colorTextureFormat = GL_RGB8; - - if (this->UseCompressedTexture && SupportsCompressedTexture) - { - gradientScalarTextureFormat = myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - colorTextureFormat = myGL_COMPRESSED_RGB_S3TC_DXT1_EXT; - } - - vtkgl::ActiveTexture(vtkgl::TEXTURE0); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); - vtkgl::TexImage3D( - vtkgl::TEXTURE_3D, 0, gradientScalarTextureFormat, dim[0], dim[1], dim[2], 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - this->Setup3DTextureParameters(true); - - glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); - vtkgl::TexImage3D(vtkgl::TEXTURE_3D, 0, colorTextureFormat, dim[0], dim[1], dim[2], 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - this->Setup3DTextureParameters(true); - } - - // Transfer the input volume to the RGBA volume - unsigned char *dataPtr = (unsigned char *)input->GetScalarPointer(); - vtkVolumeTextureMapper3DComputeRGBA(dataPtr, this, this->Volume1Index, this->Volume2Index); - - this->SavedTextureInput = input; - this->SavedTextureMTime.Modified(); - - return true; -} - -void vtkMitkOpenGLVolumeTextureMapper3D::Setup3DTextureParameters(bool linear) -{ - // GPU_INFO << "Setup3DTextureParameters"; - - if (linear) - { - glTexParameterf(vtkgl::TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(vtkgl::TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameterf(vtkgl::TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(vtkgl::TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexParameterf(vtkgl::TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf(vtkgl::TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::SetupOneIndependentTextures(vtkRenderer *vtkNotUsed(ren), vtkVolume *vol) -{ - // Update the volume containing the 2 byte scalar / gradient magnitude - this->UpdateVolumes(vol); - - // Update the dependent 2D color table mapping scalar value and - // gradient magnitude to RGBA - if (this->UpdateColorLookup(vol) || !this->ColorLookupIndex) - { - this->DeleteTextureIndex(&this->ColorLookupIndex); - this->DeleteTextureIndex(&this->AlphaLookupIndex); - - this->CreateTextureIndex(&this->ColorLookupIndex); - - vtkgl::ActiveTexture(vtkgl::TEXTURE1); - glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - // MITK_INFO << "uploading transferfunction"; - - GLint colorLookupTextureFormat = GL_RGBA8; - - if (this->UseCompressedTexture && SupportsCompressedTexture) - colorLookupTextureFormat = myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - - glTexImage2D(GL_TEXTURE_2D, 0, colorLookupTextureFormat, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->ColorLookup); - } -} - -void vtkMitkOpenGLVolumeTextureMapper3D::SetupRGBATextures(vtkRenderer *vtkNotUsed(ren), vtkVolume *vol) -{ - MITK_INFO << "SetupFourDependentTextures"; - - this->UpdateVolumesRGBA(vol); - - /* -vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); -glDisable( GL_TEXTURE_2D ); -glEnable( vtkgl::TEXTURE_3D ); - -vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); -glDisable( GL_TEXTURE_2D ); -glEnable( vtkgl::TEXTURE_3D ); - -vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); -glDisable( GL_TEXTURE_2D ); -glEnable( vtkgl::TEXTURE_3D ); - -// Update the volume containing the 3 byte scalars / gradient magnitude -if ( this->UpdateVolumes( vol ) || !this->Volume1Index || - !this->Volume2Index || !this->Volume3Index ) - { - int dim[3]; - this->GetVolumeDimensions(dim); - - vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); - glBindTexture(vtkgl::TEXTURE_3D,0); - this->DeleteTextureIndex(&this->Volume1Index); - this->CreateTextureIndex(&this->Volume1Index); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); - vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,this->InternalRGB,dim[0],dim[1], - dim[2],0,GL_RGB,GL_UNSIGNED_BYTE,this->Volume1); - - vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); - glBindTexture(vtkgl::TEXTURE_3D,0); - this->DeleteTextureIndex(&this->Volume2Index); - this->CreateTextureIndex(&this->Volume2Index); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); - vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,this->InternalLA,dim[0],dim[1], - dim[2],0,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE, - this->Volume2); - - vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); - glBindTexture(vtkgl::TEXTURE_3D,0); - this->DeleteTextureIndex(&this->Volume3Index); - this->CreateTextureIndex(&this->Volume3Index); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume3Index); - vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,this->InternalRGB,dim[0],dim[1], - dim[2],0,GL_RGB,GL_UNSIGNED_BYTE,this->Volume3); - } - -vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); -glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); -this->Setup3DTextureParameters( true ); - -vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); -glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); -this->Setup3DTextureParameters( true ); - -vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); -glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume3Index); -this->Setup3DTextureParameters( true ); - -vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); -glEnable( GL_TEXTURE_2D ); -glDisable( vtkgl::TEXTURE_3D ); - -// Update the dependent 2D table mapping scalar value and -// gradient magnitude to opacity -if ( this->UpdateColorLookup( vol ) || !this->AlphaLookupIndex ) - { - this->DeleteTextureIndex(&this->ColorLookupIndex); - - vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); - glBindTexture(GL_TEXTURE_2D,0); - this->DeleteTextureIndex(&this->AlphaLookupIndex); - this->CreateTextureIndex(&this->AlphaLookupIndex); - glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); - - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); - - //MITK_INFO << "uploading transferfunction"; - - glTexImage2D(GL_TEXTURE_2D,0,this->InternalAlpha, 256, 256, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, this->AlphaLookup ); - } - -vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); -glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); - -*/ -} - -void vtkMitkOpenGLVolumeTextureMapper3D::RenderOneIndependentShadeFP(vtkRenderer *ren, vtkVolume *vol) -{ - // GPU_INFO << "RenderOneIndependentShadeFP"; - - this->SetupOneIndependentTextures(ren, vol); - - glEnable(vtkgl::FRAGMENT_PROGRAM_ARB); - - vtkgl::BindProgramARB(vtkgl::FRAGMENT_PROGRAM_ARB, prgOneComponentShade); - - this->SetupProgramLocalsForShadingFP(ren, vol); - - // Bind Textures - { - vtkgl::ActiveTexture(vtkgl::TEXTURE0); - glDisable(GL_TEXTURE_2D); - glEnable(vtkgl::TEXTURE_3D); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); - - vtkgl::ActiveTexture(vtkgl::TEXTURE1); - glEnable(GL_TEXTURE_2D); - glDisable(vtkgl::TEXTURE_3D); - glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); - - vtkgl::ActiveTexture(vtkgl::TEXTURE2); - glDisable(GL_TEXTURE_2D); - glEnable(vtkgl::TEXTURE_3D); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); - } - - int stages[4] = {1, 1, 1, 0}; - this->RenderPolygons(ren, vol, stages); - - glDisable(vtkgl::FRAGMENT_PROGRAM_ARB); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::RenderRGBAShadeFP(vtkRenderer *ren, vtkVolume *vol) -{ - this->SetupRGBATextures(ren, vol); - - glEnable(vtkgl::FRAGMENT_PROGRAM_ARB); - - vtkgl::BindProgramARB(vtkgl::FRAGMENT_PROGRAM_ARB, prgRGBAShade); - - this->SetupProgramLocalsForShadingFP(ren, vol); - - // Bind Textures - { - vtkgl::ActiveTexture(vtkgl::TEXTURE0); - glDisable(GL_TEXTURE_2D); - glEnable(vtkgl::TEXTURE_3D); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); - - vtkgl::ActiveTexture(vtkgl::TEXTURE1); - glDisable(GL_TEXTURE_2D); - glEnable(vtkgl::TEXTURE_3D); - glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); - } - - int stages[4] = {1, 1, 1, 0}; - this->RenderPolygons(ren, vol, stages); - - glDisable(vtkgl::FRAGMENT_PROGRAM_ARB); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::GetLightInformation(vtkRenderer *ren, - vtkVolume *vol, - GLfloat lightDirection[2][4], - GLfloat lightDiffuseColor[2][4], - GLfloat lightSpecularColor[2][4], - GLfloat halfwayVector[2][4], - GLfloat ambientColor[4]) -{ - // GPU_INFO << "GetLightInformation"; - - float ambient = vol->GetProperty()->GetAmbient(); - float diffuse = vol->GetProperty()->GetDiffuse(); - float specular = vol->GetProperty()->GetSpecular(); - - vtkTransform *volumeTransform = vtkTransform::New(); - - volumeTransform->SetMatrix(vol->GetMatrix()); - volumeTransform->Inverse(); - - vtkLightCollection *lights = ren->GetLights(); - lights->InitTraversal(); - - vtkLight *light[2]; - light[0] = lights->GetNextItem(); - light[1] = lights->GetNextItem(); - - int lightIndex = 0; - - double cameraPosition[3]; - double cameraFocalPoint[3]; - - ren->GetActiveCamera()->GetPosition(cameraPosition); - ren->GetActiveCamera()->GetFocalPoint(cameraFocalPoint); - - double viewDirection[3]; - - volumeTransform->TransformPoint(cameraPosition, cameraPosition); - volumeTransform->TransformPoint(cameraFocalPoint, cameraFocalPoint); - - viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; - viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; - viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; - - vtkMath::Normalize(viewDirection); - - ambientColor[0] = 0.0; - ambientColor[1] = 0.0; - ambientColor[2] = 0.0; - ambientColor[3] = 0.0; - - for (lightIndex = 0; lightIndex < 2; lightIndex++) - { - float dir[3] = {0, 0, 0}; - float half[3] = {0, 0, 0}; - - if (light[lightIndex] == nullptr || light[lightIndex]->GetSwitch() == 0) - { - lightDiffuseColor[lightIndex][0] = 0.0; - lightDiffuseColor[lightIndex][1] = 0.0; - lightDiffuseColor[lightIndex][2] = 0.0; - lightDiffuseColor[lightIndex][3] = 0.0; - - lightSpecularColor[lightIndex][0] = 0.0; - lightSpecularColor[lightIndex][1] = 0.0; - lightSpecularColor[lightIndex][2] = 0.0; - lightSpecularColor[lightIndex][3] = 0.0; - } - else - { - float lightIntensity = light[lightIndex]->GetIntensity(); - double lightColor[3]; - - light[lightIndex]->GetDiffuseColor(lightColor); - - double lightPosition[3]; - double lightFocalPoint[3]; - light[lightIndex]->GetTransformedPosition(lightPosition); - light[lightIndex]->GetTransformedFocalPoint(lightFocalPoint); - - volumeTransform->TransformPoint(lightPosition, lightPosition); - volumeTransform->TransformPoint(lightFocalPoint, lightFocalPoint); - - dir[0] = lightPosition[0] - lightFocalPoint[0]; - dir[1] = lightPosition[1] - lightFocalPoint[1]; - dir[2] = lightPosition[2] - lightFocalPoint[2]; - - vtkMath::Normalize(dir); - - lightDiffuseColor[lightIndex][0] = lightColor[0] * diffuse * lightIntensity; - lightDiffuseColor[lightIndex][1] = lightColor[1] * diffuse * lightIntensity; - lightDiffuseColor[lightIndex][2] = lightColor[2] * diffuse * lightIntensity; - lightDiffuseColor[lightIndex][3] = 1.0; - - lightSpecularColor[lightIndex][0] = lightColor[0] * specular * lightIntensity; - lightSpecularColor[lightIndex][1] = lightColor[1] * specular * lightIntensity; - lightSpecularColor[lightIndex][2] = lightColor[2] * specular * lightIntensity; - lightSpecularColor[lightIndex][3] = 0.0; - - half[0] = dir[0] - viewDirection[0]; - half[1] = dir[1] - viewDirection[1]; - half[2] = dir[2] - viewDirection[2]; - - vtkMath::Normalize(half); - - ambientColor[0] += ambient * lightColor[0]; - ambientColor[1] += ambient * lightColor[1]; - ambientColor[2] += ambient * lightColor[2]; - } - - lightDirection[lightIndex][0] = (dir[0] + 1.0) / 2.0; - lightDirection[lightIndex][1] = (dir[1] + 1.0) / 2.0; - lightDirection[lightIndex][2] = (dir[2] + 1.0) / 2.0; - lightDirection[lightIndex][3] = 0.0; - - halfwayVector[lightIndex][0] = (half[0] + 1.0) / 2.0; - halfwayVector[lightIndex][1] = (half[1] + 1.0) / 2.0; - halfwayVector[lightIndex][2] = (half[2] + 1.0) / 2.0; - halfwayVector[lightIndex][3] = 0.0; - } - - volumeTransform->Delete(); -} - -void vtkMitkOpenGLVolumeTextureMapper3D::SetupProgramLocalsForShadingFP(vtkRenderer *ren, vtkVolume *vol) -{ - // GPU_INFO << "SetupProgramLocalsForShadingFP"; - - GLfloat lightDirection[2][4]; - GLfloat lightDiffuseColor[2][4]; - GLfloat lightSpecularColor[2][4]; - GLfloat halfwayVector[2][4]; - GLfloat ambientColor[4]; - - float ambient = vol->GetProperty()->GetAmbient(); - float diffuse = vol->GetProperty()->GetDiffuse(); - float specular = vol->GetProperty()->GetSpecular(); - float specularPower = vol->GetProperty()->GetSpecularPower(); - - vtkTransform *volumeTransform = vtkTransform::New(); - - volumeTransform->SetMatrix(vol->GetMatrix()); - volumeTransform->Inverse(); - - vtkLightCollection *lights = ren->GetLights(); - lights->InitTraversal(); - - vtkLight *light[2]; - light[0] = lights->GetNextItem(); - light[1] = lights->GetNextItem(); - - int lightIndex = 0; - - double cameraPosition[3]; - double cameraFocalPoint[3]; - - ren->GetActiveCamera()->GetPosition(cameraPosition); - ren->GetActiveCamera()->GetFocalPoint(cameraFocalPoint); - - volumeTransform->TransformPoint(cameraPosition, cameraPosition); - volumeTransform->TransformPoint(cameraFocalPoint, cameraFocalPoint); - - double viewDirection[4]; - - viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; - viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; - viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; - viewDirection[3] = 0.0; - - vtkMath::Normalize(viewDirection); - - ambientColor[0] = 0.0; - ambientColor[1] = 0.0; - ambientColor[2] = 0.0; - ambientColor[3] = 0.0; - - for (lightIndex = 0; lightIndex < 2; lightIndex++) - { - float dir[3] = {0, 0, 0}; - float half[3] = {0, 0, 0}; - - if (light[lightIndex] == nullptr || light[lightIndex]->GetSwitch() == 0) - { - lightDiffuseColor[lightIndex][0] = 0.0; - lightDiffuseColor[lightIndex][1] = 0.0; - lightDiffuseColor[lightIndex][2] = 0.0; - lightDiffuseColor[lightIndex][3] = 0.0; - - lightSpecularColor[lightIndex][0] = 0.0; - lightSpecularColor[lightIndex][1] = 0.0; - lightSpecularColor[lightIndex][2] = 0.0; - lightSpecularColor[lightIndex][3] = 0.0; - } - else - { - float lightIntensity = light[lightIndex]->GetIntensity(); - double lightColor[3]; - - light[lightIndex]->GetDiffuseColor(lightColor); - - double lightPosition[3]; - double lightFocalPoint[3]; - light[lightIndex]->GetTransformedPosition(lightPosition); - light[lightIndex]->GetTransformedFocalPoint(lightFocalPoint); - - volumeTransform->TransformPoint(lightPosition, lightPosition); - volumeTransform->TransformPoint(lightFocalPoint, lightFocalPoint); - - dir[0] = lightPosition[0] - lightFocalPoint[0]; - dir[1] = lightPosition[1] - lightFocalPoint[1]; - dir[2] = lightPosition[2] - lightFocalPoint[2]; - - vtkMath::Normalize(dir); - - lightDiffuseColor[lightIndex][0] = lightColor[0] * diffuse * lightIntensity; - lightDiffuseColor[lightIndex][1] = lightColor[1] * diffuse * lightIntensity; - lightDiffuseColor[lightIndex][2] = lightColor[2] * diffuse * lightIntensity; - lightDiffuseColor[lightIndex][3] = 0.0; - - lightSpecularColor[lightIndex][0] = lightColor[0] * specular * lightIntensity; - lightSpecularColor[lightIndex][1] = lightColor[1] * specular * lightIntensity; - lightSpecularColor[lightIndex][2] = lightColor[2] * specular * lightIntensity; - lightSpecularColor[lightIndex][3] = 0.0; - - half[0] = dir[0] - viewDirection[0]; - half[1] = dir[1] - viewDirection[1]; - half[2] = dir[2] - viewDirection[2]; - - vtkMath::Normalize(half); - - ambientColor[0] += ambient * lightColor[0]; - ambientColor[1] += ambient * lightColor[1]; - ambientColor[2] += ambient * lightColor[2]; - } - - lightDirection[lightIndex][0] = dir[0]; - lightDirection[lightIndex][1] = dir[1]; - lightDirection[lightIndex][2] = dir[2]; - lightDirection[lightIndex][3] = 0.0; - - halfwayVector[lightIndex][0] = half[0]; - halfwayVector[lightIndex][1] = half[1]; - halfwayVector[lightIndex][2] = half[2]; - halfwayVector[lightIndex][3] = 0.0; - } - - volumeTransform->Delete(); - - vtkgl::ProgramLocalParameter4fARB(vtkgl::FRAGMENT_PROGRAM_ARB, - 0, - lightDirection[0][0], - lightDirection[0][1], - lightDirection[0][2], - lightDirection[0][3]); - - vtkgl::ProgramLocalParameter4fARB( - vtkgl::FRAGMENT_PROGRAM_ARB, 1, halfwayVector[0][0], halfwayVector[0][1], halfwayVector[0][2], halfwayVector[0][3]); - - vtkgl::ProgramLocalParameter4fARB(vtkgl::FRAGMENT_PROGRAM_ARB, 2, ambient, diffuse, specular, specularPower); - - vtkgl::ProgramLocalParameter4fARB(vtkgl::FRAGMENT_PROGRAM_ARB, - 3, - lightDiffuseColor[0][0], - lightDiffuseColor[0][1], - lightDiffuseColor[0][2], - lightDiffuseColor[0][3]); - - vtkgl::ProgramLocalParameter4fARB(vtkgl::FRAGMENT_PROGRAM_ARB, - 4, - lightSpecularColor[0][0], - lightSpecularColor[0][1], - lightSpecularColor[0][2], - lightSpecularColor[0][3]); - - vtkgl::ProgramLocalParameter4fARB( - vtkgl::FRAGMENT_PROGRAM_ARB, 5, viewDirection[0], viewDirection[1], viewDirection[2], viewDirection[3]); - - vtkgl::ProgramLocalParameter4fARB(vtkgl::FRAGMENT_PROGRAM_ARB, 6, 2.0, -1.0, 0.0, 0.0); -} - -int vtkMitkOpenGLVolumeTextureMapper3D::IsRenderSupported(vtkRenderer *renderer, vtkVolumeProperty * /*property*/) -{ - // GPU_INFO << "IsRenderSupported"; - - if (!this->Initialized) - { - // this->Initialize(); - this->Initialize(renderer); - } - - if (!this->RenderPossible) - { - MITK_WARN << "vtkMitkOpenGLVolumeTextureMapper3D::IsRenderSupported Rendering not possible"; - return 0; - } - - if (!this->GetInput()) - { - MITK_WARN << "vtkMitkOpenGLVolumeTextureMapper3D::IsRenderSupported No input available"; - return 0; - } - - return 1; -} - -void vtkMitkOpenGLVolumeTextureMapper3D::Initialize(vtkRenderer *renderer) -{ - // GPU_INFO << "Initialize"; - - this->Initialized = 1; - // vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New(); - // extensions->SetRenderWindow(nullptr); // set render window to the current one. - vtkOpenGLExtensionManager *extensions = - static_cast(renderer->GetRenderWindow())->GetExtensionManager(); - - int supports_texture3D = extensions->ExtensionSupported("GL_VERSION_1_2"); - if (supports_texture3D) - { - extensions->LoadExtension("GL_VERSION_1_2"); - } - else - { - supports_texture3D = extensions->ExtensionSupported("GL_EXT_texture3D"); - if (supports_texture3D) - { - extensions->LoadCorePromotedExtension("GL_EXT_texture3D"); - } - } - - int supports_multitexture = extensions->ExtensionSupported("GL_VERSION_1_3"); - if (supports_multitexture) - { - extensions->LoadExtension("GL_VERSION_1_3"); - } - else - { - supports_multitexture = extensions->ExtensionSupported("GL_ARB_multitexture"); - if (supports_multitexture) - { - extensions->LoadCorePromotedExtension("GL_ARB_multitexture"); - } - } - - this->SupportsCompressedTexture = extensions->ExtensionSupported("GL_VERSION_1_3") == 1; - if (!this->SupportsCompressedTexture) - { - this->SupportsCompressedTexture = extensions->ExtensionSupported("GL_ARB_texture_compression") == 1; - if (this->SupportsCompressedTexture) - { - extensions->LoadCorePromotedExtension("GL_ARB_texture_compression"); - } - } - // GPU_INFO(this->SupportsCompressedTexture) << "supporting compressed textures"; - - this->SupportsNonPowerOfTwoTextures = extensions->ExtensionSupported("GL_VERSION_2_0") || - extensions->ExtensionSupported("GL_ARB_texture_non_power_of_two"); - - // GPU_INFO << "np2: " << (this->SupportsNonPowerOfTwoTextures?1:0); - - int supports_GL_ARB_fragment_program = extensions->ExtensionSupported("GL_ARB_fragment_program"); - if (supports_GL_ARB_fragment_program) - { - extensions->LoadExtension("GL_ARB_fragment_program"); - } - - int supports_GL_ARB_vertex_program = extensions->ExtensionSupported("GL_ARB_vertex_program"); - if (supports_GL_ARB_vertex_program) - { - extensions->LoadExtension("GL_ARB_vertex_program"); - } - - RenderPossible = 0; - - if (supports_texture3D && supports_multitexture && supports_GL_ARB_fragment_program && - supports_GL_ARB_vertex_program && vtkgl::TexImage3D && vtkgl::ActiveTexture && vtkgl::MultiTexCoord3fv && - vtkgl::GenProgramsARB && vtkgl::DeleteProgramsARB && vtkgl::BindProgramARB && vtkgl::ProgramStringARB && - vtkgl::ProgramLocalParameter4fARB) - { - RenderPossible = 1; - } - else - { - std::string errString = - "no gpu-acceleration possible cause following extensions/methods are missing or unsupported:"; - if (!supports_texture3D) - errString += " EXT_TEXTURE3D"; - if (!supports_multitexture) - errString += " EXT_MULTITEXTURE"; - if (!supports_GL_ARB_fragment_program) - errString += " ARB_FRAGMENT_PROGRAM"; - if (!supports_GL_ARB_vertex_program) - errString += " ARB_VERTEX_PROGRAM"; - if (!vtkgl::TexImage3D) - errString += " glTexImage3D"; - if (!vtkgl::ActiveTexture) - errString += " glActiveTexture"; - if (!vtkgl::MultiTexCoord3fv) - errString += " glMultiTexCoord3fv"; - if (!vtkgl::GenProgramsARB) - errString += " glGenProgramsARB"; - if (!vtkgl::DeleteProgramsARB) - errString += " glDeleteProgramsARB"; - if (!vtkgl::BindProgramARB) - errString += " glBindProgramARB"; - if (!vtkgl::ProgramStringARB) - errString += " glProgramStringARB"; - if (!vtkgl::ProgramLocalParameter4fARB) - errString += " glProgramLocalParameter4fARB"; - GPU_WARN << errString; - }; - - if (RenderPossible) - { - vtkgl::GenProgramsARB(1, &prgOneComponentShade); - vtkgl::BindProgramARB(vtkgl::FRAGMENT_PROGRAM_ARB, prgOneComponentShade); - vtkgl::ProgramStringARB(vtkgl::FRAGMENT_PROGRAM_ARB, - vtkgl::PROGRAM_FORMAT_ASCII_ARB, - static_cast(strlen(vtkMitkVolumeTextureMapper3D_OneComponentShadeFP)), - vtkMitkVolumeTextureMapper3D_OneComponentShadeFP); - - vtkgl::GenProgramsARB(1, &prgRGBAShade); - vtkgl::BindProgramARB(vtkgl::FRAGMENT_PROGRAM_ARB, prgRGBAShade); - vtkgl::ProgramStringARB(vtkgl::FRAGMENT_PROGRAM_ARB, - vtkgl::PROGRAM_FORMAT_ASCII_ARB, - static_cast(strlen(vtkMitkVolumeTextureMapper3D_FourDependentShadeFP)), - vtkMitkVolumeTextureMapper3D_FourDependentShadeFP); - } -} - -// ---------------------------------------------------------------------------- -// Print the vtkMitkOpenGLVolumeTextureMapper3D -void vtkMitkOpenGLVolumeTextureMapper3D::PrintSelf(ostream &os, vtkIndent indent) -{ - // vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New(); - // extensions->SetRenderWindow(nullptr); // set render window to current render window - - os << indent << "Initialized " << this->Initialized << endl; - /* if ( this->Initialized ) - { - os << indent << "Supports GL_VERSION_1_2:" - << extensions->ExtensionSupported( "GL_VERSION_1_2" ) << endl; - os << indent << "Supports GL_EXT_texture3D:" - << extensions->ExtensionSupported( "GL_EXT_texture3D" ) << endl; - os << indent << "Supports GL_VERSION_1_3:" - << extensions->ExtensionSupported( "GL_VERSION_1_3" ) << endl; - os << indent << "Supports GL_ARB_multitexture: " - << extensions->ExtensionSupported( "GL_ARB_multitexture" ) << endl; - os << indent << "Supports GL_NV_texture_shader2: " - << extensions->ExtensionSupported( "GL_NV_texture_shader2" ) << endl; - os << indent << "Supports GL_NV_register_combiners2: " - << extensions->ExtensionSupported( "GL_NV_register_combiners2" ) - << endl; - os << indent << "Supports GL_ATI_fragment_shader: " - << extensions->ExtensionSupported( "GL_ATI_fragment_shader" ) << endl; - os << indent << "Supports GL_ARB_fragment_program: " - << extensions->ExtensionSupported( "GL_ARB_fragment_program" ) << endl; - os << indent << "Supports GL_ARB_texture_compression: " - << extensions->ExtensionSupported( "GL_ARB_texture_compression" ) - << endl; - os << indent << "Supports GL_VERSION_2_0:" - << extensions->ExtensionSupported( "GL_VERSION_2_0" ) - << endl; - os << indent << "Supports GL_ARB_texture_non_power_of_two:" - << extensions->ExtensionSupported( "GL_ARB_texture_non_power_of_two" ) - << endl; - } - extensions->Delete(); - */ - - if (this->RenderWindow != 0) - { - vtkOpenGLExtensionManager *extensions = - static_cast(this->RenderWindow)->GetExtensionManager(); - - if (this->Initialized) - { - os << indent << "Supports GL_VERSION_1_2:" << extensions->ExtensionSupported("GL_VERSION_1_2") << endl; - os << indent << "Supports GL_EXT_texture3D:" << extensions->ExtensionSupported("GL_EXT_texture3D") << endl; - os << indent << "Supports GL_VERSION_1_3:" << extensions->ExtensionSupported("GL_VERSION_1_3") << endl; - os << indent << "Supports GL_ARB_multitexture: " << extensions->ExtensionSupported("GL_ARB_multitexture") << endl; - os << indent << "Supports GL_NV_texture_shader2: " << extensions->ExtensionSupported("GL_NV_texture_shader2") - << endl; - os << indent - << "Supports GL_NV_register_combiners2: " << extensions->ExtensionSupported("GL_NV_register_combiners2") - << endl; - os << indent << "Supports GL_ATI_fragment_shader: " << extensions->ExtensionSupported("GL_ATI_fragment_shader") - << endl; - os << indent << "Supports GL_ARB_fragment_program: " << extensions->ExtensionSupported("GL_ARB_fragment_program") - << endl; - os << indent - << "Supports GL_ARB_texture_compression: " << extensions->ExtensionSupported("GL_ARB_texture_compression") - << endl; - os << indent << "Supports GL_VERSION_2_0:" << extensions->ExtensionSupported("GL_VERSION_2_0") << endl; - os << indent << "Supports GL_ARB_texture_non_power_of_two:" - << extensions->ExtensionSupported("GL_ARB_texture_non_power_of_two") << endl; - } - } - - this->Superclass::PrintSelf(os, indent); -} diff --git a/Modules/MapperExt/src/vtkMitkVolumeTextureMapper3D.cpp b/Modules/MapperExt/src/vtkMitkVolumeTextureMapper3D.cpp deleted file mode 100644 index dc9e6b306a..0000000000 --- a/Modules/MapperExt/src/vtkMitkVolumeTextureMapper3D.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "vtkMitkVolumeTextureMapper3D.h" -#include "mitkCommon.h" - -#define GPU_INFO MITK_INFO("mapper.vr") -#define GPU_WARN MITK_WARN("mapper.vr") - -#include "vtkCamera.h" -#include "vtkColorTransferFunction.h" -#include "vtkDataArray.h" -#include "vtkImageData.h" -#include "vtkMath.h" -#include "vtkMatrix4x4.h" -#include "vtkPiecewiseFunction.h" -#include "vtkPointData.h" -#include "vtkRenderer.h" -#include "vtkVolume.h" -#include "vtkVolumeProperty.h" -//#include "vtkVolumeRenderingFactory.h" //VTK6_TODO - -//---------------------------------------------------------------------------- -// Needed when we don't use the vtkStandardNewMacro. -vtkInstantiatorNewMacro(vtkMitkVolumeTextureMapper3D); -//---------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -vtkMitkVolumeTextureMapper3D::vtkMitkVolumeTextureMapper3D() -{ - // GPU_INFO << "vtkMitkVolumeTextureMapper3D"; - - this->PolygonBuffer = nullptr; - this->IntersectionBuffer = nullptr; - this->NumberOfPolygons = 0; - this->BufferSize = 0; - - // The input used when creating the textures - this->SavedTextureInput = nullptr; - - // The input used when creating the color tables - this->SavedParametersInput = nullptr; - - this->SavedRGBFunction = nullptr; - this->SavedGrayFunction = nullptr; - this->SavedScalarOpacityFunction = nullptr; - this->SavedGradientOpacityFunction = nullptr; - this->SavedColorChannels = 0; - this->SavedSampleDistance = 0; - this->SavedScalarOpacityDistance = 0; - - /* - this->Volume1 = nullptr; - this->Volume2 = nullptr; - this->Volume3 = nullptr; - */ - /* - this->VolumeSize = 0; - this->VolumeComponents = 0; - */ - - this->VolumeSpacing[0] = this->VolumeSpacing[1] = this->VolumeSpacing[2] = 0; - this->VolumeDimensions[0] = 0; - this->VolumeDimensions[1] = 0; - this->VolumeDimensions[2] = 0; - - this->SampleDistance = 1.0; - this->ActualSampleDistance = 1.0; - - this->UseCompressedTexture = false; - this->SupportsNonPowerOfTwoTextures = false; - - // GPU_INFO << "np2: " << (this->SupportsNonPowerOfTwoTextures?1:0); -} - -//----------------------------------------------------------------------------- -vtkMitkVolumeTextureMapper3D::~vtkMitkVolumeTextureMapper3D() -{ - // GPU_INFO << "~vtkMitkVolumeTextureMapper3D"; - - delete[] this->PolygonBuffer; - delete[] this->IntersectionBuffer; - /* - delete [] this->Volume1; - delete [] this->Volume2; - delete [] this->Volume3; - */ -} - -//----------------------------------------------------------------------------- -// vtkMitkVolumeTextureMapper3D *vtkMitkVolumeTextureMapper3D::New() //VTK6_TODO -//{ -// //GPU_INFO << "New"; - -// // First try to create the object from the vtkObjectFactory -// vtkObject* ret = -// vtkVolumeRenderingFactory::CreateInstance("vtkMitkVolumeTextureMapper3D"); -// return static_cast(ret); -//} - -//----------------------------------------------------------------------------- -void vtkMitkVolumeTextureMapper3D::ComputePolygons(vtkRenderer *ren, vtkVolume *vol, double inBounds[6]) -{ - // GPU_INFO << "ComputePolygons"; - - // Get the camera position and focal point - double focalPoint[4], position[4]; - double plane[4]; - vtkCamera *camera = ren->GetActiveCamera(); - - camera->GetPosition(position); - camera->GetFocalPoint(focalPoint); - - position[3] = 1.0; - focalPoint[3] = 1.0; - - // Pass the focal point and position through the inverse of the - // volume's matrix to map back into the data coordinates. We - // are going to compute these polygons in the coordinate system - // of the input data - this is easiest since this data must be - // axis aligned. Then we'll use OpenGL to transform these polygons - // into the world coordinate system through the use of the - // volume's matrix. - vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); - vol->GetMatrix(matrix); - matrix->Invert(); - matrix->MultiplyPoint(position, position); - matrix->MultiplyPoint(focalPoint, focalPoint); - matrix->Delete(); - - if (position[3]) - { - position[0] /= position[3]; - position[1] /= position[3]; - position[2] /= position[3]; - } - - if (focalPoint[3]) - { - focalPoint[0] /= focalPoint[3]; - focalPoint[1] /= focalPoint[3]; - focalPoint[2] /= focalPoint[3]; - } - - // Create a plane equation using the direction and position of the camera - plane[0] = focalPoint[0] - position[0]; - plane[1] = focalPoint[1] - position[1]; - plane[2] = focalPoint[2] - position[2]; - - vtkMath::Normalize(plane); - - plane[3] = -(plane[0] * position[0] + plane[1] * position[1] + plane[2] * position[2]); - - // Find the min and max distances of the boundary points of the volume - double minDistance = VTK_DOUBLE_MAX; - double maxDistance = VTK_DOUBLE_MIN; - - // The inBounds parameter is the bounds we are using for clipping the - // texture planes against. First we need to clip these against the bounds - // of the volume to make sure they don't exceed it. - double volBounds[6]; - this->GetInput()->GetBounds(volBounds); - - double bounds[6]; - bounds[0] = (inBounds[0] > volBounds[0]) ? (inBounds[0]) : (volBounds[0]); - bounds[1] = (inBounds[1] < volBounds[1]) ? (inBounds[1]) : (volBounds[1]); - bounds[2] = (inBounds[2] > volBounds[2]) ? (inBounds[2]) : (volBounds[2]); - bounds[3] = (inBounds[3] < volBounds[3]) ? (inBounds[3]) : (volBounds[3]); - bounds[4] = (inBounds[4] > volBounds[4]) ? (inBounds[4]) : (volBounds[4]); - bounds[5] = (inBounds[5] < volBounds[5]) ? (inBounds[5]) : (volBounds[5]); - - // Create 8 vertices for the bounding box we are rendering - int i, j, k; - double vertices[8][3]; - - int idx = 0; - - for (k = 0; k < 2; k++) - { - for (j = 0; j < 2; j++) - { - for (i = 0; i < 2; i++) - { - vertices[idx][2] = bounds[4 + k]; - vertices[idx][1] = bounds[2 + j]; - vertices[idx][0] = bounds[i]; - - double d = plane[0] * vertices[idx][0] + plane[1] * vertices[idx][1] + plane[2] * vertices[idx][2] + plane[3]; - - idx++; - - // Keep track of closest and farthest point - minDistance = (d < minDistance) ? (d) : (minDistance); - maxDistance = (d > maxDistance) ? (d) : (maxDistance); - } - } - } - - int dim[6]; - this->GetVolumeDimensions(dim); - - float tCoordOffset[3], tCoordScale[3]; - - tCoordOffset[0] = 0.5 / dim[0]; - tCoordOffset[1] = 0.5 / dim[1]; - tCoordOffset[2] = 0.5 / dim[2]; - - tCoordScale[0] = (dim[0] - 1) / static_cast(dim[0]); - tCoordScale[1] = (dim[1] - 1) / static_cast(dim[1]); - tCoordScale[2] = (dim[2] - 1) / static_cast(dim[2]); - - float spacing[3]; - this->GetVolumeSpacing(spacing); - - double offset = 0.333 * 0.5 * (spacing[0] + spacing[1] + spacing[2]); - - minDistance += 0.1 * offset; - maxDistance -= 0.1 * offset; - - minDistance = (minDistance < offset) ? (offset) : (minDistance); - - double stepSize = this->ActualSampleDistance; - - // Determine the number of polygons - int numPolys = static_cast((maxDistance - minDistance) / static_cast(stepSize)); - - // Check if we have space, free old space only if it is too small - if (this->BufferSize < numPolys) - { - delete[] this->PolygonBuffer; - delete[] this->IntersectionBuffer; - - this->BufferSize = numPolys; - - this->PolygonBuffer = new float[36 * this->BufferSize]; - this->IntersectionBuffer = new float[12 * this->BufferSize]; - } - - this->NumberOfPolygons = numPolys; - - // Compute the intersection points for each edge of the volume - int lines[12][2] = {{0, 1}, {1, 3}, {2, 3}, {0, 2}, {4, 5}, {5, 7}, {6, 7}, {4, 6}, {0, 4}, {1, 5}, {3, 7}, {2, 6}}; - - float *iptr, *pptr; - - for (i = 0; i < 12; i++) - { - double line[3]; - - line[0] = vertices[lines[i][1]][0] - vertices[lines[i][0]][0]; - line[1] = vertices[lines[i][1]][1] - vertices[lines[i][0]][1]; - line[2] = vertices[lines[i][1]][2] - vertices[lines[i][0]][2]; - - double d = maxDistance; - - iptr = this->IntersectionBuffer + i; - - double planeDotLineOrigin = vtkMath::Dot(plane, vertices[lines[i][0]]); - double planeDotLine = vtkMath::Dot(plane, line); - - double t, increment; - - if (planeDotLine != 0.0) - { - t = (d - planeDotLineOrigin - plane[3]) / planeDotLine; - increment = -stepSize / planeDotLine; - } - else - { - t = -1.0; - increment = 0.0; - } - - for (j = 0; j < numPolys; j++) - { - *iptr = (t > 0.0 && t < 1.0) ? (t) : (-1.0); - - t += increment; - iptr += 12; - } - } - - // Compute the polygons by determining which edges were intersected - int neighborLines[12][6] = {{1, 2, 3, 4, 8, 9}, - {0, 2, 3, 5, 9, 10}, - {0, 1, 3, 6, 10, 11}, - {0, 1, 2, 7, 8, 11}, - {0, 5, 6, 7, 8, 9}, - {1, 4, 6, 7, 9, 10}, - {2, 4, 5, 7, 10, 11}, - {3, 4, 5, 6, 8, 11}, - {0, 3, 4, 7, 9, 11}, - {0, 1, 4, 5, 8, 10}, - {1, 2, 5, 6, 9, 11}, - {2, 3, 6, 7, 8, 10}}; - - float tCoord[12][4] = {{0, 0, 0, 0}, - {1, 0, 0, 1}, - {0, 1, 0, 0}, - {0, 0, 0, 1}, - {0, 0, 1, 0}, - {1, 0, 1, 1}, - {0, 1, 1, 0}, - {0, 0, 1, 1}, - {0, 0, 0, 2}, - {1, 0, 0, 2}, - {1, 1, 0, 2}, - {0, 1, 0, 2}}; - - double low[3]; - double high[3]; - - low[0] = (bounds[0] - volBounds[0]) / (volBounds[1] - volBounds[0]); - high[0] = (bounds[1] - volBounds[0]) / (volBounds[1] - volBounds[0]); - low[1] = (bounds[2] - volBounds[2]) / (volBounds[3] - volBounds[2]); - high[1] = (bounds[3] - volBounds[2]) / (volBounds[3] - volBounds[2]); - low[2] = (bounds[4] - volBounds[4]) / (volBounds[5] - volBounds[4]); - high[2] = (bounds[5] - volBounds[4]) / (volBounds[5] - volBounds[4]); - - for (i = 0; i < 12; i++) - { - tCoord[i][0] = (tCoord[i][0]) ? (high[0]) : (low[0]); - tCoord[i][1] = (tCoord[i][1]) ? (high[1]) : (low[1]); - tCoord[i][2] = (tCoord[i][2]) ? (high[2]) : (low[2]); - } - - iptr = this->IntersectionBuffer; - pptr = this->PolygonBuffer; - - for (i = 0; i < numPolys; i++) - { - // Look for a starting point - int start = 0; - - while (start < 12 && iptr[start] == -1.0) - { - start++; - } - - if (start == 12) - { - pptr[0] = -1.0; - } - else - { - int current = start; - int previous = -1; - int errFlag = 0; - - idx = 0; - - while (idx < 6 && !errFlag && (idx == 0 || current != start)) - { - double t = iptr[current]; - - *(pptr + idx * 6) = tCoord[current][0] * tCoordScale[0] + tCoordOffset[0]; - *(pptr + idx * 6 + 1) = tCoord[current][1] * tCoordScale[1] + tCoordOffset[1]; - *(pptr + idx * 6 + 2) = tCoord[current][2] * tCoordScale[2] + tCoordOffset[2]; - - int coord = static_cast(tCoord[current][3]); - *(pptr + idx * 6 + coord) = - (low[coord] + t * (high[coord] - low[coord])) * tCoordScale[coord] + tCoordOffset[coord]; - - *(pptr + idx * 6 + 3) = static_cast( - vertices[lines[current][0]][0] + t * (vertices[lines[current][1]][0] - vertices[lines[current][0]][0])); - - *(pptr + idx * 6 + 4) = static_cast( - vertices[lines[current][0]][1] + t * (vertices[lines[current][1]][1] - vertices[lines[current][0]][1])); - - *(pptr + idx * 6 + 5) = static_cast( - vertices[lines[current][0]][2] + t * (vertices[lines[current][1]][2] - vertices[lines[current][0]][2])); - - idx++; - - j = 0; - - while (j < 6 && (*(this->IntersectionBuffer + i * 12 + neighborLines[current][j]) < 0 || - neighborLines[current][j] == previous)) - { - j++; - } - - if (j >= 6) - { - errFlag = 1; - } - else - { - previous = current; - current = neighborLines[current][j]; - } - } - - if (idx < 6) - { - *(pptr + idx * 6) = -1; - } - } - - iptr += 12; - pptr += 36; - } -} - -void vtkMitkVolumeTextureMapper3D::UpdateMTime() -{ - this->SavedTextureMTime.Modified(); -} - -//----------------------------------------------------------------------------- -int vtkMitkVolumeTextureMapper3D::UpdateColorLookup(vtkVolume *vol) -{ - // GPU_INFO << "UpdateColorLookup"; - - int needToUpdate = 0; - - // Get the image data - vtkImageData *input = this->GetInput(); - Update(); - - // Has the volume changed in some way? - if (this->SavedParametersInput != input || this->SavedParametersMTime.GetMTime() < input->GetMTime()) - { - needToUpdate = 1; - } - - // What sample distance are we going to use for rendering? If we - // have to render quickly according to our allocated render time, - // don't necessary obey the sample distance requested by the user. - // Instead set the sample distance to the average spacing. - this->ActualSampleDistance = this->SampleDistance; - if (vol->GetAllocatedRenderTime() < 1.0) - { - float spacing[3]; - this->GetVolumeSpacing(spacing); - this->ActualSampleDistance = - 0.333 * (static_cast(spacing[0]) + static_cast(spacing[1]) + static_cast(spacing[2])); - } - - // How many components? - int components = input->GetNumberOfScalarComponents(); - - // Has the sample distance changed? - if (this->SavedSampleDistance != this->ActualSampleDistance) - { - needToUpdate = 1; - } - - vtkColorTransferFunction *rgbFunc = nullptr; - vtkPiecewiseFunction *grayFunc = nullptr; - - // How many color channels for this component? - int colorChannels = vol->GetProperty()->GetColorChannels(0); - - if (components < 3) - { - // Has the number of color channels changed? - if (this->SavedColorChannels != colorChannels) - { - needToUpdate = 1; - } - - // Has the color transfer function changed in some way, - // and we are using it? - if (colorChannels == 3) - { - rgbFunc = vol->GetProperty()->GetRGBTransferFunction(0); - if (this->SavedRGBFunction != rgbFunc || this->SavedParametersMTime.GetMTime() < rgbFunc->GetMTime()) - { - needToUpdate = 1; - } - } - - // Has the gray transfer function changed in some way, - // and we are using it? - if (colorChannels == 1) - { - grayFunc = vol->GetProperty()->GetGrayTransferFunction(0); - if (this->SavedGrayFunction != grayFunc || this->SavedParametersMTime.GetMTime() < grayFunc->GetMTime()) - { - needToUpdate = 1; - } - } - } - - // Has the scalar opacity transfer function changed in some way? - vtkPiecewiseFunction *scalarOpacityFunc = vol->GetProperty()->GetScalarOpacity(0); - if (this->SavedScalarOpacityFunction != scalarOpacityFunc || - this->SavedParametersMTime.GetMTime() < scalarOpacityFunc->GetMTime()) - { - needToUpdate = 1; - } - - // Has the gradient opacity transfer function changed in some way? - vtkPiecewiseFunction *gradientOpacityFunc = vol->GetProperty()->GetGradientOpacity(0); - if (this->SavedGradientOpacityFunction != gradientOpacityFunc || - this->SavedParametersMTime.GetMTime() < gradientOpacityFunc->GetMTime()) - { - needToUpdate = 1; - } - - double scalarOpacityDistance = vol->GetProperty()->GetScalarOpacityUnitDistance(0); - if (this->SavedScalarOpacityDistance != scalarOpacityDistance) - { - needToUpdate = 1; - } - - // If we have not found any need to update, return now - if (!needToUpdate) - { - return 0; - } - - this->SavedRGBFunction = rgbFunc; - this->SavedGrayFunction = grayFunc; - this->SavedScalarOpacityFunction = scalarOpacityFunc; - this->SavedGradientOpacityFunction = gradientOpacityFunc; - this->SavedColorChannels = colorChannels; - this->SavedSampleDistance = this->ActualSampleDistance; - this->SavedScalarOpacityDistance = scalarOpacityDistance; - this->SavedParametersInput = input; - - this->SavedParametersMTime.Modified(); - - // Find the scalar range - double scalarRange[2]; - input->GetPointData()->GetScalars()->GetRange(scalarRange, components - 1); - - int arraySizeNeeded = this->ColorTableSize; - - if (components < 3) - { - // Sample the transfer functions between the min and max. - if (colorChannels == 1) - { - grayFunc->GetTable(scalarRange[0], scalarRange[1], arraySizeNeeded, this->TempArray1); - } - else - { - rgbFunc->GetTable(scalarRange[0], scalarRange[1], arraySizeNeeded, this->TempArray1); - } - } - - scalarOpacityFunc->GetTable(scalarRange[0], scalarRange[1], arraySizeNeeded, this->TempArray2); - - float goArray[256]; - gradientOpacityFunc->GetTable(0, (scalarRange[1] - scalarRange[0]) * 0.25, 256, goArray); - - // Correct the opacity array for the spacing between the planes. - int i; - - float *fptr2 = this->TempArray2; - double factor = this->ActualSampleDistance / scalarOpacityDistance; - for (i = 0; i < arraySizeNeeded; i++) - { - if (*fptr2 > 0.0001) - { - *fptr2 = 1.0 - pow(static_cast(1.0 - (*fptr2)), factor); - } - fptr2++; - } - - int goLoop; - unsigned char *ptr, *rgbptr, *aptr; - float *fptr1; - - switch (components) - { - case 1: - // Move the two temp float arrays into one RGBA unsigned char array - ptr = this->ColorLookup; - for (goLoop = 0; goLoop < 256; goLoop++) - { - fptr1 = this->TempArray1; - fptr2 = this->TempArray2; - if (colorChannels == 1) - { - for (i = 0; i < arraySizeNeeded; i++) - { - *(ptr++) = static_cast(*(fptr1)*255.0 + 0.5); - *(ptr++) = static_cast(*(fptr1)*255.0 + 0.5); - *(ptr++) = static_cast(*(fptr1++) * 255.0 + 0.5); - *(ptr++) = static_cast(*(fptr2++) * goArray[goLoop] * 255.0 + 0.5); - } - } - else - { - for (i = 0; i < arraySizeNeeded; i++) - { - *(ptr++) = static_cast(*(fptr1++) * 255.0 + 0.5); - *(ptr++) = static_cast(*(fptr1++) * 255.0 + 0.5); - *(ptr++) = static_cast(*(fptr1++) * 255.0 + 0.5); - *(ptr++) = static_cast(*(fptr2++) * goArray[goLoop] * 255.0 + 0.5); - } - } - - for (; i < 256; i++) - { - *(ptr++) = 0; - *(ptr++) = 0; - *(ptr++) = 0; - *(ptr++) = 0; - } - } - break; - - case 2: - // Move the two temp float arrays into one RGB unsigned char array and - // one alpha array. - rgbptr = this->ColorLookup; - aptr = this->AlphaLookup; - - if (colorChannels == 1) - { - for (i = 0; i < arraySizeNeeded; i++) - { - fptr1 = this->TempArray1; - fptr2 = this->TempArray2; - for (goLoop = 0; goLoop < 256; goLoop++) - { - *(rgbptr++) = static_cast(*(fptr1)*255.0 + 0.5); - *(rgbptr++) = static_cast(*(fptr1)*255.0 + 0.5); - *(rgbptr++) = static_cast(*(fptr1++) * 255.0 + 0.5); - *(aptr++) = static_cast(*(fptr2++) * goArray[goLoop] * 255.0 + 0.5); - } - } - } - else - { - fptr1 = this->TempArray1; - fptr2 = this->TempArray2; - for (i = 0; i < arraySizeNeeded; i++) - { - for (goLoop = 0; goLoop < 256; goLoop++) - { - *(rgbptr++) = static_cast(*(fptr1)*255.0 + 0.5); - *(rgbptr++) = static_cast(*(fptr1 + 1) * 255.0 + 0.5); - *(rgbptr++) = static_cast(*(fptr1 + 2) * 255.0 + 0.5); - *(aptr++) = static_cast(*(fptr2)*goArray[goLoop] * 255.0 + 0.5); - } - fptr1 += 3; - fptr2++; - } - } - - for (; i < 256; i++) - { - for (goLoop = 0; goLoop < 256; goLoop++) - { - *(rgbptr++) = 0; - *(rgbptr++) = 0; - *(rgbptr++) = 0; - *(aptr++) = 0; - } - } - break; - - case 3: - case 4: - // Move the two temp float arrays into one alpha array - aptr = this->AlphaLookup; - - for (goLoop = 0; goLoop < 256; goLoop++) - { - fptr2 = this->TempArray2; - for (i = 0; i < arraySizeNeeded; i++) - { - *(aptr++) = static_cast(*(fptr2++) * goArray[goLoop] * 255.0 + 0.5); - } - for (; i < 256; i++) - { - *(aptr++) = 0; - } - } - - break; - } - return 1; -} - -//----------------------------------------------------------------------------- -// Print the vtkMitkVolumeTextureMapper3D -void vtkMitkVolumeTextureMapper3D::PrintSelf(ostream &os, vtkIndent indent) -{ - this->Superclass::PrintSelf(os, indent); - - os << indent << "Sample Distance: " << this->SampleDistance << endl; - os << indent << "NumberOfPolygons: " << this->NumberOfPolygons << endl; - os << indent << "ActualSampleDistance: " << this->ActualSampleDistance << endl; - os << indent << "VolumeDimensions: " << this->VolumeDimensions[0] << " " << this->VolumeDimensions[1] << " " - << this->VolumeDimensions[2] << endl; - os << indent << "VolumeSpacing: " << this->VolumeSpacing[0] << " " << this->VolumeSpacing[1] << " " - << this->VolumeSpacing[2] << endl; - - os << indent << "UseCompressedTexture: " << this->UseCompressedTexture << endl; -} diff --git a/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp b/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp index 700de1d768..ff01f7bc91 100644 --- a/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp @@ -1,70 +1,68 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkEnumerationSubclassesSerializer_h_included #define mitkEnumerationSubclassesSerializer_h_included #include "mitkEnumerationPropertySerializer.h" #include "mitkModalityProperty.h" #include "mitkPlaneOrientationProperty.h" #include "mitkPointSetShapeProperty.h" #include "mitkRenderingModeProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkRepresentationProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkVtkScalarModeProperty.h" -#include "mitkVtkVolumeRenderingProperty.h" #include #define MITK_REGISTER_ENUM_SUB_SERIALIZER(classname) \ \ namespace mitk \ { \ class classname##Serializer : public EnumerationPropertySerializer \ { \ public: \ mitkClassMacro(classname##Serializer, EnumerationPropertySerializer) \ itkFactorylessNewMacro(Self) \ itkCloneMacro(Self) \ \ virtual BaseProperty::Pointer Deserialize(const tinyxml2::XMLElement *element) override \ { \ if (nullptr == element) \ return nullptr; \ \ classname::Pointer property = classname::New(); \ property->SetValue(element->Attribute("value")); \ \ return property.GetPointer(); \ } \ \ protected: \ classname##Serializer() {} \ virtual ~classname##Serializer() {} \ }; \ } \ \ MITK_REGISTER_SERIALIZER(classname##Serializer); MITK_REGISTER_ENUM_SUB_SERIALIZER(PlaneOrientationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkInterpolationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkRepresentationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkResliceInterpolationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkScalarModeProperty); -MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkVolumeRenderingProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(ModalityProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(RenderingModeProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(PointSetShapeProperty); #endif diff --git a/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp b/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp index df7caa32f5..67dd422e65 100644 --- a/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp +++ b/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp @@ -1,202 +1,200 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkTestingMacros.h" #include "mitkCoreObjectFactory.h" #include "mitkBaseProperty.h" #include "mitkProperties.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include "mitkBasePropertySerializer.h" #include "mitkPropertyList.h" #include "mitkPropertyListSerializer.h" #include #include #include #include #include void TestAllProperties(const mitk::PropertyList *propList); /**Documentation * \brief Test for all PropertySerializer classes. * */ int mitkPropertySerializationTest(int /* argc */, char * /*argv*/ []) { MITK_TEST_BEGIN("PropertySerializationTest"); mitk::PropertyListSerializer::Pointer serializer = mitk::PropertyListSerializer::New(); // make sure something from the lib is actually used (registration of // serializers) /* build list of properties that will be serialized and deserialized */ mitk::PropertyList::Pointer propList = mitk::PropertyList::New(); propList->SetProperty("booltrue", mitk::BoolProperty::New(true)); propList->SetProperty("boolfalse", mitk::BoolProperty::New(false)); propList->SetProperty("int", mitk::IntProperty::New(-32)); propList->SetProperty("float", mitk::FloatProperty::New(-31.337)); propList->SetProperty("double", mitk::DoubleProperty::New(-31.337)); propList->SetProperty("string", mitk::StringProperty::New("Hello MITK")); mitk::Point3D p3d; mitk::FillVector3D(p3d, 1.0, 2.2, -3.3); propList->SetProperty("p3d", mitk::Point3dProperty::New(p3d)); mitk::Point3I p3i; mitk::FillVector3D(p3i, 1, 2, -3); propList->SetProperty("p3i", mitk::Point3iProperty::New(p3i)); mitk::Point4D p4d; mitk::FillVector4D(p4d, 1.5, 2.6, -3.7, 4.44); propList->SetProperty("p4d", mitk::Point4dProperty::New(p4d)); mitk::Vector3D v3d; mitk::FillVector3D(v3d, 1.0, 2.2, -3.3); propList->SetProperty("v3d", mitk::Vector3DProperty::New(v3d)); propList->SetProperty("annotation", mitk::AnnotationProperty::New("My Annotation", p3d)); propList->SetProperty("clipping", mitk::ClippingProperty::New(p3d, v3d)); propList->SetProperty("color", mitk::ColorProperty::New(1.0, 0.2, 0.2)); propList->SetProperty("modality", mitk::ModalityProperty::New("Color Doppler")); propList->SetProperty("PlaneOrientationProperty", mitk::PlaneOrientationProperty::New("Arrows in positive direction")); propList->SetProperty("VtkInterpolationProperty", mitk::VtkInterpolationProperty::New("Gouraud")); propList->SetProperty("VtkRepresentationProperty", mitk::VtkRepresentationProperty::New("Surface")); propList->SetProperty("VtkResliceInterpolationProperty", mitk::VtkResliceInterpolationProperty::New("Cubic")); propList->SetProperty("VtkScalarModeProperty", mitk::VtkScalarModeProperty::New("PointFieldData")); - propList->SetProperty("VtkVolumeRenderingProperty", mitk::VtkVolumeRenderingProperty::New("COMPOSITE")); mitk::BoolLookupTable blt; blt.SetTableValue(0, true); blt.SetTableValue(1, false); blt.SetTableValue(2, true); propList->SetProperty("BoolLookupTableProperty", mitk::BoolLookupTableProperty::New(blt)); mitk::FloatLookupTable flt; flt.SetTableValue(0, 3.1); flt.SetTableValue(1, 3.3); flt.SetTableValue(2, 7.0); propList->SetProperty("FloatLookupTableProperty", mitk::FloatLookupTableProperty::New(flt)); mitk::IntLookupTable ilt; ilt.SetTableValue(0, 3); ilt.SetTableValue(1, 2); ilt.SetTableValue(2, 11); propList->SetProperty("IntLookupTableProperty", mitk::IntLookupTableProperty::New(ilt)); mitk::StringLookupTable slt; slt.SetTableValue(0, "Hello"); slt.SetTableValue(1, "MITK"); slt.SetTableValue(2, "world"); propList->SetProperty("StringLookupTableProperty", mitk::StringLookupTableProperty::New(slt)); propList->SetProperty("GroupTagProperty", mitk::GroupTagProperty::New()); propList->SetProperty("LevelWindowProperty", mitk::LevelWindowProperty::New(mitk::LevelWindow(100.0, 50.0))); mitk::LookupTable::Pointer lt = mitk::LookupTable::New(); lt->ChangeOpacityForAll(0.25); lt->ChangeOpacity(17, 0.88); propList->SetProperty("LookupTableProperty", mitk::LookupTableProperty::New(lt)); propList->SetProperty("StringProperty", mitk::StringProperty::New("Oh why, gruel world")); MITK_TEST_CONDITION_REQUIRED(propList->GetMap()->size() > 0, "Initialize PropertyList"); TestAllProperties(propList); /* test default property lists of basedata objects */ // activate the following tests after MaterialProperty is deleted mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(mitk::PointSet::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Image::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Surface::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::VtkWidgetRendering::New()); TestAllProperties(node->GetPropertyList()); MITK_TEST_END(); } void TestAllProperties(const mitk::PropertyList *propList) { assert(propList); /* try to serialize each property in the list, then deserialize again and check for equality */ for (auto it = propList->GetMap()->begin(); it != propList->GetMap()->end(); ++it) { const mitk::BaseProperty *prop = it->second; // construct name of serializer class std::string serializername = std::string(prop->GetNameOfClass()) + "Serializer"; std::list allSerializers = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str()); MITK_TEST_CONDITION(allSerializers.size() > 0, std::string("Creating serializers for ") + serializername); if (allSerializers.size() == 0) { MITK_TEST_OUTPUT(<< "serialization not possible, skipping " << prop->GetNameOfClass()); continue; } if (allSerializers.size() > 1) { MITK_TEST_OUTPUT(<< "Warning: " << allSerializers.size() << " serializers found for " << prop->GetNameOfClass() << "testing only the first one."); } auto *serializer = dynamic_cast(allSerializers.begin()->GetPointer()); MITK_TEST_CONDITION(serializer != nullptr, serializername + std::string(" is valid")); if (serializer != nullptr) { serializer->SetProperty(prop); tinyxml2::XMLDocument doc; tinyxml2::XMLElement *valueelement = nullptr; try { valueelement = serializer->Serialize(doc); } catch (...) { } MITK_TEST_CONDITION(valueelement != nullptr, std::string("Serialize property with ") + serializername); if (valueelement == nullptr) { MITK_TEST_OUTPUT(<< "serialization failed, skipping deserialization"); continue; } mitk::BaseProperty::Pointer deserializedProp = serializer->Deserialize(valueelement); MITK_TEST_CONDITION(deserializedProp.IsNotNull(), "serializer created valid property"); if (deserializedProp.IsNotNull()) { MITK_TEST_CONDITION(*(deserializedProp.GetPointer()) == *prop, "deserialized property equals initial property for type " << prop->GetNameOfClass()); } } else { MITK_TEST_OUTPUT(<< "created serializer object is of class " << allSerializers.begin()->GetPointer()->GetNameOfClass()) } } // for all properties } diff --git a/Modules/Segmentation/Algorithms/mitkSegmentationObjectFactory.cpp b/Modules/Segmentation/Algorithms/mitkSegmentationObjectFactory.cpp index 9ae4041a66..ba93a9b4e7 100644 --- a/Modules/Segmentation/Algorithms/mitkSegmentationObjectFactory.cpp +++ b/Modules/Segmentation/Algorithms/mitkSegmentationObjectFactory.cpp @@ -1,138 +1,123 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkSegmentationObjectFactory.h" #include "mitkBaseRenderer.h" #include "mitkCoreObjectFactory.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkContour.h" #include "mitkContourMapper2D.h" #include "mitkContourSetMapper2D.h" #include "mitkContourSetVtkMapper3D.h" #include "mitkContourVtkMapper3D.h" #include mitk::SegmentationObjectFactory::SegmentationObjectFactory() : CoreObjectFactoryBase() { static bool alreadyDone = false; if (!alreadyDone) { MITK_DEBUG << "SegmentationObjectFactory c'tor" << std::endl; CreateFileExtensionsMap(); alreadyDone = true; } } mitk::Mapper::Pointer mitk::SegmentationObjectFactory::CreateMapper(mitk::DataNode *node, MapperSlotId id) { mitk::Mapper::Pointer newMapper = nullptr; mitk::BaseData *data = node->GetData(); if (id == mitk::BaseRenderer::Standard2D) { std::string classname("ContourModel"); if (dynamic_cast(node->GetData()) != nullptr) { newMapper = mitk::ContourMapper2D::New(); newMapper->SetDataNode(node); } else if (dynamic_cast(node->GetData()) != nullptr) { newMapper = mitk::ContourSetMapper2D::New(); newMapper->SetDataNode(node); } } else if (id == mitk::BaseRenderer::Standard3D) { if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::ContourVtkMapper3D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::ContourSetVtkMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } -void mitk::SegmentationObjectFactory::SetDefaultProperties(mitk::DataNode *node) +void mitk::SegmentationObjectFactory::SetDefaultProperties(mitk::DataNode *) { - if (node == nullptr) - return; - - mitk::DataNode::Pointer nodePointer = node; - - // mitk::Image::Pointer image = dynamic_cast(node->GetData()); - // if(image.IsNotNull() && image->IsInitialized()) - // { - // mitk::GPUVolumeMapper3D::SetDefaultProperties(node); - // } - // - // if (dynamic_cast(node->GetData())) - // { - // mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(node); - // } } std::string mitk::SegmentationObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::SegmentationObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } mitk::CoreObjectFactoryBase::MultimapType mitk::SegmentationObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::SegmentationObjectFactory::CreateFileExtensionsMap() { } std::string mitk::SegmentationObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } void mitk::SegmentationObjectFactory::RegisterIOFactories() { } struct RegisterSegmentationObjectFactory { RegisterSegmentationObjectFactory() : m_Factory(mitk::SegmentationObjectFactory::New()) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(m_Factory); } ~RegisterSegmentationObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory(m_Factory); } mitk::SegmentationObjectFactory::Pointer m_Factory; }; static RegisterSegmentationObjectFactory registerSegmentationObjectFactory; diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp index fe9ff8bd3f..2b6853bb74 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp @@ -1,1014 +1,1006 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkAdaptiveRegionGrowingToolGUI.h" #include #include "mitkITKImageImport.h" #include "mitkImageAccessByItk.h" #include "mitkImageTimeSelector.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkTransferFunctionProperty.h" #include "mitkImageStatisticsHolder.h" #include "itkMaskImageFilter.h" #include "itkNumericTraits.h" #include #include #include #include #include "QmitkConfirmSegmentationDialog.h" #include "itkOrImageFilter.h" #include "mitkImageCast.h" #include "mitkImagePixelReadAccessor.h" #include "mitkPixelTypeMultiplex.h" #include "mitkImageCast.h" MITK_TOOL_GUI_MACRO(, QmitkAdaptiveRegionGrowingToolGUI, "") QmitkAdaptiveRegionGrowingToolGUI::QmitkAdaptiveRegionGrowingToolGUI(QWidget *parent) : QmitkToolGUI(), m_DataStorage(nullptr), m_UseVolumeRendering(false), m_UpdateSuggestedThreshold(true), m_SuggestedThValue(0.0) { this->setParent(parent); m_Controls.setupUi(this); m_Controls.m_ThresholdSlider->setDecimals(1); m_Controls.m_ThresholdSlider->setSpinBoxAlignment(Qt::AlignVCenter); m_Controls.m_PreviewSlider->setEnabled(false); m_Controls.m_PreviewSlider->setSingleStep(0.5); // Not yet available // m_Controls.m_PreviewSlider->InvertedAppearance(true); //3D preview doesn't work: T24430. Postponed until reimplementation of segmentation m_Controls.m_cbVolumeRendering->setVisible(false); this->CreateConnections(); this->SetDataNodeNames("labeledRGSegmentation", "RGResult", "RGFeedbackSurface", "maskedSegmentation"); connect(this, SIGNAL(NewToolAssociated(mitk::Tool *)), this, SLOT(OnNewToolAssociated(mitk::Tool *))); } QmitkAdaptiveRegionGrowingToolGUI::~QmitkAdaptiveRegionGrowingToolGUI() { // Removing the observer of the PointSet node if (m_RegionGrow3DTool->GetPointSetNode().IsNotNull()) { m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetAddObserverTag); m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetMoveObserverTag); } this->RemoveHelperNodes(); } void QmitkAdaptiveRegionGrowingToolGUI::OnNewToolAssociated(mitk::Tool *tool) { m_RegionGrow3DTool = dynamic_cast(tool); if (m_RegionGrow3DTool.IsNotNull()) { SetInputImageNode(this->m_RegionGrow3DTool->GetReferenceData()); this->m_DataStorage = this->m_RegionGrow3DTool->GetDataStorage(); this->EnableControls(true); // Watch for point added or modified itk::SimpleMemberCommand::Pointer pointAddedCommand = itk::SimpleMemberCommand::New(); pointAddedCommand->SetCallbackFunction(this, &QmitkAdaptiveRegionGrowingToolGUI::OnPointAdded); m_PointSetAddObserverTag = m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand); m_PointSetMoveObserverTag = m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver(mitk::PointSetMoveEvent(), pointAddedCommand); } else { this->EnableControls(false); } } void QmitkAdaptiveRegionGrowingToolGUI::RemoveHelperNodes() { mitk::DataNode::Pointer imageNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); if (imageNode.IsNotNull()) { m_DataStorage->Remove(imageNode); } mitk::DataNode::Pointer maskedSegmentationNode = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); if (maskedSegmentationNode.IsNotNull()) { m_DataStorage->Remove(maskedSegmentationNode); } } void QmitkAdaptiveRegionGrowingToolGUI::CreateConnections() { // Connecting GUI components connect((QObject *)(m_Controls.m_pbRunSegmentation), SIGNAL(clicked()), this, SLOT(RunSegmentation())); connect(m_Controls.m_PreviewSlider, SIGNAL(valueChanged(double)), this, SLOT(ChangeLevelWindow(double))); connect((QObject *)(m_Controls.m_pbConfirmSegementation), SIGNAL(clicked()), this, SLOT(ConfirmSegmentation())); connect( m_Controls.m_ThresholdSlider, SIGNAL(maximumValueChanged(double)), this, SLOT(SetUpperThresholdValue(double))); connect( m_Controls.m_ThresholdSlider, SIGNAL(minimumValueChanged(double)), this, SLOT(SetLowerThresholdValue(double))); } void QmitkAdaptiveRegionGrowingToolGUI::SetDataNodeNames(std::string labledSegmentation, std::string binaryImage, std::string surface, std::string maskedSegmentation) { m_NAMEFORLABLEDSEGMENTATIONIMAGE = labledSegmentation; m_NAMEFORBINARYIMAGE = binaryImage; m_NAMEFORSURFACE = surface; m_NAMEFORMASKEDSEGMENTATION = maskedSegmentation; } void QmitkAdaptiveRegionGrowingToolGUI::SetDataStorage(mitk::DataStorage *dataStorage) { m_DataStorage = dataStorage; } void QmitkAdaptiveRegionGrowingToolGUI::SetInputImageNode(mitk::DataNode *node) { m_InputImageNode = node; mitk::Image *inputImage = dynamic_cast(m_InputImageNode->GetData()); if (inputImage) { mitk::ScalarType max = inputImage->GetStatistics()->GetScalarValueMax(); mitk::ScalarType min = inputImage->GetStatistics()->GetScalarValueMin(); m_Controls.m_ThresholdSlider->setMaximum(max); m_Controls.m_ThresholdSlider->setMinimum(min); // Just for initialization m_Controls.m_ThresholdSlider->setMaximumValue(max); m_Controls.m_ThresholdSlider->setMinimumValue(min); } } template static void AccessPixel(mitk::PixelType /*ptype*/, mitk::Image* im, mitk::Point3D p, int& val) { mitk::ImagePixelReadAccessor access(im); val = access.GetPixelByWorldCoordinates(p); } /**Overloaded const verison*/ template static void AccessPixel(mitk::PixelType /*ptype*/, const mitk::Image* im, mitk::Point3D p, int& val) { mitk::ImagePixelReadAccessor access(im); val = access.GetPixelByWorldCoordinates(p); } void QmitkAdaptiveRegionGrowingToolGUI::OnPointAdded() { if (m_RegionGrow3DTool.IsNull()) return; mitk::DataNode *node = m_RegionGrow3DTool->GetPointSetNode(); if (node != nullptr) { mitk::PointSet::Pointer pointSet = dynamic_cast(node->GetData()); if (pointSet.IsNull()) { QMessageBox::critical(nullptr, "QmitkAdaptiveRegionGrowingToolGUI", "PointSetNode does not contain a pointset"); return; } m_Controls.m_lblSetSeedpoint->setText(""); const mitk::Image *image = dynamic_cast(m_InputImageNode->GetData()); const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); auto image3D = GetImageByTimePoint(image, timePoint); if (nullptr == image3D) { MITK_WARN << "Cannot run segementation. Currently selected timepoint is not in the time bounds of the selected " "reference image. Time point: " << timePoint; return; } if (!pointSet->GetTimeGeometry()->IsValidTimePoint(timePoint)) return; mitk::Point3D seedPoint = pointSet ->GetPointSet(static_cast(pointSet->GetTimeGeometry()->TimePointToTimeStep(timePoint))) ->GetPoints() ->ElementAt(0); if (image3D->GetGeometry()->IsInside(seedPoint)) mitkPixelTypeMultiplex3( AccessPixel, image3D->GetChannelDescriptor().GetPixelType(), image3D, seedPoint, m_SeedpointValue) else return; /* In this case the seedpoint is placed e.g. in the lung or bronchialtree * The lowerFactor sets the windowsize depending on the regiongrowing direction */ m_CurrentRGDirectionIsUpwards = true; if (m_SeedpointValue < -500) { m_CurrentRGDirectionIsUpwards = false; } // Initializing the region by the area around the seedpoint m_SeedPointValueMean = 0; itk::Index<3> currentIndex, runningIndex; mitk::ScalarType pixelValues[125]; unsigned int pos(0); image3D->GetGeometry(0)->WorldToIndex(seedPoint, currentIndex); runningIndex = currentIndex; for (int i = runningIndex[0] - 2; i <= runningIndex[0] + 2; i++) { for (int j = runningIndex[1] - 2; j <= runningIndex[1] + 2; j++) { for (int k = runningIndex[2] - 2; k <= runningIndex[2] + 2; k++) { currentIndex[0] = i; currentIndex[1] = j; currentIndex[2] = k; if (image3D->GetGeometry()->IsIndexInside(currentIndex)) { int component = 0; m_InputImageNode->GetIntProperty("Image.Displayed Component", component); mitkPixelTypeMultiplex4(mitk::FastSinglePixelAccess, image3D->GetChannelDescriptor().GetPixelType(), image3D, nullptr, currentIndex, pixelValues[pos]); pos++; } else { pixelValues[pos] = std::numeric_limits::min(); pos++; } } } } // Now calculation mean of the pixelValues // Now calculation mean of the pixelValues unsigned int numberOfValues(0); for (auto &pixelValue : pixelValues) { if (pixelValue > std::numeric_limits::min()) { m_SeedPointValueMean += pixelValue; numberOfValues++; } } m_SeedPointValueMean = m_SeedPointValueMean / numberOfValues; mitk::ScalarType var = 0; if (numberOfValues > 1) { for (auto &pixelValue : pixelValues) { if (pixelValue > std::numeric_limits::min()) { var += (pixelValue - m_SeedPointValueMean) * (pixelValue - m_SeedPointValueMean); } } var /= numberOfValues - 1; } mitk::ScalarType stdDev = sqrt(var); /* * Here the upper- and lower threshold is calculated: * The windowSize is 20% of the maximum range of the intensity values existing in the current image * If the RG direction is upwards the lower TH is meanSeedValue-0.15*windowSize and upper TH is * meanSeedValue+0.85*windowsSize * if the RG direction is downwards the lower TH is meanSeedValue-0.85*windowSize and upper TH is * meanSeedValue+0.15*windowsSize */ const auto timeStepOfImage = image->GetTimeGeometry()->TimePointToTimeStep(timePoint); mitk::ScalarType min = image->GetStatistics()->GetScalarValueMin(timeStepOfImage); mitk::ScalarType max = image->GetStatistics()->GetScalarValueMax(timeStepOfImage); mitk::ScalarType windowSize = max - min; windowSize = 0.15 * windowSize; if (m_CurrentRGDirectionIsUpwards) { m_LOWERTHRESHOLD = m_SeedPointValueMean - stdDev; m_UPPERTHRESHOLD = m_SeedpointValue + windowSize; if (m_UPPERTHRESHOLD > max) m_UPPERTHRESHOLD = max; m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD); m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD); } else { m_UPPERTHRESHOLD = m_SeedPointValueMean; if (m_SeedpointValue > m_SeedPointValueMean) m_UPPERTHRESHOLD = m_SeedpointValue; m_LOWERTHRESHOLD = m_SeedpointValue - windowSize; if (m_LOWERTHRESHOLD < min) m_LOWERTHRESHOLD = min; m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD); m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD); } } } mitk::Image::ConstPointer QmitkAdaptiveRegionGrowingToolGUI::GetImageByTimePoint(const mitk::Image *image, mitk::TimePointType timePoint) const { if (nullptr == image) return image; if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint)) return nullptr; if (image->GetDimension() != 4) return image; auto imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(image); imageTimeSelector->SetTimeNr(static_cast(image->GetTimeGeometry()->TimePointToTimeStep(timePoint))); imageTimeSelector->UpdateLargestPossibleRegion(); return imageTimeSelector->GetOutput(); } void QmitkAdaptiveRegionGrowingToolGUI::RunSegmentation() { if (m_InputImageNode.IsNull()) { QMessageBox::information(nullptr, "Adaptive Region Growing functionality", "Please specify the image in Datamanager!"); return; } mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode(); if (node.IsNull()) { QMessageBox::information(nullptr, "Adaptive Region Growing functionality", "Please insert a seed point inside the " "image.\n\nFirst press the \"Define Seed " "Point\" button,\nthen click left mouse " "button inside the image."); return; } // safety if no pointSet or pointSet empty mitk::PointSet::Pointer seedPointSet = dynamic_cast(node->GetData()); if (seedPointSet.IsNull()) { m_Controls.m_pbRunSegmentation->setEnabled(true); QMessageBox::information( nullptr, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point."); return; } mitk::Image::Pointer orgImage = dynamic_cast(m_InputImageNode->GetData()); if (orgImage.IsNotNull()) { const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); if (!seedPointSet->GetTimeGeometry()->IsValidTimePoint(timePoint)) mitkThrow() << "Point set is not defined for specified time point. Time point: " << timePoint; int timeStep = static_cast(seedPointSet->GetTimeGeometry()->TimePointToTimeStep(timePoint)); if (!(seedPointSet->GetSize(timeStep))) { m_Controls.m_pbRunSegmentation->setEnabled(true); QMessageBox::information( nullptr, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point."); return; } QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); mitk::PointSet::PointType seedPoint = seedPointSet->GetPointSet(timeStep)->GetPoints()->Begin().Value(); auto image3D = GetImageByTimePoint(orgImage, timePoint); if (image3D.IsNotNull()) { // QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); //set the cursor to waiting AccessByItk_2(image3D, StartRegionGrowing, image3D->GetGeometry(), seedPoint); // QApplication::restoreOverrideCursor();//reset cursor } else { QApplication::restoreOverrideCursor(); // reset cursor QMessageBox::information( nullptr, "Adaptive Region Growing functionality", "Only images of dimension 3 or 4 can be processed!"); return; } } EnableControls(true); // Segmentation ran successfully, so enable all controls. node->SetVisibility(true); QApplication::restoreOverrideCursor(); // reset cursor } template void QmitkAdaptiveRegionGrowingToolGUI::StartRegionGrowing(const itk::Image *itkImage, const mitk::BaseGeometry *imageGeometry, const mitk::PointSet::PointType seedPoint) { typedef itk::Image InputImageType; typedef typename InputImageType::IndexType IndexType; typedef itk::ConnectedAdaptiveThresholdImageFilter RegionGrowingFilterType; typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); typedef itk::BinaryThresholdImageFilter ThresholdFilterType; typedef itk::MaskImageFilter MaskImageFilterType; if (!imageGeometry->IsInside(seedPoint)) { QApplication::restoreOverrideCursor(); // reset cursor to be able to click ok with the regular mouse cursor QMessageBox::information(nullptr, "Segmentation functionality", "The seed point is outside of the image! Please choose a position inside the image!"); return; } IndexType seedIndex; imageGeometry->WorldToIndex(seedPoint, seedIndex); // convert world coordinates to image indices if (m_SeedpointValue > m_UPPERTHRESHOLD || m_SeedpointValue < m_LOWERTHRESHOLD) { QApplication::restoreOverrideCursor(); // reset cursor to be able to click ok with the regular mouse cursor QMessageBox::information( nullptr, "Segmentation functionality", "The seed point is outside the defined thresholds! Please set a new seed point or adjust the thresholds."); MITK_INFO << "Mean: " << m_SeedPointValueMean; return; } // Setting the direction of the regiongrowing. For dark structures e.g. the lung the regiongrowing // is performed starting at the upper value going to the lower one regionGrower->SetGrowingDirectionIsUpwards(m_CurrentRGDirectionIsUpwards); regionGrower->SetInput(itkImage); regionGrower->AddSeed(seedIndex); // In some cases we have to subtract 1 for the lower threshold and add 1 to the upper. // Otherwise no region growing is done. Maybe a bug in the ConnectiveAdaptiveThresholdFilter mitk::ScalarType maxPixelValue = m_Controls.m_ThresholdSlider->maximum(); mitk::ScalarType minPixelValue = m_Controls.m_ThresholdSlider->minimum(); if ((m_LOWERTHRESHOLD - minPixelValue) >= 1) { regionGrower->SetLower(m_LOWERTHRESHOLD - 1); } else { regionGrower->SetLower(m_LOWERTHRESHOLD); } if ((maxPixelValue - m_UPPERTHRESHOLD) >= 1) { regionGrower->SetUpper(m_UPPERTHRESHOLD + 1); } else { regionGrower->SetUpper(m_UPPERTHRESHOLD); } try { regionGrower->Update(); } catch (itk::ExceptionObject &exc) { QMessageBox errorInfo; errorInfo.setWindowTitle("Adaptive RG Segmentation Functionality"); errorInfo.setIcon(QMessageBox::Critical); errorInfo.setText("An error occurred during region growing!"); errorInfo.setDetailedText(exc.what()); errorInfo.exec(); return; // can't work } catch (...) { QMessageBox::critical(nullptr, "Adaptive RG Segmentation Functionality", "An error occurred during region growing!"); return; } mitk::Image::Pointer resultImage = mitk::ImportItkImage(regionGrower->GetOutput())->Clone(); // initialize slider m_Controls.m_PreviewSlider->setMinimum(m_LOWERTHRESHOLD); mitk::ScalarType max = m_SeedpointValue + resultImage->GetStatistics()->GetScalarValueMax(); if (max < m_UPPERTHRESHOLD) m_Controls.m_PreviewSlider->setMaximum(max); else m_Controls.m_PreviewSlider->setMaximum(m_UPPERTHRESHOLD); this->m_DetectedLeakagePoint = regionGrower->GetLeakagePoint(); if (m_CurrentRGDirectionIsUpwards) { m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean - 1); } else { m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean + 1); } this->m_SliderInitialized = true; // create new node and then delete the old one if there is one mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(resultImage); // set some properties newNode->SetProperty("name", mitk::StringProperty::New(m_NAMEFORLABLEDSEGMENTATIONIMAGE)); newNode->SetProperty("helper object", mitk::BoolProperty::New(true)); newNode->SetProperty("color", mitk::ColorProperty::New(0.0, 1.0, 0.0)); newNode->SetProperty("layer", mitk::IntProperty::New(1)); newNode->SetProperty("opacity", mitk::FloatProperty::New(0.7)); // delete the old image, if there was one: mitk::DataNode::Pointer binaryNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); m_DataStorage->Remove(binaryNode); // now add result to data tree m_DataStorage->Add(newNode, m_InputImageNode); typename InputImageType::Pointer inputImageItk; mitk::CastToItkImage(resultImage, inputImageItk); // volume rendering preview masking typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New(); thresholdFilter->SetInput(inputImageItk); thresholdFilter->SetInsideValue(1); thresholdFilter->SetOutsideValue(0); double sliderVal = this->m_Controls.m_PreviewSlider->value(); if (m_CurrentRGDirectionIsUpwards) { thresholdFilter->SetLowerThreshold(sliderVal); thresholdFilter->SetUpperThreshold(itk::NumericTraits::max()); } else { thresholdFilter->SetLowerThreshold(itk::NumericTraits::NonpositiveMin()); thresholdFilter->SetUpperThreshold(sliderVal); } thresholdFilter->SetInPlace(false); typename MaskImageFilterType::Pointer maskFilter = MaskImageFilterType::New(); maskFilter->SetInput(inputImageItk); maskFilter->SetInPlace(false); maskFilter->SetMaskImage(thresholdFilter->GetOutput()); maskFilter->SetOutsideValue(0); maskFilter->UpdateLargestPossibleRegion(); mitk::Image::Pointer mitkMask; mitk::CastToMitkImage(maskFilter->GetOutput(), mitkMask); mitk::DataNode::Pointer maskedNode = mitk::DataNode::New(); maskedNode->SetData(mitkMask); // set some properties maskedNode->SetProperty("name", mitk::StringProperty::New(m_NAMEFORMASKEDSEGMENTATION)); maskedNode->SetProperty("helper object", mitk::BoolProperty::New(true)); maskedNode->SetProperty("color", mitk::ColorProperty::New(0.0, 1.0, 0.0)); maskedNode->SetProperty("layer", mitk::IntProperty::New(1)); maskedNode->SetProperty("opacity", mitk::FloatProperty::New(0.0)); // delete the old image, if there was one: mitk::DataNode::Pointer deprecatedMask = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); m_DataStorage->Remove(deprecatedMask); // now add result to data tree m_DataStorage->Add(maskedNode, m_InputImageNode); this->InitializeLevelWindow(); if (m_UseVolumeRendering) this->EnableVolumeRendering(true); m_UpdateSuggestedThreshold = true; // reset first stored threshold value // Setting progress to finished mitk::ProgressBar::GetInstance()->Progress(357); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkAdaptiveRegionGrowingToolGUI::InitializeLevelWindow() { // get the preview from the datatree mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); mitk::LevelWindow tempLevelWindow; newNode->GetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); mitk::ScalarType *level = new mitk::ScalarType(0.0); mitk::ScalarType *window = new mitk::ScalarType(1.0); int upper; if (m_CurrentRGDirectionIsUpwards) { upper = m_UPPERTHRESHOLD - m_SeedpointValue; } else { upper = m_SeedpointValue - m_LOWERTHRESHOLD; } tempLevelWindow.SetRangeMinMax(mitk::ScalarType(0), mitk::ScalarType(upper)); // get the suggested threshold from the detected leakage-point and adjust the slider if (m_CurrentRGDirectionIsUpwards) { this->m_Controls.m_PreviewSlider->setValue(m_SeedpointValue); *level = m_UPPERTHRESHOLD - (m_SeedpointValue) + 0.5; } else { this->m_Controls.m_PreviewSlider->setValue(m_SeedpointValue); *level = (m_SeedpointValue)-m_LOWERTHRESHOLD + 0.5; } tempLevelWindow.SetLevelWindow(*level, *window); newNode->SetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); // update the widgets mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_SliderInitialized = true; // inquiry need to fix bug#1828 static int lastSliderPosition = 0; if ((this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1) == lastSliderPosition) { this->ChangeLevelWindow(lastSliderPosition); } lastSliderPosition = this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1; if (m_UseVolumeRendering) this->UpdateVolumeRenderingThreshold((int)(*level + 0.5)); // lower threshold for labeled image } void QmitkAdaptiveRegionGrowingToolGUI::ChangeLevelWindow(double newValue) { if (m_SliderInitialized) { // do nothing, if no preview exists mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); if (newNode.IsNull()) return; mitk::LevelWindow tempLevelWindow; newNode->GetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); // get the levelWindow associated with the preview mitk::ScalarType level; // = this->m_UPPERTHRESHOLD - newValue + 0.5; mitk::ScalarType *window = new mitk::ScalarType(1); // adjust the levelwindow according to the position of the slider (newvalue) if (m_CurrentRGDirectionIsUpwards) { level = m_UPPERTHRESHOLD - newValue + 0.5; tempLevelWindow.SetLevelWindow(level, *window); } else { level = newValue - m_LOWERTHRESHOLD + 0.5; tempLevelWindow.SetLevelWindow(level, *window); } newNode->SetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); if (m_UseVolumeRendering) this->UpdateVolumeRenderingThreshold((int)(level - 0.5)); // lower threshold for labeled image newNode->SetVisibility(true); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkAdaptiveRegionGrowingToolGUI::DecreaseSlider() { // moves the slider one step to the left, when the "-"-button is pressed if (this->m_Controls.m_PreviewSlider->value() != this->m_Controls.m_PreviewSlider->minimum()) { int newValue = this->m_Controls.m_PreviewSlider->value() - 1; this->ChangeLevelWindow(newValue); this->m_Controls.m_PreviewSlider->setValue(newValue); } } void QmitkAdaptiveRegionGrowingToolGUI::IncreaseSlider() { // moves the slider one step to the right, when the "+"-button is pressed if (this->m_Controls.m_PreviewSlider->value() != this->m_Controls.m_PreviewSlider->maximum()) { int newValue = this->m_Controls.m_PreviewSlider->value() + 1; this->ChangeLevelWindow(newValue); this->m_Controls.m_PreviewSlider->setValue(newValue); } } void QmitkAdaptiveRegionGrowingToolGUI::ConfirmSegmentation() { // get image node if (m_InputImageNode.IsNull()) { QMessageBox::critical(nullptr, "Adaptive region growing functionality", "Please specify the image in Datamanager!"); return; } // get image data mitk::Image::Pointer orgImage = dynamic_cast(m_InputImageNode->GetData()); if (orgImage.IsNull()) { QMessageBox::critical(nullptr, "Adaptive region growing functionality", "No Image found!"); return; } // get labeled segmentation mitk::Image::Pointer labeledSeg = (mitk::Image *)m_DataStorage->GetNamedObject(m_NAMEFORLABLEDSEGMENTATIONIMAGE); if (labeledSeg.IsNull()) { QMessageBox::critical(nullptr, "Adaptive region growing functionality", "No Segmentation Preview found!"); return; } mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); if (newNode.IsNull()) return; QmitkConfirmSegmentationDialog dialog; QString segName = QString::fromStdString(m_RegionGrow3DTool->GetCurrentSegmentationName()); dialog.SetSegmentationName(segName); int result = dialog.exec(); switch (result) { case QmitkConfirmSegmentationDialog::CREATE_NEW_SEGMENTATION: m_RegionGrow3DTool->SetOverwriteExistingSegmentation(false); break; case QmitkConfirmSegmentationDialog::OVERWRITE_SEGMENTATION: m_RegionGrow3DTool->SetOverwriteExistingSegmentation(true); break; case QmitkConfirmSegmentationDialog::CANCEL_SEGMENTATION: return; } mitk::Image::Pointer img = dynamic_cast(newNode->GetData()); AccessByItk(img, ITKThresholding); // disable volume rendering preview after the segmentation node was created this->EnableVolumeRendering(false); newNode->SetVisibility(false); m_Controls.m_cbVolumeRendering->setChecked(false); // TODO disable slider etc... if (m_RegionGrow3DTool.IsNotNull()) { m_RegionGrow3DTool->ConfirmSegmentation(); } } template void QmitkAdaptiveRegionGrowingToolGUI::ITKThresholding(itk::Image *itkImage) { mitk::Image::Pointer originalSegmentation = dynamic_cast(this->m_RegionGrow3DTool->GetTargetSegmentationNode()->GetData()); const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); if (!originalSegmentation->GetTimeGeometry()->IsValidTimePoint(timePoint)) mitkThrow() << "Segmentation is not defined for specified time point. Time point: " << timePoint; int timeStep = static_cast(originalSegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint)); if (originalSegmentation) { typedef itk::Image InputImageType; typedef itk::Image SegmentationType; // select single 3D volume if we have more than one time step typename SegmentationType::Pointer originalSegmentationInITK = SegmentationType::New(); if (originalSegmentation->GetTimeGeometry()->CountTimeSteps() > 1) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(originalSegmentation); timeSelector->SetTimeNr(timeStep); timeSelector->UpdateLargestPossibleRegion(); CastToItkImage(timeSelector->GetOutput(), originalSegmentationInITK); } else // use original { CastToItkImage(originalSegmentation, originalSegmentationInITK); } // Fill current preiview image in segmentation image originalSegmentationInITK->FillBuffer(0); itk::ImageRegionIterator itOutput(originalSegmentationInITK, originalSegmentationInITK->GetLargestPossibleRegion()); itk::ImageRegionIterator itInput(itkImage, itkImage->GetLargestPossibleRegion()); itOutput.GoToBegin(); itInput.GoToBegin(); // calculate threhold from slider value int currentTreshold = 0; if (m_CurrentRGDirectionIsUpwards) { currentTreshold = m_UPPERTHRESHOLD - m_Controls.m_PreviewSlider->value() + 1; } else { currentTreshold = m_Controls.m_PreviewSlider->value() - m_LOWERTHRESHOLD; } // iterate over image and set pixel in segmentation according to thresholded labeled image while (!itOutput.IsAtEnd() && !itInput.IsAtEnd()) { // Use threshold slider to determine if pixel is set to 1 if (itInput.Value() != 0 && itInput.Value() >= static_cast::PixelType>(currentTreshold)) { itOutput.Set(1); } ++itOutput; ++itInput; } // combine current working segmentation image with our region growing result originalSegmentation->SetVolume((void *)(originalSegmentationInITK->GetPixelContainer()->GetBufferPointer()), timeStep); originalSegmentation->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkAdaptiveRegionGrowingToolGUI::EnableControls(bool enable) { if (m_RegionGrow3DTool.IsNull()) return; // Check if seed point is already set, if not leave RunSegmentation disabled // if even m_DataStorage is nullptr leave node nullptr mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode(); if (node.IsNull()) { this->m_Controls.m_pbRunSegmentation->setEnabled(false); } else { this->m_Controls.m_pbRunSegmentation->setEnabled(enable); } // Check if a segmentation exists, if not leave segmentation dependent disabled. // if even m_DataStorage is nullptr leave node nullptr node = m_DataStorage ? m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE) : nullptr; if (node.IsNull()) { this->m_Controls.m_PreviewSlider->setEnabled(false); this->m_Controls.m_pbConfirmSegementation->setEnabled(false); } else { this->m_Controls.m_PreviewSlider->setEnabled(enable); this->m_Controls.m_pbConfirmSegementation->setEnabled(enable); } this->m_Controls.m_cbVolumeRendering->setEnabled(enable); } void QmitkAdaptiveRegionGrowingToolGUI::EnableVolumeRendering(bool enable) { mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); if (node.IsNull()) return; - if (enable) - { - node->SetBoolProperty("volumerendering", enable); - node->SetBoolProperty("volumerendering.uselod", true); - } - else - { - node->SetBoolProperty("volumerendering", enable); - } + node->SetBoolProperty("volumerendering", enable); double val = this->m_Controls.m_PreviewSlider->value(); this->ChangeLevelWindow(val); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkAdaptiveRegionGrowingToolGUI::UpdateVolumeRenderingThreshold(int) { typedef short PixelType; typedef itk::Image InputImageType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; typedef itk::MaskImageFilter MaskImageFilterType; mitk::DataNode::Pointer grownImageNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); mitk::Image::Pointer grownImage = dynamic_cast(grownImageNode->GetData()); if (!grownImage) { MITK_ERROR << "Missing data node for labeled segmentation image."; return; } InputImageType::Pointer itkGrownImage; mitk::CastToItkImage(grownImage, itkGrownImage); ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New(); thresholdFilter->SetInput(itkGrownImage); thresholdFilter->SetInPlace(false); double sliderVal = this->m_Controls.m_PreviewSlider->value(); PixelType threshold = itk::NumericTraits::min(); if (m_CurrentRGDirectionIsUpwards) { threshold = static_cast(m_UPPERTHRESHOLD - sliderVal + 0.5); thresholdFilter->SetLowerThreshold(threshold); thresholdFilter->SetUpperThreshold(itk::NumericTraits::max()); } else { threshold = sliderVal - m_LOWERTHRESHOLD + 0.5; thresholdFilter->SetLowerThreshold(itk::NumericTraits::min()); thresholdFilter->SetUpperThreshold(threshold); } thresholdFilter->UpdateLargestPossibleRegion(); MaskImageFilterType::Pointer maskFilter = MaskImageFilterType::New(); maskFilter->SetInput(itkGrownImage); maskFilter->SetInPlace(false); maskFilter->SetMaskImage(thresholdFilter->GetOutput()); maskFilter->SetOutsideValue(0); maskFilter->UpdateLargestPossibleRegion(); mitk::Image::Pointer mitkMaskedImage; mitk::CastToMitkImage(maskFilter->GetOutput(), mitkMaskedImage); mitk::DataNode::Pointer maskNode = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); maskNode->SetData(mitkMaskedImage); } void QmitkAdaptiveRegionGrowingToolGUI::UseVolumeRendering(bool on) { m_UseVolumeRendering = on; this->EnableVolumeRendering(on); } void QmitkAdaptiveRegionGrowingToolGUI::SetLowerThresholdValue(double lowerThreshold) { m_LOWERTHRESHOLD = lowerThreshold; } void QmitkAdaptiveRegionGrowingToolGUI::SetUpperThresholdValue(double upperThreshold) { m_UPPERTHRESHOLD = upperThreshold; } void QmitkAdaptiveRegionGrowingToolGUI::Deactivated() { // make the segmentation preview node invisible mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); if (node.IsNotNull()) { node->SetVisibility(false); } // disable volume rendering preview after the segmentation node was created this->EnableVolumeRendering(false); m_Controls.m_cbVolumeRendering->setChecked(false); } void QmitkAdaptiveRegionGrowingToolGUI::Activated() { } diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox index 267ea020c8..4414f06d79 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox +++ b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox @@ -1,140 +1,130 @@ /** \page org_mitk_views_volumevisualization The Volume Visualization Plugin \imageMacro{volume_visualization-dox.svg,"Icon of the Volume Visualization Plugin",2.00} \tableofcontents \section QVV_Overview Overview The Volume Visualization Plugin is a basic tool for volume rendering of three dimensional medical images. MITK provides generic transfer function presets for medical CT and MRT data. These functions that map the gray-value to color and opacity can be interactively edited. Additionally, there are controls to quickly generate commonly used transfer function shapes like the threshold and bell curve to help identify a range of grey-values. \imageMacro{QmitkVolumeVisualization_Overview.png,"",16.00} \section QVV_EnableVRPage Volume Rendering \subsection QVV_LoadingImage Select an image and enable volume rendering -\imageMacro{QmitkVolumeVisualization_Checkboxen.png,"",8.21} - -Select an image on top of the view and click on the checkbox left of 'Volumerendering'. Please be patient, while the image is prepared for rendering, which can take up to a half minute. +Select an image on top of the view and click on the checkbox left of 'Volume rendering'. \note Volume Visualization imposes following restrictions on images:
  • It has to be a 3D scalar image, that means e.g. a CT or MRT image.
  • 3D+t images are supported for rendering, but the histograms are not computed.
  • Also be aware that volume visualization requires a huge amount of memory. Very large images may not work unless you use the 64bit version.
-\subsection QVV_LODGPU Dropdown menus for the rendering and blend modes - -Two dropdown menus are located right next to the 'Volumerendering' checkbox. They allow you to select a rendering mode (Default, RayCast, GPU) and the blend mode (Composite, Max, Min, Avg, Add). +\subsection QVV_LODGPU Dropdown menu for the blend modes -Any rendering mode requires a lot of computing resources including processor, memory and often also graphics card. -The 'Default' selection usually finds the best 'rendering' mode for the available hardware. -Alternatively, it is possible to manually specify the selections 'RayCast' and 'GPU'. -The 'RayCast' selection is based on CPU computation and therefore typically slow, but allows to render without hardware acceleration. -The 'GPU' selection uses computing resources on the graphics card to accelerate volume rendering. -It requires a powerful graphics card and OpenGL hardware support for shaders but achieves much higher frame rates than software-rendering. +Two dropdown menu is located right next to the 'Volume rendering' checkbox. It allows you to select a blend mode (Composite, Maximim intensity, Minimum intensity, Average intensity, and Additive intensity). -Blend modes define how the volume voxels, intersected by the rendering rays, are pooled. The 'Composite' mode specifies standard volume rendering, -for which each voxel contributes equally with opacity and color. Other 'blend' modes simply visualize the voxel of the maximum / -minimum intensity and average / add the intensities along the rendering ray. +Blend modes define how the volume voxels, intersected by the rendering rays, are pooled. The 'Composite' mode specifies standard volume rendering, +for which each voxel contributes equally with opacity and color. Other 'blend' modes visualize the voxel of the maximum or minimum intensity or average or add the intensities along the rendering ray. \section QVV_PresetPage Applying premade presets \subsection QVV_Preset Internal presets There are some internal presets given that can be used with normal CT data (given in Houndsfield units). A large set of medical data has been tested with those presets, but they may not suit some special cases. Click on the 'Preset' tab for using internal or custom presets. \imageMacro{QmitkVolumeVisualization_InternalPresets.png,"",8.30}
  • 'CT Generic' is the default transfer function that is first applied.
  • 'CT Black&White' does not use any colors for the volume visualization as it may be distracting on some data.
  • 'CT Cardiac' is well-suited for CT images containing the heart.
  • 'CT Bone' emphasizes bones and shows other areas more transparent.
  • 'CT Bone (Gradient)' is like 'CT Bone' but shows only the surface from other organs by using the gradient.
  • 'MR Generic' is the default transfer function that can be used on MRT data (which is not normalized like CT data).
  • 'CT Thorax small' is useful if only a proportion of the thorax is selected to emphasize details.
  • 'CT Thorax large' is useful if a large proportion or the entire thorax is selected to emphasize details.
\subsection QVV_CustomPreset Saving and loading custom presets After creating or editing a transfer function (see \ref QVV_Editing or \ref QVV_ThresholdBell), the custom transfer function can be stored and later retrieved on the filesystem. Click 'Save' (respectively 'Load') button below the preset selection to save (load) the threshold-, color- and gradient function combined in a single .xml file. \section QVV_ThresholdBell Interactively create transfer functions Besides the possibility to directly edit the transfer functions (\ref QVV_Editing), the plugin provides two commonly known shapes to quickly generate transfer functions with a few clicks. Both generators have two parameters that can be modified by first clicking on the cross and then moving the mouse up/down and left/right. The first parameter 'center' (controlled by horizontal movement of the mouse) specifies the gray value where the center of the shape will be located. The second parameter 'width' (controlled by vertical movement of the mouse) specifies the width (or steepness) of the shape. \subsection Threshold Click on the 'Threshold' tab to activate the threshold function generator. \imageMacro{QmitkVolumeVisualization_Threshold.png,"",8.21} A threshold shape begins with zero and raises to one across the 'center' parameter. Lower widths result in steeper threshold functions. \subsection Bell Click on the 'Bell' tab to activate the bell-shaped threshold function generator. \imageMacro{QmitkVolumeVisualization_Bell.png,"",8.23} A threshold shape begins with zero and raises to one at the 'center' parameter and then lowers again to zero. The 'width' parameter corresponds to the width of the bell. \section QVV_Editing Customize transfer functions in detail \subsection QVV_Navigate Choosing gray value interval to edit \imageMacro{QmitkVolumeVisualization_Slider.png,"",8.23} To navigate across the gray value range or to zoom in some ranges use the 'range'-slider. All three function editors have in common following:
  • By left-clicking a new point is added.
  • By right-clicking a point is deleted.
  • By left-clicking and holding, an exisiting point can be dragged.
  • By pressing arrow keys, the currently selected point is moved.
  • By pressing the 'DELETE' key, the currently selected point is deleted.
  • Between points the transferfunctions are linear interpolated.
There are three transfer functions to customize: \subsection QVV_GO Grayvalue -> Opacity \imageMacro{QmitkVolumeVisualization_Opacity.png,"Gray values will be mapped to opacity.",8.04} An opacity of 0 means total transparent, an opacity of 1 means total opaque. The opacity editor allows changing the opacity for all gray values independently. You can alter the position of control points using your mouse. You can add control points by left-clicking on the graph. To remove a control point again you can right-click on the respective point. \subsection QVV_GC Grayvalue -> Color \imageMacro{QmitkVolumeVisualization_Color.png,"Gray values will be mapped to color.",8.81} The color transfer function editor also allows you to change its color by double-clicking a point. You can add color control points by left-clicking on the color bar. To remove a control point again right-click on the respective point. \subsection QVV_GGO Grayvalue and Gradient -> Opacity \imageMacro{QmitkVolumeVisualization_Gradient.png,"",8.85} The gradient editor allows you to change the gradient influence for all gray values independently. You can move the existing control points using your mouse. Additionally, you can add control points by left-clicking on the graph. To remove a control point again, right-click on the respective point. */ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png deleted file mode 100644 index dac50d7795..0000000000 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp index 90e0d7ecf0..b4e5ff02af 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp @@ -1,313 +1,239 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkVolumeVisualizationView.h" #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkVolumeVisualizationView::VIEW_ID = "org.mitk.views.volumevisualization"; enum { DEFAULT_RENDERMODE = 0, RAYCAST_RENDERMODE = 1, GPU_RENDERMODE = 2 }; QmitkVolumeVisualizationView::QmitkVolumeVisualizationView() : QmitkAbstractView() , m_Controls(nullptr) { } void QmitkVolumeVisualizationView::SetFocus() { } void QmitkVolumeVisualizationView::CreateQtPartControl(QWidget* parent) { m_Controls = new Ui::QmitkVolumeVisualizationViewControls; m_Controls->setupUi(parent); m_Controls->volumeSelectionWidget->SetDataStorage(GetDataStorage()); m_Controls->volumeSelectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateOr::New(mitk::NodePredicateDimension::New(3), mitk::NodePredicateDimension::New(4)), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); m_Controls->volumeSelectionWidget->SetSelectionIsOptional(true); m_Controls->volumeSelectionWidget->SetEmptyInfo(QString("Please select a 3D / 4D image volume")); m_Controls->volumeSelectionWidget->SetPopUpTitel(QString("Select image volume")); // Fill the transfer function presets in the generator widget std::vector names; mitk::TransferFunctionInitializer::GetPresetNames(names); for (const auto& name : names) { m_Controls->transferFunctionGeneratorWidget->AddPreset(QString::fromStdString(name)); } - // see enum in vtkSmartVolumeMapper - m_Controls->renderMode->addItem("Default"); - m_Controls->renderMode->addItem("RayCast"); - m_Controls->renderMode->addItem("GPU"); - // see vtkVolumeMapper::BlendModes - m_Controls->blendMode->addItem("Comp"); - m_Controls->blendMode->addItem("Max"); - m_Controls->blendMode->addItem("Min"); - m_Controls->blendMode->addItem("Avg"); - m_Controls->blendMode->addItem("Add"); + m_Controls->blendMode->addItem("Composite", vtkVolumeMapper::COMPOSITE_BLEND); + m_Controls->blendMode->addItem("Maximum intensity", vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND); + m_Controls->blendMode->addItem("Minimum intensity", vtkVolumeMapper::MINIMUM_INTENSITY_BLEND); + m_Controls->blendMode->addItem("Average intensity", vtkVolumeMapper::AVERAGE_INTENSITY_BLEND); + m_Controls->blendMode->addItem("Additive", vtkVolumeMapper::ADDITIVE_BLEND); connect(m_Controls->volumeSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkVolumeVisualizationView::OnCurrentSelectionChanged); connect(m_Controls->enableRenderingCB, SIGNAL(toggled(bool)), this, SLOT(OnEnableRendering(bool))); - connect(m_Controls->renderMode, SIGNAL(activated(int)), this, SLOT(OnRenderMode(int))); connect(m_Controls->blendMode, SIGNAL(activated(int)), this, SLOT(OnBlendMode(int))); connect(m_Controls->transferFunctionGeneratorWidget, SIGNAL(SignalUpdateCanvas()), m_Controls->transferFunctionWidget, SLOT(OnUpdateCanvas())); connect(m_Controls->transferFunctionGeneratorWidget, SIGNAL(SignalTransferFunctionModeChanged(int)), SLOT(OnMitkInternalPreset(int))); m_Controls->enableRenderingCB->setEnabled(false); m_Controls->blendMode->setEnabled(false); - m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); m_Controls->volumeSelectionWidget->SetAutoSelectNewNodes(true); this->m_TimePointChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_TimePointChangeListener, &QmitkSliceNavigationListener::SelectedTimePointChanged, this, &QmitkVolumeVisualizationView::OnSelectedTimePointChanged); } void QmitkVolumeVisualizationView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) { this->m_TimePointChangeListener.RenderWindowPartActivated(renderWindowPart); } void QmitkVolumeVisualizationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart) { this->m_TimePointChangeListener.RenderWindowPartDeactivated(renderWindowPart); } void QmitkVolumeVisualizationView::OnMitkInternalPreset(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto node = m_SelectedNode.Lock(); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction")) { // first item is only information if (--mode == -1) return; // -- Creat new TransferFunction mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(transferFuncProp->GetValue()); tfInit->SetTransferFunctionMode(mode); RequestRenderWindowUpdate(); m_Controls->transferFunctionWidget->OnUpdateCanvas(); } } void QmitkVolumeVisualizationView::OnCurrentSelectionChanged(QList nodes) { m_SelectedNode = nullptr; if (nodes.empty() || nodes.front().IsNull()) { UpdateInterface(); return; } auto selectedNode = nodes.front(); auto image = dynamic_cast(selectedNode->GetData()); if (nullptr != image) { m_SelectedNode = selectedNode; } UpdateInterface(); } void QmitkVolumeVisualizationView::OnEnableRendering(bool state) { if (m_SelectedNode.IsExpired()) { return; } m_SelectedNode.Lock()->SetProperty("volumerendering", mitk::BoolProperty::New(state)); UpdateInterface(); RequestRenderWindowUpdate(); } -void QmitkVolumeVisualizationView::OnRenderMode(int mode) +void QmitkVolumeVisualizationView::OnBlendMode(int index) { if (m_SelectedNode.IsExpired()) - { return; - } auto selectedNode = m_SelectedNode.Lock(); - - bool usegpu = false; - bool useray = false; - if (DEFAULT_RENDERMODE == mode) - { - useray = true; - usegpu = true; - } - else if (GPU_RENDERMODE == mode) - { - usegpu = true; - } - else if (RAYCAST_RENDERMODE == mode) - { - useray = true; - } - - selectedNode->SetProperty("volumerendering.usegpu", mitk::BoolProperty::New(usegpu)); - selectedNode->SetProperty("volumerendering.useray", mitk::BoolProperty::New(useray)); - - RequestRenderWindowUpdate(); -} - -void QmitkVolumeVisualizationView::OnBlendMode(int mode) -{ - if (m_SelectedNode.IsExpired()) - { - return; - } - - auto selectedNode = m_SelectedNode.Lock(); - - bool usemip = false; - if (vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND == mode) - { - usemip = true; - } - - selectedNode->SetProperty("volumerendering.usemip", mitk::BoolProperty::New(usemip)); + int mode = m_Controls->blendMode->itemData(index).toInt(); selectedNode->SetProperty("volumerendering.blendmode", mitk::IntProperty::New(mode)); - RequestRenderWindowUpdate(); + this->RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::OnSelectedTimePointChanged(const mitk::TimePointType & /*newTimePoint*/) { this->UpdateInterface(); } void QmitkVolumeVisualizationView::UpdateInterface() { if (m_SelectedNode.IsExpired()) { // turnoff all m_Controls->enableRenderingCB->setChecked(false); m_Controls->enableRenderingCB->setEnabled(false); m_Controls->blendMode->setCurrentIndex(0); m_Controls->blendMode->setEnabled(false); - m_Controls->renderMode->setCurrentIndex(0); - m_Controls->renderMode->setEnabled(false); - m_Controls->transferFunctionWidget->SetDataNode(nullptr); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->SetDataNode(nullptr); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); return; } bool enabled = false; auto selectedNode = m_SelectedNode.Lock(); selectedNode->GetBoolProperty("volumerendering", enabled); m_Controls->enableRenderingCB->setEnabled(true); m_Controls->enableRenderingCB->setChecked(enabled); if (!enabled) { // turnoff all except volumerendering checkbox m_Controls->blendMode->setCurrentIndex(0); m_Controls->blendMode->setEnabled(false); - m_Controls->renderMode->setCurrentIndex(0); - m_Controls->renderMode->setEnabled(false); - m_Controls->transferFunctionWidget->SetDataNode(nullptr); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->SetDataNode(nullptr); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); return; } // otherwise we can activate em all m_Controls->blendMode->setEnabled(true); - m_Controls->renderMode->setEnabled(true); // Determine Combo Box mode - { - bool usegpu = false; - bool useray = false; - bool usemip = false; - selectedNode->GetBoolProperty("volumerendering.usegpu", usegpu); - selectedNode->GetBoolProperty("volumerendering.useray", useray); - selectedNode->GetBoolProperty("volumerendering.usemip", usemip); - - int blendMode; - if (selectedNode->GetIntProperty("volumerendering.blendmode", blendMode)) - m_Controls->blendMode->setCurrentIndex(blendMode); + int blendMode; + if (selectedNode->GetIntProperty("volumerendering.blendmode", blendMode)) + m_Controls->blendMode->setCurrentIndex(blendMode); - if (usemip) - m_Controls->blendMode->setCurrentIndex(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND); - - int mode = DEFAULT_RENDERMODE; - - if (useray) - mode = RAYCAST_RENDERMODE; - else if (usegpu) - mode = GPU_RENDERMODE; - - m_Controls->renderMode->setCurrentIndex(mode); - } auto time = this->GetRenderWindowPart()->GetTimeNavigationController()->GetSelectedTimeStep(); m_Controls->transferFunctionWidget->SetDataNode(selectedNode, time); m_Controls->transferFunctionWidget->setEnabled(true); m_Controls->transferFunctionGeneratorWidget->SetDataNode(selectedNode, time); m_Controls->transferFunctionGeneratorWidget->setEnabled(true); } diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h index 658d5fc133..51e5949bec 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h @@ -1,69 +1,68 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QMITKVOLUMEVISUALIZATIONVIEW_H #define QMITKVOLUMEVISUALIZATIONVIEW_H #include "ui_QmitkVolumeVisualizationViewControls.h" // mitk core #include #include #include #include #include /** * @brief */ class QmitkVolumeVisualizationView : public QmitkAbstractView, public mitk::IRenderWindowPartListener { Q_OBJECT public: static const std::string VIEW_ID; QmitkVolumeVisualizationView(); ~QmitkVolumeVisualizationView() override = default; void SetFocus() override; private Q_SLOTS: void OnCurrentSelectionChanged(QList nodes); void OnMitkInternalPreset(int mode); void OnEnableRendering(bool state); - void OnRenderMode(int mode); - void OnBlendMode(int mode); + void OnBlendMode(int index); void OnSelectedTimePointChanged(const mitk::TimePointType &); protected: void RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) override; void RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart) override; private: void CreateQtPartControl(QWidget* parent) override; void UpdateInterface(); Ui::QmitkVolumeVisualizationViewControls* m_Controls; mitk::WeakPointer m_SelectedNode; QmitkSliceNavigationListener m_TimePointChangeListener; }; #endif // QMITKVOLUMEVISUALIZATIONVIEW_H diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui index 94fd15064f..1ed8af665d 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui @@ -1,128 +1,132 @@ QmitkVolumeVisualizationViewControls 0 0 - 300 + 319 600 0 0 Volume visualization - + Selected image: 0 0 0 40 - + + + + 0 + 0 + + - Click this checkbox to enable volumerendering in the 3D view of the selected image + Enable volume rendering of the selected image in the 3D view - Volumerendering + Volume rendering - - - - 0 - 1 - - - - Select render mode + + + Blend mode: - + + + Switch between different blend modes + + 0 0 0 0 0 1 QmitkSingleNodeSelectionWidget QWidget
QmitkSingleNodeSelectionWidget.h
QmitkTransferFunctionWidget QWidget
QmitkTransferFunctionWidget.h
QmitkTransferFunctionGeneratorWidget QWidget
QmitkTransferFunctionGeneratorWidget.h
1