要将时变的纹理(从暗到亮)应用到管状模型(例如血管)上,可以使用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. 设置定时器
- 使用
vtkRenderWindowInteractor
的CreateRepeatingTimer
方法,设置一个每50ms触发一次的定时器。 - 将自定义的回调类注册为定时器事件的观察者,用于定期更新纹理。
5. 渲染和交互
- 创建渲染窗口和交互器,启动渲染和交互循环。
- 设置交互样式为
vtkInteractorStyleTrackballCamera
,以便用户可以通过鼠标旋转和缩放模型。
运行效果
运行上述代码后,会显示一个管状模型(代替血管),纹理的颜色会从暗到亮动态变化。用户可以通过鼠标交互旋转和缩放模型,观察纹理的动态效果。
依赖项
- 需要安装VTK库,并确保版本支持
vtkTubeFilter
和vtkTimerCallback
。 - 代码中使用了
vtkInteractorStyleTrackballCamera
,需要确保VTK版本支持该功能。