VTK笔记-相机vtkCamera

vtk相机

  VTK是用vtkCamera类来表示三维渲染场景中的相机。vtkCamera负责把三维场景投影到二维平面,如屏幕、图像等。
  在VTK中,相机的实质是一个观测点,与人眼的功能相同,相机的视野范围是一个锥状体。
  VTK中的相机的使用示意图如下:
在这里插入图片描述
  相机位置和焦点位置定义了相机的位置和投影方向,前裁剪平面为CCD镜头平面(图像平面),后裁剪平面为物体平面。

与相机投影相关的因素主要有:

  • 相机位置:即相机所在的位置,用方法vtkCamera::SetPosition()设置。
  • 相机焦点:用方法vtkCamera::SetFocusPoint()设置,默认的焦点位置在世界坐标系的原点。
  • 朝上方向:即哪个方向为相机朝上的方向。就好比我们直立看东西,方向为头朝上,看到的东西也是直立的,如果我们倒立看某个东西,这时方向为头朝下,看到的东西当然就是倒立的。相机位置、相机焦点和朝上方向三个因素确定了相机的实际方向,即确定相机的视图。
  • 投影方向:相机位置到相机焦点的向量方向即为投影方向。
  • 投影方法:确定Actor是如何映射到像平面的。vtkCamera定义了两种投影方法,一种是正交投影(OrthographicProjection),也叫平行投影(Parallel Projection),即进入相机的光线与投影方向是平行的。另一种是透视投影(PerspectiveProjection),即所有的光线相交于一点。
  • 视角:透视投影时需要指定相机的视角(View Angle),默认的视角大小为30º,可以用方法vtkCamera::SetViewAngle()设置。
  • 前后裁剪平面:裁剪平面与投影方向相交,一般与投影方向也是垂直的。裁剪平面主要用于评估Actor与相机距离的远近,只有在前后裁剪平面之间的Actor才是可见的。裁剪平面的位置可以用方法vtkCamera::SetClippingRange()设置。
      这里的前后裁剪平面和摄影中的近和远剪裁的平面相同,近和远剪裁的平面是虚构平面,位于沿着摄影机的视线方向上距离摄影机的两个特定距离上。只有摄影机的两个剪裁平面之间的对象才会在摄影机的视图中被渲染。对于场景中与摄影机之间的距离比与近剪裁平面的之间距离近的任何对象,或与摄影机之间的距离比与远剪裁平面之间的距离远的任何对象,系统都不会进行渲染。 一句话,剪切平面是为了消除距离相机过近或过远的图像数据。
      如果某个对象的一部分位于近剪裁平面的前面,则该对象中仅有超出近剪裁平面的那一部分才会被渲染。在这里插入图片描述

相机的运动

当物体在处于静止位置时,相机可以在物体周围移动,摄取不同角度的图像;
相机的运动分为移动、旋转;
在这里插入图片描述

移动

  移动分为相机的移动,和相机焦点的移动;移动改变了相机相对焦点的位置,离焦点更近或者更远;这样就会改变被渲染的物体在视野中的部分;
  相机的移动可以有水平上的移动,垂直方向的移动,前后的移动;

旋转

  相机的旋转可以分为水平上围绕焦点旋转,垂直上围绕焦点旋转,围绕相机和焦点的连线的旋转;
  物体围绕相机做水平上旋转,垂直旋转;
  相机的旋转:是相机在以焦点为中心的圆球面上移动,因为相机可以水平旋转和垂直旋转;水平旋转就是在相机围绕球心过朝上方向这个轴旋转,也可以说是在球面上的维度进行旋转,但相机的镜头始终指向焦点;垂直旋转就是在相机绕球面上的经线向上或者向下旋转;旋转的范围不包括90度;大家可以试试垂直旋转90度会有什么样的效果;
  从上面可知,相机的旋转是跟朝上方向有关系,不同的方面,水平旋转和垂直旋转的效果不一样;
在这里插入图片描述

vtkCamera

  用于三维绘制的虚拟摄像机;
  vtkCamera是一种用于三维渲染的虚拟相机。它提供了定位和定向视点到焦点的方法,还提供了围绕焦点移动的方便操作;更复杂的方法允许操纵计算机图形模型,包括视图上方向向量、剪裁平面和相机透视。
