如何使用 vtk.js 渲染 Float32Array 立方体?

How to render a Float32Array cube with vtk.js?

我想用 vtk.js 渲染 3D 体积。我的问题是 vtk.js 文档中的所有 tutorials/examples 都加载并呈现 vti 文件。就我而言,我的数据只是一个 Float32Array,其中包含 3D 图像的值。如何使用 vtk.js 对其进行体积渲染?我需要一个不在文件系统上创建额外文件的解决方案。

我设法(在同事的帮助下)渲染了一个像这样的随机立方体体积:

// 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>

Resistance is futile!