简介
简单介绍下这个系列的初衷吧,这个专题下的例子都是搬运于https://kitware.github.io/vtk-examples 这个网站,首先本人英语不太好,可能翻译的有些误差hhhhh。这个系列在csdn上也有付费版不过听说质量不是很好,我这边会翻译后把坑踩一遍然后将每个example的工程上传到GitHub上。vtk在国内比较小众,用的人也不多,前一阵有个同学也是找到了我问了些问题,我觉得做这个事情还是有些意义的,希望自己能坚持下来...
工程环境
visual studio 2019
项目模板
Cmake项目
Example
程序功能圆锥与球体的动画
代码
AnimateActors.h
#pragma once
#include <vtkActor.h>
#include <vtkAnimationCue.h>
#include <vtkCommand.h>
#include <vtkSmartPointer.h>
#include <vtkVector.h>
#include <vtkVectorOperators.h>
class ActorAnimator
{
public:
ActorAnimator()
: Actor(nullptr)
, StartPosition(0, 0, 0)
, EndPosition(0.5, 0.5, 0.5)
{
}
~ActorAnimator() = default;
void SetActor(vtkActor* actor) { this->Actor = actor; }
void SetStartPosition(const vtkVector3d& position)
{
this->StartPosition = position;
}
void SetEndPosition(const vtkVector3d& position)
{
this->EndPosition = position;
}
void AddObserversToCue(vtkAnimationCue* cue)
{
cue->AddObserver(vtkCommand::StartAnimationCueEvent, this, &ActorAnimator::Start);
cue->AddObserver(vtkCommand::EndAnimationCueEvent, this, &ActorAnimator::End);
cue->AddObserver(vtkCommand::AnimationCueTickEvent, this, &ActorAnimator::Tick);
}
private:
//@{
/**
* These are callbacks that called when corresponding events are fired by the
* cue (see AddObserversToCue)
*/
void Start()
{
this->Actor->SetPosition(this->StartPosition.GetData());
}
void Tick(vtkObject* vtkNotUsed(caller), unsigned long vtkNotUsed(event), void* calldata)
{
vtkAnimationCue::AnimationCueInfo* info =
reinterpret_cast<vtkAnimationCue::AnimationCueInfo*>(calldata);
const double t = (info->AnimationTime - info->StartTime) /
(info->EndTime - info->StartTime);
vtkVector3d position = this->StartPosition + (this->EndPosition - this->StartPosition) * t;
this->Actor->SetPosition(position.GetData());
}
void End()
{
this->Actor->SetPosition(this->EndPosition.GetData());
}
//@}
vtkSmartPointer<vtkActor> Actor;
vtkVector3d StartPosition;
vtkVector3d EndPosition;
};
AnimateActors.cpp
#include "AnimateActors.h"
#include <vtkAnimationCue.h>
#include <vtkAnimationScene.h>
#include <vtkCamera.h>
#include <vtkColor.h>
#include <vtkCommand.h>
#include <vtkConeSource.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
int main(int argc, char* 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);
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);
ren1->AddActor(sphere);
// Generate a cone
auto coneSource = vtkSmartPointer<vtkConeSource>::New();
coneSource->SetResolution(31);
auto coneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
coneMapper->SetInputConnection(coneSource->GetOutputPort());
auto cone = vtkSmartPointer<vtkActor>::New();
cone->SetMapper(coneMapper);
cone->GetProperty()->SetDiffuseColor(coneColor.GetData());
ren1->AddActor(cone);
// Create an Animation Scene
auto scene = vtkSmartPointer<vtkAnimationScene>::New();
//scene->SetModeToRealTime();
scene->SetModeToSequence();
scene->SetLoop(0);
scene->SetFrameRate(30);
scene->SetStartTime(0);
scene->SetEndTime(20);
scene->AddObserver(vtkCommand::AnimationCueTickEvent, renWin.GetPointer(), &vtkWindow::Render);
// Create an Animation Cue for each actor
auto cue1 = vtkSmartPointer<vtkAnimationCue>::New();
cue1->SetStartTime(5);
cue1->SetEndTime(23);
scene->AddCue(cue1);
auto cue2 = vtkSmartPointer<vtkAnimationCue>::New();
cue2->SetStartTime(1);
cue2->SetEndTime(10);
scene->AddCue(cue2);
// Create an ActorAnimator for each actor;
ActorAnimator animateSphere;
animateSphere.SetActor(sphere);
animateSphere.AddObserversToCue(cue1);
ActorAnimator animateCone;
animateCone.SetEndPosition(vtkVector3d(-1, -1, -1));
animateCone.SetActor(cone);
animateCone.AddObserversToCue(cue2);
renWin->SetWindowName("AnimateActors");
renWin->Render();
ren1->ResetCamera();
ren1->GetActiveCamera()->Dolly(.5);
ren1->ResetCameraClippingRange();
// Create Cue observer.
scene->Play();
scene->Stop();
iren->Start();
return EXIT_SUCCESS;
}
说明
1、使用vtkNamedColors设置球体、圆锥、背景的颜色。
GetColor3d是获取对应颜色名称的rgb值,还有GetColor4d等函数可以获取对应颜色名称的rgba值等(vtkNamedColors (htmlpreview.github.io))对照表已添加到工程里。
2、使用vtkSphereSource创建球体
常用接口:
SetThetaResolution (int) | 设置经度方向上的点数(从StartTheta到EndTheta) |
SetPhiResolution (int) | 设置纬度方向上的点数(范围从StartPhi到EndPhi) |
SetRadius (double) | 设置球体半径。默认值为0.5 |
SetCenter (double, double, double) | 设置球体的中心。默认值为0,0,0 |
3、使用vtkConeSource创建锥体
SetResolution设置圆锥的棱边数
4、使用vtkPolyDataMapper设置对应多边形的mapper
5、使用vtkActor创建渲染场景
常用接口:
SetShade | 打开或者关闭阴影测试 |
SetAmbient | 设置环境光 |
SetDiffuse | 设置漫反射光 |
SetSpecular | 设置镜面反射光 |
SetSpecularPower | 设置镜面反射亮点的大小(0-128) |
6、使用vtkAnimationScene创建一个动画场景
SetModeToRealTime | 设置实时播放模式 |
SetModeToSequence | 设置顺序播放模式 |
SetLoop | 设置循环播放模式 |
SetFrameRate | 设置帧率,单位时间内渲染的帧数 |
SetStartTime | 动画开始时间 |
SetEndTime | 动画结束时间 |
AddObserver对AnimationCueTickEvent这个事件添加回调函数将动画运行显示绑定到渲染窗口进行显示。
cue有三种状态:未初始化、激活和未激活。未初始化表示在cue开始时间之前的一个时间点。激活表示在cue开始时间和结束时间之间的某个时间点。但是,在结束时间之后,它处于未激活状态。当提示进入激活状态时,StartAnimationCueEvent被触发,此事件可以初始化动画的实体。当提示离开激活状态时,EndAnimationCueEvent被触发,此事件处理动画运行结束后的需要进行的操作。在激活过程中会触发AnimationCueTickEvent 事件,此事件用来处理实际动画的运行效果。
头文件中也是利用AddObserversToCue这个函数来对这三个事件进行绑定。start函数设置Actor的起始位置,Tick函数计算每次Actor移动到的位置,End函数设置Actor的结束位置。
7、使用vtkAnimationCue创建两个个随时间变化/动态的实体加入到动画场景中
8、使用scene->Play()、scene->Stop()进行动画的开始和停止。
GitHub地址
VTKExamples/Animation/AnimateActors at main · 18810186103/VTKExamples (github.com)