虚拟现实VRML简明教程
第五节 动态修改场景图

  注意它的出事件child的类型是MFNode,也就是说通过这个事件送出的是节点。节点S的testNode域是对球体SphereChild引用(USE语句),引用不复制该节点,而是把同一节点再次插入场景图,从而导致SphereChild拥有多个父亲,所以场景图仅仅是层次结构,而不是树形结构。加上下面的路由语句,建立事件联系:

  ROUTE TS.isActive TO S.isActive
  ROUTE S.child TO leftBox.removeChildren
  ROUTE S.child TO rightBox.addChildren

  接触检测器TS的激活事件isActive连接到脚本节点S的isActive,这样用户一旦按动绿方块,就会启动脚本节点的事件处理函数isActive(),此函数把testNode节点(即球体节点SphereChild )送至出事件S.child.根据路由,左边红方块的事件入口leftBox.removeChildren 收到此事件,按照removeChildren的语义,球体节点SphereChild从leftBox的子节点列表中删除。与此同时,右边蓝方块的事件入口rightBox.addChildren也收到S.child出事件,根据addChildren的语义,球体节点SphereChild加入 rightBox的子节点列表。通过这个过程,球体节点SphereChild的父节点从leftBox更换成rightBox.

子节点增删的具体任务由Script节点来完成:

DEF S Script {
  eventIn SFBool isActive
  eventOut MFNode child
  field MFNode testNode USE SphereChild  
  url"javascript :
   function isActive (value) {
    if (value)child = testNode;
    }"
   }

DEF onoff Transform {
  translation 0 -5 0
   children [
    Shape {
     appearance Appearance {
      material Material {
       diffuseColor 0 1 0
       }
      }
     geometry Box {}
     }
    DEF TS TouchSensor {} #接触检测器
    ]
   }

  为了以后引用方便,这里还为球体子节点起了名字:SphereChild .为了让用户能够增删这个儿子,把绿方块定义成接触检测器:

 

DEF leftBox Transform {
  translation -5 0 0
  children [
   Shape {
    appearance Appearance {
     material Material {
      diffuseColor 1 0 0
      }
     }
    geometry Box {}
    }
  DEF SphereChild Shape { #球体子节点
   appearance Appearance {
    material Material {
     diffuseColor 1 0 1
     }
    }
   geometry Sphere {
     radius 1.2
     }
    }

   ]
  }
其中左边的方块为红色,右边的方块为蓝色,下边的方块为绿色,都是Transform类型,三者都位于场景图的最高层,都是场景图的根节点,都包含一个Box几何体作为子节点。下面为红方块增加一个球体子节点:
#VRML V2.0 utf8
Viewpoint { #视点
  position 0 0 15
  }
DEF leftBox Transform {
  translation -5 0 0
  children [
   Shape {
    appearance Appearance {
     material Material {
      diffuseColor 1 0 0
      }
     }
    geometry Box {} #红色方块
    }
   ]
  }

DEF rightBox Transform {
  translation 5 0 0
  children [
   Shape {
    appearance Appearance {
     material Material {
      diffuseColor 0 0 1
      }
     }
    geometry Box {} #蓝色方块
    }
   ]
  }

DEF onoff Transform {
  translation 0 -3 0
   children [
    Shape {
     appearance Appearance {
      material Material {
       diffuseColor 0 1 0
       }
      }
     geometry Box {} #绿色方块
     }
    ]
   }
  下面是我们这一节要建立的境界,开始的时候球体位于左边红色方块的内部,在按动底部的绿色方块后,球体进入右边蓝色方块之内。 首先定义三个方块:

  场景图是描述境界结构的基本概念,节点是构成场景图的基本单元。

  组节点是能够包含字节点的节点,组节点本身还可作为其它组节点的子节点,从而形成层次性体系结构。VRML中的组节点包含Anchor(锚)、 Billboard(布告牌)、 Collision(碰撞)、Group (组)、Inline (内联)、LOD(细节层次)、 Switch(开关)、Transform(变换)共八种,除Inline、LOD、Switch这几个具有特殊功能外,它们都定义了入事件addChildren 和removeChildren ,前者用于向组节点的子节点域children 中增加新的子节点,后者用于从中删除子节点,这样就可以动态修改场景图的结构。