当前位置:首页 > 专题范文 > 公文范文 >

photoscan专业版1.4中文教程

时间:2022-05-22 10:20:02 浏览量:

下面是小编为大家整理的photoscan专业版1.4中文教程,供大家参考。希望对大家写作有帮助!

photoscan专业版1.4中文教程

photoscan专业版1.4中文教程3篇

【篇一】photoscan专业版1.4中文教程

Microsoft Office 专业版 2007 中文版产品密钥

W6YQG-CPXTH-M373K-GBGQY-V93B6

KBM42-V8T4F-V4VVF-RBTKP-M4WRT

PVG3C-3B2Q3-Q83TC-4J63C-67DB6

P9Y83-7GRPX-4FQCD-BMV2T-KB8RW

Microsoft Office 专业版 2007英文版产品密钥

DPY3Y-GQ4G6-3YFH2-QH6FB-B9Q8G

MD9YQ-48R27-2X4XP-4VCVG-7QQB6

B8K92-MD6QW-P982C-9WQXY-VBR4W

Microsoft Office 家庭与学生版 2007 中文版产品密钥

JX8J3-8VWYT-3WMBD-FVDKB-K7H23

V2XPX-HBBRX-7VJBD-86FX4-XM8XJ

PD9FC-HM9C2-Q3H34-DY3F3-WF726

KTQCB-RJQDT-QVG4K-KBWY9-7Q2KG

Microsoft Office 家庭与学生版 2007 英文版产品密钥

Q6TQT-C4GMV-PM4KD-78GQ3-BRBP6

K3C63-Q8GVP-34PFJ-2HG3T-XQ66T

Microsoft Office 标准版 2007 中文版产品密钥

RDR7K-JH32M-86VWV-Y7MCC-6PC9B

QMXMQ-BXXVX-VYGKQ-7BD92-34BGQ

WB3RX-BYHPF-XXFPP-K7G8K-X7PC3

VTYG9-RGJ39-JD9FG-GJWMF-C7HTQ

Microsoft Office 中小型企业版 2007 英文版产品密钥

WFH6D-MYWGM-C3RJM-PKYCH-YFKJ3

WMQMJ-P3PHT-GGXHG-FHW3T-9B8PQ

Microsoft Office Visio 专业版 2007 中文版产品密钥

GXVD9-6MQ22-X98WF-BJBQG-VPTW3

BY9XR-GHW74-GV7MF-873WC-33VTG

Microsoft Office Visio 专业版 2007 英文版产品密钥

B4WYW-G3BKQ-9422R-W96DH-63P86

C9G4H-7H4HD-2MFJW-QD9DP-VWP86

Microsoft Office OneNote 2007中文版产品密钥

KVTB4-8X6J6-Y6R6F-P2GQ8-6TGW6

TC6RB-BYX7R-KWTKF-97HVV-YM36G

Microsoft Office OneNote 2007英文版产品密钥

BKCKP-BYM3D-2M6M6-KBV2T-QM8PQ

Microsoft Office Project Professional 2007 中文版产品密钥

HP4KH-R4CKV-4R2MV-KTBVP-HRQ6D

M3PKY-B8MPQ-JHTXX-RQ8BQ-RWVTD

Microsoft?Office Project Professional 2007 英文版产品密钥

TB9RJ-G6DKK-TWVTP-6TG3B-7MMGG

WRG6C-CDR3K-XX9XG-9CB3K-GYXJ6

Microsoft Office Visio 标准版 2007 中文版产品密钥

PY4FB-WV7V9-F7W7H-GH6Y4-QWJPQ

TRFQP-JVQFJ-98J9R-VT8RQ-XBCCQ

Microsoft Office Visio 标准版 2007英文版产品密钥

KWDBY-7XRCJ-TTC93-RHBYR-2VHTD

Microsoft Office Project 标准版 2007中文版产品密钥

TG7DX-VPRXY-WVX7B-WXKQF-RDJPQ

WG6T4-4QQP7-V746K-94Q6X-7KQ6D

Microsoft Office Project 标准版 2007 英文版产品密钥

RP4V3-YBJGV-DQ2JX-74TMX-MCPCM

TJ39G-7D6JM-7P6HP-XHTH4-BD6WY

Microsoft Office Sharepoint Designer 2007 中文版产品密钥

TMXC7-XVYDH-QQ39Y-J6BKD-8DJPW

THY7Y-H82WR-Y28WB-Y4TBG-R636J

Microsoft Office Sharepoint Designer 2007 英文版产品密钥

XHVWJ-KMKK8-M39D7-TPG8C-BMXJ8

FFTGC-YYVG9-VYQXT-6PJG4-382CW

Microsoft Office Groove 2007 中文版产品密钥

XHBQT-GMYRH-WH87K-X3JMT-GRQ6J

XFF6Q-W6FK9-R3DDF-JWMHG-VMR2W

Microsoft Office Groove 2007 英文版产品密钥

JBTYD-T3M3C-Q7VX2-93872-FXQ6M

T48W8-TQG7Q-P7B8C-7MTBW-FM8PW

Microsoft Office Publisher 2007中文版产品密钥

H8X62-6QKMF-F2HWV-MPB9G-XB36G

QKCD2-GP6BK-WKFV8-V63GF-9HYGG

Microsoft Office Publisher 2007英文版产品密钥

JJB7M-HYTGH-WQ8TR-C27TV-49WPW

H4J9V-RCWYR-QPQD2-GVW7C-RF7TJ

特殊的版本(例如企业版、繁体版等)产品密钥 :

V9MTG-3GX8P-D3Y4R-68BQ8-4Q8VD

【篇二】photoscan专业版1.4中文教程

Inspiration中文教程

一、在WINDOWS中启动Inspiration:
打开【开始】菜单,选择【所有程序】,单击【Inspiration 7】,即可打开一个新窗口,默认为无标题的图表形式。
二、介绍图表界面
打开Inspiration,即进入图表界面,在这里你可以处理、组织和排列可视化的各种信息。主要功能都列在了顶部的图表工具条、底部的格式工具条和左侧的符号控制面板中。

三、输入主题内容:
当你打开Inspiration时,在工作区中央就显示出一个符号框图,默认状态下里面写着“Main Idea”字样,这就是开始主题。
.单击符合框图,选择符号控制面板中中的符号,输入有关主题内容为“事业”。
四、利用创建工具增加已经互相连接的符合框图
在视图界面中有多种增加符号框图的方法,其中利用创建工具(Create tool)增加已经互相连接的符合框图是一种简单的方法,利用这种方法你可以直接进行选择。
1.在符号控制面板中选择一种符号框图,图表工具条上的“Create”按钮处于可操作状态,当鼠标移到按钮上面时,指向每一点时,该点改变颜色,即可直接增加相应方向的新符号框图。

2.在右上方的点上单击鼠标,即可在对应的位置增加一个符号框图,这个符合框图已经被连接好了,只需要输入有关内容即可。
3.在新的符号框图中输入“我喜欢的工作”。然后单击右上边的点,再直接建立一个已经连接的符号框图。
试一试
现在利用【Create tool】再创建一个符号框图。
1.在符号控制面板中选择一个符号框图。
注意当选中符号框图时,在符号框图的右上角有一个副题快捷控制
,它可以控制显示该框图以下的主题。
2.在图表工具条中,【Create】按钮的左下角的点。

3.点击左下角的点,在主题下面相应的位置建立一个已经连接好的符号框图。
4.在新符号框图中输入“我喜欢做的事情”。
5.按下“Shift+Return(Shift+Enter)”键,结束输入状态,并同时选择该符号框图。
如下图所示:

五、利用闪电工具(RapidFire)工具捕捉转瞬即逝的念头
在讨论你感兴趣的事情时,可以利用闪电工具增加同一层概念中的一个符号框图,这样较同时创建多个符号框图更容易把注意力集中在有关思想内容上。
闪电工具可以自由的放置符号框图,没有必要进行组织排列,你只管迅速记录下闪光的思维然后即可“观察”你所想。在本指南的后续内容中将介绍如何进一步组织安排这些信息。
1.选择“我喜欢做的事情”符号框图,在图表工具条中单击闪电(RapidFire)工具按钮。

下图显示闪电工具已经启动。


2.输入“修理东西”,然后按回车键。
3.输入“修汽车”,然后按回车键。
4.输入“整理花园”。
5.再次点击闪电工具按钮,取消该项操作。
结果如下图所示。

六、通过选择、输入方式增加独立的符号框图
有时你想增加一种想法,但是不能确定它适合的位置,此时可以通过选择、输入的方式很容易的建立这样的独立符号框图。Inspiration能自动的创建一个显示输入文本内容的符号框图。
1.打开前文中的图表视图,在标有“事业”的符号框图右侧点击鼠标。
2.键盘输入“没有在办公室”
Inspiration能够直接创建输入文本的符号框图,这个符号框图没有和任何其它符号相连接。
3.在其它空白地方单击鼠标,取消对当前符号框图的操作。

七、改变符号框图的图形
利用符号控制面板中的符号框图可以很容易的替代图表视图中的符号图形。在灵感中提供了 1300 个彩色的常用符号图形,其中包括几百个图象品质高的和动画符号图形,这些符号框图被分门别类放置在符号库中。
1.选择“修汽车”符号框图。
2.在符号控制面板中,打开符号图库,选择其中的 "日常类" (每天的)中 "运输 1" (传送 1 )项。
3.点击灰色的小汽车。
 “修汽车”的符号框图就自动变换为这个图形了。
现在,图表视图如下:

八、利用拖曳方式增加特殊的符合框图
你也可以利用拖曳方式从符号控制面板中选择符号框图,这时的符号框图没有和任何其它符号框图相联系。
1.在符号控制面板中,打开 "地理类" (地理学)图库,选择 "地形" (地形)项。
2.用鼠标左键点击“山”的符号框图,并拖动它到工作区,然后释放鼠标。


九、连接符号框图
现在开始进行符号框图间的连接,从而显示出彼此地关系。
1.选择“事业”符号框图,这是连接的起点。
2.在图表工具条中,点击连接工具按钮,使它处于激活状态。

3.选择“没在办公室”符号框图,它作为连接的末端,此时就出现了一条有箭头的线指向这个符号框图。
4.再点击“事业”符号框图。
5.点击“山形状”的符号框图,又一条有向直线指向了这个符号。
6.点击连接工具按钮,关闭连接工具。


 十、加入连接说明
当每个连接被选中时,就会显示出一个文本框,在此可以加入对两个符号框图关系的详细说明。
1.选择“事业”和“山”两个符号框图间的连接,你会看到与此连接相关联的一个文本框,可以在其中输入你的内容。
2.输入“离开城市”,再点击鼠标取消输入状态。
结果如下图所示:

 十一、加入符号框图的注释
在图表视图中,为每个符号框图加入注释是非常有用的。这些注释允许你拓展自己的思想,并且当能够坚持用这种可视化方式思考时,事实上加入注释就是写作过程的开始。
1.选择 "山" 符号框图,在图表工具条中点击注释(注意)按钮。

2.在注释中输入“我喜欢住在这里”。

 十二、移动注释
因为有不同的情况,所以注释显示位置是可以灵活移动的。为某框图写完一个注释后,可以将这个注释移到符号框图上面或者图表视图中其它任何位置。
1.选择一个打开的注释。
2.点击注释的标题栏,拖曳到“山”符号框图的右边。
如下图所示:

 十三、移动符号框图
你也能够将符号框图移到图表视图界面的其它位置。
1.选择“整理花园”符号框图。
2.拖动这个符号框图到“我喜欢做的事情”符号框图的下面、“修汽车”和“修理东西”两个框图的中间,再释放鼠标。
当你重新排列符号框图位置时,灵感会保留原来的连接。
移动后的视图如下:

 十四、改变符号的背景颜色
颜色对于符号图象是很重要的,它有利于区别图表视图中的不同项目,也常用来标识同一类的相关思想。
1.选择“整理花园”、“我喜欢做的事情”和“修理东西”三个符号框图。
当选择多个符号框图,可以按下 "变化" 键,然后依次点击各个项目,或者按下鼠标并拖动画出一个选择框,包含进要选择的符号框图。
2.在格式工具条,点击填充颜色按钮,并在弹出的调色板中选择一种颜色。

