前言
开始vtk实战,了解vtk的一些基本框架,通过代码是最好的方式。
本篇实现一个vtk实现多球体半透明的Demo。



下面是osg存在的问题:

计算机图形学里常用的坐标系统主要有4中,分别是model坐标系统、world坐标系统、view坐标系统和Display坐标系统。

- Model坐标系统:定义模型时所采用的坐标系统,笛卡尔坐标系。
- World坐标系统:actor(渲染模型)的三维控件坐标系,就是世界坐标系。每一个 actor可以通过缩放、旋转、平移等操作讲model坐标系放入world,就是三维相对坐标系变换。World坐标系也是相机和灯光所在的坐标系。
- View坐标系统:相机能看见的坐标系统,XYZ轴取值都为[-1,1],表示平面上的位置,Z值表示到相机的距离。
- Display坐标系统:屏幕坐标系,坐标轴取值就是像素。

数据源->多线段数据映射->【演员->渲染器->渲染窗口】。
复杂一点的渲染管线:


- Source:用于创建数据或者读取数据,跟字面意义一样是数据源。Source可作为Filter的输入,进行数据的过滤,生成新的数据。
- Filter:特定规则进行处理过滤,比如轮廓线、比如剖面,更多的后续再讲究。
- Mapper:映射器,更多的后续再讲究。
智能指针会自动管理引用计数的增加或者减少,这个概念在编程语言中有,在ogs中也有,且使用方式基本一致。当指针{}作用域过了,其智能指针实际还存在,只有在其计数为0时,此时没有对象使用它了,则会销毁。
vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
智能指针类型可以作为函数返回值,正确的写法如下:
vtkSmartPointer<vtkImageData> MyFunction() { vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New(); return myObject; }
函数MyFunction()的返回值是通过复制的方式,讲数据赋值给调用的变量,因此该数据的引用计数保持不变,而且函数MyFunction里的myObject也不会删除。
反过来,要是函数里面定义是智能指针类型,返回类型是指针,其计数会减去1,示例如下:
vtkImageData * MyFunction() { vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New(); return myObject; } vtkImageData *pImageData = MyFunction();
(注意:这里有点拗口难理解,为什么返回指针就-1,osg处理这块是无所谓的,混合了代码做过osg的测试,并不会崩溃,但是vtk说是会崩溃)
Vtk的智能指针,还有一个注意点,就是一个智能指针的对象,在第一次赋值的时候,智能指针会分配对象相关的内存,初始化引用计数,后续不能再把这个指针更换对象,否则会引用计数出错,
以上这几个点,都要注意,其在osg的智能指针中没这些讲究,比较完善,但是vtk如果使用智能指针,就要遵循这些,会轻微增加代码,主要是函数返回类型和赋值给的变量类型定义这两块为主。





vtkSmartPointer<vtkSphereSource> VTKManager::createSphereSource(double x, double y, double z, double r, int vNum, int hNum) { /* * 继承关系: * vktObject ---> vtkAlhorithm ---> vtkPolyDataAlgorithm ---> vtkSphereSource * 渲染关系: * vtkSphereSource ---> vtkPolyDataMapper ---> vtkActor */ // 步骤一:智能指针定义 vtkSmartPointer<vtkSphereSource> pSphereSource; // 步骤二:智能指针实例化 pSphereSource = vtkSmartPointer<vtkSphereSource>::New(); // 步骤三:设置球心坐标 pSphereSource->SetCenter(x, y, z); // 步骤三:设置球体的半径 pSphereSource->SetRadius(r); // 步骤四:设置球体的纬度分辨率,即球体纵向的切片数量(垂直/纵向精细度) pSphereSource->SetPhiResolution(vNum); // 步骤五:设置球体的经度分辨率,即球体横向的切片数量(横向/水平精细度) pSphereSource->SetThetaResolution(hNum); return pSphereSource; } vtkSmartPointer<vtkPolyDataMapper> VTKManager::createPolyDataMapper(vtkSphereSource * pSphereSource) { // 步骤一:智能指针定义 vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper; // 步骤二:智能指针实例化 pPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); // 步骤三:设置 pPolyDataMapper->SetInputConnection(pSphereSource->GetOutputPort()); return pPolyDataMapper; } vtkSmartPointer<vtkActor> VTKManager::createActor(vtkPolyDataMapper *pPolyDataMapper, double r, double g, double b) { // 步骤一:智能指针定义 vtkSmartPointer<vtkActor> pActor; // 步骤二:智能指针实例化 pActor = vtkSmartPointer<vtkActor>::New(); // 步骤三:设置映射器 pActor->SetMapper(pPolyDataMapper); // 步骤四:设置颜色 pActor->GetProperty()->SetColor(r, g, b); return pActor; } vtkSmartPointer<vtkActor> VTKManager::createActor(vtkPolyDataMapper *pPolyDataMapper, double r, double g, double b, double a) { // 步骤一:智能指针定义 vtkSmartPointer<vtkActor> pActor; // 步骤二:智能指针实例化 pActor = vtkSmartPointer<vtkActor>::New(); // 步骤三:设置映射器 pActor->SetMapper(pPolyDataMapper); // 步骤四:设置颜色 pActor->GetProperty()->SetColor(r, g, b); // 步骤五:设置透明度 pActor->GetProperty()->SetOpacity(a); return pActor; } vtkSmartPointer<vtkRenderer> VTKManager::createRenderer(vtkActor *pActor) { // 步骤一:智能指针定义 vtkSmartPointer<vtkRenderer> pRenderer; // 步骤二:智能指针实例化 pRenderer = vtkSmartPointer<vtkRenderer>::New(); // 步骤三:设置映射器 pRenderer->AddActor(pActor); return pRenderer; } vtkSmartPointer<vtkRenderer>
