VTK随笔十二:体绘制(体绘制管线、vtkVolumeMapper、vtkVolume、不规则网格数据体绘制技术 )

news2024/9/22 18:31:32

        体绘制,有时又称作三维重建(区别于投影图像的三维重建),是一种直接利用体数据来生成二维图像的绘制技术。与面绘制不同,体绘制技术不需要提取体数据内部的等值面,它是一个对三维体数据进行采样和合成的过程。体绘制能够通过设置不透明度值来显示体数据内部的不同成分和细节,例如显示人体 CT图像的不同器官和组织。

一、体绘制管线 

从可视化管线的组成上来讲,体绘制的渲染管线与几何渲染管线基本一致。

1、首先定义vtkVolumeRayCastMapper 对象。定义了一个光线投射体绘制 Mapper。

2、定义 vtkVolumeProperty 体绘制属性对象,并设置标量不透明度传输函数、梯度不透
明度函数和颜色传输函数以及阴影。

3、定义 vtkVolume 对象。vtkVolume 与几何渲染中的 vtkActor 作用一致。

4、定义vtkRenderer 对象,建立可视化管线。

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    // //设置光线采样距离
    // volumeMapper->SetSampleDistance(volumeMapper->GetSampleDistance()*4);
    // //设置图像采样步长
    // volumeMapper->SetAutoAdjustSampleDistances(0);
    // volumeMapper->SetImageSampleDistance(4);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    //测试隐藏部分数据,对比不同的设置
    // compositeOpacity->AddPoint(120,  0.00);
    // compositeOpacity->AddPoint(180,  0.60);
    // volumeProperty->SetScalarOpacity(compositeOpacity);

    vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    volumeGradientOpacity->AddPoint(10,  0.0);
    volumeGradientOpacity->AddPoint(90,  0.5);
    volumeGradientOpacity->AddPoint(100, 1.0);
    //volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    color->AddRGBPoint(0.000,  0.00, 0.00, 0.00);
    color->AddRGBPoint(64.00,  1.00, 0.52, 0.30);
    color->AddRGBPoint(190.0,  1.00, 1.00, 1.00);
    color->AddRGBPoint(220.0,  0.20, 0.20, 0.20);
    volumeProperty->SetColor(color);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renderer->AddVolume( volume );

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("VolumeRendering");
    w.show();

    return a.exec();
}

运行效果:

二、vtkVolumeMapper

        vtkVolumeMapper 是所有体绘制 Mapper 类的虚基类,提供接口函数,并由其子类实现具体的功能。

1、vtkFixedPointVolumeRayCastMapper

        该类能够实现基于 Alpha 合成的体绘制方法和最大密度投影体绘制方法,能够支持任意类型的一元或者独立多元数据。例如,当输入数据的二元独立数据时,第一元数据用于颜色映射而第二元用于不透明度映射;对于四元的unsigned char 类型数据,则前三元数据作为颜色值而第四元作为不透明度使用。该类使用了空间跳跃技术来加速体绘制渲染过程,而且在内部计算时统一使用了 float 数据类型。

2、vtkGPUVolumeRayCastMapper

        vtkGPUVolumeRayCastMapper 实现了基于GPU 加速的光线投射体绘制算法。该类可以利用下面的函数设置光线采样步长、图像采样距离、是否自动调节图像采样距离等。
void SetSampleDistance (float)
void SetlmageSampleDistance (float)
void SetAutoAdjustSampleDistances (int)