当你选择一种颜色后,符号框图中的背景颜色就变化了。
选择淡紫色作为填充颜色。
3.点击鼠标取消当前对符号框图的操作。
将符号框图变得五彩缤纷
五彩缤纷的符号框图能使你的工作更个性化,你能够利用调色板变化符号框图的色彩。
1.选择“修汽车”符号框图,打开格式工具条中,调色板中的是常用的颜色。
2.选择第一种颜色——浅灰色,,从弹出的调色板中选择和“我喜欢做的事情”框图匹配的颜色,这种颜色就取代了原来的显示颜色了。
保存作品
当你无论操作什么文件时,最好的习惯是定时进行保存。不论是第一次保存还是再存到相同的文件名下,都要用到“保存”(Save)命令。
1.在“文件”(File)菜单中,选择“保存”(Save),会弹出一个以主题符号框图名字作为默认文件名的对话框来。
2.如果有必要,选择你存储文件的文件夹。
3.单击“保存”。
在windows系统中,文件的扩展名是.isf。
退出Inspiration
如果你准备中断教程学习,在保存你的文件后可以退出Inspiration,下次可以跳过这步选择下一个教程内容。
1.在“文件”菜单中选择“退出”(Quit,Exit)即可关闭文件,退出Inspiration,如果你改变了当前文件,系统会提示是否进行保存。
2.点击“是”即保存了你的修改并推迟Inspiration.
然后继续下面的课程吧。


十五、 图表视图转换为大纲视图
将图表视图转换为大纲视图后,原来的信息内容结构会按照习惯的层次展现。
1.选择“事业”符号框图
2.点击图表工具条中的大纲视图按钮(Outline),

即可将图表视图转换为大纲视图,现在符号框图以及注释的内容以提纲的形式展现出来,即使是原来没有命名的“山”的符号框图也被自动地按照图片的主题进行了转换,并且在转换过程中不会丢掉任何思想间的关系。
如下图所示:

十六、增加主题
在大纲视图中也可以象在图表视图中一样容易地增加主题。
1.点击“事业”主题的选择控制条,在该主题周围显示出一个方框,即表示处于被选中状态。
2.在大纲工具条中点击主题按钮(Topic)。

Inspiration会增加一个主题,并自动的进行标识序号,同时新增的主题处于编辑状态,你可以输入内容了。
3.输入“野外工作”

十七、增加副题
增加副题内容也很容易,还提供了为主题追加信息等功能。
1.选择“野外工作”主题,点击大纲工具条中的副题按钮(Subtopic)。

当为一个主题增加副题时,Inspiration会自动的在该主题下增加栏目,并且标识序号,该栏目处于编辑状态。
2.输入“也许在国家森林”。
现在的状态如下图所示:

十八、移动主题
有许多方法组织大纲视图,其中一种比较简单的方式是拖动主题或者它的副题至某处。
1.选择“没在办公室”主题。
2.直接将它拖到“也许在国家森林”副题,释放鼠标。
在你释放鼠标之前,被拖动的主题还在原处,你可以从移动的黑线确定主题将到的新位置,黑线上的小箭头表示出该主题在新位置的层次。要将“不在办公室”主题显示为“野外工作”的副题,小箭头就要和“也许在国家森林”在同一层次。
操作结果如下图所示:

十九、 格式工具栏上的部分按钮意义图解

二十、词汇表

Outline n.轮廓;
略图;
大纲

arrange vt.整理,分类,排列

create vt.创造;
创作;
引起

symbol n.象征;
符号,记号

hyperlink n.[计]超链接

reverse vt.颠倒,翻转 n.背面

cluster n.一串 vt.使成群

stack n.堆,垛 vt.堆积

rectangle n.矩形,长方形

decision n.决定,决心;
果断

oval adj.卵形的 n.卵形

【篇三】photoscan专业版1.4中文教程

Vega Prime培训教材

Version 1.2 for Windows® 2000, Windows® XP Professional Edition, Solaris® 8.0, and Red Hat 8.0 Linux®

北京华力创通科技有限公司

仿真系统事业部

2003年12月


说明 4

第一章 开始 6

介绍 6

使用VP和LP 6

VP应用的组成 7

启动LP 8

退出LP 8

保存 9

LP的界面构成 9

第二章 创建你的场景 13

介绍 13

Prime连接 13

添加和浏览物体 14

小结 21

第三章 运动方式和观察者 22

介绍 22

运动和观察 22

设置观察者 22

创建Transforms 24

添加运动模式 26

添加碰撞检测 27

定义通道 30

修改视窗 36

小结 37

第四章 环境 38

介绍 38

环境设置 38

定义环境 38

添加光点 40

小结 42

第五章 特效 42

介绍 42

添加特效 42

制作碎片效果 43

制作龙卷风效果 43

为粮仓制作特效 53

小结 53

第六章 运行应用 53

介绍 53

编译和运行tornado应用程序 54

建立VC编译环境 54

小结 55

附录一 Vega Prime API 56

介绍 56

设置API 56

初始化 56

vpApp类 57

定义语句 58

配置 59

仿真循环 59

仿真更新 59

关闭 60

VP最小的应用 60

附录二 tornado应用程序 61

介绍 61

程序剥析 61




说明

本书主要介绍如何掌握Vega Prime的基本用法。您可以根据书的内容在自己的工作地点学习使用Vega Prime。本书将介绍Vega Prime实时应用、Lynx Prime用户界面,和Vega Prime工具箱的基本用法。您将学会如何创建一个能够移动的模块,小范围地形,特殊效果和爆炸的实时3D应用。

我们建议您按本书的章节顺序依次学习。因为书中的章节是按创建和创建过程遇到的相应主题顺序依次排列。因此本书也是一个使用方便,按主题顺序的参考书。

学习完成本书内容,您将能够完成以下操作:

⏹创建一个应用结构文件(ACF)文档,包括相关的静态和动态物体,多通道视角,动作执行规化和特殊效果。

建立一个微软开发演示工作平台,用于编辑您的Vega Prime应用。

准备工作

⏹在您学习本书内容时,请先安装Vega Prime并按书内容操作软件。

⏹本书只包括为Window设定的文件路径。如果您在Solaris或Linux中使用Vega Prime,缺省路径为/usr/local/MultiGen-Paradigm/

⏹完整的应用结构文件和代码位于C:\ProgramFiles\MultiGen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\tor nado\completed_ACF 目录下,使得转入程序任何部分或检查运行结果都非常容易。

⏹用于参考的文件(PDF格式)在C:\Program Files\Multigen-Paradigm\docs\vegaprime\pdf 目录下。


第一章 开始介绍

Vega Prime(以下简称VP)是一个实时三维驱动的工具包。LP(以下简称LP)是用来定义VP中的类及其参数的人机交互界面,定义好的内容可以保存到一个文件中。

这部分内容描述了VP的结构和用户界面。

使用VP和LP

VP最好与LP一起使用。尽管VP包含了创建一个应用所需的所有API,但LP简化了开发过程,而且LP允许开发者无需编写代码即可创建一个应用。

LP是一个编辑器,用于增加不同种类的模型,为模型定义参数。这些参数都存贮于应用配置文件(ACF)中的一个模型结构内,例如观察者的位置,模型及它们在场景中的位置,在场景中的移动,光线,环境效果,及目标硬件平台。ACF文件包含了VP在初始化和运行时所需的信息。

您可以在Active Preview(动画预览)中查看你所定义的内容。AP可以允许您使用交互式方法进行配置ACF,Active Preview会根据变化信息持续修改ACF内容。当出现变化,AP将用新的数据更新VP仿真窗口内容。

您同样可以用C++语言编写程序使场景更加生动。您可以根据应用中的特殊场景修改模型的参数。当一个模型建立完成后,您可以修改它位置。VP应用同样可以将ACF加载到一个图像数据流中。

当您编辑完应用后,它就成为一个可运行的3D实时应用!

VP系统结构

如你需要了解更多LP内容及它如何与VP一起工作,请查询Vega Prime程序员指南。

VP应用的组成

应用程序

应用程序控制场景,模型在场景中的移动,和场景中其它大量的动态模型。实时应用程序包括汽车驾驶,动态模型的飞行,碰撞检测,和特殊效果,如爆炸。

您在VP外的开发平台创建应用程序,并将文件以.ccp格式存档。它就包含了C++可以调用的VP库的功能和分类。在编辑完成后就形成了一个可执行的实时3D应用文件。

应用配置文件

应用配置文件包含了VP应用在初始化和运行时所需的一切信息。通过编译不同的ACF文件,一个VP能够生成不同种类的应用。ACF文件为扩展Mark-up语言(XML)格式。

您可以使用VP编辑器LP来开发一个ACF,然后您可以使用VP API动态地改变应用中模型运动。对于实时应用来说,ACF不是必要的,但它可以将改动信息进行译码,记录在.cpp程序中,这样可以为您节省大量的时间。

模型包

以前,通常是通过计算机辅助设计系统或几何学来创建单个模型,但这些方法在实时应用很难进行编码。

现在,可以使用MulitGen Creator和ModelBuilder 3D,以OpenFlight的格式来创建实时3D应用中所有独立的模型。可以使用Creator Terrain Studio(CTS),以MetaFlight格式来生成大面积地形文件。并可以使用这两种格式在VP中增加模型文件。

启动LP

在本章开始前,请先安装好VP,并正确建立许可协议。帮助文件夹安装在:C:\ProgramFiles\Multigen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\tornado\data目录下,它包含了本书所有练习的所需的源文件。请参照Vega Prime启动指南,以获取安装和运行的有关信息。

您可以根据操作系统的类型来打开LP:

⏹如操作系统是Windows,请按开始-程序-MultiGen-Paradigm-Vega Prime顺序点击,然后从第二级目录中启动LP。你也可以点击桌面上LP的快捷键启动程序,这个快捷键应在安装程序时创建完成。

⏹如操作系统是Solaris或是Linux,请打开命令窗口,在命令行中输入LP,启动该程序。

退出LP

如需退出LP,选择文件-退出,或同时按Ctrl和Q键。您也可单击窗口上方的标准关闭键。

保存

我们建议您经常在LP操作过程中进行保存。这样在出现突然停电或系统故障时,不会丢失数据。LP在文件目录中提供了所有标准文件工具。你必须学会使用这些工具。

Save 保存这在这个文件,我们建议您在修改原文件前进行保存,快捷键:Ctril+S。

Save As 以其它文件进行存档。自动给文件名附加.acf或.mft后缀。

LP的界面构成

LynX Prime用户界面包括四个部分:实例树形显示区(Instance Tree View),用户操作区(GUI View),应用程序区(API View),和工具条(Toolbar)和目录区(Menus)。所有这些区域将显示同一选定的对象的信息,但是这些信息是以不同格式进行安排的。你可以在一个或多个工作区进行操作来定义ACF。

GUI View

用户操作区在用户界面中显示ACF模型及相关的参数,操作起来十分方便。你可以从一个下拉菜单中选择参数,也可在空格处输入参数。

当您打开Lynx Prime,第一个显示的用户操作窗口叫myKernel,这是Vega Prime中Kernal类型中的一个实例。Kernel即是应用的起始点。

Instance Tree View

实例树形显示区显示目前正在操作的ACF文件和文件中包含的所有模型。实例树用一个等级结构显示了模型间的关系,及与它们的上级模型和下级模型的关系。通过实例树你可以直观的了解到应用中的模型之间的联系。

如果您选定等级中一个模型,在所有的操作区中同时显示这个模型的有关信息。

如果一个模型在文件中的不同的地方被使用,在这个模型的文件名旁就标有蓝色的箭头。向下的箭头表示文件第一次被使用。向上的箭头表示这个模型的其它应用。

如上面图例所示,MyPipeline的子目录MyWindow调用MyChannel,这是MyChannel第一次被调用,所以在它旁边标有一个向下的箭头。MyChannel后又被myObserver调用,所以这时在它旁边标有一个向上的箭头。

当您选定一个图标时,图标的属性和当前的参数就会显示在用户操作区和API区。

API View

API区显示选定的模型的所有可能的变量。在这里可以定义模型的值,就象在用户操作区一样。但是在API中,你可以直接给变量赋值。当您更改应用中的参数时,你可参考API区中要使用的变量的值。

Toolbar

