在用 VTK 进行对象可视化时,明确各组件的位置是很有必要的,坐标系统的出现就是为了区分对象之间的位置区间,在 VTK
中,一共提供四种不同的坐标系统分别是 model、view、world
、以及 display
,每种坐标系都有自己的应用场景
model
坐标系统用于定义模型本身,通常可以当作局部笛卡尔坐标系, 该模型有固定的坐标系,该坐标系由生成模型的人决定
world
(世界)坐标系用于确定每个 actor
的位置,因为 actor
进行缩放、旋转和平移都是在世界坐标系中进行的,因此将model
坐标系转化为世界坐标系对于actor
是非常有必要的;在世界坐标系中,Light
和 Camera
的位置和方向都可以指定
view
坐标系,用于确定对于 Camera
哪些组件是可见的,x 、y
轴的取值范围在 -1
到 1
之间,以及一个 z
深度坐标;x 、y
值指定在图像平面中位置,z值代表源于相机的距离、范围。其中 4×4
变换矩阵 来代表相机属性,将世界坐标系转化为 view
坐标系。
display
坐标系统与 view
相似,两者较大区别是定义x、y
值时,把view
中[-1,1]
范围映射成最终的窗口像素大小。
下面这张图就是对四种坐标系关系间准确描述:
最后的绘制的对象都展现在一个窗口中,若要实现一个窗口绘制多个对象,可以在将对象放置在不同的 Render
(绘制器中),分别把 Render
放置在窗口的 viewport
即可,viewport
中 x、y
轴的取值范围都为 [0,1]
在同一个窗口内分别渲染一个圆锥和一个椭圆,实现代码如下
#include<vtkActor.h>
#include<vtkSmartPointer.h>
#include<vtkPolyDataMapper.h>
#include<vtkConeSource.h>
#include<vtkRenderer.h>
#include<vtkRenderWindow.h>
#include<vtkCamera.h>
#include<vtkNamedColors.h>
#include<vtkSphereSource.h>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);
int main()
{
vtkSmartPointer<vtkConeSource> Cone = vtkSmartPointer<vtkConeSource>::New();
vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New();
Cone->SetHeight(3.0);//Cone Height
Cone->SetRadius(1.0);//Cone Radius
Cone->SetResolution(9);//Cone faces
vtkSmartPointer<vtkPolyDataMapper> coneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
coneMapper->SetInputConnection(Cone->GetOutputPort());//Mapper data
vtkSmartPointer<vtkActor> coneActor = vtkSmartPointer<vtkActor>::New();
coneActor->SetMapper(coneMapper);
vtkSmartPointer<vtkRenderer> coneRender = vtkSmartPointer<vtkRenderer>::New();
coneRender->AddActor(coneActor);
coneRender->SetBackground(colors->GetColor3d("MidnightBlue").GetData());//Bachground color
coneRender->SetViewport(0.0, 0.0, 0.5, 1.0);//Set Cone View Port;
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetStartTheta(10);
sphere->SetEndTheta(300);
vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection(sphere->GetOutputPort());//Mapper data
vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();
sphereActor->SetMapper(sphereMapper);
vtkSmartPointer<vtkRenderer> sphereRender = vtkSmartPointer<vtkRenderer>::New();
sphereRender->AddActor(sphereActor);
sphereRender->SetBackground(colors->GetColor3d("SlateGray").GetData());//Bachground color
sphereRender->SetViewport(0.5, 0.0, 1.0, 1.0);//Set Cone View Port;
vtkSmartPointer<vtkRenderWindow> renWindow = vtkSmartPointer<vtkRenderWindow>::New();
renWindow->AddRenderer(coneRender);
renWindow->AddRenderer(sphereRender);
renWindow->SetSize(600, 300);//Size of Window;
//coneRender->GetActiveCamera()->Azimuth(1);
renWindow->Render();
//for (auto i = 0; i < 360; ++i)
//{
// //render the image;
// renWindow->Render();
// //rotate the active camera by one degree
// coneRender->GetActiveCamera()->Azimuth(1);
//}
return EXIT_SUCCESS;
}
代码中先后定义了两个 vtkRenderer
(绘制器),一个用于绘制圆锥,一个用于绘制椭圆(这里的椭圆是不完整的,源于对椭圆的参数进行了修改);为了加大区分,背景颜色设置为两种;最后用SetViewport()
函数加入窗口中的不同位置
最终的效果图如下
文章首发于公号:Z先生点记。