其实,网上有不少介绍VTK Camera的内容。在3D图形学中,相机对于渲染对象来说是必不可少的。我们可以通过它来观察物体,包括执行放大缩小、移动相机等操作,所以它是我们需要了解的基础和重要的知识之一。
本篇博客记录的是相机的作用,相机的参数,以及如何控制相机和在实际中的应用。
在三维渲染场景中,相机好比人的眼睛,人站立的位置影响事物的大小,视角的不同影响看到事物的范围,目光的朝向影响看到事物的正反。我们可以通过VTK的相机来控制三维图形,物体的缩放、视角的切换等。
下图是vtkCamera的模型示意图,需要注意的是左边的摄像机,它和焦点都是在相机内部。
VTK用vtkCamera来表示相机,vtkCamera负责把三维场景投影到二维平面,如屏幕、图像等,vtkCamera定义观察者的位置、焦点以及相关的属性。
光心的位置,可以理解为小孔相机模型中小孔的位置。可以通过vtkCamera::SetPosition()和vtkCamera::GetPosition()设置和获取。
焦点的位置,用三维坐标表示,默认相机焦点的位置在世界坐标系的原点。通过vtkCamera::SetFocusPoint()和vtkCamera::GetFocusPoint()设置和获取。
ViewUp指图像的正方向。由Position和FocalPoint我们可以确定5个自由度,相机仍然可以沿着主光轴任意旋转。所以这里要指定正方向,即ViewUp。这里注意,ViewUp是一个方向向量,不存在位置,或者说起点永远在原点。
Position、Focal Point和View Up三个因素确定了相机的实际方向,即确定了相机的视图。
ViewAngle是视角,默认是30°。这个是一个重要的参数,它决定了图像的比例大小,通过设置vtkCamera::SetViewAngle()可以对图像缩放。
前/后剪切平面,包含两个。只有在这两个剪切平面之间的内容才会被渲染和显示,默认值是(0.1,1000)。这个参数一般不需要修改。可以调用vtkRenderer::ResetCameraClippingRange()方法来自动重设渲染范围。
一个三维矢量,从光心位置Position指向焦点位置FocalPoint。
如果你想获取vtkRenderer里默认的相机,可以用方法vtkRenderer::GetActiveCamera()。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int, char *[])
{
// Create a cone
vtkSmartPointer sphereSource =
vtkSmartPointer::New();
sphereSource->SetRadius(.5);
sphereSource->SetCenter(0, 0, 0);
// Visualize
vtkSmartPointer mapper =
vtkSmartPointer::New();
mapper->SetInputConnection(sphereSource->GetOutputPort());;
vtkSmartPointer actor =
vtkSmartPointer::New();
actor->SetMapper(mapper);
vtkSmartPointer renderer =
vtkSmartPointer::New();
renderer->AddActor(actor);
renderer->SetBackground(.3, .3, .5); // Background color purple
vtkSmartPointer renderWindow =
vtkSmartPointer::New();
renderWindow->SetSize(600, 600);
renderWindow->AddRenderer(renderer);
vtkSmartPointer renderWindowInteractor =
vtkSmartPointer::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkCamera *activeCamera = renderer->GetActiveCamera();
double position[3] = { 0 };
activeCamera->GetPosition(position);
cout << "Default Camera Position: [" << position[0] << "," << position[0] << "," << position[2] << "]" << endl;
double focalPoint[3];
activeCamera->GetFocalPoint(focalPoint);
cout << "Default Camera Focal Point: [" << focalPoint[0] << "," << focalPoint[0] << "," << focalPoint[2] << "]" << endl;
double viewAngle = activeCamera->GetViewAngle();
cout << "Default Camera View Angle: " << viewAngle << endl;
cout << "------------------------------------" << endl;
vtkSmartPointer camera = vtkSmartPointer::New();
position[0] = 1;
position[0] = 0;
position[0] = 0;
cout << "Set Camera Position: [" << position[0] << "," << position[0] << "," << position[2] << "]" << endl;
camera->SetPosition(position);
focalPoint[0] = 0;
focalPoint[1] = 1;
focalPoint[2] = 0;
cout << "Set Camera Focal Point: [" << focalPoint[0] << "," << focalPoint[0] << "," << focalPoint[2] << "]" << endl;
camera->SetFocalPoint(focalPoint);
viewAngle = 60.0;
cout << "Camera View Angle: " << viewAngle << endl;
camera->SetViewAngle(viewAngle);
Render->SetActiveCamera(camera);
cout << "------------------------------------" << endl;
camera->GetPosition(position);
cout << "Get Camera Position: [" << position[0] << "," << position[0] << "," << position[2] << "]" << endl;
camera->GetFocalPoint(focalPoint);
cout << "Get Camera Focal Point: [" << focalPoint[0] << "," << focalPoint[0] << "," << focalPoint[2] << "]" << endl;
viewAngle = camera->GetViewAngle();
cout << "Get Camera View Angle: " << viewAngle << endl;
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
实际的项目开发中,可能你想知道Actor正处在哪个视角,就可以通过活动相机来计算角度。
double curPosition[3], curFocalPoint[3], curViewUp[3];
vtkCamera *curCamera =renderer->GetActiveCamera();
curCamera->GetPosition(curPosition);
curCamera->GetFocalPoint(curFocalPoint);
curCamera->GetViewUp(curViewUp);
double curViewDirection[3];
// curViewDirection = curPosition - curFocalPoint
vtkMath::Subtract(curPosition, curFocalPoint, curViewDirection);
double viewDirection[3] = { curViewDirection[0], curViewDirection[1], curViewDirection[2] };
double zAxis[3] = {0, 0, 1};
//viewDirection*zAxis
double dotValue = viewDirection[0] * zAxis[0] + viewDirection[1] * zAxis[1] + viewDirection[2] * zAxis[2];
double angle = acosf(dotValue) * 180.0 / vtkMath::Pi();
cout << "Angle: " << angle << endl;
Reference
The-Visualization-Toolkit-An-Object-Oriented-Approach-To-3D-Graphics
VTK相机类vtkCamera原理及用法
03-VTK基础概念(2)