LynX Prime工具条包括所有操作模型及属性的快捷按钮。这些功能同样可以在LynX Prime的目录中找到。

New File

创建一个新的,含有默认类型值的ACF文件。

Open File

打开文件浏览器,你就可以选择一个ACF文件加载到LynX Prime。所选定的ACF文件将替换目前正在显示的ACF文件。如果目前显示文件已经更改过并且还没有存盘,LynX Prime将会在打开文件浏览器之前提醒您保存更改。

Save File

保存当前的ACF。如果这个文件没有保存过,你可以在显示的对话框中输入文件名和保存目录。

Create Instance

将显示一个对话框,其中包含可以增加的模型类型列表。也可以根据名称或范围在对话框中显示或分类这些项目。

Cut Instance

将当前选定的模型拷贝到剪切板,并从当前的ACF文件中移走。

Copy Instance

拷贝当前选定的模型到剪切板,但模型仍留在ACF文件中。

Paste Instance

将剪切板中所存的模型加到当前ACF文件中。只有剪切板中含有模型才能执行此操作。

Delete Instance

从当前的ACF中移走选定的模型。将会出现一个对话框提示您进行删除或取消操作。删除操作不会在剪切板中留下模型的拷贝。

Backward

显示前一步显示。

Forward

显示下一个。只有操作过退后键才能操作这一步。

Views

在LynX Prime中四个不同的操作区之间转换:

⏹用户操作区在上面,同时API区在下面

⏹API区在上面,同时用户操作区在下面

⏹只显示用户操作区

⏹只显示API区

Active Preview

当LynX Prime中的参数发生变化时,显示运行一个基本Vega Prime应用,这个应用接收LynX Prime的发送的参数。您可以在您的ACF的三维场景显示中移动。

ACF Information

弹出一个对话框,显示当前ACF文件的信息。这个对话框同样可以用于执行其它ACF文件的操作,和生成一个在当前ACF文件中运行的应用。

LP Documentation

发布在线帮助阅览器,可以访问到每一个API和构成API各种方法。在线帮助提供Vega PrimeAPI的最新信息。


第二章 创建你的场景介绍

在您的应用中将要创建一个场景,包括一片郊区,一所农舍,一辆行驶的汽车,和一个谷仓。

在下一章中,您将在场景中增加龙卷风,它摧毁所经过的地区的所有东西。在场景中增加一头奶牛,它被龙卷风从地面刮起卷到空中。

开始时,您将使用LynX Prime来创建模型。这些文件是Vega Prime的一个类别(myObject)中的实例。

Prime连接

您将用农舍,汽车和谷仓的模型来实现Prime连接。其中你可以在MultiGen Creator桌面指南中找到农舍的实例,稍做修改后即可完成它的连接。

注意!

当您学习书中所有操作时,请按书中所标明的文件名或物体名进行操作。您随后运行的应用将按您存在ACF的文件的文件名进行调用。

目标

这部分的学习目标是使用LynX Prime的基本内容。您将把OpenFlight文件作为物体添加到场景中,并且为它们定位。一个物体对应着一个OpenFlight文件。一个场景就是一个观察者可以浏览到的事件集合。然后您可以在Active Preview(动画预览)中查看场景并在其中移动,也可以交互式修改ACF。

在此过程中,您将学到一些基本Vega Prime概念,包括:

⏹在LynX Prime中创建和存贮一个ACF文件

⏹熟悉LynX Prime用户操作界面和其它界面

⏹在您的仿真中加入OpenFlight模型做为物体。

⏹在场景中添加新的物体。

⏹在API区更改模型的参数。

⏹使用动画预览工具预览和修改应用。

添加和浏览物体

您将把OpenFlight文件作为物体加入到场景中。这些物体包括地形,农舍和汽车文件。您还要给他们固定好位置和方向,然后在动Active Preview中交互式的浏览这些物体。

添加地形

地形创建是应用的基础。在LynX Prime中为场景类赋一个地形OpenFlight文件值。您可以在Active Preview实时应用中浏览场景,并在其中移动。

Step 1 在C盘中创建一个文件夹 “VegaPrime_Desktop_Tutoria”,把所有完成的ACF文件存于这个目录中。

Step 2 单击 开始 > 程序 > MultiGen-Paradigm > Vega Prime > LynX Prime,打开LynXPrime.

Step 3 单击Vega Prime的菜单栏中的文件,选择另存于(Save as),弹出对话框,将对话框中的目录改为C:\VegaPrime_Desktop_Tutorial,将您的ACF文件重命名为Chapter2.acf。

Step 4 单击保存,将您的ACF文件存于C:\VegaPrime_Desktop_Tutorial中,对话框关闭,LynX Prime窗口标题条显示新的ACF文件名。

Step 5 单击用户操作区顶部的实例键,选择myObject。您也可以在实例树中单击myScene,在它下面选定myObject。

myScene实例是myObject的上一级实例。

您可单击实例键,从它的选择列表中选择myObject。

注意在文件名区中有town.flt文件,它是在默认ACF模板中myScende实例的默认子物体,但是你必须用新的OpenFlight文件来替换它。

Step 6 点击Filename区旁的浏览键,在C:\Program Files\Multigen- Paradigm\resources\tutorials\vegaprime\desktop_tutor\tornado\data\land 目录下选定Prime_Junction.flt文件。

当您在对话框中点击Open,Prime_Junction就将替换town.flt文件。

Step 7 在API区中在LynX Prime窗口下面,选择myObject的value,将其改为terrain,在用户操作区和实例树区中,myObject改为terrain。

Step 8 在实例树区,点击myScene,注意在所有的三个显示区内,都显示terrain是myScene实例的子物体

Step 9 保存。

预览应用

现在您可以在Active Preview中预览您的场景。利用Active Preview你可以实时观测到开发出的应用。Active Preview运行时, 任何ACF参数的变化也会立即显示出来。

Step 1 选择Tools下的Active Preview,弹出命令提示窗口,然后Active Preview打开,开始运行Chapter2.acf文件。

注意

如果Active Preview充满了您的屏幕,您可以缩小它的尺寸。自先,按Esc键关闭Active Preview窗口,在实例树区内,点击myWindow实例打开myWindow用户操作区,这个实例控制Active Preview窗口,例如,将窗口的长和宽的值改为5,12,形成一个较小窗口。

可以用鼠标和键盘来控制场景中的方向,如要在场景中向前进,按住鼠标左键。如要向后退,按住鼠标右键。如要停止(刹车),按下键盘中的X键。将鼠标拉向你,可在场景中向上;
将鼠标推离你,可在场景中向下。鼠标固定在窗口的中央,可保持盘旋模式。

⏹在场景中向前进,按住鼠标左键。

⏹在场景中向后退,按住鼠标右键。

⏹如要停止(刹车),按下键盘中的X键。

⏹将鼠标拉向你,可在场景中向上;

⏹将鼠标推离你,可在场景中向下。

⏹鼠标固定在窗口的中央,可保持盘旋模式。

Step 2 查看这片区域,这个场景有大片贫脊的土地,但在高山的另一边有一个小湖!

Step 3 完成检查后,按Esc关闭Active Preview。加入一个经典农舍。

添加农舍

也许您已经在Creator Desktop Tutor中建立一个农舍。为这个Desktop Tutor,这个农舍已经进行了修改,并安装在Vega Prime目录中。

把农舍作为其它物体加入场景,然后修改它的位置。

Step 1 在实例树区,点击myScene,它的用户操作区即显示出来。将农舍作为子物体加在这个用户操作区中的子区。

Step 2 在Children区点击创建实例键,为新实例选择Object类型。

Step 3 在对话框中选择Object,点击OK。

Step 4 在子区点击前进键进入myObject用户操作区。

Step 5 在API区,选择myObject的Value,将值改为farmhouse.

Step 6 点击在文件名区旁的浏览键,在c:\Program Files\Multigen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\torna do\data\farmhouse目录下选择farmhouse.flt文件。

Step 7 在地形中确定农舍的位置,在Position区中输入X,Y,Z的值为(773.822,945.877,-1.000)

Step 8 在工具条中点击Active Preview键,在场景中确定农舍的位置(固定在湖边!)。用鼠标和键盘控制在场景中的位置。

Step 9 做完后关闭Active Preview。

Step 10 保存你的工作。




改变位置

尽管上一步农舍被固定在湖边,但我们需要将农舍移到靠近公路和农场的中心区域。这个操作十分简单。

Step 1 在farmhouse用户操作区,将农舍的坐标位置改为(1960,1000,0)。

Step 2 点击Active Preview键,重新查看农舍的新位置。农舍已经移到山的另一边,现在固定了它的位置。

增加汽车

在农场中添加一辆汽车非常容易,你可以将汽车固定在靠近农舍的位置,在后面,您将学习让汽车运动起来。

Step 1 进入myScene用户操作区。

Step 2 在Children区点击创建实例键,选择物体类别为新实例。

Step 3 在创建实例对话框中选择Object,单击OK。

Step 4 在子区中myObject会突出显示,点击前进键进行myObject用户操作区。

Step 5 在API区,选择myObject的Value,将值改为Hummer。

Step 6 在用户操作区中,点击文件名称区旁的浏览键,在c:\Program Files\Multigen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\torna do\data\dirtyHumv目录下选择humv-dirty.flt文件。

Step 7 在位置区输入(1990,1000,0)

Step 8 在方向区内输入汽车的头朝向,斜度,转弯度分别为:(140,0,0)车的位置就定为在农舍前的公路上。

Step 9 点击工具条动画预览键,在场景中将汽车位置固定在农庄旁。

Step 10 关闭Active Preview,保存。

添加谷仓

这里添加一个大谷仓来储存粮食。

Step 1 进入myScene用户操作区。

Step 2 在Children区点击创建实例键,选择Object类别为新实例。

Step 3 在创建实例对话框中选择Object,单击OK。

Step 4 在子区中myObject会突出显示,点击前进键进入myObject用户操作区。

Step 5 在API区,选择myObject的Value,将值改为grainStorage(注意大写字母S)。

Step 6 在用户操作区中,点击文件名称区旁的浏览键,在c:\Program Files\Multigen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\torna do\data\grainstorage目录下选择grainStorage.flt文件。

Step 7 在位置区输入(2450,2465,0)头朝向,斜度,转弯度都为0。

Step 8 运行Active Preview,谷仓的位置与农庄保持一定距离。存盘。





小结

我们创建了一些模型,并把他们放入场景中。当我们在场景中移动时,这些物体才像是在移动,但这并不是我们希望的最后结果。下一章,我们将讨论观察者,物体的运行方式s,及通道。

第三章 运动方式和观察者介绍

现在,你已经可以在场景中移动了。如果让场景中的物体也活动起来就好了。运动模式仿真与定位方法不同,例如有飞行,行驶,行走或盘旋。当你将一个运动模式与一个您希望它在场景中运动起来的物体连接起来时,你同样可以将观察点放在或靠近运动物体,这样你就可以感觉到你正用鼠标来控制它的运动。本章,你将学到如何在不同位置上设置观察点,连接运动,定义通道,以实现在同一时间观察场景的不同点。

运动和观察

目的

这个指南将使您学会如何在LynX Prime中定义和定位观察点,以从不同的有利点观察场景。你还将给汽车加上行驶和碰撞检测,为场景中的与汽车相联的土地加上碰撞检测。最后你将设立不同的通道,这样您就能在Active Preview中从不同的观测点观察场景中的物体。

目标

你将学到以下这些概念:

⏹定义观察点的位置和朝向

⏹使用transform来放置观察者

⏹用运动模块给物体加载运动

⏹为物体加载碰撞检测

⏹为Active Preview设置场景的不同观察点。

设置观察者

一个观察者就是您仿真的观察点。观察所有的物体都是从观察点发出的。在Vega Prime中观察者的起始位置的默认值是地形的原点。原点的通常位置是在西南角或地形的中点。您可以在MultiGen Creator或ModelBuilder 3D中的地形OpenFlight文件中找到原点位置。

Prime_Junction.flt地形的默认位置在西南角。

在Vega Prime平面地面的坐标系统中,用X,Y,Z来表示观察者的位置。观察者的方向是用坐标系统中的朝向,斜度和转角度的HPR值来表示。

让我们来看一下坐标系统是什么样的:

观察者的位置是在三维空间中的XYZ坐标点。

●+X指向右

