在C#中通过引用vtk的.net版本,也就是ActiViz.net,可以实现桌面三维应用程序开发,比如下面这个博主开发的类似谷歌地球的小应用。在此开发过程中,遇到了各种各样的问题,现在分享给大家。
后面的博客里,博主会上传源代码,请持续关注本人的博客!!
我们知道,通过在场景中增加vtkActor,可以添加各种三维几何体,但如何实现高效的生成vtkActor,并实现快速场景绘制和浏览,则需要很多技巧,我们以球体(点)生成为例,给大家介绍几种生成方法,以下为第一种,直接基于单个位置,生成一个独立的vtkActor。这也是网上最通用,或者说大模型通常给出的方法。
using Kitware.VTK;
class Program
{
static void Main(string[] args)
{
// 创建一个球体
vtkSphereSource sphereSource = vtkSphereSource.New();
sphereSource.SetRadius(1.0); // 设置球体半径
sphereSource.SetThetaResolution(20); // 设置经度分辨率
sphereSource.SetPhiResolution(20); // 设置纬度分辨率
sphereSource.SetCenter(1.0, 1.0, 1.0); // 设置球体中心位置 (x, y, z)
// 创建一个映射器
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(sphereSource.GetOutputPort());
// 创建一个演员
vtkActor actor = vtkActor.New();
actor.SetMapper(mapper);
actor.GetProperty().SetColor(1, 0, 0); // 设置球体颜色为红色
// 创建一个渲染器
vtkRenderer renderer = vtkRenderer.New();
renderer.AddActor(actor);
renderer.SetBackground(0.1, 0.2, 0.4); // 设置背景颜色
// 创建一个渲染窗口
vtkRenderWindow renderWindow = vtkRenderWindow.New();
renderWindow.AddRenderer(renderer);
// 创建一个交互器
vtkRenderWindowInteractor renderWindowInteractor = vtkRenderWindowInteractor.New();
renderWindowInteractor.SetRenderWindow(renderWindow);
// 开始渲染和交互
renderWindow.Render();
renderWindowInteractor.Start();
}
}
运行程序后,你会看到一个红色的球体,其中心位于 (1.0, 1.0, 1.0)
的位置,半径为1.0。
要是按照这个方法,生成100个球,那生成速度和浏览速度都非常慢,非常卡。那么我们看看有没有稍微优化的方法。
先建立一个全局唯一的SphereSource,大家都可以用,像孙悟空72变一样,其它球都从它变出来,这样就省内存了。
/// <summary>
/// 球体数据源
/// </summary>
private static vtkSphereSource SphereSource = null;
/// <summary>
/// 球体数据源的PolyData
/// </summary>
private static vtkPolyData SphereSourcePolyData = null;
/// <summary>
/// 球体数据源的面数
/// </summary>
private static int SphereFace = 10;
/// <summary>
/// 更新球体数据源的面数,面数越多,效率越低
/// 同时初始化球体数据源机及其PolyData
/// </summary>
/// <param name="face"></param>
public static void UpdateSphereSource(int face)
{
// 创建球体数据源
SphereSource = vtkSphereSource.New();
SphereSource.SetRadius(1);
SphereSource.SetPhiResolution(face);
SphereSource.SetThetaResolution(face);
SphereSource.Update();
SphereFace=face;
// 获取单个球体的 vtkPolyData
SphereSourcePolyData = SphereSource.GetOutput();
}
现在开始生成一个球
public static vtkActor CreateSphereActor(X3DVertex position, double radius, Color color)
{
if (SphereSource == null) UpdateSphereSource(SphereFace);
vtkTransform transform = vtkTransform.New();
transform.Translate(position.x, position.y, position.z); // 将球体平移到position
transform.Scale(radius, radius, radius); // 将球体放大radius倍
// 创建 vtkTransformPolyDataFilter 来应用变换
vtkTransformPolyDataFilter transformFilter = vtkTransformPolyDataFilter.New();
transformFilter.SetInputConnection(SphereSource.GetOutputPort());
transformFilter.SetTransform(transform);
transformFilter.Update();
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputData(transformFilter.GetOutput());
return BuildActor(mapper, color);
}
大家看到了,这是用transform的方法生成不同位置和大小的球。
通过上述方法也许生成速度快些,内存占用少些,但是也许浏览效果仍然不能令人满意。
请期待下一篇博客,介绍更高效的一种方法!