第06章 03 随时间变化的纹理

要将时变的纹理(从暗到亮)应用到管状模型(例如血管)上,可以使用VTK中的vtkTubeFilter生成管状模型,并结合vtkTexture动态更新纹理。以下是一个完整的C++示例代码,展示如何实现这一效果。


C++示例代码

#include <vtkSmartPointer.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkTexture.h>
#include <vtkImageData.h>
#include <vtkUnsignedCharArray.h>
#include <vtkTubeFilter.h>
#include <vtkTimerCallback.h>
#include <vtkInteractorStyleTrackballCamera.h>

// 自定义回调类,用于更新纹理
class TextureUpdateCallback : public vtkTimerCallback
{
public:
    static TextureUpdateCallback* New()
    {
        return new TextureUpdateCallback;
    }

    void SetTexture(vtkSmartPointer<vtkTexture> texture)
    {
        this->Texture = texture;
    }

    void Execute(vtkObject* caller, unsigned long eventId, void* callData) override
    {
        // 动态更新纹理的像素值
        static int frame = 0;
        frame++;

        // 纹理尺寸
        int width = 256;
        int height = 256;

        // 创建新的图像数据
        vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
        image->SetDimensions(width, height, 1);
        image->AllocateScalars(VTK_UNSIGNED_CHAR, 3);

        // 填充像素值,实现从暗到亮的渐变
        unsigned char* pixelData = static_cast<unsigned char*>(image->GetScalarPointer());
        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x)
            {
                int offset = 3 * (y * width + x);
                double intensity = (double)(x + frame) / (width + frame); // 线性渐变
                pixelData[offset] = static_cast<unsigned char>(255 * intensity);     // R
                pixelData[offset + 1] = static_cast<unsigned char>(255 * intensity); // G
                pixelData[offset + 2] = static_cast<unsigned char>(255 * intensity); // B
            }
        }

        // 更新纹理
        this->Texture->SetInputData(image);
        this->Texture->Modified();
    }

private:
    vtkSmartPointer<vtkTexture> Texture;
};

int main()
{
    // 创建一个示例管状模型(使用圆柱体代替)
    vtkSmartPointer<vtkCylinderSource> cylinderSource = vtkSmartPointer<vtkCylinderSource>::New();
    cylinderSource->SetHeight(5.0);
    cylinderSource->SetRadius(0.5);
    cylinderSource->SetResolution(50);

    // 使用TubeFilter生成管状模型
    vtkSmartPointer<vtkTubeFilter> tubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
    tubeFilter->SetInputConnection(cylinderSource->GetOutputPort());
    tubeFilter->SetRadius(0.2); // 管道的半径
    tubeFilter->SetNumberOfSides(20); // 管道的分段数

    // 创建PolyDataMapper
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(tubeFilter->GetOutputPort());

    // 创建Actor并设置纹理
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    // 创建纹理对象
    vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
    actor->SetTexture(texture);

    // 设置Actor的表面属性
    actor->GetProperty()->SetColor(1.0, 1.0, 1.0);

    // 创建Renderer
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);
    renderer->SetBackground(0.1, 0.2, 0.4);

    // 创建RenderWindow
    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    // 创建RenderWindowInteractor
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);

    // 设置交互样式
    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    renderWindowInteractor->SetInteractorStyle(style);

    // 创建并设置回调对象
    vtkSmartPointer<TextureUpdateCallback> callback = vtkSmartPointer<TextureUpdateCallback>::New();
    callback->SetTexture(texture);

    // 注册回调函数到定时器
    renderWindowInteractor->CreateRepeatingTimer(50); // 每50ms触发一次回调
    renderWindowInteractor->AddObserver(vtkCommand::TimerEvent, callback);

    // 渲染和启动交互
    renderWindow->Render();
    renderWindowInteractor->Start();

    return 0;
}


代码解释

1. 管状模型生成
  • 使用vtkCylinderSource创建一个圆柱体模型(代替血管)。
  • 使用vtkTubeFilter将圆柱体转换为管状模型,设置管道的半径和分段数。
2. 自定义回调类 TextureUpdateCallback
  • 创建一个继承自vtkTimerCallback的类,用于动态更新纹理。
  • Execute方法中,创建新的vtkImageData对象,并根据当前帧数动态生成从暗到亮的线性渐变纹理。
  • 将生成的图像数据设置为纹理的输入,并触发纹理的更新。
3. 动态生成渐变纹理
  • 使用一个循环遍历纹理的每个像素,根据当前帧数计算像素的亮度值。
  • 像素的亮度值从0(暗)到255(亮)逐渐变化,形成动态的时变效果。
4. 设置定时器
  • 使用vtkRenderWindowInteractorCreateRepeatingTimer方法,设置一个每50ms触发一次的定时器。
  • 将自定义的回调类注册为定时器事件的观察者,用于定期更新纹理。
5. 渲染和交互
  • 创建渲染窗口和交互器,启动渲染和交互循环。
  • 设置交互样式为vtkInteractorStyleTrackballCamera,以便用户可以通过鼠标旋转和缩放模型。

运行效果

运行上述代码后,会显示一个管状模型(代替血管),纹理的颜色会从暗到亮动态变化。用户可以通过鼠标交互旋转和缩放模型,观察纹理的动态效果。


依赖项

  • 需要安装VTK库,并确保版本支持vtkTubeFiltervtkTimerCallback
  • 代码中使用了vtkInteractorStyleTrackballCamera,需要确保VTK版本支持该功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值