●-X指向左

●+Y指向前

●-Y指向后

●+Z指向上

●-Z指向下

观察者的方向是用坐标系统中的朝向,斜度和转角度的HPR值来表示。

朝向是指Z轴上的转向:

●+H指看向左旋转

●-H指看向右旋转

斜度指X轴的转向:

●+P指向上旋转

●-P指向下旋转

转角度指Y轴转向:

●+R指运动转向右边旋转

●-R指运动转向左边旋转

现在观察者的位置和方向已经定义好了,我们就要开始让它进行运动了!

创建Transforms

Transform是一个动态坐标系统。您在场景中设置的位置是物体,特殊效果光线或其它transform的子系统。也就是说,transform的值与父系统有关。

这部分将讨论如何将transform做为出发点用于一个观察者,它将设置于汽车的后面。观察者将随着场景中汽车位置的移动而移动。

Step 1 打开Chapter2.acf。

Step 2 在工具条中点击创建新实例键,打开创建实例的对话框。

Step 3 在实例列表中选择transform,点击create。在LynX Prime窗口中显示myTransform用户操作区。

Step 4 在API区,将名字改为hummerTransform,这个tranform将用于从汽车上设置我们的观察点。

Step 5 在hummerTransform用户操作区,在Parent列表中选择car,这样transform的父系统就是hummer。所有赋于transform的值都与car物体相关联。

Step 6 将transform的位置设为(0,-30,5)transform的位置就为在汽车后的30个数据库单位(米),汽车上空5个数据库单位。

Step 7 保存您的工作,目录为C:\VegaPrime_Desktop_Tutorial。文件名为Chapter3.acf。


为观察者设置目标

我们将把观察者的观察角度设置在汽车上。

Step 1 在实例树区选择myObserver,打开myObserver操作区。

Step 2 注意在Look At Target中的设置为无。

Step 3 在Look From Target列表中选择hummerTtransform。

Step 4 在更新位置(Update Position)区中清除Enabled的复选框,这样观察者的位置就随汽车的位改变而改变。(您将在下节中学习为汽车加载运动)。

Step 5 打开Active Preview(Ctrl+A)。检查观察者的位置应在汽车后面。

Step 6 检查完毕后关闭Active Preview。

Step 7 保存ACF文件。(Ctrl+S)

在下节中,你将学会给汽车添加运动模式。

添加运动模式

运动模式是一个位置方法,它允许通过使用一些标准输入设备执行经过准确定义的定位方法,这些设备包括,例如:鼠标,键盘和操纵杆。Vega Prime中的vpmotion类是所有运动模式的基础。

在上几章中,用来在场景中移动的默认的运动模式叫MotionUFO。这种运动模式是一个无重力运动模式,它可以迅速移动,并且可以移动到任何地方。还有其它运动模式可以支持飞行,行走,驾驶等等。

首先您要将UFO运动模式添加到汽车上,然后,您将学习如何更改运动模式。

Step 1 从Instance Tree区选择汽车。

Step 2 在hummer的用户操作区,在Update Position列表中选择myMotion。

Step 3 注意选择Enable复选框,这样汽车就能从运动模式中接收并处理最新的信息。

Step 4 打开Active Preview(Ctrl+A)。

注意汽车正以UFO运动模式在地上运动,但这种运动方式对于普通汽车是不正常的。所以我们要更改,选择更好模式以适应汽车的运动。

Step 5 关闭Active Preview。

更改运动模式

MotionUFO适合飞行穿越仿真,但是如果您希望改为行驶穿越仿真,你就必须将运动模式改为MotionDrive,在三种地形中可以应用MotionDrive。使用可以控制运动模式的速度和驾驭动作。另外,还可经常看到汽车驾驭!

Step 1 在Instance Tree中选择myMotion,显示myMotion的用户操作区。

Step 2 在Type列表中选择MotionDrive。

Step 3 在Speed区中将最高速度减小为10.00,以便容易驾驭。

Step 4 打开Active Preview,根据窗口下方的提示,用鼠标在场景中行驶您的汽车。试着围绕农庄,并湖边停下。

⏹按鼠标左键为加速,朝各个方向拖拉鼠标,汽车的方向就随鼠标就动。

⏹按鼠标右键为减速,连续按右键,汽车就慢慢减速。

⏹停止运动(刹车),按鼠标中键。

⏹后退是按鼠标右键并向后拖。

Step 5 保存您的设置。

您可能觉得汽车一直在下沉,不用担心。您的运动模式不是与地面接触,或者说,您的运动模式根本不能找到地。在添加接触检测后情况就会好一些。

添加碰撞检测

Isectors是接触检测,一些接触检测有大量复杂的运算,可以支持你用地线夹将运动模式固定在地面。还有一些相对简单的,包含几行代码行的运算,用来区分目标。根据检测类型的不同,您可以在C++程序中编写适当的反应程序,如在墙体前停车。

你可以从以下内容选择运算:

⏹Tripod – 三条聚集数据的直立线段,指引使用t者到指到目标。Tripod用于在水平地面上。

⏹Bump-六条线段,沿X,Y,Z轴正负方向聚集爆炸。

⏹LOS-单根视线线段,沿Y轴向辐射。它聚集您面前的数据。

⏹HAT-单根线段,沿Z轴辐射,它计算地形上的高度。

⏹XYZPR-计算及斜度和转向

⏹ZPR-计算爆炸点的Z轴方向的斜度和转向

⏹Z-计算Z轴上的爆炸点。

在我们指南中,我们将添加一个Isector来用地线夹将汽车固定在地形上,然后给汽车添加一个bump检测爆炸。我们将使用LynX Prime添加这两个运算。

添加一个Tripod检测

添加之前,你必须创建一个实例来用地夹线通过Isector来固定一个运动模式。

Step 1 在myMotion的用户操作区中,点击创建新实例的键,这个按键在Next Position Strategy列表旁边。

Step 2 在创建新实例对话框中,选择GroundClamp,点击Ok。

Step 3 点前进键显示myGoundClamp用户操作区。

Step 4 点击Isector列表旁边的创建新实例键。

Step 5 在创建新实例的对话框中选择IsectorTripod,Ground Clamp实例将会使用这个功能来计算爆炸信息。最终运动方法将接触信息反馈给汽车。

Step 6 点击前进键显示myisector用户操作区

Step 7 将mylsector改名称为tripodIsector.

Step 8 保存。

设置Tripod检测

我们需要将地形做为tripod检测的目标,tripodIsector将用地形来寻找接触,并将信息传递给所有相关的运动模式。

Step 1 在tripodIsector用户操作区,在Target列表中选择地形物体作为目标。

Step 2 设置选择Render Isectort复选框用于isector显示。如果isector找到地形目标,线条显示为绿色,否则线条显示为红色。

Step 3 运行Active Preview,你将能在屏幕上发现从汽车发出三条绿垂直线。

Step 4 设置tripod检测的宽度为10,长度为12,这样可以检测更大的接触面。宽度和长度的参数表示三根线彼此之间的距离。重新设置后,三根线的之间距离会拉大,您将能看到地面上三根直线间的三角形联线。但这个三角形不处理任何爆炸信息,而是由这三根垂线处理所有的工作。

Step 5 现在,沿湖边驾驭汽车。请注意你现在不会再觉得汽车在向下陷。当心,别开到湖里去。

Step 6 现在请开到马路上,开始练习您的驾驭技术。

Step 7 将汽车驶离数据库区,当你离开仿真世界的边缘时,汽车发出的三根线呈红色,因为这时他们无法再检测到与地面目标的接触。

Step 8 退出Active Preview,别忘了存盘。

添加Bump检测

如果汽车面前有农舍时,Bump检测就会检验到。

注意:

如果在LynX Prime定义碰撞检测,那么它无法阻止汽车穿越农舍。你必须在API中定义这个动作,这部分将不在本文范围之内。随后,你要在LynX Prime中添加汽车与房屋相撞时的效果。

Step 1 在工具条中点击创建实例键。

Step 2 在对话框中选择IsectiorBump。

Step 3 点击Create。

Step 4 将myIsector改名为bumpIsector。

Step 5 将碰撞的宽,长和高的参数设置为10,因为默认设置值太小。

Step 6 在Target列表中选择农舍为目标。接触检测将根据边靠边标准检测与农舍的接触。

Step 7 打开Isector Mask旁的浏览按键打开Bitmask Editor,bitmask将会把指导地形目标(我们将在后面的指南中建立这些地形目标)从一些检测中排除出去,在检测最新过程中节约时间。

Step 8 除了Bit1之外,清除所有的的bit。Bitmask将会显示为0000001。

Step 9 点击ok保存bitmask。

Step 10 在Position Reference列表中选择汽车目标,碰撞检测自己就会与汽车建立联接。

Step 11 在用户操作区中选择Render Isector复选框,以便在Active Preview中查看线段。

Step 12 点击Owning Isector Service列表旁的创建实例键,并且选择IsectorServiceInline。在线服务将会为每个结构提供最新的相关的检测,这样就把接触数据存贮起来为以后使用做准备。处理接触信息的流程与处理应用的流程一样。

注意:

我们不必给tripod检测添加在线服务,因为三角检测不直接联接于运动模式,而运动模式处理最新数据。但是,接触测试不与地夹线或运动模式联接。三角检测本身只确认它的位置与汽车直接相关。在线服务确认每个结构的检测是最新的,这样才能存贮数据。

意外收获!

如果您不喜欢在汽车后面驾驭汽车,你可以将transform添加在汽车内。

Step 1 在hummerTransform用户操作区,将transform的位置改为(-9,-13.2,2.93)。

Step 2 运行Active Preview来检测新的设置,你觉得驾驭变得容易了不是更难了?如果你喜欢这个设置,就把它保存起来,如果不,你可将设置改回原来的值(0,-30,5)。

Step 3 退出Active Preview,退出前请先保存。

定义通道

通道就是进入图形窗口的视角。一个窗口可能有几个通道。通道的位置由拖曳区来管理。拖曳区是根据相关窗口的规范值。

通道的默认值是与窗口大小一样,但是你可以调节它的大小。你同样可以调节拖曳区的值来排列或叠加通道。

我们将要用一些观察者来创建通道,然后调节他们。

创造新的通道和观察者

Step 1 从工具条中点击创建实例键,显示创建实例对话框。

Step 2 在Class列表中选择Channel和Observer。

Step 3 点击Create。这样你可以同时创建通道和观察者。

Step 4 将myChannel 1改名为houseChannel。

Step 5 将myObserve 1改名为houseObserver.

配置房屋通道

要配置房屋通道,要先将房屋观察者和房屋通道联接起来,然后在Active Preview窗口中放置房屋的视角。

Step 1 在houseChannel用户操作区,在Used By Observer列表中选择houseObserver。

Step 2 在Used By Window列表中选择myWindow。

Step 3 在拖曳区输入以下值,在窗口的左上方设定房屋通道。

⏹左边=0

⏹右边=0.5

⏹底边=0.5

⏹顶边=1

Step 4 保存ACF文件。

配置房屋观察者

Step 1 在houseChannel用户操作区中,点击前进键选择Used By Observer列表中houseObserver。houseObserver用户操作区打开。

Step 2 在Scene列表中选择myScene。

Step 3 将观察者的位置设为(1280,880,140)。

Step 4 选择farmhouse作为注视目标。农舍就一直处于房屋观察者通道的中心。

Step 5 注意在Get Position From列表中选择No Selection。

Step 6 在Attachments区,点击添加联接按键,选择myEnv与房屋观察者联接,将在houseChannel中有光线显示与myEnv联接。

Step 7 运行Active Preview。你将会看到两个窗口,一个是原来的窗口,另一个左上角的窗口显示的是从上向下看农舍的情景。

Step 8 退出Active Preview, 注意保存您的设置。

让我们在农庄前视点增加更多的通道,再添一个俯视通道。

从前方设定一个通道

首先,主我们从前方设定一个视角。

Step 1 点击工具条上的创建实例键,打开创建对话框。

Step 2 在Instances to Create区输入2,创建2个通道。

Step 3 在Class列表中选择Channel。

Step 4 单击Create。

Step 5 转入myChannel1用户操作区。

Step 6 将mychannel1改名为portchChannel。

Step 7 在拖曳区输入以下值,在Active Preview窗口的左下角设定前方通道位置:

⏹左边=0

⏹右边=0.5

⏹底边=0

⏹顶边=0.5

Step 8 在Used By Window列表中选择myWindow。

Step 9 选择Used By Observer列表旁的创建实例键。这样就创建了一个新的观察者,并将porch渠道与新创建的观察联接起来。

Step 10 保存。

配置前入口观察者

Step 1 在Used By区域,点击前进键进入myObserver1用户操作区。

Step 2 将myObserver1改名为porchObserver。

Step 3 在Scene列表中选定myScene。

Step 4 在Attachment区,点击增加联系键来建立与myEnv的联接。这个操作也将增加光线。

Step 5 点击Look From Target列表旁的增加实例键来增加一个新的transform,并将它与入口观察者建立联接。

Step 6 保存。

配置入口transform

Step 1 在porchObserver用户操作区,在Look From Targe列表中myTransform旁有前进键,点击此键后显示myTransform用户操作区。

Step 2 将myTransform改名为porchTransform。

Step 3 将父系统设置为farmhouse。

Step 4 设置位置为(3.5,-4,5),设置朝向为180。这个朝向和位置位于农舍的前门向外看。

Step 5 运行Active Preview,因为观察设置为入口transform,你可以从入口transform处看到景物,你仍然可能看到农舍,也可从汽车后部看。

新设置的通道叠加在原始通道,通道按创建的先后进行排列。所以最新创建的通道在窗口的上方,我们将很快调整原始通道。

Step 6 保存ACF文件,退出Active Preview。

创建一个俯视通道

一个俯视通道可象看地图一样看您的场景。

Step 1 在实例树图中,选定myChannel2显示它的用户操作区。

Step 2 将myChannel2改名为orthoChannel。

Step 3 在Projection列表中选择Orthographic。俯视投影不是一个透视俯视。

Step 4 在Frustum区中输入以下参数:

●左=-1500

●右=1500

●下=-1500

●顶=1500

这个截面参数确定了俯视图的周长大小。

Step 5 在Draw区输入以下参数

●左=0.5

●右=1

●底边=0.5

●顶边=1

俯视图通道位于屏幕的右上角。

Step 6 将偏移量定为(0,0,600),将这些输入朝向,斜度和转向值。

⏹朝向=0

⏹斜度=-90

⏹转向=0

这个通道向下旋转90度,截取的Z轴上的值为600米,这样屏幕将无法显示物体高于600米的部分。

Step 7 在Used By Window列表选定myWindow。

Step 8 点击Used By Window列表旁的创建新实例键,为OrthoChannel创建一个新观察者。

Step 9 保存。

配置Orthographic观察者

Step 1 在orthoChannel用户操作区中,点击刚创建的新观察者旁边的前进键。

Step 2 将myObserver1改名为orthoObserver。

Step 3 将myScene设置为屏幕。

Step 4 将myEnv加上光线。

Step 5 将观察者的位置设为(1500,1500,0)

Step 6 运行Active Preview,查看四个屏幕j内容。

正如先前提到的,需要调节原始窗口。现在我们将在Active Preview运行时来调节它。

调节原始窗口

Step 1 在实例树区中选择myChannel用户操作区。

Step 2 在Draw区

⏹左=0.5

⏹右=1

⏹底边=0

⏹顶边=0.5

现在您能看到所有四个窗口,Prime联接的最初设置的物体现在看上去生动多了。

Step 3关闭Active Preview并保存。

修改视窗

Active Preview窗口的默认名字为Vega Prime Window,但是最好能给窗口一个独特的名字。

你能为Active Preview一个独特的名字,这样在它运行时可以反映这个名字代表的程序。例如,如果您的观察者能在不同通道间转换,你能将窗口名称改成现在正在使用的通道名称。比如View of Satellite from Shuttle 或 View of Target

我们也可以进行窗口的其它参数修改,例如隐藏窗口的边框和窗口内的鼠标。

Step 1 在实例树区选择myWindow。

Step 2 在Label区输入Prime Junction Application。

Step 3 运行Active Preview,你就s可以在顶边显示窗口的新名字。

Step 4 在Options区,取消Border的复选框,如果你取消了边框,窗口的修饰和信息栏都会消失,你可以随意打开或关闭边框。

Step 5 取消鼠标的复选框,那么在Active Preview窗口内就不再出现鼠标。

Step 6 设置窗口边框为打开。

Step 7 设置鼠标为无。

Step 8 保存,并关闭Active Preview。

小结

我们现在可以在地面上行驶汽车了。在Active Preview中我们为观察者设定了位置,并把他们与场景中的物体联接起来,我们还从不同的视角设置了一些通道。我们也为接触检测进行了定义,并且我们将在其它章节继续学习这部分内容,到时我们还将添加一些特殊效果。

接下来我们要改变一下环境,并给汽车加上车头灯以适应在黑暗中行驶!

第四章 环境介绍

LP里面的环境效果包括阳光、月光、雾、风等。还可以控制一天中时间的流逝速度效果。你可以在几分钟的时间内将黎明变成白天、黄昏和夜晚。

这章中将会讲解如何设置天时、天空和云层的效果以及添加光点。

环境设置

目的

学会为自己的应用设置环境效果,例如依据天时而变化的阳光和月光、多云的天空。还可以给汽车加上光点,这样就可以在黑暗里行驶。

目标

⏹学会以下VP概念:

⏹控制天时

⏹改变天空颜色

⏹改变云层纹理

⏹在物体上定位光源

定义环境

VP中的环境是云、雾等大气现象的综合体。它包含了阳光和月光源。LP中阳光和月光会依据天时进行自动调整。

LP提供以下几种效果来帮你创建一个实时的环境:

⏹太阳-由一个亮盘来代表太阳在天空中的位置。

⏹月亮-由另一个亮盘来代表月亮在天空中的位置。

⏹云层-云层的一层。

⏹穹顶-刻划出天际线的效果。穹顶有一个无边的地平面,颜色可以自定义。

改变天时

默认天时是从午时12点开始,时间决定了光照的强度。一天中太阳和月亮交替出现。

Time Multiplier是控制时间快慢的工具。默认值为1,表示仿真时间和现实时间快慢相同;
若值设为0,表示时间静止;
若值设为60,表示仿真时间是现实时间速度的60倍,这时在半小时的现实时间内你就可以看到几乎整天的仿真天时效果。

Step 1 打开文件Chapter3.acf

Step 2 转到myEnv的配置界面

Step 3 将Time Multiplier的值设为1200,这样一整天的天时渲染在不到2分钟之内就可以完成

Step 4 运行Active Preview,这样你就可以看到天色慢慢变黑的过程;
同时还能看到太阳和月亮的升降效果

Step5 推出Active Preview

Step 6 将文件保存为Chapter4.acf

改变天空的颜色

一场风暴就在眼前!我们可以改变天空的颜色和云层的纹理来制造出风暴的效果!

Step 1 在myEnv界面,点击Sky旁边的Browse按钮

Step 2 将天空颜色选为红色

Step 3 运行Active Preview,就可以看到天空颜色和云层纹理混合后的效果

Step 4 接下来将颜色换成灰色或蓝灰色,这样更接近于风暴的颜色,下一小节将会改变云层的纹理以接近风暴的效果

Step 5 退出Active Preview,别忘了存盘

改变云层纹理

Step 1 在myEnv界面的Environmental Effects选项里选择myEnvCloudLayer

Step 2 点击旁边的转向按钮,打开myEnvCloudLayer界面

Step 3 在Texture一栏里点击Filename旁边的Browse按钮

Step 4 选择E:\Program Files\Multigen-Paradigm\config\vegaprime\vpenv(安装目录)下面的clouds_storm.inta文件

Step 5 运行Active Preview,就可以看到风暴来临前夕的天空效果

Step 6 退出Active Preview,别忘了存盘

添加多云层:

Step 1 在工具栏点击创建按钮

Step 2 所创建类别的数量就保持默认值1

Step 3 在Class的列表中选择myEnvcloudvolume

Step 4 点击Create,这样在LP中就出现一个myEnvcloudvolume类

Step 5 在EnvironmentParent列表选择myEnv.

Step 6 将EnvironmentParent更名为thunderCloud

Step 7 在Translate列表里输入thunderCloud的位置,X:1460 Y:300 Z:650(如图)

Step 8 运行Active preview 你将会在不远处看见一团乌云。

Step 9 退出Active Preview,别忘了存盘

添加闪电:

Step 1 在thunderCloud界面选择effort标签

Step 2 在lighting列表里设置;Seveirty 为 1;IntraCloudSeverity 为0.5;(如图)

Step 3 运行Active preview,你将会看到闪电周期性的出现。

Step 4 退出Active Preview,别忘了存盘

这样的天气里驾驶需要打开车前灯!下面我们要在汽车的前面添加光点来模拟车前灯!

添加光点

为了模拟光照效果,需要加入多个光源。光源在仿真场景中用于照亮物体。可以通过LP来完成这些配置。光源分为:

⏹定向光源-指向特定的方向

⏹位置光源-某一个位置上的漫反射光源

⏹电光源-某一位置上的定向光源

这里我们要在汽车的车头上安装点光源。

创建车头灯

这里我们先创建一个车头灯,第二个可以通过复制来完成。

Step 1 在工具栏点击创建按钮

Step 2 所创建类别的数量就保持默认值1

Step 3 在Class的列表中选择Light

Step 4 点击Create,这样在LP中就出现一个myLight类

Step 5 将myLight更名为leftHeadlight

Step 6 在Type列表中选择Spot

Step 7 在Parent列表中选择car(Object)

Step 8 将光点的Position设为(-0.05,2.24,0.9),Pitch值设为-10

Step 9 在Attenuation的Constant栏中输入0.5,这表示光照强度在照明方向上随距离增加而减弱的程度

Step 10 将Spot Cone的值设为:

⏹Inner=20

⏹Outer=45

⏹Falloff=0.5

Step 11 选上Render前面的小方框,光点将被一个小圆球代替

Step 12 运行Active Preview,当太阳落山时,就可以看到明显的车灯效果

Step 13 退出Active Preview,别忘了存盘

创建第二个车头灯

创建另一个车头灯的快捷简便的方法是复制第一个车头灯。

Step 1 在Instance Tree面板中点击leftHeadlight

Step 2 选择Edit-》Copy Instance

Step 3 选择Edit-》Paste Instance,你将会看见出现一个leftHeadlight1

Step 4 将leftHeadlight更名为rightHeadlight

Step 5 将rightHeadlight的X坐标改为0.05

Step 6 将Parent改为hummer(Object)

Step 7 运行Active Preview,看看新效果

Step 8 保存

小结

可以看出,在LP里设置天时和大气效果是很方便的。通过设置车头灯可以在黑暗中自由行驶。

下一章讲解特效效果的制作,包括龙卷风举起物体的效果!

第五章 特效介绍

特效能让你的应用变得更加真实、丰富及夺目。你可以定义烟火、爆炸、碎片等特效,也可以通过VP的粒子特效来模拟烟尘等效果。场景中的物体可以用来撞击或破坏,造成的结果可以加上特效。所有这些都可以通过LP来方便的进行定义。

这章将从一个农舍的简单特效做起。当汽车撞击房屋时,碎片会四处散落。然后可以利用粒子效果创建一个龙卷风,并通过碰撞检测和场景中的的物体进行交互。

添加特效

VP的特效模块提供了一个实时的特效库,你可以通过LP来配置特效,也可以通过VP的API来配置特效。并且特效也可以进行形状、比例和颜色的变化。

VP提供的特效包括以下几种:

⏹Blade(vpFxBlade)-旋转的螺旋桨,可以缩放和定位,适合用于直升机和飞机的螺旋桨效果

⏹Missile Trail(vpFxMissileTrail)-用有烟的轨迹来代表飞机或导弹的飞行效果,可以随着时间而变淡

⏹Particle System(vpFxParticleSystem)-多边形集聚体,用来模拟诸如焰火和烟雾等效果

⏹Debris(vpFxDebris)-飞扬的碎片效果,经常用于爆炸

⏹Explosion(vpFxExplosion)-地面或空中的爆炸效果

⏹Fire(vpFxFire)-火焰效果

⏹Smoke(vpFxSmoke)-翻腾的烟云效果

目的

学会给物体添加特效并和碰撞检测对应起来,同时要学会利用粒子系统来创建特效,并给粒子系统提供标把。

目标

学习以下概念:

⏹给目标添加一至多个特效

⏹给碰撞检测添加特效

⏹利用粒子系统创建特效

⏹定义诸如颜色、粒子数量和尺寸、喷射间隔、方向、速率等属性

制作碎片效果

在第三章中我们已经给汽车和房子碰撞定义了一个Bump的碰撞检测。当汽车和房子相撞时,应该有一个撞后的效果。

这里我们将给房子加上碎片效果,并且和汽车的碰撞关联起来。

Step 1 打开Chapter4.acf

Step 2 点击Create Instance按钮

Step 3 在Create Instance对话框里选中vpFx,能看到特效的各种类

Step 4 新建的数值采用默认值1

Step 5 选择FxDebris类

Step 6 点击Create按钮

Step 7 将myFx更名为Debris

Step 8 在Debris的界面里将farmhouse(Object)作为Parent

Step 9 在Trigger Method列表里选择Isector

Step 10 在Isector列表里选择bumpIsector

Step 11 选择Positioning标签打开Positioning界面

Step 12 将Scale值设为(20,20,20)

Step 13 运行Active Preview。将汽车撞向房屋,可以看到有碎片飞出

Step 14 转到bumpIsector的界面,去掉Render Isector前面的勾,同样将tripodIsector界面里Render Isector前面的勾也去掉,这样看起来的效果好些

Step 15 关掉Active Preview

Step 16 将文件存为tornado.acf

制作龙卷风效果

这里我们要添加一个龙卷风的效果来对物体进行撼动!

一共要使用三个粒子效果:一个为碎片层,一个是龙卷风的漏斗部分,另一个为龙卷风的顶部。

Step 1 点击Create Instance按钮

Step 2 将Instances to Create设为3

Step 3 在Class列表里选择FxParticleSystem类

Step 4 点击Create,可以看到生成三个新的类(myFx,myFx1,myFx2)

Step 5 保存ACF

配置顶部

Step 1 将myFx更名为w_tornado Top

Step 2 在w_tornado Top面板里,打开Main所属界面

Step 3 点击Texture旁边的Browse按钮,选择安装目录(如C:\Program Files\MultiGen-Paradigm\config\vegaprime\vpfx)下的smoke.inta文件,这个纹理是tornado的三个部分都要用到的

Step 4 打开Positioning界面

Step 5 将Z值设为550,这样龙卷风的高度就是550米

Step 6 打开Particle Generation界面

Step 7 在Maximum Number of Particles栏里输入1500

Step 8 在Number of Particles to Release栏里输入30

Step 9 将Release Interval值设为0.25秒,这是新粒子出现的时间间隔

Step 10 将Particle Life Cycle值设为10秒,这是新粒子出现前旧粒子所持续的时间

Step 11 在Source Domain Shape栏里选择Circle(默认值)

Step 12 将Size值设为250

Step 13 打开Particle Characteristics界面

Step 14 在Size栏里,将默认值改为50,这是粒子的初始尺寸

Step 15 点击Scale Along Velocity旁边的Create Instance按钮

Step 16 输入以下数值,使球状体变得平一点:

Step 17 点击Color旁边的Create Instance

Step 18 点击新Color旁边的Browse按钮,打开Color窗口。

为了造成龙卷风的浑浊效果,需要指定三个不同的灰度。这样在一个生命周期内,龙卷风首先是显示灰色,然后变亮,再变暗。

Step 19 将Red,Green,Blue值设为(193,193,193)

Step 20 点击OK

Step 21 将Color旁边的Create Instance按钮点击两次

Step 22 用下列值添加明暗两种颜色:

Particle Characteristics界面应该为如下图所示

Step 23 打开Particle Movement界面

Step 24 在Velocities栏里添加下列值:

Velocity Vector定义了粒子在特定时间间隔里的方向

Step 25 在Spherical Velocities栏里添加下列值:

Spherical Velocities使粒子以特定的速度按球形轨迹运动

Step 26 在Random Velocities栏里添加两个值:

Random Velocities添加粒子的随机运动

Step 27 以上步骤为龙卷风的顶部配置,先保存一下

定位

Step 1 在w_tornado Top界面里打开Main窗口

Step 2 创建一个新parent类,在Class列表里选择Transform

Step 3 打开myTransform界面

Step 4 将myTransform更名为tornado Transform

Step 5 将tornado Transform的parent设为myScene

Step 6 输入(1460,300,12)以定位tornado

Step 7 保存

Step 8 运行Active Preview,在正视图上就可以看见龙卷风的顶部移动

Step 9 退出Active Preview

配置漏斗

Step 1 打开myFx1界面

Step 2 将myFx1更名为tornadoFunnel

Step 3 在Main面板里,将Parent设为tornado Transform

Step 4 点击Texture旁边的Browse按钮,选择安装目录下(如C:\Program Files\MultiGen-Paradigm\config\vegaprime\vpfx)的smoke.inta文件

Step 5 打开Positioning界面

Step 6 将Z值设为550,这样龙卷风的漏斗部分就和顶部一样高了

Step 7 打开Particle Generation界面

Step 8 将Maximum Number of Particles设为25000

Step 9 将Number of Particles to Release设为75

Step 10 将Release Interval设为0.30秒

Step 11 将Particle Life Cycle设为12秒

Step 12 将Source Domain Shape设为Circle(默认值)

Step 13 在Size输入75

Step 14 打开Particle Characteristics界面

Step 15 在Sizes表里,将默认值改为60,这是粒子的初始值

Step 16 在Sizes表里添加以下值:

Step 17 在Scale Along Velocity表里输入如下值:

Step 18 在Color表里添加如下值:

以上值是让漏斗进行亮度的变化

Step 19 打开Particle Movement界面

Step 20 在Velocities表里输入如下值:

Step 21 在Spherical Velocities表里添加如下值:

以上值是用来形成一个逼真的锥形或漏斗形

Step 22 在Random Velocities表里添加如下值:

Step 23 至此漏斗部分已完成,存盘

Step 24 运行Active Preview,几秒钟内,龙卷风的漏斗部分就会从顶部降下并且往右移动一些。从原始视图里浏览的效果会好一些

剩下来只需要建立龙卷风的碎片层了

配置碎片层

Step 1 打开myFx2界面

Step 2 将myFx2更名为tornadoDebris

Step 3 在Main面板里,将Parent设为tornado Transform

Step 4 点击Texture旁边的Browse按钮,选择安装目录下(如C:\Program Files\MultiGen-Paradigm\config\vegaprime\vpfx)的smoke.inta文件

Step 5 打开Positioning界面

Step 6 将X值设为-50,这样碎片层就在龙卷风的偏左部

Step 7 打开Particle Generation界面

Step 8 将Maximum Number of Particles设为1000

Step 9 将Number of Particles to Release设为10

Step 10 将Release Interval设为0.05秒

Step 11 将Particle Life Cycle设为5秒

Step 12 将Source Domain Shape设为Sphere

Step 13 在Size输入40

Step 14 为Velocity Distribution选择Sphere

Step 15 打开Particle Characteristics界面

Step 16 在Sizes表里,将默认值改为15,这是粒子的初始尺寸

Step 17 在Scale Along Velocity表里添加如下值,让球形变得稍微平一些:

Step 18 在Color表里添加如下值:

这样碎片层将从中等灰度变亮一些

Step 19 打开Particle Movement界面

Step 20 在Velocities表里添加如下值:

Step 21 在Spherical Velocities表里添加如下值:

Step 22 在Random Velocities表里添加如下值:

Step 23 至此龙卷风已经制作完成,保存ACF文件

Step 24 运行Active Preview,可以看到在漏斗部分下降之前,有一部分碎片层在地面运动。将视点驶离房子,然后转回头看,就能看到龙卷风的整体效果

Step 25 关闭Active Preview,别忘了存盘

添加碰撞检测

这里我们添加一个碰撞检测来实现龙卷风在场景中的碰撞效果。通过碰撞检测能够判断出龙卷风是否碰撞到了场景中的物体,例如粮仓、房子等。

为了排除龙卷风和地形的碰撞,需要关掉碰撞检测的bit mask中的Bit 1。

需要说明的是,以下步骤稍有简化,如果需要某些详细的配置过程,请参照前面的步骤。

Step 1 点击Create Instance按钮

Step 2 创建一个IsectorBump类,命名为tornadoBumpIsector

Step 3 将myIsectorService添加给tornadoBumpIsector(在Owning Isector Service域),myIsectorService能让tornadoBumpIsector实现碰撞效果并接收到碰撞数据

Step 4 将target设为scene。在每一帧的渲染中,碰撞检测会检查场景中具有相同lsector mask的bits的物体

Step 5 选择tornado Transform为tornadoBumpIsector的positon reference。这表示碰撞检测和龙卷风的位置关联起来

Step 6 将tornadoBumpIsector的Width,Length和Height值设为50,50和50

Step 7 选上Render Isector,这样就可以在Active Preview中看见碰撞检测的范围

Step 8 将lsector service和tornadoBumpIsector关联起来

Step 9 保存设置

给龙卷风添加目标

接下来,我们将为龙卷风添加一个碰撞目标-一头奶牛!

Step 1 添加一个新Object类

Step 2 将myObject更名为cow

Step 3 将安装目录下(如C:\Program Files\MultiGen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\tornado\data\cow)的cow.flt作为模型

Step 4 将cow的parent设为scene

Step 5 将cow的position设为(2300,1625,0)

Step 6 将cow的X,Y,Z的scale都设为2。这样奶牛在碎片层中看起来就现眼一点,否则容易看成碎片层的一部分

Step 7 保存ACF

Step 8 运行Active Preview,可以看到奶牛处在房子后面的原野上

运行Active Preview,可以看到有趣的事情发生了,奶牛被直接卷入了龙卷风的碎片层中!

Step 9 退出Active Preview

为粮仓制作特效

这一节讲解如何给粮仓加上特效。当龙卷风撞上粮仓时,会产生碎片飞扬和火焰冲天的效果。

需要说明的是,Active Preview中看不到这些效果,因为这次的碰撞配置只在runtime application中生效。下一节我们再对application进行编译运行。

Step 1 各创建一个FxDebris、FxFire和FxExplosion的类

Step 2 打开myFx界面,将myFx更名为grainStorageDebris

Step 3 将parent设为grainStorage

Step 4 Triggering Method中选择Don’t Trigger,必要时我们会使用一行代码来打开这个效果

Step 5 打开Position界面

Step 6 将special effect的X,Y,Z的scale设为50

Step 7 对FxFire和FxExplosion重复第2步至第6步,同时别忘了将这两个特效类更名为grainStorageFire和grainStorageExplosion

Step 8 保存ACF

小结

到此为止,我们可以在Active Preview里看到龙卷风并不移动,只是原地打转。下一章我们要编译一段代码,执行的时候可以让龙卷风按固定的路径移动,同时进行破坏!

第六章 运行应用介绍

我们已经知道了如何在LP中配置ACF文件,这里我们要编译一段应用程序,需要结合ACF文件运行。

最后一章里,要学会如何设置VC6.0的环境,以后就可以运行自己的代码了!

编译和运行tornado应用程序

应用程序和你在ACF中定义的类互相作用,程序将指针指向程序中的类,并且依据程序所定义的条件来反应。当龙卷风碰到粮仓时,你可以看到火光和爆炸。类似的,当龙卷风刮过房子时,一个被破坏的房子模型会出现在你眼前(这个被破坏的模型是在原模型文件里做了一个切换)

这里你要在VC6.0的环境里建立一个workspace和project,将ACF文件关联在一起。然后可以通过键盘来启动龙卷风的破坏之旅!

建立VC编译环境

VC里要做的事情就是创建workspace、配置project、添加files,然后编译运行即可。

创建VC的workspace

workspace是你在Microsoft Visual Studio中创建project所需所有文件的一个工作环境。

Step 1 检查并确认当VP安装完时,系统环境变量中已经配置了如下参数:

⏹MPI_LOCATE_VEGA_PRIME,值为安装目录,如e:\Program Files\Multigen-Paradigm

⏹MPI_LOCATE_VEGA_PRIME_LIB,值为lib目录,如e:\Program Files\Multigen-Paradigm\lib

