利用vtkTransform类对模型位置变换、缩放、镜面成像等
vtk的vtkTransform类可以对三维模型进行位置变换、缩放、镜面成像,如下代码绘制了一个球体和一个三棱锥,通过vtkTransform类对球体、三棱锥位置变换、缩放、镜面成像:
#include <vtkConeSource.h>
#include <vtkLogger.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
int main(int argc, char* argv[])
{
vtkLogger::Init(argc, argv);
// Colors
vtkNew<vtkNamedColors> colors;
vtkColor3d coneColor = colors->GetColor3d("Tomato");
vtkColor3d sphereColor = colors->GetColor3d("Banana");
vtkColor3d backgroundColor = colors->GetColor3d("Peacock");
// Create the graphics structure. The renderer renders into the
// render window.
vtkNew<vtkRenderWindowInteractor> iren;
vtkNew<vtkRenderer> ren1;
ren1->SetBackground(backgroundColor.GetData());
vtkNew<vtkRenderWindow> renWin;
iren->SetRenderWindow(renWin);
renWin->AddRenderer(ren1);
// Generate a sphere
vtkNew<vtkSphereSource> sphereSource;
sphereSource->SetPhiResolution(31);
sphereSource->SetThetaResolution(31);
//sphereSource->SetStartTheta(135);
//sphereSource->SetStartPhi(135);
vtkNew<vtkPolyDataMapper> sphereMapper;
sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
vtkNew<vtkActor> sphere;
sphere->SetMapper(sphereMapper);
sphere->GetProperty()->SetDiffuseColor(sphereColor.GetData());
sphere->GetProperty()->SetDiffuse(.7);
sphere->GetProperty()->SetSpecular(.3);
sphere->GetProperty()->SetSpecularPower(30.0);
vtkNew<vtkTransform> sphereTrans;
sphereTrans->Scale(5, 5, 5);
sphere->SetUserTransform(sphereTrans);
ren1->AddActor(sphere);
// Generate a cone
vtkNew<vtkConeSource> coneSource;
coneSource->SetResolution(31);
vtkNew<vtkPolyDataMapper> coneMapper;
coneMapper->SetInputConnection(coneSource->GetOutputPort());
// auto cone = vtkSmartPointer<vtkActor>::New();
vtkNew<vtkActor> cone;
cone->SetMapper(coneMapper);
cone->GetProperty()->SetDiffuseColor(coneColor.GetData());
vtkNew<vtkTransform> coneTrans;
coneTrans->Translate(6.0, 0.0, 0.0);
//coneTrans->Scale(-1, 1, 1);
cone->SetUserTransform(coneTrans);
ren1->AddActor(cone);
renWin->SetWindowName("AnimateActors");
renWin->Render();
ren1->ResetCamera();
ren1->ResetCameraClippingRange();
vtkNew<vtkInteractorStyleTrackballCamera> style;
iren->SetInteractorStyle(style);
iren->Initialize();
iren->Start();
return EXIT_SUCCESS;
}
其中53~55行将球分别沿X、Y、Z轴方向放大5倍;70~73行将三菱锥沿X轴正方向移动6个单位,效果如下:
将72行注释取消,则效果如下:
可以看到圆锥体在X轴反向了,即以Y轴所在平面(VTK默认的Y轴正方向为从屏幕底部指向屏幕顶部)且垂直于屏幕的平面为镜子成镜面成像,可以理解为对X坐标取相反数了,即如果X坐标原来是1,镜面成像后变为-1。
将53~55行、70~73行都注释,即不加任何变换的原始效果如下图:
以上是场景中的模型个数大于1,对场景中模型个数为1时,如果不另外处理,则vtkTransform类无效果,如下代码,整个场景中只绘制了一个三棱锥:
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkConeSource.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include<vtkTransform.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
int main(int, char* [])
{
vtkNew<vtkNamedColors> colors;
//
// Next we create an instance of vtkConeSource and set some of its
// properties. The instance of vtkConeSource "cone" is part of a
// visualization pipeline (it is a source process object); it produces data
// (output type is vtkPolyData) which other filters may process.
//
vtkNew<vtkConeSource> cone;
cone->SetHeight(3.0);
cone->SetRadius(1.0);
cone->SetResolution(10);
//
// In this example we terminate the pipeline with a mapper process object.
// (Intermediate filters such as vtkShrinkPolyData could be inserted in
// between the source and the mapper.) We create an instance of
// vtkPolyDataMapper to map the polygonal data into graphics primitives. We
// connect the output of the cone source to the input of this mapper.
//
vtkNew<vtkPolyDataMapper> coneMapper;
coneMapper->SetInputConnection(cone->GetOutputPort());
//
// Create an actor to represent the cone. The actor orchestrates rendering
// of the mapper's graphics primitives. An actor also refers to properties
// via a vtkProperty instance, and includes an internal transformation
// matrix. We set this actor's mapper to be coneMapper which we created
// above.
//
vtkNew<vtkActor> coneActor;
coneActor->SetMapper(coneMapper);
coneActor->GetProperty()->SetColor(colors->GetColor3d("Bisque").GetData());
vtkNew<vtkTransform> trans;
trans->Translate(1.0, 0.0, 0.0);
trans->Scale(3, 3, 3);
coneActor->SetUserTransform(trans);
//
// Create the Renderer and assign actors to it. A renderer is like a
// viewport. It is part or all of a window on the screen and it is
// responsible for drawing the actors it has. We also set the background
// color here.
//
vtkNew<vtkRenderer> ren1;
ren1->AddActor(coneActor);
ren1->SetBackground(colors->GetColor3d("MidnightBlue").GetData());
//ren1->GetActiveCamera()->Dolly(0.15);
//ren1->GetActiveCamera()->SetFocalPoint(0.15, 0, 0);
//
// Finally we create the render window which will show up on the screen.
// We put our renderer into the render window using AddRenderer. We also
// set the size to be 300 pixels by 300.
//
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren1);
renWin->SetSize(800, 600);
renWin->SetWindowName("vtkTransform");
//
// The vtkRenderWindowInteractor class watches for events (e.g., keypress,
// mouse) in the vtkRenderWindow. These events are translated into
// event invocations that VTK understands (see VTK/Common/vtkCommand.h
// for all events that VTK processes). Then observers of these VTK
// events can process them as appropriate.
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
//
// By default the vtkRenderWindowInteractor instantiates an instance
// of vtkInteractorStyle. vtkInteractorStyle translates a set of events
// it observes into operations on the camera, actors, and/or properties
// in the vtkRenderWindow associated with the vtkRenderWinodwInteractor.
// Here we specify a particular interactor style.
vtkNew<vtkInteractorStyleTrackballCamera> style;
iren->SetInteractorStyle(style);
//
// Unlike the previous scripts where we performed some operations and then
// exited, here we leave an event loop running. The user can use the mouse
// and keyboard to perform the operations on the scene according to the
// current interaction style. When the user presses the "e" key, by default
// an ExitEvent is invoked by the vtkRenderWindowInteractor which is caught
// and drops out of the event loop (triggered by the Start() method that
// follows.
//
iren->Initialize();
iren->Start();
//
// Final note: recall that observers can watch for particular events and
// take appropriate action. Pressing "u" in the render window causes the
// vtkRenderWindowInteractor to invoke a UserEvent. This can be caught to
// popup a GUI, etc. See the Tcl Cone5.tcl example for an idea of how this
// works.
return EXIT_SUCCESS;
}
上述代码的53~56行设置了平移和放大变换,但并未按预想的那样平移和放大模型,模型依然和没加53~56行代码时的效果一样,为使平移和放大变换起作用,必须取消67或68行中的任意一行才行。关于Dolly函数的作用,请参考:vtkCamera类的Dolly函数作用及相机拉近拉远