Skip to content

Instantly share code, notes, and snippets.

@AOphagen
Last active October 25, 2018 18:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AOphagen/f09d302320db67168dd9fe7316bd35e5 to your computer and use it in GitHub Desktop.
Save AOphagen/f09d302320db67168dd9fe7316bd35e5 to your computer and use it in GitHub Desktop.
MultiVolumeRenderWindow - prototypical test of multi volume handling with VTK
// Created by: A. Ophagen
// Created on: 2018-10-25
#define RENDERPIPELINEOUTPUT 0
#include "MultiVolumeRenderWindow.h"
#include <vtkNew.h>
#include <vtkImageData.h>
#include <vtkTrivialProducer.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <vtkMultiVolume.h>
#include <vtkOpenGLGPUVolumeRayCastMapper.h>
int main(int , char *[])
{
// Multi volume instance
// ---------------------
vtkNew<vtkMultiVolume> overlappingVol;
vtkNew<vtkOpenGLGPUVolumeRayCastMapper> mapper;
mapper->SetUseJittering(0);
overlappingVol->SetMapper(mapper);
// Create data
std::vector< vtkSmartPointer< vtkTrivialProducer > > producers{};
std::vector< vtkSmartPointer< vtkColorTransferFunction > > ctfs{};
std::vector< vtkSmartPointer< vtkPiecewiseFunction > > sofs{};
std::vector< vtkSmartPointer< vtkPiecewiseFunction > > gofs{};
std::vector< vtkSmartPointer< vtkVolume > > volumes{};
// Volume 0 (value 0 - -127, size 128 x 128 x 128)
// ---------------------------
int index = static_cast< int >( producers.size() );
producers.emplace_back( vtkSmartPointer< vtkTrivialProducer >::New() );
producers.back()->SetOutput( createVtkImage( true, 128, 128, 128 ) );
producers.back()->Update();
ctfs.emplace_back( vtkSmartPointer<vtkColorTransferFunction>::New() );
ctfs.back()->AddRGBPoint( -127, 0.0, 0.0, 0.0 );
ctfs.back()->AddRGBPoint( -63, 1.0, 0.5, 0.3 );
ctfs.back()->AddRGBPoint( 0, 1.0, 1.0, 0.9 );
ctfs.back()->SetColorSpaceToHSV();
sofs.emplace_back( vtkSmartPointer<vtkPiecewiseFunction>::New() );
sofs.back()->AddPoint( -127, 0.0 );
sofs.back()->AddPoint( 0, 1.0 );
// gofs.emplace_back( vtkSmartPointer<vtkPiecewiseFunction>::New() );
// gofs.back()->AddPoint( 0, 1.0 );
// gofs.back()->AddPoint( 100, 1.0 );
volumes.emplace_back( vtkSmartPointer<vtkVolume>::New() );
volumes.back()->GetProperty()->SetColor(ctfs.back());
volumes.back()->GetProperty()->SetScalarOpacity(sofs.back());
// volumes.back()->GetProperty()->SetGradientOpacity(gofs.back());
volumes.back()->GetProperty()->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
// use data for volume 0
mapper->SetInputConnection( index, producers.back()->GetOutputPort());
overlappingVol->SetVolume( volumes.back(), index );
// Volume 1 (value 0 - 63, size 64 x 64 x 64)
// ---------------------------
index = static_cast< int >( producers.size() );
producers.emplace_back( vtkSmartPointer< vtkTrivialProducer >::New() );
producers.back()->SetOutput( createVtkImage( false, 64, 64, 64 ) );
producers.back()->Update();
ctfs.emplace_back( vtkSmartPointer<vtkColorTransferFunction>::New() );
ctfs.back()->AddRGBPoint( 0, 0.0, 0.0, 0.0 );
ctfs.back()->AddRGBPoint( 15, 0.5, 1.0, 0.3 );
ctfs.back()->AddRGBPoint( 47, 0.5, 1.0, 0.3 );
ctfs.back()->AddRGBPoint( 63, 1.0, 1.0, 0.9 );
ctfs.back()->SetColorSpaceToHSV();
sofs.emplace_back( vtkSmartPointer<vtkPiecewiseFunction>::New() );
sofs.back()->AddPoint( 0, 0.0 );
sofs.back()->AddPoint( 63, 1.0 );
// gofs.emplace_back( vtkSmartPointer<vtkPiecewiseFunction>::New() );
// gofs.back()->AddPoint( 0, 1.0 );
// gofs.back()->AddPoint( 100, 1.0 );
volumes.emplace_back( vtkSmartPointer<vtkVolume>::New() );
volumes.back()->GetProperty()->SetColor(ctfs.back());
volumes.back()->GetProperty()->SetScalarOpacity(sofs.back());
// volumes.back()->GetProperty()->SetGradientOpacity(gofs.back());
volumes.back()->GetProperty()->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
volumes.back()->RotateX( -55. );
volumes.back()->SetPosition( 80., 50., 130. );
// use data for volume 1
mapper->SetInputConnection( index, producers.back()->GetOutputPort());
overlappingVol->SetVolume( volumes.back(), index );
// Volume 2 (value 0 - 127, size 64 x 128 x 64)
// -----------------------------
index = static_cast< int >( producers.size() );
producers.emplace_back( vtkSmartPointer< vtkTrivialProducer >::New() );
producers.back()->SetOutput( createVtkImage( false, 64, 128, 64 ) );
producers.back()->Update();
ctfs.emplace_back( vtkSmartPointer<vtkColorTransferFunction>::New() );
ctfs.back()->AddRGBPoint( 0, 1.0, 0.3, 0.2 );
ctfs.back()->AddRGBPoint( 64, 0.3, 0.2, 0.9 );
ctfs.back()->AddRGBPoint( 127, 0.5, 0.6, 1.0 );
sofs.emplace_back( vtkSmartPointer<vtkPiecewiseFunction>::New() );
sofs.back()->AddPoint( 0, 0.3 );
sofs.back()->AddPoint( 127, 0.8 );
// gofs.emplace_back( vtkSmartPointer<vtkPiecewiseFunction>::New() );
// gofs.back()->AddPoint( 0, 1.0 );
// gofs.back()->AddPoint( 100, 1.0 );
volumes.emplace_back( vtkSmartPointer<vtkVolume>::New() );
volumes.back()->GetProperty()->SetColor( ctfs.back() );
volumes.back()->GetProperty()->SetScalarOpacity( sofs.back() );
// volumes.back()->GetProperty()->SetGradientOpacity( gofs.back() );
volumes.back()->GetProperty()->SetInterpolationType( VTK_LINEAR_INTERPOLATION );
volumes.back()->SetPosition( 210., 200., -90. );
volumes.back()->RotateX( 90. );
volumes.back()->RotateY( -95. );
volumes.back()->RotateZ( -5. );
// use data for volume 2
mapper->SetInputConnection( index, producers.back()->GetOutputPort() );
overlappingVol->SetVolume( volumes.back(), index );
// Rendering context
vtkNew<vtkRenderWindow> renWin;
renWin->SetSize( 512, 512 );
renWin->SetMultiSamples( 0 );
vtkNew<vtkRenderer> ren;
renWin->AddRenderer( ren );
ren->SetBackground( 0.0, 0.0, 0.0 );
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow( renWin );
#if RENDERPIPELINEOUTPUT
std::cout << "RENDERER " << std::endl;
std::cout << "======== " << std::endl;
ren->PrintSelf( std::cout, vtkIndent() );
std::cout << "MAPPER " << std::endl;
std::cout << "====== " << std::endl;
mapper->PrintSelf( std::cout, vtkIndent() );
std::cout << "MULTI VOLUME " << std::endl;
std::cout << "============ " << std::endl;
overlappingVol->PrintSelf( std::cout, vtkIndent() );
for( size_t i = 0; i < volumes.size(); ++i )
{
std::cout << "VOLUME " << i << std::endl;
std::cout << "========" << std::endl;
volumes.at( i )->PrintSelf( std::cout, vtkIndent() );
vtkImageData* image = vtkImageData::SafeDownCast( producers.at( i )->GetOutputDataObject( 0 ) );
if(image)
{
std::cout << "IMAGE DATA " << i << std::endl;
std::cout << "============" << std::endl;
image->PrintSelf( std::cout, vtkIndent(2) );
}
std::cout << "VOLUME PROPERTIES " << i << std::endl;
std::cout << "===================" << std::endl;
volumes.at( i )->GetProperty()->PrintSelf( std::cout, vtkIndent(2) );
std::cout << "-> COLOR TRANSFER FUNCTION " << i << std::endl;
std::cout << " =========================" << std::endl;
volumes.at( i )->GetProperty()->GetRGBTransferFunction()->PrintSelf( std::cout, vtkIndent(3) );
std::cout << "-> SCALAR OPACITY " << i << std::endl;
std::cout << " ================" << std::endl;
volumes.at( i )->GetProperty()->GetScalarOpacity()->PrintSelf( std::cout, vtkIndent(3) );
std::cout << "-> GRADIENT OPACITY " << i << std::endl;
std::cout << " ==================" << std::endl;
volumes.at( i )->GetProperty()->GetGradientOpacity()->PrintSelf( std::cout, vtkIndent(3) );
}
#endif
ren->AddVolume(overlappingVol);
renWin->Render();
iren->Start();
}
vtkSmartPointer<vtkImageData> createVtkImage(bool invert , int x, int y, int z)
{
// Create an image data
vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
// Specify the size of the image data
imageData->SetDimensions( x, y, z);
imageData->AllocateScalars(VTK_DOUBLE,1);
int* dims = imageData->GetDimensions();
// Fill every entry of the image data with "2.0"
for (int slice = 0; slice < dims[2]; slice++)
{
for (int row = 0; row < dims[1]; row++)
{
for (int voxel = 0; voxel < dims[0]; voxel++)
{
double value = invert ? -slice : slice;
double* pixel = static_cast<double*>( imageData->GetScalarPointer(
voxel, row, slice ) );
pixel[0] = value;
}
}
}
return imageData;
}
// Created by: Angelika Ophagen
// Created on: 2018-10-25
#include <vtkSmartPointer.h>
class vtkImageData;
vtkSmartPointer<vtkImageData> createVtkImage(bool invert, int x = 3, int y = 3, int z = 3 );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment