VTK开发笔记(三):熟悉VTK开发流程,编写球体,多半透明球体Demo

前言

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

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时,此时没有对象使用它了,则会销毁。

cpp 复制代码
vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();

智能指针类型可以作为函数返回值,正确的写法如下:

cpp 复制代码
vtkSmartPointer<vtkImageData> MyFunction()
{
    vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New();
    return myObject;
}

函数MyFunction()的返回值是通过复制的方式,讲数据赋值给调用的变量,因此该数据的引用计数保持不变,而且函数MyFunction里的myObject也不会删除。   反过来,要是函数里面定义是智能指针类型,返回类型是指针,其计数会减去1,示例如下:

cpp 复制代码
vtkImageData * MyFunction()
{
    vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New();
return myObject;
}
vtkImageData *pImageData = MyFunction();

(注意:这里有点拗口难理解,为什么返回指针就-1,osg处理这块是无所谓的,混合了代码做过osg的测试,并不会崩溃,但是vtk说是会崩溃)   Vtk的智能指针,还有一个注意点,就是一个智能指针的对象,在第一次赋值的时候,智能指针会分配对象相关的内存,初始化引用计数,后续不能再把这个指针更换对象,否则会引用计数出错,   以上这几个点,都要注意,其在osg的智能指针中没这些讲究,比较完善,但是vtk如果使用智能指针,就要遵循这些,会轻微增加代码,主要是函数返回类型和赋值给的变量类型定义这两块为主。

绘制一个球体

步骤一:创建球体数据源

步骤二:创建多边形映射器

步骤三:创建演员类(类似osg模型结点)

步骤四:创建渲染器

步骤五:设置渲染器到渲染窗口

源码

VTKManager.cpp

cpp 复制代码
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> VTKManager::createRenderer(std::vector<vtkActor *> listPActor)
{
    // 步骤一:智能指针定义
    vtkSmartPointer<vtkRenderer> pRenderer;
    // 步骤二:智能指针实例化
    pRenderer = vtkSmartPointer<vtkRenderer>::New();
    // 步骤三:设置映射器
    for(int index = 0; index < listPActor.size(); index++)
    {
        pRenderer->AddActor(listPActor.at(index));
    }

    return pRenderer;
}

VTKWidget.cpp

