将 .obj
数据进行 Elevation 着色并可视化渲染的完整流程
和.ply文件处理方式一样
处理OBJ文件
void ThreeDimensionalDisplayPage::loadObjFile(vtkSmartPointer<vtkPolyData> _poly_data)
{
renderer_->RemoveAllViewProps();
renderer_->SetBackground(1.0, 1.0, 1.0); // 白色背景
// 获取边界和中心
double bounds[6];
_poly_data->GetBounds(bounds);
double center[3] = {
(bounds[0] + bounds[1]) / 2.0,
(bounds[2] + bounds[3]) / 2.0,
(bounds[4] + bounds[5]) / 2.0};
// Elevation Filter 按 Z 值添加标量
vtkNew<vtkElevationFilter> elevationFilter;
elevationFilter->SetInputData(_poly_data);
elevationFilter->SetLowPoint(0, 0, bounds[4]); // 最低Z
elevationFilter->SetHighPoint(0, 0, bounds[5]); // 最高Z
elevationFilter->Update();
// 获取标量范围
double scalarRange[2];
elevationFilter->GetOutput()->GetScalarRange(scalarRange);
vtkSmartPointer<vtkLookupTable> colorLookupTable = createJetLookupTable(scalarRange[0], scalarRange[1]);
// 映射器
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(elevationFilter->GetOutputPort());
mapper->SetScalarRange(scalarRange);
mapper->SetLookupTable(colorLookupTable);
mapper->SetColorModeToMapScalars();
mapper->ScalarVisibilityOn();
// 面Actor
surfaceActor_ = vtkSmartPointer<vtkActor>::New();
surfaceActor_->SetMapper(mapper);
surfaceActor_->GetProperty()->SetOpacity(1.0);
renderer_->AddActor(surfaceActor_);
surfaceActor_->SetVisibility(is_surface_visible_);
// 线框Actor
wireframeActor_ = vtkSmartPointer<vtkActor>::New();
wireframeActor_->SetMapper(mapper);
wireframeActor_->GetProperty()->SetRepresentationToWireframe();
wireframeActor_->GetProperty()->SetColor(0.2, 0.2, 0.2);
wireframeActor_->GetProperty()->SetLineWidth(1.0);
renderer_->AddActor(wireframeActor_);
wireframeActor_->SetVisibility(is_wireframe_visible_);
// 点Actor
pointsActor_ = vtkSmartPointer<vtkActor>::New();
pointsActor_->SetMapper(mapper);
pointsActor_->GetProperty()->SetRepresentationToPoints();
pointsActor_->GetProperty()->SetPointSize(6);
pointsActor_->GetProperty()->SetColor(0.0, 0.0, 1.0);
renderer_->AddActor(pointsActor_);
pointsActor_->SetVisibility(is_points_visible_);
renderer_->ResetCamera();
renderWindow_->Render();
m_pScene->update();
}
将jet风格渲染封装成了一个函数,统一调用
Jet渲染风格
vtkSmartPointer<vtkLookupTable> ThreeDimensionalDisplayPage::createJetLookupTable(double minValue,
double maxValue, double gamma)
{
auto lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetNumberOfTableValues(256);
lut->SetRange(minValue, maxValue); // 设置标量范围
for (int i = 0; i < 256; ++i)
{
double t = static_cast<double>(i) / 255.0;
// 非线性调整 t,使颜色更集中于中间值
t = std::pow(t, gamma);
// Jet 配色映射:蓝 → 青 → 绿 → 黄 → 红
double r = std::clamp(1.5 - std::abs(4.0 * t - 3.0), 0.0, 1.0);
double g = std::clamp(1.5 - std::abs(4.0 * t - 2.0), 0.0, 1.0);
double b = std::clamp(1.5 - std::abs(4.0 * t - 1.0), 0.0, 1.0);
lut->SetTableValue(i, r, g, b);
}
lut->Build();
return lut;
}
Viridis渲染风格
vtkSmartPointer<vtkLookupTable> ThreeDimensionalDisplayPage::createViridisLookupTable(double minValue,
double maxValue)
{
auto lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetNumberOfTableValues(256);
lut->SetRange(minValue, maxValue);
for (int i = 0; i < 256; ++i)
{
double t = i / 255.0;
// 近似 Matplotlib Viridis 色带(更精确的RGB值可参考官方定义)
double r = 0.2795 + 0.4702 * t + 0.1649 * t * t - 0.0008 * t * t * t;
double g = 0.0021 + 0.7047 * t + 0.0704 * t * t - 0.0053 * t * t * t;
double b = 0.3904 + 0.1066 * t + 0.1968 * t * t - 0.0641 * t * t * t;
lut->SetTableValue(i, r, g, b);
}
lut->Build();
return lut;
}
CoolToWarm渲染风格
vtkSmartPointer<vtkLookupTable> ThreeDimensionalDisplayPage::createCoolToWarmLookupTable(double minValue,
double maxValue)
{
auto lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetNumberOfTableValues(256);
lut->SetRange(minValue, maxValue);
for (int i = 0; i < 256; ++i)
{
double t = i / 255.0;
double r = t; // 红:从0→1
double g = 1 - fabs(t - 0.5) * 2; // 绿:中间最亮
double b = 1 - t; // 蓝:从1→0
lut->SetTableValue(i, r, g, b);
}
lut->Build();
return lut;
}
Grayscale渲染风格
vtkSmartPointer<vtkLookupTable> ThreeDimensionalDisplayPage::createGrayscaleLookupTable(double minValue,
double maxValue)
{
auto lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetNumberOfTableValues(256);
lut->SetRange(minValue, maxValue);
for (int i = 0; i < 256; ++i)
{
double gray = i / 255.0; // 从黑→白
lut->SetTableValue(i, gray, gray, gray);
}
lut->Build();
return lut;
}
Rainbow渲染风格
vtkSmartPointer<vtkLookupTable> ThreeDimensionalDisplayPage::createRainbowLookupTable(double minValue,
double maxValue)
{
auto lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetNumberOfTableValues(256);
lut->SetHueRange(0.666, 0.0); // 色相从蓝(0.666)→红(0.0)
lut->SetSaturationRange(1.0, 1.0);
lut->SetValueRange(1.0, 1.0);
lut->SetRange(minValue, maxValue);
lut->Build();
return lut;
}
切换风格按钮槽函数(可优化)
void ThreeDimensionalDisplayPage::updateColorStyle(int style)
{
current_color_style = style;
if (ply_point_actor_) // PLY点云模型
{
auto mapper = vtkPolyDataMapper::SafeDownCast(ply_point_actor_->GetMapper());
if (mapper)
{
vtkSmartPointer<vtkLookupTable> new_lut;
switch (style)
{
case 0:
new_lut = createJetLookupTable(current_scalar_range[0], current_scalar_range[1], 1.0);
break;
case 1:
new_lut = createViridisLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 2:
new_lut = createCoolToWarmLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 3:
new_lut = createGrayscaleLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 4:
new_lut = createRainbowLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
}
mapper->SetLookupTable(new_lut);
renderWindow_->Render();
}
}
if (surfaceActor_) // OBJ网格模型
{
auto mapper = vtkPolyDataMapper::SafeDownCast(surfaceActor_->GetMapper());
if (mapper)
{
vtkSmartPointer<vtkLookupTable> new_lut;
switch (style)
{
case 0:
new_lut = createJetLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 1:
new_lut = createViridisLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 2:
new_lut = createCoolToWarmLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 3:
new_lut = createGrayscaleLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
case 4:
new_lut = createRainbowLookupTable(current_scalar_range[0], current_scalar_range[1]);
break;
}
mapper->SetLookupTable(new_lut);
renderWindow_->Render();
}
}
}
相关代码git链接
https://gitee.com/strange-tree-qian/vtktest