在这里插入图片描述

接口

相机坐标

  相机所在的位置坐标;

   void SetPosition(double x, double y, double z);
   void SetPosition(const double a[3]) { this->SetPosition(a[0], a[1], a[2]); }
   vtkGetVector3Macro(Position, double);

相机焦点

  相机焦点所在的位置坐标;

   void SetFocalPoint(double x, double y, double z);
   void SetFocalPoint(const double a[3]) { this->SetFocalPoint(a[0], a[1], a[2]); }
   vtkGetVector3Macro(FocalPoint, double);

  通过设置相机焦点与相机坐标的距离,来移动焦点坐标,注意:设置的值必须为正值。

void SetDistance(double);
vtkGetMacro(Distance, double);  

朝上方向

  使用SetViewUp设置相机的朝上方向;
  一般默认朝上方向是Y轴正向:(0,1,0);
  修改相机的朝上方向,可以实现相机绕XYZ轴旋转的功能;
  一般情况都是写0或者1,如果是斜着旋转,就要输入0-1范围内的小数,大家可以动手自己实验一下;

   void SetViewUp(double vx, double vy, double vz);
   void SetViewUp(const double a[3]) { this->SetViewUp(a[0], a[1], a[2]); }
   vtkGetVector3Macro(ViewUp, double);

投影方式

  设置/获取ParallelProjection实例变量的值。
  这决定了相机应该进行透视投影还是平行投影

   void SetParallelProjection(vtkTypeBool flag);
   vtkGetMacro(ParallelProjection, vtkTypeBool);
   vtkBooleanMacro(ParallelProjection, vtkTypeBool);

投影方向

  投影方向是指从相机位置到焦点方向的矢量。

double DirectionOfProjection[3];
vtkGetVector3Macro(DirectionOfProjection, double);

  这通常与ViewPlaneNormal相反,即垂直于屏幕的向量,除非视图是倾斜的。

旋转

  void Roll(double angle):围绕投影方向旋转相机
  void Azimuth(double angle); 以焦点为中心,围绕朝上方向方向向量,即在焦点为中心,焦距为半径的圆球的维度线上水平旋转;
  void Elevation(double angle); 以焦点为中心,在焦点为中心,焦距为半径的圆球的经度线方向上旋转垂直旋转;
  void Yaw(double angle); 同Azimuth相似,以相机为中心,移动焦点坐标;
  void Pitch(double angle); 同Elevation相似,以相机为中心,移动焦点坐标;

调整裁剪平面距离

  ClippingRange即剪切平面,分为前后两个。只有在这两个剪切平面之间的内容才会被渲染和显示。默认值是(0.1,1000)。这个量一般不需要修改,而是在vtkRenderer对象中调用ResetCameraClippingRange()方法来自动重设渲染范围。如果你的图像显示不完整,但是稍微用鼠标旋转或平移一下又变完整了。建议试一下调用一次这个方法。
  设置前裁剪平面和后裁剪平面,前裁剪平面就是距离相机较近的平面,后平面就是距离相机较远位置;
  dNear和dFar是距离相机坐标的距离,在相机坐标向焦点方向上的距离

void SetClippingRange(double dNear, double dFar);
void SetClippingRange(const double a[2]) { this->SetClippingRange(a[0], a[1]); }
vtkGetVector2Macro(ClippingRange, double);

重置相机参数

  vtkRenderer类可以重置使用的相机参数;
  virtual void ResetCamera();
  根据可见的vtkActor自动设置相机参数。使得相机会重新定位以观察演员的中心点,并沿其初始视图平面法线移动(即,从镜头位置到焦点),这样所有的vtkActor都可以在相机中看到。
  从源码中可以看到ResetCamera()只会重置相机的焦点焦距朝上方向等信息,不会重置旋转角度,如果要从一个Renderer中获取多个旋转后图像,需要对角度进行修正后计算,每次ResetCamera()都会保留上一次旋转的角度;