cpp 复制代码
void VTKWidget::test_demo2_1_createSphere()
{
    // 步骤一:创建球体数据源
    vtkSmartPointer<vtkSphereSource> pSphereSource1 =
            VTKManager::createSphereSource(0, 0, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource2 =
            VTKManager::createSphereSource(-20, 0, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource3 =
            VTKManager::createSphereSource(20, 0, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource4 =
            VTKManager::createSphereSource(0, 20, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource5 =
            VTKManager::createSphereSource(0, -20, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource6 =
            VTKManager::createSphereSource(0, 0, 20, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource7 =
            VTKManager::createSphereSource(0, 0, -20, 10, 100, 100);
    // 步骤二:创建多边形映射器
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper1 =
            VTKManager::createPolyDataMapper(pSphereSource1);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper2 =
            VTKManager::createPolyDataMapper(pSphereSource2);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper3 =
            VTKManager::createPolyDataMapper(pSphereSource3);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper4 =
            VTKManager::createPolyDataMapper(pSphereSource4);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper5 =
            VTKManager::createPolyDataMapper(pSphereSource5);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper6 =
            VTKManager::createPolyDataMapper(pSphereSource6);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper7 =
            VTKManager::createPolyDataMapper(pSphereSource7);
    // 步骤三:创建演员
    vtkSmartPointer<vtkActor> pActor1 =
            VTKManager::createActor(pPolyDataMapper1, 1.0, 0.0, 0.0, 0.25);
    vtkSmartPointer<vtkActor> pActor2 =
            VTKManager::createActor(pPolyDataMapper2, 0.0, 1.0, 0.0, 0.25);
    vtkSmartPointer<vtkActor> pActor3 =
            VTKManager::createActor(pPolyDataMapper3, 0.0, 0.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor4 =
            VTKManager::createActor(pPolyDataMapper4, 1.0, 1.0, 0.0, 0.25);
    vtkSmartPointer<vtkActor> pActor5 =
            VTKManager::createActor(pPolyDataMapper5, 0.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor6 =
            VTKManager::createActor(pPolyDataMapper6, 1.0, 0.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor7 =
            VTKManager::createActor(pPolyDataMapper7, 1.0, 1.0, 1.0, 0.25);

    // 步骤四:创建渲染器
    std::vector<vtkActor *> listActor;
    listActor.push_back(pActor1);
    listActor.push_back(pActor2);
    listActor.push_back(pActor3);
    listActor.push_back(pActor4);
    listActor.push_back(pActor5);
    listActor.push_back(pActor6);
    listActor.push_back(pActor7);
    vtkSmartPointer<vtkRenderer> pRenderer =
            VTKManager::createRenderer(listActor);

    // 步骤五:渲染器添加到QVTKWidget渲染
    _pQVTKWidget->GetRenderWindow()->AddRenderer(pRenderer);
}

void VTKWidget::test_demo2_2_createSphere()
{
    // 步骤一:创建球体数据源
    vtkSmartPointer<vtkSphereSource> pSphereSource1 =
            VTKManager::createSphereSource(0, 0, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource2 =
            VTKManager::createSphereSource(-20, 0, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource3 =
            VTKManager::createSphereSource(20, 0, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource4 =
            VTKManager::createSphereSource(0, 20, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource5 =
            VTKManager::createSphereSource(0, -20, 0, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource6 =
            VTKManager::createSphereSource(0, 0, 20, 10, 100, 100);
    vtkSmartPointer<vtkSphereSource> pSphereSource7 =
            VTKManager::createSphereSource(0, 0, -20, 10, 100, 100);
    // 步骤二:创建多边形映射器
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper1 =
            VTKManager::createPolyDataMapper(pSphereSource1);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper2 =
            VTKManager::createPolyDataMapper(pSphereSource2);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper3 =
            VTKManager::createPolyDataMapper(pSphereSource3);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper4 =
            VTKManager::createPolyDataMapper(pSphereSource4);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper5 =
            VTKManager::createPolyDataMapper(pSphereSource5);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper6 =
            VTKManager::createPolyDataMapper(pSphereSource6);
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper7 =
            VTKManager::createPolyDataMapper(pSphereSource7);
    // 步骤三:创建演员
    vtkSmartPointer<vtkActor> pActor1 =
            VTKManager::createActor(pPolyDataMapper1, 1.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor2 =
            VTKManager::createActor(pPolyDataMapper2, 1.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor3 =
            VTKManager::createActor(pPolyDataMapper3, 1.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor4 =
            VTKManager::createActor(pPolyDataMapper4, 1.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor5 =
            VTKManager::createActor(pPolyDataMapper5, 1.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor6 =
            VTKManager::createActor(pPolyDataMapper6, 1.0, 1.0, 1.0, 0.25);
    vtkSmartPointer<vtkActor> pActor7 =
            VTKManager::createActor(pPolyDataMapper7, 1.0, 1.0, 1.0, 0.25);

    // 步骤四:创建渲染器
    std::vector<vtkActor *> listActor;
    listActor.push_back(pActor1);
    listActor.push_back(pActor2);
    listActor.push_back(pActor3);
    listActor.push_back(pActor4);
    listActor.push_back(pActor5);
    listActor.push_back(pActor6);
    listActor.push_back(pActor7);
    vtkSmartPointer<vtkRenderer> pRenderer =
            VTKManager::createRenderer(listActor);

    // 步骤五:渲染器添加到QVTKWidget渲染
    _pQVTKWidget->GetRenderWindow()->AddRenderer(pRenderer);
}

工程模板v1.1.0

相关推荐
Jooolin4 小时前
【C++】C++11都有什么新特性?
c++·ai编程·编程语言
Mr_Xuhhh5 小时前
Qt中UDP回显服务器和客户端
服务器·qt·udp
蓝风破云5 小时前
模拟实现STL中的list容器
c语言·数据结构·c++·链表·迭代器·list·iterator
Quz5 小时前
QML Chart组件之图例
qt
☆璇5 小时前
【C++】C++的IO流
开发语言·c++
HalvmånEver5 小时前
盛最多水的容器:双指针法的巧妙运用(leetcode 11)
c++·学习·leetcode
励志不掉头发的内向程序员6 小时前
STL库——stack/queue(类函数学习)
开发语言·c++·学习
努力努力再努力wz6 小时前
【c++进阶系列】:万字详解异常
java·linux·运维·服务器·开发语言·c++
俞凡7 小时前
Go/C++ 指针比较
c++·go