3、裁剪

        对于一些体积比较大、结构比较复杂的体数据进行体绘制的渲染效果难以展示其内部细节,需要用到裁剪技术来渲染部分数据。vtkVolumeMapper 类中提供了两种裁剪技术,分别是 Cropping 和 Clipping。 

        Cropping 技术只支持 vtkmageData 数据的裁剪。该方法在每个坐标轴上定义两个裁剪面,共6个裁剪平面将三维空间分割为 27 个可视区域。

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    //cropping
    volumeMapper->SetCropping(1);
    volumeMapper->SetCroppingRegionPlanes(100,200, 100,200, 100,200);
    volumeMapper->SetCroppingRegionFlags(0x0002000);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    //volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    volumeGradientOpacity->AddPoint(10,  0.0);
    volumeGradientOpacity->AddPoint(90,  0.5);
    volumeGradientOpacity->AddPoint(100, 1.0);
    volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    color->AddRGBPoint(0.000,  0.00, 0.00, 0.00);
    color->AddRGBPoint(64.00,  1.00, 0.52, 0.30);
    color->AddRGBPoint(190.0,  1.00, 1.00, 1.00);
    color->AddRGBPoint(220.0,  0.20, 0.20, 0.20);
    volumeProperty->SetColor(color);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renderer->AddVolume( volume );

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("VolumeRendering");
    w.show();

    return a.exec();
}

运行效果:

Clipping 技术支持 vtkImageData和 vtkUnstructuredGrid 数据类型。 

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkPlane.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    //clipping
    vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
    plane->SetOrigin(100,100,0);
    plane->SetNormal(1,1,0);
    volumeMapper->AddClippingPlane(plane);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    volumeGradientOpacity->AddPoint(10,  0.0);
    volumeGradientOpacity->AddPoint(90,  0.5);
    volumeGradientOpacity->AddPoint(100, 1.0);
    volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    color->AddRGBPoint(0.000,  0.00, 0.00, 0.00);//设置颜色传输函数
    color->AddRGBPoint(64.00,  1.00, 0.52, 0.30);
    color->AddRGBPoint(190.0,  1.00, 1.00, 1.00);
    color->AddRGBPoint(220.0,  0.20, 0.20, 0.20);
    volumeProperty->SetColor(color);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(1.0, 1.0, 1.0);
    renderer->AddVolume( volume );

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("Clipping");
    w.show();

    return a.exec();
}

运行效果:

三、vtkVolume 

        vtkVolume 类似于几何渲染中的 vtkActor,用于表示渲染场景中的对象。除了存储基本的变换信息(平移、旋转、放缩等),其内部还存储了两个重要对象。这两个对象分别是vtkAbstractVolumeMapper 对象和 vtkVolumeProperty 对象。

1、不透明度传输函数

         不透明度传输函数是一个分段线性标量映射函数,利用该函数可将光线投射过程中的采样点灰度值映射为不同的不透明度值,以决定最终的颜色值。

2、梯度不透明度函数

         将梯度模值映射为一个不透明度乘子,从而增强过渡区域的显示效果。该函数同样使用的是 vtkPiecewiseFunction类。例如,在不同材料的临界区域,如空气到软组织,或者软组织到骨头的临界区,梯度值会比较大,而材料的内部梯度值则会相对比较小。

3、颜色传输函数

        颜色传输函数与不透明度传输函数的使用类似,二者的不同之处在于颜色传输函数是将一个标量值映射为一个颜色值。这个颜色值既可以是RGB值,也可以是HSV值。VTK中颜色传输函数采用 vtkColorTransferFunction 类实现。

4、光照与阴影

        通过 vtkVolumeProperty可以设置体绘制的阴影效果(Shading)。阴影效果主要受环境光系数、散射光系数、反射光系数和高光强度四个参数影响。使用vkVolumeProperty::SetAmbient()设置环境光系数;使用vtkVolumeProperty::SetDiffuse()设置散射光系数;使用vtkVolumeProperty::SetSpecular()设置反射光系数。一般情况下,这三个系数之和为 1。但是有时在体绘制过程中为了提高亮度,三值之和会大于1。另外,还有一个参数是高光强度(Specular Power),用于控制体绘制的外观平滑程度。可使用vtkVolumeProperty::SetSpecularPower()设置该参数。

