I want to render a 3D volume with vtk.js. My issue is that all the tutorials/examples in the vtk.js documentation load and render vti
files. In my case, my data is just a Float32Array
which contains the values of a 3D image. How can I volume-render that using vtk.js? I need a solution that creates no additional files on the file system.
I managed (with a coworker's help) to render a random cube volume like this:
// pseudo imports (avoids having to use fully qualified names)
var vtkFullScreenRenderWindow = vtk.Rendering.Misc.vtkFullScreenRenderWindow;
var vtkImageData = vtk.Common.DataModel.vtkImageData;
var vtkDataArray = vtk.Common.Core.vtkDataArray;
var vtkVolume = vtk.Rendering.Core.vtkVolume;
var vtkVolumeMapper = vtk.Rendering.Core.vtkVolumeMapper;
var vtkColorTransferFunction = vtk.Rendering.Core.vtkColorTransferFunction;
var vtkPiecewiseFunction = vtk.Common.DataModel.vtkPiecewiseFunction;
var VtkDataTypes = vtkDataArray.VtkDataTypes;
function initRandomCubeVolume() {
var width = 50, height = 50, depth = 50;
var size = width * height * depth;
var values = [];
for (var i = 0; i < size; i++) {
values[i] = Math.random();
}
var scalars = vtkDataArray.newInstance({
values: values,
numberOfComponents: 1, // number of channels (grayscale)
dataType: VtkDataTypes.FLOAT, // values encoding
name: 'scalars'
});
var imageData = vtkImageData.newInstance();
imageData.setOrigin(0, 0, 0);
imageData.setSpacing(1, 1, 1);
imageData.setExtent(0, width - 1, 0, height - 1, 0, depth - 1);
imageData.getPointData().setScalars(scalars);
var volumeMapper = vtkVolumeMapper.newInstance();
volumeMapper.setInputData(imageData);
volumeMapper.setSampleDistance(0.7);
var volumeActor = vtkVolume.newInstance();
volumeActor.setMapper(volumeMapper);
initProps(volumeActor.getProperty());
var view3d = document.getElementById("view3d");
var fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
rootContainer: view3d,
containerStyle: {
height: '100%',
overflow: 'hidden'
},
background: [0, 0, 0]
});
var renderer = fullScreenRenderer.getRenderer();
renderer.addVolume(volumeActor);
renderer.resetCamera();
renderer.getActiveCamera().elevation(-70);
renderer.updateLightsGeometryToFollowCamera();
var renderWindow = fullScreenRenderer.getRenderWindow();
renderWindow.render();
}
function initProps(property) {
property.setRGBTransferFunction(0, newColorFunction());
property.setScalarOpacity(0, newOpacityFunction());
property.setScalarOpacityUnitDistance(0, 4.5);
property.setInterpolationTypeToLinear();
property.setUseGradientOpacity(0, true);
property.setGradientOpacityMinimumValue(0, 0, 5);
property.setGradientOpacityMinimumOpacity(0, 0.0);
property.setGradientOpacityMaximumValue(0, 1);
property.setGradientOpacityMaximumOpacity(0, 1.0);
property.setShade(true);
property.setAmbient(0.2);
property.setDiffuse(0.7);
property.setSpecular(0.3);
property.setSpecularPower(8.0);
}
function newColorFunction() {
var fun = vtkColorTransferFunction.newInstance();
fun.addRGBPoint(0, 0.4, 0.2, 0.0);
fun.addRGBPoint(1, 1.0, 1.0, 1.0);
return fun;
}
function newOpacityFunction() {
var fun = vtkPiecewiseFunction.newInstance();
fun.addPoint(0, 0);
fun.addPoint(0.5, 0);
fun.addPoint(0.5, 1);
fun.addPoint(1, 1);
return fun;
}
initRandomCubeVolume();
#view3d { height: calc(100vh - 20px); /* avoid scrollbar because of margins */ }
<script src="https://unpkg.com/vtk.js"></script>
<div id="view3d"></div>