1. 相机原理
投影方向 :相机位置到相机焦点的向量方向即为投影方向。
投影方法:确定Actor是如何映射到像平面的。
- tkCamera定义了两种投影方法,一种是正交投影(OrthographicProjection),也叫平行投影(Parallel
Projection),即进入相机的光线与投影方向是平行的。 - 另一种是透视投影(PerspectiveProjection),即所有的光线相交于一点。
视角:透视投影时需要指定相机的视角(View Angle),默认的视角大小为30º,可以用方法vtkCamera::SetViewAngle()设置。
前后裁剪平面:裁剪平面与投影方向相交,一般与投影方向也是垂直的。裁剪平面主要用于评估Actor与相机距离的远近,只有在前后裁剪平面之间的Actor才是可见的。裁剪平面的位置可以用方法vtkCamera::SetClippingRange()设置。
原文链接:
2. vtk.VtkCamera() 定义及参数意义
vtkSmartPointer<vtkCamera>myCamera = vtkSmartPointer<vtkCamera>::New();
myCamera->SetClippingRange(0, 0);
myCamera->SetFocalPoint(0,0,0);
myCamera->SetPosition(0,1,0);
myCamera->ComputeViewPlaneNormal();
myCamera->SetViewUp(0,0,1);
-
myCamera->SetClippingRange(0, 0);
用于设置相机前后剪裁平面 -
myCamera->SetFocalPoint(0,0,0);
设置焦点 -
myCamera->SetPosition(0,1,0);
设置相机位置 -
myCamera->SetViewUp(0,0,1);
设置相机朝上方向 -
myCamera->ComputeViewPlaneNormal();
根据设置的相机位置、焦点等信息,重新计算视平面(View Plane)的法向量 -
vtkRenderer::SetActiveCamera()
把相机设置到渲染场景中
坐标系统及空间变换
坐标系统主要有四种,分别是:
- Model坐标系统:定义模型时所采用的坐标系统,通常是局部的笛卡尔坐标系。
- World坐标系统:是放置Actor的三维空间坐标系,Actor其中的一个功能就是负责将模型从Model坐标系统变换到World坐标系统。每一个模型可以定义有自己的Model坐标系统,但World坐标系只有一个,每一个Actor必须通过放缩、旋转、平移等操作将Model坐标系变换到World坐标系。World坐标系同时也是相机和光照所在的坐标系统。
- View坐标系统:相机所看见的坐标系统。X、Y、Z轴取值为[-1,1],X、Y值表示像平面上的位置,Z值表示到相机的距离。相机负责将World坐标系变换到View坐标系。
- Display坐标系统:跟View坐标系统类似,但是各坐标轴的取值不是[-1, 1],而是使用屏幕像素值。屏幕上显示的不同窗口的大小会影响View坐标系的坐标值[-1,1]到Display坐标系的映射。可以把不同的渲染场景放在同一个窗口进行显示,例如,在一个窗口里,分为左右两个渲染场景,这左右的渲染场景(vtkRenderer)就是不同的视口(Viewport)。
参考链接:
关系如下:
上面例子Viewport演示了把一个窗口分为四个视口,用vtkRenderer::SetViewport()来设置视口的范围(取值为[0, 1]):
4. 设置已有的相机
cam1 = ren1->GetActiveCamera();
//获取渲染器的相机cam1->Zoom(1.4);
//放大相机,通过改变视角(SetViewAngle()),
另外,也可以使用Dolly()方法沿着视平面法向移动相机,实现放大或缩小可见角色物体。
基于焦点,使用Azimuth()和Elevation()方法设置相机的方位角和高度角/仰角(度,degree)[球坐标系统]。
注意其中在南极和北极存在奇异点,即视向量平行于视平面法向。此时可以使用OrthogonalizeViewUp()
方法强制其正交。但这会改变相机坐标系统。
正交投影vs透视投影vtkCamera::ParallelProjectionOn()
开启平行/正交投影。此时需通过SetParallelScale()方法控制角色物体的缩放。Zoom不再有效。
参考链接:http://swyxgc.blog.163.com/blog/static/4567575320112433642190/
5. 成像过程
人眼或相机的视野可以想象成一个圆椎体。这个圆椎体的尖端是我们的眼球中心或者说相机的光心,底端朝向被摄物体。这个视锥体将决定我们能看到什么,以及看到的物体的透视变形幅度是怎样的(见下图)。最右边图片中棍子的倾斜角度就是圆锥体的张角。所以在图像中,棍子恰好重合为一个圆点。
(个人觉得图更好理解)
通过顶点位置、张角和底面中心来唯一确定一个圆锥体。这里顶点位置对应光心Position,张角对应ViewAngle,底面中心就是焦点FocalPoint。
ViewAngle的计算如下:
其中的成像平面高度“height of image plane”在现实相机中就对应传感器的高度。在vtk中我们也可以设置UseHorizontalViewAngle来决定是使用横向比例还是纵向比例。默认以及习惯上都是纵向比例。
根据我们设置的Position,ViewAngle和FocalPoint VTK已经可以完全确定视锥体了。也就是说到目前为止,相机内到底拍到什么(或者说视野中到底能看到什么)已经确定了。注意,到目前为止,所有量都是没有单位的。
在VTK中,相机vtkCamera可以视作胶片相机,也就是说分辨率可以达到无限高。而vtkRenderWindows对象的作用就是数字化。我们通过vtkRenderWindows::SetSize()来设置图像的分辨率。然后VTK会像切蛋糕一样,用一个长方形把视锥体底面套住(高度对齐),然后按照设置的分辨率把长方形内框住的内容切成一个一个的小像素,变成数字化的图片显示到屏幕上完成了渲染。下图为视锥体套上了一个高度对齐底面直径的渲染窗口RenderWindow。
这一过程也就解释了,为什么增加VTK中的焦距时,图片内容没有放大的原因。当更改焦距(FocusPoint-Position)时,ViewAngle没有改变。所以对应的成像平面向外平移,视锥体底面成比例的放大了。vtkRenderWindows只能用一个更大的长方形套住视锥体体面。但是分辨率不变的,所以长方形被切分成同样多的小像素。虽然成像变大了,但是每个像素的大小也成比例变大了。所以最后表现在屏显图片上没有发生任何改变。
这个图非常直观,大家可以去围观原博主哦