Vega Prime入门教程13.02:基本开发流程

Vega Prime入门教程索引:Vega Prime入门教程索引

API

Vega Prime的API通过模板和继承性的使用使得仿真循环更加简洁而有效,基于STL(标准模板库)和C++的API显得非常紧凑和灵活。

实时控制包括定义ACF、配置ACF和系统、运行仿真循环以及最后退出仿真循环。

初始化

vp::initialize执行如下任务:

  • 检查license是否正确
  • 初始化静态变量(static variables)和单例类(singleton classes)
  • 初始化内存分配(memory allocator)
  • 初始化渲染库(rendering library)
  • 初始化场景(scene graph)
  • 初始化ACF剥析程序(ACF parser)
  • 初始化模块界面(module interface)
  • 初始化内核(kernel classes)

需要注意的是:在自己开发的应用中,ACF中的模块不需要初始化。

初始化实例:

1
vpModule::initializeModule(modulename);

vpModule::initializeModule是告诉你如何初始化你的应用中所添加的模块。初始化所添加模块和用户定制模块需要使用以下句法:

1
2
3
4
5
6
7
//初始化所有模块
vpModule::initializeModule( "vp" );
vpModule::initializeModule( "vpEnv" );
vpModule::initializeModule( "vpMotion" );
vpModule::initializeModule( "vpLADBM" );
vpModule::initializeModule( "vpFx" );
vpModule::initializeModule( "vpIR" );

vpApp类

vpApp 类用来定义一个典型的VP应用的框架。它的定义在 vpApp.h 中。所有子方法(member methods)都被内嵌了。使用者可以复制和修改 vpApp 类 。

vpApp的主体封装了VP应用中经常用到的vpKernel的功能。vpApp类控制实时功能(包括定义ACF、配置仿真类、仿真循环、更新和退出)。

例子:

1
2
// create a vpApp instance
vpApp *app = new vpApp;

从vpApp 类创建一个新类,这是开始的最简单的方法。如果你对C++很熟悉,你就会明白你现在可以轻松运用vpApp 类了 。

vpApp 类的所有成员都可以多次定制以满足你自己的应用的需求 。

用户可以通过vpApp 类来创建自己的类 。

