1.6.4 VRML的节点和域

节点是VRML文件中最基本的单位,节点是VRML的精髓与核心。每个节点还包含子节点和描述节点属性的“域名”或“域值”,在高级语言中称为变量、数组等,在数据库中常称为字段。

单一节点的语法定义如下:

            节点名{
                  域名   域值   #域值类型说明
                  ...      ....
                  }

节点由节点名、一对花括号组成,花括号内又包括节点的域名、域值及域值类型说明等。

下面以锥体节点Cone为例来加以说明。

            Cone{
                        外                      #Cone节点(注释)
                        bottomRadius  1.0          #field SFFloat单值浮点域
                        height        2.0          #field SFFloat单值浮点域
                        side         TRUE       #field SFFloat单值浮点域
                        bottom       TRUE       #field SFBool单值布尔域
            }

其中,“#”为注释语句。

节点的作用是描述空间造型(对象)及其属性。“节点”可以理解为高级语言中的函数、子程序、结构体及可视化编程语言中的类和对象等。

VRML节点的层次关系分为父节点和子节点。父节点即根节点。在一个嵌套节点中,最顶层的节点就是父节点,由它派生的节点称为子节点。例如,Group编组节点中,有一个域children[],children就是子节点,而Group就是父节点,如图1-9所示。

图1-9 节点层次关系图

1.节点的域名和域值

节点中包括“域”、“域值”或子节点。根据语法结构的要求,节点之间可以并列或层层嵌套使用。不同作用的节点有着不同的语法结构,父节点包括“域”、“域值”或子节点,子节点中也包含“域”、“域值”等。

域分为两种:一种称为“域”;另一种称为“暴露域”。“域”相当于高级语言中的普通变量,而“暴露域”相当于C语言中的外部变量,相当于可视编程语言VC++中的公共变量或公共函数。

域包含有各种类型的数据,可以是单值的或多值的。“域”可理解为高级语言中的“变量”、“数组”及C语言中的“结构体变量”或数据库中的“字段”等。

每一个节点都是由一个域多个域组成的,域即“属性”,描述空间造型尺寸。每个域有相应的“域值”,这些域值指定了一个场景的尺寸、大小和颜色等特征。“域值”相当于高级语言中的变量取值或取值范围,也相当于数据库中的字段取值。

同一节点中的域遵循如下规则。

● 同一节点中的各个域之间无先后次序之分。

● 同一节点中的各个域均有自己相应的默认值。

● 不同的域对应不同的域值类型。

域名:域的标识符叫域名。在节点作用域的范围内,域名是唯一的,也是VRML的保留字或关键字。

常见的两类域名的域值类型前缀如下。

● 单值类型的域名,以“SF”开始,只包含单值。单值可以是一个独立的数,也可以是一个向量、颜色的几个数等,甚至可以是图像数据。

● 还有一种多值域名以“MF”开始,它包含多个值,所以称为多值域名。

在VRML文件中,表示多域值的方法是:整个用方括号括起来的一系列用逗号和空格间隔开的单值。如果一个多值域不包含任何值,则只标出方括号“[]”。如果一个多值域恰好只包含一个数,可以不写括号,直接写该值。

例如,以“MF”开始的多域值的表示如下:

            skyColor[
            0.2 1.0 1.0
            0.6 0.8 1.0
            1.0 0.2 0.5
            ]

在VRML文件中,各个节点语法的各种“域值类型”详细说明为:单值域类型名用“SF”表示,多值域名称用“MF”表示。

1)SFBool

SFBool域是一个单值布尔量,常用于开启或关闭一个节点的性质特征。SFBool域输出事件的默认值为TRUE(真),否则为FALSE(假)。

2)SFFlot和MFFlot

SFFlot域是单值单精度浮点数,含有一个ANSIC格式的单精度浮点数。SFFlot域输出事件的初始值是0.0。

MFFlot域是多值单精度浮点数,含有零个域多个ANSIC格式的单精度浮点数。MFFlot域输出事件的初始值是[]。

3)SFInt32和MFInt32

SFInt32域是一个单值含有32位的整数。一个SFInt32值由一个十进制或十六进制格式(以OX开头)的整数构成。SFInt32域输出事件的初始值为0。

MFInt32域是一个多值域,由任意数量的以逗号或空格分隔的整数组成。MFInt32域输出事件的初始值为[]。

4)SFString和MFString

SFString域包含一个字符串。SFString的域值含有双引号括起来的字符串。任何字符都可在引号中出现。为了在字符中使用双引号,在它之前加一个反斜杆“\”,为了在字符串中使用反斜杆,可连续使用两个反斜杆“\\”。SFString域输出事件的初始值为“”。