5、体绘制加速:vtkLODProp3D

        对于一个大数据来讲,体绘制是一个计算量非常庞大、非常耗时的操作。尤其是在用户交互过程,需要不断对数据进行渲染,这样就造成了交互不流畅,用户体验差。可以使用VTKLODProp3D来解决这个问题,提高绘制速度。vtkLODProp3D类的用法与vtkVolume类似,两者都继承自vtkProp3D。不同的是,vtkLODProp3D类能够支持多个Mapper、Property和Texture对象,并由他选择Mapper对象实现绘制。
        vtkLODProp3D在渲染过程中,会为每个Mapper估计一个渲染时间,并选择一个最优的实现渲染。 

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkLODProp3D.h>
#include <vtkCamera.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/mummy.128.vtk");
    reader->Update();

    vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
    volumeMapper->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn();  //打开或者关闭阴影测试
    volumeProperty->SetAmbient(0.4);
    volumeProperty->SetDiffuse(0.6);
    volumeProperty->SetSpecular(0.2);

    vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
    compositeOpacity->AddPoint(70,   0.00);
    compositeOpacity->AddPoint(90,   0.40);
    compositeOpacity->AddPoint(180,  0.60);
    volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

    vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
    color->AddRGBPoint(0.000,  0.00, 0.00, 0.00);
    color->AddRGBPoint(64.00,  1.00, 0.52, 0.30);
    color->AddRGBPoint(190.0,  1.00, 1.00, 1.00);
    color->AddRGBPoint(220.0,  0.20, 0.20, 0.20);
    volumeProperty->SetColor(color);

    vtkSmartPointer<vtkGPUVolumeRayCastMapper> hiresMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
    hiresMapper->SetInputConnection(reader->GetOutputPort());
    hiresMapper->SetAutoAdjustSampleDistances(0);

    vtkSmartPointer<vtkGPUVolumeRayCastMapper> lowresMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
    lowresMapper->SetInputConnection(reader->GetOutputPort());
    lowresMapper->SetAutoAdjustSampleDistances(0);
    lowresMapper->SetSampleDistance(4*hiresMapper->GetSampleDistance());
    lowresMapper->SetImageSampleDistance(4*hiresMapper->GetImageSampleDistance());

    vtkSmartPointer<vtkLODProp3D> prop = vtkSmartPointer<vtkLODProp3D>::New();
    prop->AddLOD(lowresMapper, volumeProperty, 0.0);
    prop->AddLOD(hiresMapper,  volumeProperty, 0.0);

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    double volumeView[4]={0, 0, 0.5, 1 };
    double lodpropView[4]={0.5,0, 1,1 };

    vtkSmartPointer<vtkRenderer> volumeRender = vtkSmartPointer<vtkRenderer>::New();
    volumeRender->SetBackground(1,1, 0);
    volumeRender->AddVolume(volume);
    volumeRender->SetViewport(volumeView);

    vtkSmartPointer<vtkRenderer> propRender = vtkSmartPointer<vtkRenderer>::New();
    propRender->SetBackground(0,1, 0);
    propRender->AddVolume(prop);
    propRender->SetViewport(lodpropView);

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(volumeRender);
    renderWindow->AddRenderer(propRender);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("vtkLODProp3D");
    w.show();

    volumeRender->GetActiveCamera()->SetPosition(0, -1, 0);
    volumeRender->GetActiveCamera()->SetFocalPoint(0, 0, 0);
    volumeRender->GetActiveCamera()->SetViewUp(0, 0, 1);
    volumeRender->GetActiveCamera()->Azimuth(30);
    volumeRender->GetActiveCamera()->Elevation(30);
    volumeRender->ResetCamera();
    propRender->SetActiveCamera(volumeRender->GetActiveCamera());

    return a.exec();
}

 运行效果:

四、不规则网格数据体绘制技术 

        在 VTK中,不规则网格的体绘制渲染的流程与规则网格的体绘制流程一致。不同的是,
需要选择应用于不规则网格数据的 Mapper 对象。所有支持不规则网格体绘制的 Mapper 类都继承自vtkUnstructuredGridVolumeMapper。 

1、vtkUnstructuredGridVolumeRayCastMapper

        vtkUnstructuredGridVolumeRayCastMapper 实现了基于软件实现的不规则网格光线投射算法。该 Mapper 仅支持四面体数据,因此对于非四面体数据,需要借助四面体化Filter 进行数据转换。vtkUnstructuredGridVolumeRayCastMapper::SetRayCastFunction()函数可以设置光线投射函数的类型。该类型必须为vkUnstructuredGridVolumeRayCastFunction。目前 VTK 中仅有一个子类:vtkUnstructuredBunykRayCastFunction。该方法需要较大的内存,因此不适合大数据的渲染处理。