实例(源于vpApp 的用户定义类 ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//通过公用 vpApp 定制的自定义类
class myApp:public vpApp
{
public
myApp() {}; // constructor
~myApp() {}; // destructor
//其它方法
void printMessage()//prints a message into the console window
/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~
Method―― 键盘输入
这种方法在vpApp 类中定义
用户可以不考虑这种方法来重新定义键盘输入
默认的键盘采取操作应答,除非你采取自己的命令
所支持/定义的键盘命令如下 :
Esc 键 : //退出应用
TILDE 键 : //切换帧速显示
Backspace 键 : //重置观察者状态矢量
Enter 键 : //重新捕捉观察者状态矢量
c 键 : //将观察者置于屏幕中心点
f 键 : //切换雾的开 /关
l 键 : //切换灯光效果的开 /关
p 键 : //输出观察者绝对位置
t 键 : //切换纹理显示开 /关
T 键 : //切换透明度开 /关
w 键 : //切换线框开 /关
x 键 : //切换运动模式开 /关
~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/
virtual void onKeyInput(vrWindow::Key key, int mod)
{
switch (key)
{
//按 “ P” 键时 , 打印信息
case vrWindow::KEY_P:
printMessage();
break
default
//按 vpApp 定义的执行
vpApp::onKeyInput(key, mod);
break
}//switch(key)结束
}//无效的 onKeyInput 定制结束
private
//自定义变量和成员到这里 !
}; //myApp 类定义结束

本例里,当按下大写字母“P”键时,打印出一个信息,从而onKeyInput方法无效。当你在预先定义无效的onKeyInput里定义好默认功能键时,这些键也会失效。

定义语句

类实例可通过代码创建或通过传递ACF文件给vpKernel::define方法(或vpApp::define,若vpApp已经使用)。ACF文件中的类实例将在VP解析文件时自动创建。

定义语句可以替代ACF执行功能。参数就是用字符串来替代ACF。与以往的Vega不同的是,在VP中,你可以多次定制并且实时调用多个ACF。这个功能顶替
了Vega 的vgScan函数。

1
2
3
4
//调入 ACF 文件
//假定 argv[1]就是当前的 ACF 文件
if (argv[1])
app->define(argv[1]);

函数定义

1
2
define(const char*)
virtual int vpApp::define(const char *filename)
  • 描述-装载和解析ACF文件
  • 自变量-filename是所需ACF文件的名称。这个值可以用一行语句来表示,也可以通过复杂的语句来表示。

配置

配置从ACF中分解而来,同时将不同的类关联起来。例如,它将系统中定义的pipeline添加给服务管理器,并且为每个类配置相关的联系。configure功能是相互的,通过unconfigure可以将应用配置返回到configure前的状态。configure方法经常被用户反复运用。

1
2
//configure my app
app->configure();

仿真循环(帧循环)

仿真循环包括一个函数调用:

1
void vpApp:run();

run()执行主要的仿真循环。这个功能会持续调用beginFrame(),接下来是endFrame()用来结束循环,当然还可以在循环过程中用breakFrameLoop()来结束循环。接着这项功能会调用unconfigure()

这种方法也经常被用户反复运用于自己定义的应用中。

仿真更新

更新kernel发生在主循环的中间:

1
vpKernel::update()

这种方法在主循环的中间通过应用来调用。否则它会被vpKernel::endFrame()自动调用,这个过程发生在pKernel::processNonLatencyCritical信息传递给 kernel之前,发生在仿真循环的non-latency-critical 阶段 。

关于帧的准确位置有几点说明。所有仿真对象都由应用程序来定位,要么是通过使用vsTraversalUpdate来自动更新,要么是通过代码来手动更新。因此,应用程序的仿真更新部分大概分为三部分:

  • Pre-update: 这部分包括仿真循环的代码和由vpKernel::EVENT_PRE_UPDATE_TRAVERSAL事件执行的代码
  • VSG 更新:VSG场景更新由vpKernel::update内部触发
  • Post-update:包括vpKernel::EVENT_POST_UPDATE_TRAVERSAL事件执行的代码和主仿真循环中vpKernel::update执行后的代码

依赖于vsTraversalLocate 或者直接获取信息(如vsTransform)的位置查询是保持不变的,它们并不修改或更新场景。因此,通常来说位置查询可能产生不同的结果,这要看位置查询是在场景更新前还是更新后。如果在更新前执行,结果就会和预期的不同;如果在更新后执行,结果就会和预期的一致。因此,建议所有的位置查询都在仿真更新后执行。

关闭

1
vp::shutdown();

vp::shutdown执行如下任务:

  • 释放被kernel classes分配的内存
  • 结束各模块以释放它们在应用中所占用的内存
  • 终止多线程
  • 将licenses返回给license server

完整流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <vpApp.h>
int main(int argc, char *argy[])//初始化VP
{
vp::initialize(argc, argv);//创建vpApp实例
vpApp *app = new vpApp;//载入acf文件
if(argc<=1)
app->define("vp_simple.acf");
else
app->define(argy[1]);
//配置应用
app->configure();
//帧循环
app->run();
//取消引用
app->unref();
//关闭,退出VP
vp::shutdown();
return 0;
}

编译运行效果:

运行效果

同时会提示内存情况

1
2
3
4
5
6
7
8
9
10
11
12
vuAllocTracer Report

Allocator | Leaked Memory (bytes)
------------------------------------------
vuAllocRaw | 0
vuAllocRefBase | 0
vuAllocAligned | 0
vuAllocFrameData | 0

************************************************
* Total leak is: 0 bytes in 0 blocks *
************************************************

在源码目录中会生成可执行文件,可以部署至其他PC中

编译结果文件

编译结果

说明

  • 完整代码工程在C:\Presagis\Suite18\Vega_Prime\resources\samples\vegaprime\vp\vp_simple
  • acf和代码有什么区别呢?Vega Prime入门教程12.01:运行测试中单独使用acf可以实现视景开发,那要代码有什么用呢?目前看来,acf实现模型的配置,代码实现编译独立运行。

Vega Prime入门教程13.02:基本开发流程
https://feater.top/vegaprime/basic-development-routine-of-vegaprime/
作者
JackeyLea
发布于
2023年9月19日
许可协议