// Automatically set up the camera based on a specified bounding box
// (xmin,xmax, ymin,ymax, zmin,zmax). Camera will reposition itself so
// that its focal point is the center of the bounding box, and adjust its
// distance and position to preserve its initial view plane normal
// (i.e., vector defined from camera position to focal point). Note: if
// the view plane is parallel to the view up axis, the view up axis will
// be reset to one of the three coordinate axes.
void vtkRenderer::ResetCamera(double bounds[6])
{
  double center[3];
  double distance;
  double vn[3], *vup;

  this->GetActiveCamera();
  if ( this->ActiveCamera != nullptr )
  {
    this->ActiveCamera->GetViewPlaneNormal(vn);
  }
  else
  {
    vtkErrorMacro(<< "Trying to reset non-existant camera");
    return;
  }

  // Reset the perspective zoom factors, otherwise subsequent zooms will cause
  // the view angle to become very small and cause bad depth sorting.
  this->ActiveCamera->SetViewAngle(30.0);

  this->ExpandBounds(bounds, this->ActiveCamera->GetModelTransformMatrix());

  center[0] = (bounds[0] + bounds[1])/2.0;
  center[1] = (bounds[2] + bounds[3])/2.0;
  center[2] = (bounds[4] + bounds[5])/2.0;

  double w1 = bounds[1] - bounds[0];
  double w2 = bounds[3] - bounds[2];
  double w3 = bounds[5] - bounds[4];
  w1 *= w1;
  w2 *= w2;
  w3 *= w3;
  double radius = w1 + w2 + w3;

  // If we have just a single point, pick a radius of 1.0
  radius = (radius==0)?(1.0):(radius);

  // compute the radius of the enclosing sphere
  radius = sqrt(radius)*0.5;

  // default so that the bounding sphere fits within the view fustrum

  // compute the distance from the intersection of the view frustum with the
  // bounding sphere. Basically in 2D draw a circle representing the bounding
  // sphere in 2D then draw a horizontal line going out from the center of
  // the circle. That is the camera view. Then draw a line from the camera
  // position to the point where it intersects the circle. (it will be tangent
  // to the circle at this point, this is important, only go to the tangent
  // point, do not draw all the way to the view plane). Then draw the radius
  // from the tangent point to the center of the circle. You will note that
  // this forms a right triangle with one side being the radius, another being
  // the target distance for the camera, then just find the target dist using
  // a sin.
  double angle=vtkMath::RadiansFromDegrees(this->ActiveCamera->GetViewAngle());
  double parallelScale=radius;

  this->ComputeAspect();
  double aspect[2];
  this->GetAspect(aspect);

  if(aspect[0]>=1.0) // horizontal window, deal with vertical angle|scale
  {
    if(this->ActiveCamera->GetUseHorizontalViewAngle())
    {
      angle=2.0*atan(tan(angle*0.5)/aspect[0]);
    }
  }
  else // vertical window, deal with horizontal angle|scale
  {
    if(!this->ActiveCamera->GetUseHorizontalViewAngle())
    {
      angle=2.0*atan(tan(angle*0.5)*aspect[0]);
    }

    parallelScale=parallelScale/aspect[0];
  }

  distance =radius/sin(angle*0.5);

  // check view-up vector against view plane normal
  vup = this->ActiveCamera->GetViewUp();
  if ( fabs(vtkMath::Dot(vup,vn)) > 0.999 )
  {
    vtkWarningMacro(<<"Resetting view-up since view plane normal is parallel");
    this->ActiveCamera->SetViewUp(-vup[2], vup[0], vup[1]);
  }

  // update the camera
  this->ActiveCamera->SetFocalPoint(center[0],center[1],center[2]);
  this->ActiveCamera->SetPosition(center[0]+distance*vn[0],
                                  center[1]+distance*vn[1],
                                  center[2]+distance*vn[2]);

  this->ResetCameraClippingRange( bounds );

  // setup default parallel scale
  this->ActiveCamera->SetParallelScale(parallelScale);
}