MFString域是一个含有零个或多个单值的多值域,每个单值都和SFString值的格式相同。MFString域输出事件的初始值为[]。

5)SFVect2f和MFVec2f

SFVect2f域定义了一个二维向量。SFVect2f的域值由两个分隔的浮点数组成。SFVect2f域输出事件的初始值为(0 0)。

MFVec2f域是一个包含任意数量的二维向量的多值域。MFVec2f域输出事件的初始值为[]。

6)SFVec3f和MFVec3f

SFVec3f域定义了一个三维向量空间。一个SFVec3f域值包含有3个浮点数,数与数之间用空格分隔。该值表示从原点到给定点的向量。SFVec3f域输出事件的初始值为(0 0 0)。

MFVec3f域是一个包含任意数量的三维向量的多值域。MFVec3f域输出事件的初始值为[]。

7)SFTime和MFTime

SFTime域含有一个单独的时间值。每个时间值是一个ANSIC格式的双精度浮点数,表示从1970年1月1日(GMT,格林尼治平均时)子夜开始计时,延续当前时间的秒数。SFTime域输出事件的初始值为-1。

MFTime域包含任意数量的时间值。

8)SFRotation和MFRotation

SFRotation域规定了一个绕任意轴的任意角度的旋转。SFRotation的域值含有4个浮点数,各数之间用空格分隔,前3个数表示旋转轴,第4个数表示围绕该轴旋转多少弧度。SFRotation域输出事件的初始值为(0 0 1 0)。

MFRotation域可包含任意数量的这类旋转值。MFRotation域输出事件的初始值为[]。

9)SFImage

SFImage域含有非压缩的二维彩色图像或灰度图像。SFImage域首先列出3个整数值,前两个整数表示图像的宽度和高度,第三个整数表示构成图像格式的元素个数,随后按“宽度×高度”的格式列出一组十六进制数,数与数之间用空格或逗号分隔,每一个十六进制数表示图像中一个单独的像素,像素的排列按从左到右、从下到上的顺序。第一个十六进制数描述一个图像左下角的像素,最后一个则描述右上角的像素。SFImage域输出事件的初始值为(0 0 0)。

10)SFColor和MFColor

SFColor域是只有一个颜色的单值域。SFColor的域值由一组3 个浮点数组成,每个数都在0.1~1.0范围内,分别表示构成颜色的红、绿、蓝3个分量。SFColor域输出事件的初始值是(0 0 0)。

MFColor域是一个多值域,包含任意数量的RGB颜色值。MFColor域输出事件的初始值是[]。

11)SFNode和MFNode

SFNode域含有一个单节点,必须按标准节点语法写成。一个SFNode域允许包含一个关键字,表示不包含任何节点。SFNode域输出事件的初始值为NULL。

MFNode域包含任意数量的节点。MFNode域输出事件的初始值为[]。在编写VRML文件、节点和域时,特别要注意大小写,因为VRML源文件对大小写很敏感,即VRML源文件要严格区分大小写。

2.节点名的重定义和重用

在VRML虚拟空间的场景中,为了减少VRML源代码的编写量,提高VRML编程效率,对重复的造型或多个同样的造型在场景中多次出现时,可通过定义这个造型节点,然后再重复调用该定义的节点。

1)重定义节点:DEF

在VRML中,使用DEF命令可为空间的造型重新定义节点,以便在以后的节点重用或调用时引用,从而使程序编写简练,减少程序代码的重复和冗余,而且具有层次清晰、结构合理的软件工程设计的风格。

重定义节点的语法定义如下:

            DEF  节点名   节点类型 {}

其中,DEF是重定义节点的VRML关键字,节点名可以由任何字母和数字及下划线组成,但不要使用与VRML保留字或关键字相重复的节点名。

在VRML中,对节点名的规定是:节点名区分大小写,命名不能以数字开头,不能带有非印刷的ASCII字符,不能包括单引号、双引号、数字运算或英镑符号等。

2)重用节点:USE

当重定义一个节点名之后,便可在VRML源程序中重复使用该节点名,即可以一次或多次调用该节点名。

重用节点的语法定义如下:

            USE   节点名

其中,USE是VRML的保留字,节点名就是前面用DEF重定义的节点名。

节点重新定义和重复引用的文件结构形式如下:

            VRML V2.0 utf8            #VRML文件在第一行必须有的头文件
            节点名{                  #VRML中各种类型的"节点"
                  域      域值
                  ...     ...
                }
            DEF  节点1  节点类型{     #定义节点
                域     域值         #相应"节点"的"域"和"域值"
                  ...     ...
                }
            USE  节点名1            #重用节点语法