Step 2 选择开始-》程序-》Microsoft Visual Studio 7.1-》Microsoft Visual C++7.1,打开VC编译环境

Step 3 在菜单中选择File-》New

Step 4 选择Workspaces标签

Step 5 在Workspace name中输入tornadoApplication

Step 6 在Location中指定一个位置,例如C:\VegaPrime_Desktop_Tutorial

Step 7 点击OK,可以看到File View中生成了一个新的名为tornadoApplication的Workspace

Step 8 选择File-》New

Step 9 选择Projects标签

Step 10 在projects列表中选择Win32 Console Application

Step 11 Project name中输入tornado

Step 12 选择Add to current workspace

Step 13 点击OK,出现Win32 Console Application的向导

Step 14 选择An empty project

Step 15 点击Finish

Step 16 在出现的New Project Information对话框中,确保路径是C:\VegaPrime_Desktop_Tutorial\tornadoApplication

Step 17 点击OK,就可以看到一个project出现在当前的workspace中

配置project

Step 1 选择Projects-》Settings

Step 2 在Settings For列表里,选择All Configurations

Step 3 选择Debug标签

Step 4 在Program arguments中输入ACF文件的保存路径加上文件名,例如C:\VegaPrime_Desktop_Tutorial\tornado.acf,

Step 5 选择C/C++标签

Step 6 在Category列表中选择Code Generation

Step 7 在Use run-time library列表中选择Multithreaded DLL

Step 8 Category中选择Preprocessor

Step 9 在Additional include directories中加入下列值:

$(MPI_LOCATE_VEGA_PRIME)\include\vsg\stlport,

$(MPI_LOCATE_VEGA_PRIME)\include\vegaprime,

$(MPI_LOCATE_VEGA_PRIME)\include\vsg

Step 10 选择Link标签

Step 11 在Category列表中选择Input

Step 12 在Additional library path中输入$(MPI_LOCATE_VEGA_PRIME_LIB)

Step 13 点击OK

添加files

Step 1 选择Project-》Add To Project-》Files

Step 2 找到tornado.cpp所在目录,例如C:\Program Files\Multigen-Paradigm\resources\tutorials\vegaprime\desktop_tutor\tornado\application

Step 3 选择tornado.cpp文件

Step 4 选择Build-》Build tornado.exe来编译程序

Step 5 选择Build-》Execute tornado.exe来运行程序

Step 6 使用以下字母键来控制运动

⏹G - Starts the tornado on its path

⏹R - Resets the tornado, cow, and farmhouse

⏹L - Toggles the headlights of the car on and off

⏹O - Toggles the action observer from looking at the farmhouse, the grain storage unit, and the tornado

小结

通过前面的练习,主要是学会了如何配置一个简单的应用程序。通过LP的配置,你可以发现它替你节省了大量的时间,只需要将自己的程序同LP的类关联起来即可。

附录是关于VP的API的信息以及一些CPP例子。

附录一 Vega Prime API介绍

附录包含了配置VP的API的一些基本指导,包括你用来初始化、定义、配置和退出仿真循环的API命令和类。

设置API

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

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

初始化

vp::initialize执行如下任务:

⏹检查license是否正确

⏹初始化静态变量(static variables)和单例类(singleton classes)

⏹初始化内存分配(memory allocator)

⏹初始化渲染库(rendering library)

⏹初始化场景(scene graph)

⏹初始化ACF剥析程序(ACF parser)

⏹初始化模块界面(module interface)

⏹初始化内核(kernel classes)

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

初始化实例:

//vpModule::initializeModule(modulename);

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

//

//初始化所有模块

//

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、配置仿真类、仿真循环、更新和退出)。

例子:

// create a vpApp instance

vpApp *app = new vpApp;

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

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

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

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

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

//通过公用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执行功能。参数就是用字符串来替代ACF。与以往的Vega不同的是,在VP中,你可以多次定制并且实时调用多个ACF。这个功能顶替了Vega的vgScan函数。

例子

//调入ACF文件

//假定argv[1]就是当前的ACF文件

if (argv[1])

app->define(argv[1]);

define(const char*)

virtual int vpApp::define(const char *filename);

描述-装载和解析ACF文件

自变量-filename是所需ACF文件的名称。这个值可以用一行语句来表示,也可以通过复杂的语句来表示。

配置

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

Config()例子

//configure my app

app->configure();

仿真循环

仿真循环包括一个功能呼叫:

void vpApp::run()

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

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

仿真更新

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

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)的位置查询是保持不变的,它们并不修改或更新场景。因此,通常来说位置查询可能产生不同的结果,这要看位置查询是在场景更新前还是更新后。如果在更新前执行,结果就会和预期的不同;
如果在更新后执行,结果就会和预期的一致。因此,建议所有的位置查询都在仿真更新后执行。

关闭

//退出VP

vp::shutdown();

vp::shutdown执行如下任务:

⏹释放被kernel classes分配的内存

⏹结束各模块以释放它们在应用中所占用的内存

⏹终止多线程

⏹将licenses返回给license server

VP最小的应用

//这个例子是VP的最基本应用程序配置

#include

int main(int argc,char *argv[1])

{

//初始化VP

vp::initialize(argc,argv);

//创建一个vpApp类

vpApp *app=new vpApp;

//装载ACF文件

app->define(argv[1]);

//配置应用

app->configure();

//仿真循环

app->run();

//取消引用

app->unref();

//退出VP

vp::shutdown();

return 0;

}

附录二 tornado应用程序介绍

附录二列举了程序tornado.cpp的详细代码,同时包含有详细的注释。

程序剥析

#include "vsgu.h"

#include "vsSwitch.h"

#include "vrString.h"

#include "vp.h"

#include "vpLight.h"

#include "vpApp.h"

#include "vpIsector.h"

#include

#include

#include

#include

#include

vuAllocTracer tracer;

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

//your user defined Subscriber class derived from vpIsector::Subscriber

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~**/

class myAppSubscribers:public vpIsector::Subscriber{

public:

//variable declaration

//variables for the farmhouse and switch node

//public methods for this class

int initializeSubscriberInstances();

void initializeSubscriberFlags();

//methods for retrieving pointers

vpObject * getFarmhouse(){ return m_farmhouse;};

vpObject * getCow() { return m_cow;};

vpObject * getGrainStorage() {return m_grainStorage;};

//processing methods

void processFarmhouseSwitch();

void processGrainStorageHit();

void processRoadKill();

void rotateDebris();

//method to reset everything

void resetSubscriberInstances();

//Vega Prime requires the user to implement ALL subscriber signitures for

//typedef safety.

//By forcing the user to implement the subscriber functions Vega Prime

//will be able to catch major errors at compile time.

//first signiture which we don"t really care about at this time

virtual void notify(vpIsector::Event event, const vpIsector *)

{

switch(event)

{

case vpIsector::EVENT_PRE_TRAVERSE:

case vpIsector::EVENT_CLEAR_HIT:

case vpIsector::EVENT_POST_TRAVERSE:

break;

}//end of switch

}

//2nd signiture which contains all of the hit information; This is the one we will use

virtual uint notify(vpIsector::Event event, const vpIsector *isector, vsIsector::Hit *hitInstance )

{

switch (event)

{

case vsIsector::EVENT_HIT:

{

//retrieve a pointer to the object the isector has hit

//the object will be one of the targets assigned to the

//isector

vpObject *hitObj = isector->getHitOb-ject();

//validate the pointer

if (hitObj != NULL)

{

//check to see which object was hit and then act accordingly

if ( hitObj->com-pare(m_farmhouse))

//if this is the farmhouse

{

//this message will appear with the error notification set to DEBUG.

vuNotify::print(vuNo-tify::LEVEL_DEBUG, NULL, "You are hitting the farm-house\n");

//this method activate the switch node rendering the farm house as a pile of rubble

processFarmhouseSwitch();

}

else if (hitObj->com-pare(m_grainStorage)) //if this is the grain storage unit

{

//this message will appear with the error notification set to DEBUG.

vuNotify::print(vuNo-tify::LEVEL_DEBUG, NULL, "You are hitting the grain storage unit\n");

//this method will turn on the explosion,fire and debris special effects

processGrainStorageHit();

}

else if (hitObj->com-pare(m_cow)) //if this is the cow

{

//this message will appear with the error notification set to DEBUG.

vuNotify::print(vuNo-tify::LEVEL_DEBUG, NULL, "You are hitting the cow\n");

// this method will sweep the cow into the debris cloud

processRoadKill();

}

}//end if hitObj ! = NULL

}//end of EVENT_HIT

break;

}//end of switch

return vsTraversal::RESULT_CONTINUE;

}// end of notify

private:

vpObject *m_hitObj;

vpObject *m_farmhouse;

vsSwitch *m_farmhouseSwitch;

vpObject *m_grainStorage;

vpFx *m_grainStorageFire, *m_grainStorageExplosion, *m_grainStorageDebris;

bool m_farmhouseDestroyed, m_grainStorageDestroyed, m_roadKillDestroyed;

vpObject *m_cow;

vpFx *m_tornadoDebrisCloud;

};//end of myAppSubscribers

//other methods for the subscribers class

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- initializeSubscriberInstances find the pointers for the instances the farm house, grainStorage, the switch in the farm house etc.

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

int myAppSubscribers::initializeSubscriberInstances()

{

m_farmhouse = vpObject::find("farmhouse");

if (m_farmhouse == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "farmhouse not found");

return vsgu::FAILURE;

}

//find and validate a pointer to the farmhouse switch node

// this node was defined and named when the farmhouse was created.

m_farmhouseSwitch = (vsSwitch *) m_farmhouse->find-Named("damage");

if (m_farmhouseSwitch == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "damage switch not found");

return vsgu::FAILURE;

}

// find and validate a pointer to the grainstorage unit

m_grainStorage = vpObject::find("grainStorage");

if (m_grainStorage == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "grainStorage not found");

return vsgu::FAILURE;

}

//find and validate the pointer to the grainStorage-Fire

m_grainStorageFire = vpFx::find("grainStorageFire");

if (m_grainStorageFire == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "grainStorageFire not found");

return vsgu::FAILURE;

}

//find and validate the pointer to the grainStorageDebris

m_grainStorageDebris = vpFx::find("grainStorageDe-bris");

if (m_grainStorageDebris == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "grainStorageDebris not found");

return vsgu::FAILURE;

}

//find and validate the pointer to the grainStorage-Explosion

m_grainStorageExplosion = vpFx::find("grainStorageEx-plosion");

if (m_grainStorageExplosion == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "grainStorageExplosion not found");

return vsgu::FAILURE;

}

// find and validate the pointer to the cow "road kill"

m_cow = vpObject::find("cow");

if (m_cow == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "cow not found");

return vsgu::FAILURE;

}

// find and validate the pointer to the cow "road kill"

m_tornadoDebrisCloud = vpFx::find("tornadoDebris");

if (m_tornadoDebrisCloud == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "tornadoDebris

not found");

return vsgu::FAILURE;

}

return vsgu::SUCCESS;

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- resetSubscriberInstances

put everything back where it was

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/
void myAppSubscribers::resetSubscriberInstances()

