VTK 中的坐标变换 | 基础
VTK 中的坐标变换 | 基础
前情提要
之前提到过 VTK 的坐标系统:VTK 三维场景。
VTK 坐标变换的三个原则
VTK 坐标变换的三个原则:
- 对物体(们)进行变换和对摄像机进行变换能取得相同的效果。
- 变换的本质是矩阵运算,所有的变换都能用一个矩阵表达。
- 变换矩阵可以拆解成最基本的变换(移动、放缩、旋转)的有序组合。
预备知识
在计算机图形学中,我们用齐次坐标系表示坐标:
Translation 矩阵,用于移动物体的位置:
Translation 变换:
Scaling 矩阵,用于改变物体的大小:
Rotation 矩阵 —— X 轴旋转:
Rotation 矩阵 —— Y 轴旋转:
Rotation 矩阵 —— Z 轴旋转:
Rotation 矩阵 —— 自由旋转:
实例 1:旋转摄像机
编写一个 VTK 程序,读取一个模型并显示,同时显示坐标轴:
#include "VTKCoordinateTransform.h"
#include <vtkBYUReader.h>
#include <vtkNamedColors.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
#include <vtkRenderWindow.h>
VTKCoordinateTransform::VTKCoordinateTransform(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
this->_pVTKWidget = new QVTKOpenGLNativeWidget();
this->setCentralWidget(_pVTKWidget);
// this->showMaximized();
vtkNew<vtkRenderer> renderer;
this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
this->_pVTKWidget->renderWindow()->Render();
this->_widgetCamOrien = vtkCameraOrientationWidget::New();
this->_widgetCamOrien->SetParentRenderer(renderer);
this->_widgetCamOrien->On();
vtkNew<vtkNamedColors> colors;
vtkNew<vtkBYUReader> cow;
cow->SetFileName("cow.g");
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(cow->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(colors->GetColor3d("Gold").GetData());
renderer->AddActor(actor);
renderer->SetBackground(colors->GetColor3d("DarkSlateGray").GetData());
}
VTKCoordinateTransform::~VTKCoordinateTransform()
{
delete this->_pVTKWidget;
this->_widgetCamOrien->Delete();
}
运行效果:
添加以下代码,将摄像机在水平方向上旋转 90 度:
renderer->GetActiveCamera()->Azimuth(90);
renderer->ResetCamera();
运行效果:
实例 2:使用 vtkTransform 对模型进行平移
#include "VTKCoordinateTransform.h"
#include <vtkBYUReader.h>
#include <vtkNamedColors.h>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
#include <vtkRenderWindow.h>
VTKCoordinateTransform::VTKCoordinateTransform(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
this->_pVTKWidget = new QVTKOpenGLNativeWidget();
this->setCentralWidget(_pVTKWidget);
// this->showMaximized();
vtkNew<vtkRenderer> renderer;
this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
this->_pVTKWidget->renderWindow()->Render();
this->_widgetCamOrien = vtkCameraOrientationWidget::New();
this->_widgetCamOrien->SetParentRenderer(renderer);
this->_widgetCamOrien->On();
vtkNew<vtkNamedColors> colors;
vtkNew<vtkBYUReader> cow;
cow->SetFileName("cow.g");
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(cow->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(colors->GetColor3d("Gold").GetData());
renderer->AddActor(actor);
renderer->SetBackground(colors->GetColor3d("DarkSlateGray").GetData());
vtkNew<vtkTransform> transform;
transform->Translate(10, 0, 0);
vtkNew<vtkTransformFilter> transFilter;
transFilter->SetInputConnection(cow->GetOutputPort());
transFilter->SetTransform(transform);
vtkNew<vtkPolyDataMapper> transMapper;
transMapper->SetInputConnection(transFilter->GetOutputPort());
vtkNew<vtkActor> transActor;
transActor->SetMapper(transMapper);
transActor->GetProperty()->SetColor(colors->GetColor3d("Silver").GetData());
renderer->AddActor(transActor);
}
VTKCoordinateTransform::~VTKCoordinateTransform()
{
delete this->_pVTKWidget;
this->_widgetCamOrien->Delete();
}
运行效果:
实例 3:使用 vtkTransform 对模型进行旋转
注释掉:
transform->Translate(10, 0, 0);
换成:
transform->RotateY(90);
运行效果:
或者换成:
transform->Translate(10, 0, 0);
transform->RotateY(90);
transform->Translate(-10, 0, 0);
运行效果:
其实,对 vtkActor 也可以直接旋转,仅推荐在做简单变换时使用:
actor->RotateY(45);