2、vtkUnstructuredGridVolumeZSweepMapper

        vtkUnstructuredGridVolumeZSweepMapper 实现了一种可以在任何平台下运行的体绘制方法。该方法是 VTK中不规则网格体绘制方法中最慢的一种,但相对于光线投射方法,该方法对内存的需求较小,因此可以用来渲染大数据。与光线投射Mapper类似,该类支持vtkUnstructuredGridVolumeZSweepMapper:SetRayIntegrator()函数,默认情况下 VTK 会自动为用户选择 Ray Integrator 类型。 

3、vtkProjectedTetrahedraMapper

        vtkProjectedTetrahedraMapper 类实现了经典的投影四面体法。该方法利用 OpenGL 在给定视点下将四面体转换为三角面片,通过硬件加速渲染这些三角面片,提高了染效率。但是,并非所有硬件都会支持该类中用到的OpenGL技术,可能会导致染失败。通常该类常与ZSweep方法或者光线投射法相结合,组成LOD(LevelofDetail),使得在交互过程中使用投影四面体方法能够快速地渲染,而交互完成后利用光线投射或者ZSweep技术生成更为精确的图像。 

示例代码:

#include <QApplication>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkStructuredPointsReader.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkDataSetTriangleFilter.h>
#include <vtkThreshold.h>
#include <vtkUnstructuredGridVolumeRayCastMapper.h>
#include <vtkUnstructuredGridVolumeZSweepMapper.h>
#include <vtkProjectedTetrahedraMapper.h>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
    ren->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New();
    reader->SetFileName("D:/data/ironProt.vtk");
    reader->Update();

    vtkSmartPointer<vtkThreshold> thresh = vtkSmartPointer<vtkThreshold>::New();
    thresh->SetUpperThreshold(80);
    thresh->AllScalarsOff();
    thresh->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkDataSetTriangleFilter> trifilter = vtkSmartPointer<vtkDataSetTriangleFilter>::New();
    trifilter->SetInputConnection(thresh->GetOutputPort());

    vtkSmartPointer<vtkPiecewiseFunction> opacityTransferFunction = vtkSmartPointer<vtkPiecewiseFunction>::New();
    opacityTransferFunction->AddPoint(80.0,  0.0);
    opacityTransferFunction->AddPoint(120.0, 0.2);
    opacityTransferFunction->AddPoint(255.0, 0.2);

    vtkSmartPointer<vtkColorTransferFunction> colorTransferFunction = vtkSmartPointer<vtkColorTransferFunction>::New();
    colorTransferFunction->AddRGBPoint(80.0,  0.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(120.0, 0.0, 0.0, 1.0);
    colorTransferFunction->AddRGBPoint(160.0, 1.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(200.0, 0.0, 1.0, 0.0);
    colorTransferFunction->AddRGBPoint(255.0, 0.0, 1.0, 1.0);

    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    volumeProperty->SetColor(colorTransferFunction);
    volumeProperty->SetScalarOpacity(opacityTransferFunction);
    volumeProperty->ShadeOff();
    volumeProperty->SetInterpolationTypeToLinear();

    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetProperty(volumeProperty);

    int RenderType = 3;
    if (RenderType == 1)
    {
        vtkSmartPointer<vtkUnstructuredGridVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkUnstructuredGridVolumeRayCastMapper>::New();
        volumeMapper->SetInputConnection(trifilter->GetOutputPort());
        volume->SetMapper(volumeMapper);
        ren->AddVolume(volume);
    }
    else if(RenderType == 2)
    {
        vtkSmartPointer<vtkUnstructuredGridVolumeZSweepMapper> volumeMapper = vtkSmartPointer<vtkUnstructuredGridVolumeZSweepMapper>::New();
        volumeMapper->SetInputConnection(trifilter->GetOutputPort());
        volume->SetMapper(volumeMapper);
        ren->AddVolume(volume);
    }
    else if(RenderType == 3)
    {
        vtkSmartPointer<vtkProjectedTetrahedraMapper> volumeMapper = vtkSmartPointer<vtkProjectedTetrahedraMapper>::New();
        volumeMapper->SetInputConnection(trifilter->GetOutputPort());
        volume->SetMapper(volumeMapper);
        ren->AddVolume(volume);
    }

    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(ren);

    QVTKOpenGLNativeWidget w;
    w.resize(640, 480);
    w.setRenderWindow(renderWindow);
    w.setWindowTitle("UnstructuredGridVolumeRendering");
    w.show();

    return a.exec();
}

 运行效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习入门】计算机视觉任务

一、引言 对于神经网络&#xff0c;可以把中间的隐藏层看作一个黑盒子&#xff0c;这个黑盒子能自动选择如何提取特征&#xff0c;这不同于传统机器学习的人工操作&#xff0c;它的实现原理也是我们学习深度学习的重点。本文章以计算机视觉任务中的图像分类任务为例子&#xff…

zookeeper 集群搭建 及启动关闭脚本

1准备奇数台机子3&#xff0c;5&#xff0c;7 我准备的是三台 192.168.58.81 zookeeper-1 192.168.58.82 zookeeper-2 192.168.58.83 zookeeper-3 下载jdk 把他配置环境变量并检查是否是环境变量 echo $JAVA_HOME cd /opt/software wget http://mirrors.hust.edu.…

docker部署project-exam-system项目

8月30日笔记 项目实战&#xff1a;使用docker部署project-exam-system 1、背景&#xff1a; 使用基础的docker指令来创建镜像&#xff0c;实现项目的发布&#xff0c;使用Dockderfile&#xff0c;docker compose编排容器。 2、环境准备&#xff1a; &#xff08;1&#x…

sts 0/1 没有 pod生成 -> kube-controller-manager没了

kube-controller-manager.yaml 在 nerdctl ps -a 看不到 journalctl -xu kubelet > /tmp/kubelet.log /tmp/kubelet.log 老6

OpenSetting组件的用法

文章目录 1. 概念介绍2. 使用方法与主要功能2.1 使用方法2.2 主要功能 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取App自身信息"相关的内容&#xff0c;本章回中将介绍一个三方包:open_setting.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念…

JavaWeb:实验二JSP表单开发及访问数据库

一、实验目的 1&#xff0e;掌握JSP表单的开发方法。 2&#xff0e;熟悉JDBC技术和使用JDBC连接各种数据库。 二、实验性质 综合性实验 三、实验内容 实现注册与登录功能&#xff1a; 1.创建一个数据库&#xff0c;在数据库建立用户表。&#xff08;5分&#xff09; 2…

城市管理违规行为智能识别 Task3学习心得

本次学习主要针对数据集增强和模型预测 1、数据增强&#xff1a; 1&#xff09;将四张训练图像组合成一张&#xff0c;增加物体尺度和位置的多样性。 2&#xff09;复制一个图像的随机区域并粘贴到另一个图像上&#xff0c;生成新的训练样本 3&#xff09;图像的随机旋转、…

day25 Java基础——面向对象两万字详解!(纯干货)

day25 Java基础——面向对象两万字详解&#xff01;&#xff08;纯干货&#xff09; 文章目录 day25 Java基础——面向对象两万字详解&#xff01;&#xff08;纯干货&#xff09;1. 类与对象的关系类&#xff08;Class&#xff09;对象&#xff08;Object&#xff09;类与对象…

gitee绑定公钥后依旧无法使用_gitee push添加公钥无效

解决&#xff1a; 步骤按照官网操作即可&#xff1a;gitee官方说明 看看远程地址是否使用的http模式&#xff0c;是的话换ssh模式

Adobe Acrobat Reader的高级功能详解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; Adobe Acrobat Reader是广泛使用的PDF查看器&#xff0c;其不仅可以用于查看和打印PDF文件&#xff0c;还具有一些高级功能&#xff0c;可以提升用户的PDF文档处理效率。以下是对Adobe Acrobat Reader的一些…

RH850系列芯片深度剖析 1.7-启动流程解析

RH850系列芯片深度剖析 1.7-启动流程解析 文章目录 RH850系列芯片深度剖析 1.7-启动流程解析一、简介二、启动相关文件说明三、启动相关的段四、启动流程4.1 启动文件启动4.1.1 寄存器初始化4.1.2 时钟初始化4.1.3 模块Standby寄存器初始化4.1.4 启动从核4.1.5 硬件初始化4.1.5…

vector模拟实现迭代器失效

目录 1.vector和vector> 1.1两者的区别 1.2遍历的方法 2.vector模拟实现的准备 3.reserve出现的问题及解决方案 4.遍历vector的三种方式 5.关于typename的使用 6.insert导致的迭代其实失效问题 6.1因为扩容导致的迭代器失效 6.2因为插入数据倒置的迭代器失效 1.vec…

【精彩回顾·成都】成都 UG 生成式 AI 工作坊:AI 革命下的商业模式创新!

文章目录 前言一、活动介绍二、精彩分享内容及活动议程2.1、亚马逊云科技社区情况和活动介绍2.2、《浅谈 AIGC 商业化》2.3、《AI 浪潮下的产品落地》2.4、现场互动情况2.5、休息茶歇时间2.6、《AI 赋能商业革新&#xff1a;智能化转型的策略与实践》2.7、《动手实践&#xff1…

GAMES104:10+11游戏引擎中物理系统的基础理论算法和高级应用-学习笔记

文章目录 概览一&#xff0c;物理对象与形状1.1 对象 Actor1.2 对象形状Actor Shape 二&#xff0c;力与运动2.1 牛顿定律2.2 欧拉法2.2.1 显式欧拉法Explicit (Forward) Euler’s Method2.2.2 隐式欧拉法 Implicit (Backward) Euler’s Method2.2.3 半隐式欧拉法 Semi-implici…

【iOS】通过第三方库Masonry实现自动布局

目录 前言 约束 添加约束的规则 使用Masonry自动布局 Masonry的常见使用方法 补充 前言 在暑期完成项目时&#xff0c;经常要花很多时间在调试各种控件的位置上&#xff0c;因为每一个控件的位置都需要手动去计算&#xff0c;在遇到循环布局的控件时&#xff0c;还需要设…

使用文件系统管理硬件设备

1、描述一个文件系统 介绍如何使用文件系统来管理计算机系统中所有的硬件设计和磁盘 之前直接在sys_open/sys_read/sys_read中对具体的tty设备的打开、读写进行操作&#xff0c;并且只是非常粗浅地介绍了文件系统的一些概念。接下来将正式引入文件系统 由于文件系统需要考虑不…

从FasterTransformer源码解读开始了解大模型(2.4)代码通读05

从FasterTransformer源码解读开始了解大模型&#xff08;2.4&#xff09;代码解读05-ContextDecoder的前向01 写在前面的话 ContextDecoder部分是用于处理输入部分的组件层&#xff0c;在这一层中&#xff0c;会对所有输入的input ids进行处理&#xff0c;计算Attention&…

全国大学生数学建模比赛——关联规则

一、问题背景与关联规则适用性 在数学建模比赛中&#xff0c;常常会遇到需要分析大量数据以寻找变量之间潜在关系的问题。关联规则分析作为一种数据挖掘技术&#xff0c;特别适用于这种场景。例如&#xff0c;在一些实际问题中&#xff0c;可能需要从众多的因素中找出哪些因素之…

基于Python的量化交易回测框架Backtrader初识记录(一)

版权声明&#xff1a;本文为博主原创文章&#xff0c;如需转载请贴上原博文链接&#xff1a;基于Python的量化交易回测框架Backtrader初识记录&#xff08;一&#xff09;-CSDN博客 前言&#xff1a;近期以来&#xff0c;对股市数据获取及预处理算是告一段落&#xff0c;下一步…

Java-多线程机制

上篇我提到一些多线程的基本使用方法&#xff0c;但并没有说到底层原理&#xff0c;你或许会有一些疑问&#xff0c;为什么不直接调用Run方法而是要用start方法启动线程&#xff1f;多线程到底是怎样执行的&#xff1f;接下来我会详细带你了解多线程的机制原理。 多线程的底层…