如果要设定相机的坐标和焦点的坐标,需要重新调用vtkRenderer的ResetCameraClippingRange函数,重新调整前裁剪面和后裁剪面的范围,如果没有设定,就会出现渲染窗口没有被渲染的物体或者是只出现部分物体图像,是因为被渲染物体部分超出了前后裁剪平面范围;只有移动或者滚动鼠标后,出现图像,是因为vtkInteractorStyle::AutoAdjustCameraClippingRange会自动调整相机的前后裁剪平面范围,使得物体可以在前后裁剪平面范围内,得以出现在渲染窗口中;

示例

当在点击鼠标旋转相机,会看到控制台有相机的坐标位置输出:

#include "pch.h"
#include <iostream>
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkActor.h"
#include "vtkCommand.h"
#include "vtkRenderWindow.h"
#include "vtkCamera.h"
#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2); 
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;
class vtkMyCallback :public vtkCommand
{
public:
	static vtkMyCallback* New()
	{
		return new vtkMyCallback;
	}
	virtual void Execute(vtkObject *caller, unsigned long, void*)
	{
		vtkRenderer *render = reinterpret_cast<vtkRenderer*>(caller);
		cout << render->GetActiveCamera()->GetPosition()[0] << " "
			<< render->GetActiveCamera()->GetPosition()[1] << " "
			<< render->GetActiveCamera()->GetPosition()[2] << endl;
	}
};

int main()
{
	vtkConeSource *cone = vtkConeSource::New();
	cone->SetHeight(3.0);
	cone->SetRadius(1.0);
	cone->SetResolution(10);

	vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
	coneMapper->SetInputConnection(cone->GetOutputPort());
	vtkActor *coneActor = vtkActor::New();
	coneActor->SetMapper(coneMapper);

	vtkRenderer* ren1 = vtkRenderer::New();
	ren1->AddActor(coneActor);
	ren1->SetBackground(0.1, 0.2, 0.4);
	ren1->ResetCamera();

	vtkRenderWindow *renWin = vtkRenderWindow::New();
	renWin->AddRenderer(ren1);
	renWin->SetSize(300, 300);

	vtkMyCallback *mo1 = vtkMyCallback::New();
	ren1->AddObserver(vtkCommand::StartEvent, mo1);	
	mo1->Delete();

	for (size_t i = 0; i < 360; i++)
	{
		renWin->Render();
		ren1->GetActiveCamera()->Azimuth(1);
	}

	renWin->Delete();
	ren1->Delete();
	coneActor->Delete();
	coneMapper->Delete();
	cone->Delete();

	system("pause");
	return 0;
}
#pragma once
#include "vtk_include.h"
#include <vtkAppendFilter.h>
#include <vtkCamera.h>
#include <vtkCellArray.h>
#include <vtkConeSource.h>
#include <vtkContourFilter.h>
#include <vtkCubeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkImplicitModeller.h>
#include <vtkLODActor.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkRotationalExtrusionFilter.h>
#include <vtkSphereSource.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkWarpTo.h>

#include <algorithm>
#include <array>