{

// put the farmhouse back together

m_farmhouseSwitch->setActiveMask(0);

// restore the grainStorage Unit special effects

// turn off all of the special effects

m_grainStorageFire->setEnable(false);

m_grainStorageExplosion->setEnable(false);

m_grainStorageDebris->setEnable(false);

// put the cow back in it"s grazing state

// take it out of the debris cloud

// restore the initial translation and orientation

m_tornadoDebrisCloud->removeChild(m_cow);

m_cow->setTranslate(2300, 1625, 0);

m_cow->setRotate(0, 0, 0);

m_roadKillDestroyed = false;

// turn off the farmhouse destroyed flag

// turn off the grainStorage destroyed flag

// turn off the roadKillDestroyed flag

initializeSubscriberFlags();

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- initializeSubscriberFlags turn off the flags

The flags are used later to determine if the tornado has already damaged the farmhouse, grainstorage or cow to avoid overkilling anything.

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myAppSubscribers::initializeSubscriberFlags()

{

m_farmhouseDestroyed = false;

m_grainStorageDestroyed = false;

m_roadKillDestroyed = false;

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- processFarmhouseSwitch() change the farmhouse from perfect farmhouse to tornado damaged farmhouse.

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myAppSubscribers::processFarmhouseSwitch()

{

int currentMask;

int mask;

if (m_farmhouseDestroyed == false)

{

// get the current mask

mask = m_farmhouseSwitch->getActiveMask();

if (mask == 0)

{

currentMask = 1;

m_farmhouseSwitch->setActiveMask(current-Mask);

m_farmhouseDestroyed = true;

}

}// farmhouse is not destroyed

}// end of farmhouse processing

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- processGrainStorageHit() trigger just the right special effects ~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myAppSubscribers::processGrainStorageHit()

{

if (m_grainStorageDestroyed == false)

{

// turn on the grainstorage special effects

m_grainStorageExplosion->setEnable( true );

m_grainStorageDebris->setEnable( true );

m_grainStorageFire->setEnable(true );

}

}// end of grainStorage hit

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- processRoadKill() pick up the cow and add it to the debris cloud

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myAppSubscribers::processRoadKill()

{

if (m_roadKillDestroyed == false)

{

// pick up the cow and add it to the debris cloud

m_tornadoDebrisCloud->addChild(m_cow);

// tilt the cow

m_cow->setTranslate(10, 0, 39);

m_cow->setRotate (22, 11, -26);

m_roadKillDestroyed = true;

}

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- rotateDebris() rotate the debris by 30 degrees

This method is called from th update which means the debris cloud will rotate 30 degrees per frame

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myAppSubscribers::rotateDebris()

{

//rotate the debris cloud in 30 degree increments

m_tornadoDebrisCloud->setRotateH(30, true);

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

// your user defined myApp class derived from vpApp

This master class will take care of basic application and rendering needs. ~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

class myApp : public vpApp {

public:

// Constructor do all of the little initializations here

myApp()

{

// create a file pointer instance

m_file = new vuFile();

}; // end of constructor

// do all of your cleanup here

~myApp()

{

// just in case the tornado.path file was acciden tally

// left open somewhere

m_file->close();

delete m_file;

}; // destructor

// other methods for this class

int initializeInstances();

void processHeadlights();

void processObserverLookAt();

void processTornado();

void moveTornado();

void resetEverything();

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*

Method-- onKeyInput

This method is defined in the vpApp class

Users can overload this method to redirect keystrokes.

The "default" keys are in tact until you override the commands with your own.

Supported/ defined KEYS are:

KEY_ESCAPE: // quit the application

KEY_TILDE: // toggle the frame rate display

KEY_BACKSPACE: // reset observer state vector

KEY_ENTER: // recapture observer state vector

KEY_c: // put observer at the center of the scene

KEY_f: // enable / disable fog

KEY_l: // enable / disable lighting

KEY_p: // print observer absolute position

KEY_t: // enable / disable texture

KEY_T: // enable / disable transparency

KEY_w: // enable / disable wireframe

KEY_x: // enable / disable the motion model

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

virtual void onKeyInput(vrWindow::Key key, int mod)

{

switch (key)

{

case vrWindow::KEY_L: // toggle the head light on and off

{

processHeadlights();

}

break;

case vrWindow::KEY_G: // start the tornado motion

{

processTornado();

}

break;

case vrWindow::KEY_O:

// toggle the lookAt target for the observer

processObserverLookAt();

break;

case vrWindow::KEY_R:

// start it all over

resetEverything();

break;

default:

// do what vpApp has defined

vpApp::onKeyInput(key, mod);

break;

}// end of switch(key)

} // end of overloaded onKeyInput method

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

Method-- configure()

This method is defined in the vpApp class Handles the configuration process, reading ACF, initializing the kernel, pipeline, window managing the relationships between the classes

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

int configure()

{

// configure vega prime system first

vpApp::configure();

// find pointers to the necessary instances we need during

// the application.

// it is always a good idea to validate the pointers to avoid

// null pointer processing/errors/problems

// initialize instances

// if things go wrong.. get out!!!

if (initializeInstances() == vsgu::FAILURE)

return vsgu::FAILURE;

// Subscribe to the tornadoBumpIsector"s hit event so we can figure

// out what was hit and react appropriately.

m_tornadoBumpIsector->addSubscriber(vpIsec-tor::EVENT_HIT, &m_myAppSub);

// initialize the Subscriber class instances

// if things go wrong ... get out!!!

if (m_myAppSub.initializeSubscriberInstances() == vsgu::FAILURE)

return vsgu::FAILURE;

// set the flags

m_myAppSub.initializeSubscriberFlags();

// post-configuration

return vsgu::SUCCESS;

}// end of overloaded configuration method

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

Method-- run ()

This method is defined in the vpApp class Handles the frame rendering process

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void run()

{

while (beginFrame() != 0)

{

endFrame();

update ();

}

// to put everything back the way it was unconfigure();

}// end of overloaded run method

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

Method-- update ()

This method is defined in the vpApp class Handles the updates

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void update()

{

// update vega prime system first

vpApp::update();

// check to see if the tornado is supposed to be in motion

if(m_tornadoFlag == true)

{

// check to see if we have reached the end of the

// tornado path file.

// if not, move the tornado

if (m_file->eof() == false)

moveTornado();

else

{

// if we have reached the end of the file turn off the

// move flag

// close the tornado.path file

m_tornadoFlag = FALSE;

m_file->close();

}

}// end of tornado processing

}// end of overloaded update method

private:

// private variables and members go here!

// variables for the left and right headlights

vpLight *m_leftHeadlight, *m_rightHeadlight;

// variables for the tornado pieces and parts

vpFxParticleSystem *m_tornadoTop;

vpFxParticleSystem *m_tornadoDebris;

vpTransform *m_tornadoTransform;

// variables to hold the tornado path values

double m_X,m_Y,m_Z;

// pointer for the cow tornado will "pick up" during its

// cycle of destruction

vpObject *m_myCow;

// pointer for the tornadoBumpIsector

vpIsector *m_tornadoBumpIsector;

// pointer for the file containing the tornado path

vuFile *m_file;

// boolean flag verify if the tornado is in motion or not.

bool m_tornadoFlag;

//pointer to the actionObserver, you know the observer who

// goes where the action is.

vpObserver *m_actionObserver;

int m_currentTarget;

protected:

// pointer to the subscribers class

myAppSubscribers m_myAppSub;

};// end of myApp class definition

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- main() enuff said

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

int main(int argc, char *argv[])

{

// initialize vega prime

vp::initialize(argc, argv);

// initialize addition modules here

//vpModule::initializeModule(modulename);

// create a vpApp instance but use the class

// you just created

myApp *app = new myApp;

// load acf

// use the hardcoded default ACF value or

// use the 2nd argument from the command line

if (argc define("tornado.acf");

else

app->define(argv[1]);

// configure my app

// if the application configuration fails for some reason

// shut down the application.

// The penalty for a failed configuration is user defined

if (app->configure() == vsgu::FAILURE)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "configuration failed! Exiting NOW!");

app->unref();

vp::shutdown();

}

// runtime loop

app->run();

// unref my app instance

app->unref();

// shutdown vega prime

vp::shutdown();

return 0;

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

Method-- update ()

This method is defined in the vpApp class Handles the updates

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

int myApp::initializeInstances()

{

// find and validate a pointer to the left headlight instance

m_leftHeadlight = vpLight::find("leftHeadlight");

if (m_leftHeadlight == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "leftHeadlight not found"); return vsgu::FAILURE;}

// find and validate a pointer to the right headlight instance

m_rightHeadlight = vpLight::find("rightHead-light");

if (m_rightHeadlight == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "rightHeadlight not found");

return vsgu::FAILURE;

}

// find and validate a pointer to the actionObserver instance

m_actionObserver = vpObserver::find("houseOb-server");

if (m_actionObserver == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "actionObserver not found");

return vsgu::FAILURE;

}

// find and validate a pointer to the tornadoDebris instance

m_tornadoDebris = vpFxParticleSystem::find ("tornadoDebris");

if (m_tornadoDebris == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "tornadoDebris not found");

return vsgu::FAILURE;

}

// find and validate a pointer to the tornadoTransform instance

m_tornadoTransform = vpTransform::find("tornadoT-ransform");

if (m_tornadoTransform == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "tornadoTransform not found");

return vsgu::FAILURE;

}

// find and validate a pointer to the tornadoBump-Isector instance

m_tornadoBumpIsector = vpIsector::find("torna-doBumpIsector");

if (m_tornadoBumpIsector == NULL)

{

vuNotify::print(vuNotify::LEVEL_WARN, NULL, "tornadoBumpIsector not found");

return vsgu::FAILURE;

}

return vsgu::SUCCESS;

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- processHeadlights turn the headlights on and off with a keystroke.

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myApp::processHeadlights()

{

bool lightSetting;

if (m_leftHeadlight->getEnable() == true)

lightSetting = false;

else

lightSetting = true;

m_leftHeadlight->setRenderEnable(lightSetting);

m_leftHeadlight->setEnable(lightSetting);

m_rightHeadlight->setRenderEnable(lightSetting);

m_rightHeadlight->setEnable(lightSetting);

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- processTornado() open up the tornado

path file turn on the tornadoFlag

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myApp::processTornado()

{

// open the binary tornado.path file stored on the disk for reading only.

m_file->open("C:\\TUTORIAL\\DATA\\tornadoPath\\tor-nado.path", "rb");

// turn on the tornadoFlag so we can start moving the tornado

// on a per-frame basis in the update method.

m_tornadoFlag = true; }

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- moveTornado() read the XYZ from the binary file

move the tornado

rotate the debris cloud

This call is made during the update

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myApp::moveTornado()

{

// read the XYZ coordinates from the tornado.path file

m_file->read(&m_X, sizeof(m_X));

m_file->read(&m_Y, sizeof(m_Y));

m_file->read(&m_Z, sizeof(m_Z));

// move the tornado transform; parent of the tornado top, funnel and debris

m_tornadoTransform->setTranslate(m_X,m_Y,m_Z);

// update the heading of the tornado debris so it appears to

// turn on it"s own axis faster than the funnel

m_myAppSub.rotateDebris();

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- processObserverLookAt set the lookAt target for the observer to switch between looking at :

the house

the grainstorage

the tornado

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myApp::processObserverLookAt()

{

// declare a few local variables

double X,Y,Z;

vpPositionable *newTarget;

vpPositionable *currentTarget;

vpPositionable * localFarmhouse, *localGrainStorage;

// retrieve a pointer to the current look at Target from the observer

currentTarget = (vpPositionable *)m_actionObserver->getLookAt();

localFarmhouse = (vpPositionable *) m_myAppSub.get-Farmhouse();

localGrainStorage = (vpPositionable *) m_myAppSub.getGrainStorage();

// if the current target is the tornado transform

// set the new look at target to be the farmhouse

// modify the XYZ coordinates so it is somewhere near

// the farmhouse

if (currentTarget == m_tornadoTransform)

{

// action observer should now look at the farmhouse

X = 1950.00;

Y = 1200.00;

Z = 130.00;

newTarget = m_myAppSub.getFarmhouse();

}

// if the current target is the farmhouse

// set the new look at target to be the grainStorage Unit

// modify the XYZ coordinates so it is somewhere near

// the grainStorage unit

else if (currentTarget == localFarmhouse)

{

// action observer should look at the grain Storage

X = 2500.00;

Y = 2200.00;

Z = 120.00;

newTarget = m_myAppSub.getGrainStorage();

}

// if the current target is the grainStorage Unit

// set the new look at target to be the tornado Trans-form

// modify the XYZ coordinates so it is somewhere near

// the tornado Transform

else if (currentTarget == localGrainStorage)

{

// action observer should look at the tornado transform

X = 1000.00;

Y = 3000.00;

Z = 140.00;

newTarget = m_tornadoTransform;

}

// update the observer with the new lookat target and new position

m_actionObserver->setLookAt(newTarget);

m_actionObserver->setTranslate(X, Y, Z, false);

}

/*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~

method -- resetEverything()

restore the inital states

~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*~~*/

void myApp::resetEverything()

{

// tornado goes back to its initial position

// turn off the tornado flag

m_tornadoTransform->setTranslate(1460, 300, 12);

m_tornadoFlag = false;

m_myAppSub.resetSubscriberInstances();

}

推荐访问:专业版 中文 教程