相机介绍:
首先,这里的相机并不是我们生活中常说的相机,但也有类似的地方,在计算机图形学中,相机的位置焦点等参数实际上对应生活中人眼的位置和所看的点。无论是OpenGL还是VTK中,都有相机,当前使用的相机将决定我们看到的事物。
很多做三维设计的朋友都会知道,设计完成后,可以创建多个相机用于作品展示,我们选择相机,实际上也就是选择的我们眼睛的位置,从不同的空间位置查看作品,不用每次都手动调整当前相机位置到比较好的位置。
在计算机中,相机可以看成空间中的一个矢量(仅仅是看成),起点即为当前相机的位置,也就是我们眼睛的位置,方向就是相机朝向,也就是我们眼睛看的方向。实际上,vtk中的相机还包含其他的参数,比如焦点,俯仰角、偏航角、高程等,甚至很多参数都可以通过已有的其他参数计算出来,但是,为了方便不同的方式使用相机,vtk相机做了很多方法的封装,可以通过不同方式设定相机达到相同的结果。很显然,对于一个相机而言,本身是简单的,常用的方法也不会太多。因此,本文并不会对大量不常用的方法作介绍。
VTK相机:
在vtk中,如果没有创建自己的相机,vtkRender会默认创建一个相机,在最开始,太会自动调整相机位置及焦点(位置和焦点决定朝向),自动调整使得这个Render中的所有模型居中显示,便于观察。实际上,我们还可以创建自己的相机,并将之应用到一个渲染器,也可以创建多个相机备用。
如图所示,vtk相机直接继承于vtkobject,对于相机参数的设置,与属性类似,属性的设置可以是vtkActor->GetProperty()->Setxxx(),也可以使直接对属性对象设置好后使用vtkActor->SetProperty(xx)来设置。相机是作用域vtkRender的,因此相机的设置可以使下面两种方式:1、vtkRender->GetActiveCamera()->Setxxx()来设置们2、还可以申请一个相机对象,对相机参数进行设置,然后使用vtkRender->SetActiveCamera来设置到渲染器。
相机常见移动方式介绍:
1、相机前后左右上下移动,就是相机的正常移动,向前移动,就是向有当前位置向焦点的方向移动,其他方向也类似,我们可以通过vtkCamera->SetPosition()来设置相机的位置,从而实现个方向移动,特别注意,这个是设置的世界坐标。
2:相机旋转,指的是相机本身俯仰旋转,偏航旋转以及横滚旋转,俯仰旋转为Pitch()函数设置的,调用Pitch(1)就会使相机抬头1度,同样的,负数会向下看。参数就是这一次改变的度数(非总度数)。同理,调用Yaw()是改变偏航角,传入正数会向左看(体现为物体向右移动),Roll()是调整翻滚角,传入正数角度,相机顺时针旋转。
class vtkMyCallback : public vtkCommand
{
public:
static vtkMyCallback *New()
{
return new vtkMyCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*) // 强制实现的方法
{
vtkRenderer *ren = reinterpret_cast<vtkRenderer*>(caller);
cout << ren->GetActiveCamera()->GetPosition()[0] << " "
<< ren->GetActiveCamera()->GetPosition()[1] << " "
<< ren->GetActiveCamera()->GetPosition()[2] << "\n";
}
};
int main()
{
vtkSmartPointer<vtkRenderWindow> m_pRenderWin = vtkRenderWindow::New();
vtkSmartPointer<vtkRenderWindowInteractor> m_pInteractor = vtkRenderWindowInteractor::New();
vtkSmartPointer<vtkInteractorStyleTrackballCamera> m_pInteractorStyle = vtkInteractorStyleTrackballCamera::New();
vtkSmartPointer<vtkActor> m_actor = vtkActor::New();
vtkSmartPointer<vtkRenderer> m_render = vtkRenderer::New();
vtkSmartPointer<vtkEarthSource> m_earth = vtkEarthSource::New();
vtkSmartPointer<vtkPolyDataMapper> m_earthMap = vtkPolyDataMapper::New();
vtkSmartPointer<vtkTransform> m_trans = vtkTransform::New();
vtkSmartPointer<vtkCamera> m_pCamera = vtkCamera::New();
m_earth->SetRadius(15);
m_earth->SetOnRatio(6); // 设置精度(0~16)16精度最低
// m_earth->OutlineOff(); // 打开绘制大陆作为填充多边形或线框轮廓 效果不是很好
m_earthMap->SetInputConnection(m_earth->GetOutputPort());
m_trans->Translate(0, 0, 0);
m_trans->RotateX(0); // 沿x轴正方向顺时针旋转
m_actor->SetMapper(m_earthMap);
m_actor->SetUserTransform(m_trans);
m_actor->GetProperty()->SetDiffuse(0.6); // 设置漫反射分量
m_actor->GetProperty()->SetSpecular(0.3); // 设置镜面反射分量
m_actor->GetProperty()->SetSpecularPower(20); // 设置镜面反射
// m_actor->VisibilityOff(); // 隐藏模型
m_render->AddActor(m_actor);
//-------------------------------------------------------------------------
// 相机设置
m_pCamera->SetPosition(0, 0, 50);
m_pCamera->SetFocalPoint(0, 0, 0);
//-------------------------------------------------------------------------
m_render->SetActiveCamera(m_pCamera);
vtkMyCallback* mol = vtkMyCallback::New();
m_render->AddObserver(vtkCommand::StartEvent, mol); // 为渲染器添加观察器(回调函数)
mol->Delete();
m_render->SetViewport(0.0, 0.0, 1.0, 1.0);
m_render->SetBackground(0.5, 0.3, 0.2);
m_render->SetGradientBackground(true); // 背景色渐变
m_pRenderWin->AddRenderer(m_render);
m_pRenderWin->SetSize(800, 600);
m_pRenderWin->Render();
m_pInteractor->SetInteractorStyle(m_pInteractorStyle);
m_pInteractor->SetRenderWindow(m_pRenderWin);
m_pRenderWin->Render();
// -----------相机设置------------------------
for (int i = 0; i < 200; ++i)
{
m_pCamera->Pitch(0.1); // 自行更改为 Yaw和Roll尝试
m_pRenderWin->Render();
}
// ----------------------------
m_pInteractor->Start();
return 0;
}
3:相机还能绕着某一点移动,即绕一点旋转(类似于蚂蚁在乒乓球上面爬),这个点就是焦点。但是,只有两个方向,可以是竖直面上上下旋转,水平面上左右旋转,如果相机焦点是在物体中心,表现结果就是物体在旋转。
Elevation:上下旋转,传入角度为正则相机向上旋转(物体向下旋转)。Azimuth,相机绕焦点向右旋转,如果焦点在物体中心,看起来就是物体向左旋转,大家可以将上面的程序更改位使用Elevation和Azimuth函数,看看效果。
相机常用方法:
上面所讲的SetPosition,Pitch,Yaw,Roll,Elevation、Azimuth六个方法这里就不做介绍了。
(1)Zoom:视角设置,正常视角为45度,也可以设置成其他度数,看看效果。
(2)SetClippingRange:设置近裁剪平面和远裁剪平面的位置,同样,也有Get方法。
(3)SetFocalPoint:设置焦点。
(4)Dolly:向焦点或者远离焦点移动。传入参数1.1代表每次向前移动0.1倍相机至焦点距离,传入0.9代表每次远离0.1倍距离。
(5)SetViewUp:设置相机查看方向(就是相机正上方的方向),Roll就会影响这个方向。OrthogonalizeViewUp可以强制重新计算上方向。
(6)SetRoll:设置相机横滚角,相对于世界空间的。同样有获取横滚角
还有很多其他方法,但大多不是很常用。还可以为相机添加观察者等,每次更改就调用回调函数,这里不做介绍,详细学习可以访问vtkCamera类列表。