class Test_CameraModel1
{
public:
	static void Test()
	{
		vtkNew<vtkNamedColors> colors;

		// Set the colors.
		std::array<unsigned char, 4> azArrowColor{ {255, 77, 77} };
		colors->SetColor("AzimuthArrowColor", azArrowColor.data());
		std::array<unsigned char, 4> elevArrowColor{ {77, 255, 77} };
		colors->SetColor("ElevationArrowColor", elevArrowColor.data());
		std::array<unsigned char, 4> rollArrowColor{ {255, 255, 77} };
		colors->SetColor("RollArrowColor", rollArrowColor.data());
		std::array<unsigned char, 4> spikeColor{ {255, 77, 255} };
		colors->SetColor("SpikeColor", spikeColor.data());
		// Set the background color.
		std::array<unsigned char, 4> bkg{ {26, 51, 102} };
		colors->SetColor("BkgColor", bkg.data());

		// Create the RenderWindow, Renderer and both Actors
		vtkNew<vtkRenderer> ren1;
		vtkNew<vtkRenderWindow> renWin;
		renWin->AddRenderer(ren1);
		vtkNew<vtkRenderWindowInteractor> iren;
		iren->SetRenderWindow(renWin);

		// create a camera model
		vtkNew<vtkConeSource> camCS;
		camCS->SetHeight(1.5);
		camCS->SetResolution(12);
		camCS->SetRadius(0.4);

		vtkNew<vtkCubeSource> camCBS;
		camCBS->SetXLength(1.5);
		camCBS->SetZLength(0.8);
		camCBS->SetCenter(0.4, 0, 0);

		vtkNew<vtkAppendFilter> camAPD;
		camAPD->AddInputConnection(camCS->GetOutputPort());
		camAPD->AddInputConnection(camCBS->GetOutputPort());

		vtkNew<vtkDataSetMapper> camMapper;
		camMapper->SetInputConnection(camAPD->GetOutputPort());

		vtkNew<vtkLODActor> camActor;
		camActor->SetMapper(camMapper);
		camActor->SetScale(2, 2, 2);

		// draw the arrows
		vtkNew<vtkPolyData> pd;
		vtkNew<vtkCellArray> ca;
		vtkNew<vtkPoints> fp;
		fp->InsertNextPoint(0, 1, 0);
		fp->InsertNextPoint(8, 1, 0);
		fp->InsertNextPoint(8, 2, 0);
		fp->InsertNextPoint(10, 0.01, 0);
		fp->InsertNextPoint(8, -2, 0);
		fp->InsertNextPoint(8, -1, 0);
		fp->InsertNextPoint(0, -1, 0);
		ca->InsertNextCell(7);
		ca->InsertCellPoint(0);
		ca->InsertCellPoint(1);
		ca->InsertCellPoint(2);
		ca->InsertCellPoint(3);
		ca->InsertCellPoint(4);
		ca->InsertCellPoint(5);
		ca->InsertCellPoint(6);
		pd->SetPoints(fp);
		pd->SetPolys(ca);

		vtkNew<vtkPolyData> pd2;
		vtkNew<vtkCellArray> ca2;
		vtkNew<vtkPoints> fp2;
		fp2->InsertNextPoint(0, 1, 0);
		fp2->InsertNextPoint(8, 1, 0);
		fp2->InsertNextPoint(8, 2, 0);
		fp2->InsertNextPoint(10, 0.01, 0);
		ca2->InsertNextCell(4);
		ca2->InsertCellPoint(0);
		ca2->InsertCellPoint(1);
		ca2->InsertCellPoint(2);
		ca2->InsertCellPoint(3);
		pd2->SetPoints(fp2);
		pd2->SetLines(ca2);

		vtkNew<vtkImplicitModeller> arrowIM;
		arrowIM->SetInputData(pd);
		arrowIM->SetSampleDimensions(50, 20, 8);

		vtkNew<vtkContourFilter> arrowCF;
		arrowCF->SetInputConnection(arrowIM->GetOutputPort());
		arrowCF->SetValue(0, 0.2);

		vtkNew<vtkWarpTo> arrowWT;
		arrowWT->SetInputConnection(arrowCF->GetOutputPort());
		arrowWT->SetPosition(5, 0, 5);
		arrowWT->SetScaleFactor(0.85);
		arrowWT->AbsoluteOn();

		vtkNew<vtkTransform> arrowT;
		arrowT->RotateY(60);
		arrowT->Translate(-1.33198, 0, -1.479);
		arrowT->Scale(1, 0.5, 1);

		vtkNew<vtkTransformFilter> arrowTF;
		arrowTF->SetInputConnection(arrowWT->GetOutputPort());
		arrowTF->SetTransform(arrowT);

		vtkNew<vtkDataSetMapper> arrowMapper;
		arrowMapper->SetInputConnection(arrowTF->GetOutputPort());
		arrowMapper->ScalarVisibilityOff();

		// draw the azimuth arrows
		vtkNew<vtkLODActor> a1Actor;
		a1Actor->SetMapper(arrowMapper);
		a1Actor->RotateZ(180);
		a1Actor->SetPosition(1, 0, -1);
		a1Actor->GetProperty()->SetColor(colors->GetColor3d("AzimuthArrowColor").GetData());
		a1Actor->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
		a1Actor->GetProperty()->SetSpecular(0.3);
		a1Actor->GetProperty()->SetSpecularPower(20);
		a1Actor->GetProperty()->SetAmbient(0.2);
		a1Actor->GetProperty()->SetDiffuse(0.8);

		vtkNew<vtkLODActor> a2Actor;
		a2Actor->SetMapper(arrowMapper);
		a2Actor->RotateZ(180);
		a2Actor->RotateX(180);
		a2Actor->SetPosition(1, 0, 1);
		a2Actor->GetProperty()->SetColor(colors->GetColor3d("AzimuthArrowColor").GetData());
		a2Actor->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
		a2Actor->GetProperty()->SetSpecular(0.3);
		a2Actor->GetProperty()->SetSpecularPower(20);
		a2Actor->GetProperty()->SetAmbient(0.2);
		a2Actor->GetProperty()->SetDiffuse(0.8);

		// draw the elevation arrows
		vtkNew<vtkLODActor> a3Actor;
		a3Actor->SetMapper(arrowMapper);
		a3Actor->RotateZ(180);
		a3Actor->RotateX(90);
		a3Actor->SetPosition(1, -1, 0);
		a3Actor->GetProperty()->SetColor(colors->GetColor3d("ElevationArrowColor").GetData());
		a3Actor->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
		a3Actor->GetProperty()->SetSpecular(0.3);
		a3Actor->GetProperty()->SetSpecularPower(20);
		a3Actor->GetProperty()->SetAmbient(0.2);
		a3Actor->GetProperty()->SetDiffuse(0.8);

		vtkNew<vtkLODActor> a4Actor;
		a4Actor->SetMapper(arrowMapper);
		a4Actor->RotateZ(180);
		a4Actor->RotateX(-90);
		a4Actor->SetPosition(1, 1, 0);
		a4Actor->GetProperty()->SetColor(colors->GetColor3d("ElevationArrowColor").GetData());
		a4Actor->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
		a4Actor->GetProperty()->SetSpecular(0.3);
		a4Actor->GetProperty()->SetSpecularPower(20);
		a4Actor->GetProperty()->SetAmbient(0.2);
		a4Actor->GetProperty()->SetDiffuse(0.8);

		// draw the DOP
		vtkNew<vtkTransform> arrowT2;
		arrowT2->Scale(1, 0.6, 1);
		arrowT2->RotateY(90);

		vtkNew<vtkTransformPolyDataFilter> arrowTF2;
		arrowTF2->SetInputData(pd2);
		arrowTF2->SetTransform(arrowT2);

		vtkNew<vtkRotationalExtrusionFilter> arrowREF;
		arrowREF->SetInputConnection(arrowTF2->GetOutputPort());
		arrowREF->CappingOff();
		arrowREF->SetResolution(30);

		vtkNew<vtkPolyDataMapper> spikeMapper;
		spikeMapper->SetInputConnection(arrowREF->GetOutputPort());

		vtkNew<vtkLODActor> a5Actor;
		a5Actor->SetMapper(spikeMapper);
		a5Actor->SetScale(.3, .3, .6);
		a5Actor->RotateY(90);
		a5Actor->SetPosition(-2, 0, 0);
		a5Actor->GetProperty()->SetColor(colors->GetColor3d("SpikeColor").GetData());
		a5Actor->GetProperty()->SetAmbient(0.2);
		a5Actor->GetProperty()->SetDiffuse(0.8);

		// focal point
		vtkNew<vtkSphereSource> fps;
		fps->SetRadius(0.5);
		vtkNew<vtkPolyDataMapper> fpMapper;
		fpMapper->SetInputConnection(fps->GetOutputPort());
		vtkNew<vtkLODActor> fpActor;
		fpActor->SetMapper(fpMapper);
		fpActor->SetPosition(-9, 0, 0);
		fpActor->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
		fpActor->GetProperty()->SetSpecular(0.3);
		fpActor->GetProperty()->SetAmbient(0.2);
		fpActor->GetProperty()->SetDiffuse(0.8);
		fpActor->GetProperty()->SetSpecularPower(20);

		// create the roll arrows
		vtkNew<vtkWarpTo> arrowWT2;
		arrowWT2->SetInputConnection(arrowCF->GetOutputPort());
		arrowWT2->SetPosition(5, 0, 2.5);
		arrowWT2->SetScaleFactor(0.95);
		arrowWT2->AbsoluteOn();

		vtkNew<vtkTransform> arrowT3;
		arrowT3->Translate(-2.50358, 0, -1.70408);
		arrowT3->Scale(0.5, 0.3, 1);

		vtkNew<vtkTransformFilter> arrowTF3;
		arrowTF3->SetInputConnection(arrowWT2->GetOutputPort());
		arrowTF3->SetTransform(arrowT3);

		vtkNew<vtkDataSetMapper> arrowMapper2;
		arrowMapper2->SetInputConnection(arrowTF3->GetOutputPort());
		arrowMapper2->ScalarVisibilityOff();

		// draw the roll arrows
		vtkNew<vtkLODActor> a6Actor;
		a6Actor->SetMapper(arrowMapper2);
		a6Actor->RotateZ(90);
		a6Actor->SetPosition(-4, 0, 0);
		a6Actor->SetScale(1.5, 1.5, 1.5);
		a6Actor->GetProperty()->SetColor(colors->GetColor3d("RollArrowColor").GetData());
		a6Actor->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
		a6Actor->GetProperty()->SetSpecular(0.3);
		a6Actor->GetProperty()->SetSpecularPower(20);
		a6Actor->GetProperty()->SetAmbient(0.2);
		a6Actor->GetProperty()->SetDiffuse(0.8);

		// Add the actors to the renderer, set the background and size
		ren1->AddActor(camActor);
		ren1->AddActor(a1Actor);
		ren1->AddActor(a2Actor);
		ren1->AddActor(a3Actor);
		ren1->AddActor(a4Actor);
		ren1->AddActor(a5Actor);
		ren1->AddActor(a6Actor);
		ren1->AddActor(fpActor);
		ren1->SetBackground(colors->GetColor3d("BkgColor").GetData());
		ren1->SetBackground(colors->GetColor3d("SlateGray").GetData());
		renWin->SetSize(640, 480);
		renWin->SetWindowName("CameraModel1");

		// render the image

		vtkCamera* cam1 = (ren1->GetActiveCamera());
		ren1->ResetCamera();
		cam1->Azimuth(150);
		cam1->Elevation(30);
		cam1->Dolly(1.5);
		ren1->ResetCameraClippingRange();

		// Create a TextActor for azimuth  (a1 and a2 actor's color)
		vtkNew<vtkTextActor> text;
		text->SetInput("Azimuth");
		vtkTextProperty* tprop = text->GetTextProperty();
		tprop->SetFontFamilyToArial();
		tprop->ShadowOff();
		tprop->SetLineSpacing(1.0);
		tprop->SetFontSize(36);
		tprop->SetColor(a1Actor->GetProperty()->GetColor());
		text->SetDisplayPosition(20, 50);
		ren1->AddActor2D(text);

		// Create a TextActor for elevation  (a3 and a4 actor's color)
		vtkNew<vtkTextActor> text2;
		text2->SetInput("Elevation");
		tprop = text2->GetTextProperty();
		tprop->SetFontFamilyToArial();
		tprop->ShadowOff();
		tprop->SetLineSpacing(1.0);
		tprop->SetFontSize(36);
		tprop->SetColor(a3Actor->GetProperty()->GetColor());
		text2->SetDisplayPosition(20, 100);
		ren1->AddActor2D(text2);

		// Create a TextActor for roll (a6 actor's color)
		vtkNew<vtkTextActor> text3;
		text3->SetInput("Roll");
		tprop = text3->GetTextProperty();
		tprop->SetFontFamilyToArial();
		tprop->ShadowOff();
		tprop->SetLineSpacing(1.0);
		tprop->SetFontSize(36);
		tprop->SetColor(a6Actor->GetProperty()->GetColor());
		text3->SetDisplayPosition(20, 150);
		ren1->AddActor2D(text3);

		renWin->Render();
		iren->Initialize();
		iren->Start();
	}
};

在这里插入图片描述

参考文献

1.03-VTK基础概念(2)
2.vtkCamera Class Reference
3.VTK相机类vtkCamera原理及用法

  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑山老妖的笔记本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值