1.6.3 VRML语法
VRML文件的语法主要包括VRML文件头、节点、原型、造型、脚本和路由等。不是每一个VRML文件都必须包括这几个部分,只有VRML文件头是必需的,而其他项不一定是必需的。VRML立体空间的场景和造型是由节点构成的,再通过路由实现动态交互和感知或者使用脚本文件与外部接口进行动态交互。在软件开发中,根据不同的实际情况编写不同VRML程序,它所包含的成分也可能不同。在VRML文件中,“节点”是核心、灵魂,如果没有节点,VRML也就不存在了。
1.VRML文件
VRML文件可由文本编辑器编写或由专用编辑器VrmlPad编写。VRML文件的扩展名为.wrl或.wrz,使用较多的是.wrl文件。任何扩展名为.wrl文件都是VRML文件。通过VRML浏览器可以直接运行VRML文件。
VRML文件名的全称为:*.wrl或*.wrz。
2.VRML文件的结构
VRML文件的语法结构由VRML文件头、节点、事件、脚本和路由等组成。“节点”可以由一个或多个组成,也可以创建新的节点,即原型节点。
VRML文件的语法结构如下:
#VRML V2.0 utf8 #VRML文件在第一行必须有头文件 节点名{ #VRML中各种类型的"节点" 域 域值 #相应"节点"的"域"和"域值" . } Script{ #脚本Script节点 } ROUTE #路由:把入事件与出事件联系起来
在VRML文件的结构中,要突出软件工程的设计思想,使VRML文件的结构设计层次清晰、结构严谨、条理清楚,使读者、用户易于理解和掌握。
3.VRML文件头
在每一个VRML文件中,文件头是必须,且位于VRML文件的第一行。
VRML文件头的语法结构是:#VRML V2.0 utf8。
VRML文件头的作用相当于高级C语言程序中的主函数的作用,每一个C语言程序必须从main()开始,否则编译程序时就会出错。
VRML文件头包含4个部分,每一个部分代表一定的含义。
(1)以#开头,这里的#不是注释含义,而是VRML文件头的一部分。
(2)“VRML”告诉浏览器该文件是一个VRML文件。
(3)“V2.0”告诉浏览器该VRML文件遵循VRML规范的2.0版本。
(4)“utf8”表示该VRML文件是一个使用国际UTF-8字符集的文件。UTF-8的英文全称是“UCS Transform Fromat”,而UCS是“Universal Character Set”的缩写。国际UTF-8字符集包含任何计算机键盘上能够找到的字符,而多数计算机使用的ASCII字符集则是UTF-8字符集的子集,因此,使用UTF-8书写和阅读VRML文件很方便。UTF-8支持多种语言字符集,由国际标准化组织的“ISO 10646-1:1993”标准定义。
VRML文件头必须按上述语法格式书写,必须位于VRML文件的第一行,不得随意更改。
4.VRML文件注释
在编写VRML源程序时,为了使源程序结构更合理、更清晰及层次更强,经常在源程序中添加注释信息。在VRML文件中允许编程人员在文件的任何地方进行注释说明,以进一步增加源程序的可读性,从而使层次清晰、结构合理,形成好的文档资料,并符合软件开发的要求。
VRML文件注释部分以一个符号“#”开头,结束于该行的末尾。当注释信息多于一行时,将产生语法错误,因此VRML不支持多行注释信息。浏览器在浏览VRML文件时将跳过“#”之后本行的所有内容。另外,浏览器在浏览VRML文件时将自动忽略VRML文件中的所有空格和空行。开发人员可根据软件开发的结构和思想编写VRML源程序。
5.事件、路由和脚本
1)事件
在VRML中,每一个节点一般都有两种事件:一个“入事件”和一个“出事件”,每一个节点通过这些“入事件”和“出事件”来改变节点自身的某个域的值。在多数情况下,每个节点事件只是一个要改变域值的请求:“入事件”请求节点改变自己某个域的值,而“出事件”则是请求别的节点改变它的某个赋值。
“事件”相当于高级程序语言中的函数调用:“入事件”相当于高级程序语言中函数调用时的入口参数,“出事件”相当于高级程序语言中函数调用返回时的参数。
在VRML中的每一个节点内部都有一些定义为“暴露域”(exposedField)的内容。一个“暴露域”能够接收“入事件”,也能产生“出事件”。事件的调用是短暂的,事件的值是不会被写入VRML文件中的。“暴露域”就像变量一样被放置在VRML文件中。例如,如果一个节点中的“暴露域”叫做translation,那么它的“入事件”为set_translation,而“出事件”则为translation_changed。
每一个节点的“入事件”和“出事件”的命名规则如下。
(1)大部分“入事件”都是以“set_”为开头的事件,除了addChildren和removeChildren这两个“入事件”。
(2)大部分“出事件”都以“_changed”为结尾的事件,除了形式为SFBool的“出事件”,但布尔值的“出事件”是以is作为开头的,如isBound、isActive等。
(3)“入事件”和“出事件”的形式为SFTime时,就不再使用“set_”和“_changed”作为连接,如bindTime和touchTime等。
2)路由
路由是连接一个节点的“入事件”和“出事件”的节点之间的通道。路由不是节点,它只是简单的语法结构,只说明为了确立被指定的域的一个事件如何从某个节点到达另一个节点。路由说明可以在VRML文件的顶部,也可以在VRML文件节点的某一个域中。
路由的作用是将各个不同的节点联系在一起,使虚拟空间具有更好的交互性、立体感、动感性和灵活性。在VRML中,每一个节点都有输入和输出接口,它们分别是“入事件”和“出事件”,但有一些节点不同时具有这两种事件。一个节点一般具有多个不同的“入事件”和“出事件”。
路由绑定不同节点时应注意以下3点。
(1)两个节点的路由在没有被触发之前一直都处于休眠的状态,只有在被触发时,才有事件从输出接口的节点输出,通过路由传送到输入接口的节点,从而引起相应虚拟现实世界中的某种变化。
(2)在VRML中,节点的“入事件”和“出事件”同样具有一定的数值类型。
(3)在VRML中,可以将多个节点绑定在一起,从而创建复杂的路线(联系),以便在虚拟现实世界中实现更真实的交互。
3)脚本
脚本是一套程序,是与各种高级语言或数据库的接口。在VRML文件的两个节点之间存在着路由,事件可以通过相应的路径从一个节点传送到另一个节点。此外,还可以通过添加脚本对这些事件与路由进行编程设计,这能产生更加鲜明的交互性和生动逼真的动画效果。
在VRML中可以用Script节点利用Java或JavaScript语言编写的程序脚本来扩充VRML的功能。脚本通常作为一个事件级联的一部分而执行,脚本可以接受事件,处理事件中的信息,还可以产生基于处理结果的输出事件。
例如,Transform空间变换节点的语法结构定义如下:
Transform { children[] #暴露域MF节点 translation 0.0 0.0 0.0 #暴露域SFVec3f rotation 0.0 0.0 1.0 0.0 #暴露域SFRotation ... }
VRML源文件如下:
#VRML V2.0 utf8 #VRML文件在第一行必须有的头文件 节点名{ #VRML中各种类型的"节点" 域 域值 #相应"节点"的"域"和"域值" ... ... } DEF zjz Transform{ #重新定义节点为zjz children [ ... DEF sensor PlaneSensor{} #PlaneSensor平面检测器节点 ] Script{ #脚本Script节点 } ROUTE sensor.translation_changed TO zjz.set_translation #ROUTE路由:把Transform节点的域translation的"入事件"与"出事件"联系起来 }
注意:上例只举出一种路由与事件之间关系的应用,在实际编程设计中要学会举一反三。