在VRML中,将不同物体放置在不同的wrl文件中的最大好处是,使VRML场景的层次结构更加清晰,代码可读性强,维护修改容易。
通常,我们可以将一个场景里的不同物体写在不同的wrl文件中,最后在主场景wrl文件里将各个物体通过“Inline”节点导入,形成一个完整场景。
这种方式对于用户交互和动画比较少并且形式单纯的方式比较合适,但是在一些复杂情况下,用“Inline”节点是无法实现的。其原因在于“Inline”节点没有用于交互的输入输出事件。
举一个最简单的例子。场景中有两个物体A和B,A具有插值动画,可以旋转,B具有一个touchSensor(触摸感应器)。
现在要求实现:
1.A物体的绘制和动画代码写在a.wrl文件中,B物体的绘制和触发器代码写在b.wrl文件中(这样做的目的是为了实现前面描述的好处。)
2.鼠标点击物体B后,触发A物体的动画。
显然,使用“Inline”节点是无法同时满足上面两个条件的。
但是两个条件在VRML中并非无法满足。
这个时候,我们需要使用PROTO节点和EXTERNPROTO进行原型声明和外部引用。下面对代码编写进行详细说明。
首先,将a.wrl和b.wrl的完整代码贴上来:
a.wrl:
通常,我们可以将一个场景里的不同物体写在不同的wrl文件中,最后在主场景wrl文件里将各个物体通过“Inline”节点导入,形成一个完整场景。
这种方式对于用户交互和动画比较少并且形式单纯的方式比较合适,但是在一些复杂情况下,用“Inline”节点是无法实现的。其原因在于“Inline”节点没有用于交互的输入输出事件。
举一个最简单的例子。场景中有两个物体A和B,A具有插值动画,可以旋转,B具有一个touchSensor(触摸感应器)。
现在要求实现:
1.A物体的绘制和动画代码写在a.wrl文件中,B物体的绘制和触发器代码写在b.wrl文件中(这样做的目的是为了实现前面描述的好处。)
2.鼠标点击物体B后,触发A物体的动画。
显然,使用“Inline”节点是无法同时满足上面两个条件的。
但是两个条件在VRML中并非无法满足。
这个时候,我们需要使用PROTO节点和EXTERNPROTO进行原型声明和外部引用。下面对代码编写进行详细说明。
首先,将a.wrl和b.wrl的完整代码贴上来:
a.wrl:
- #VRML V2.0 utf8
- #Cosmo Worlds V2.0
- PROTO KfaPositionInterpolator [
- eventIn SFFloat set_fraction
- eventOut SFVec3f value_changed
- exposedField MFFloat key 0
- exposedField MFInt32 keyTypes 2
- exposedField MFVec3f keyValue 0 0 0
- field MFFloat authorKey 0
- field MFVec3f authorKeyValue 0 0 0
- ]
- {
- PositionInterpolator {
- key IS key
- set_fraction IS set_fraction
- keyValue IS keyValue
- value_changed IS value_changed
- }
- }
- PROTO KfaAnimation [
- field SFFloat framesPerSecond 10
- field SFFloat zoom 1
- field SFBool snap TRUE
- field SFBool viewInFrames TRUE
- field SFBool showEmptyFieldLines FALSE
- field SFFloat playRangeStart 0
- field SFFloat playRangeEnd 1
- field SFBool usePlayRange TRUE
- field SFNode timeSensor NULL
- field MFNode fieldInterps []
- field MFNode actors []
- ]
- {
- Group {
- }
- }
- PROTO AnimationInA [
- eventIn SFTime TouchTime
- ]
- {
- DEF _0 Transform {
- children [
- Shape {
- appearance Appearance {
- material Material {