#VRML V2.0 utf8
DEF cube Transform {
rotation 1 1 1 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0 1 0
}
}
geometry Box {}
}
DEF TouchS TouchSensor {}
]
}
DEF revolver OrientationInterpolator {
key [0,1]
keyValue [ 0.5 0.5 0.5 0,0.5 0.5 0.5 3.14159]
}
DEF ticker TimeSensor {
cycleInterval 2
loop TRUE
enabled FALSE
}
ROUTE TouchS.isOver TO ticker.set_enabled
ROUTE ticker.fraction_changed TO revolver.set_fraction
ROUTE revolver.value_changed TO cube.set_rotation
3。 朝向插补器
插补器节点可认为是VRML内置的脚本节点,它们执行简单的动态计算,通常和时间检测器或者能够使对象产生动作的节点结合在一起使用,生成线性关键帧动画。插补器节点实际上是一个由关键点和对应关键值定义的分段线形函数。根据插值类型的不同,VRML共定义六个插补器节点:
ColorInterpolator(颜色插补器)、
CoordinateInterpolator(坐标插补器)、
NormalInterpolator(法线插补器)、
OrientationInterpolator(朝向插补器)、
positionInterpolator(位置插补器)、
ScalarInterpolator(标量插补器)。
所有插补器的域和事件都是类似的:
eventIn SFFloat set_fruction
exposedField MFFloat key [...]
exposedField MF[type] keyValue [.....]
eventOut [S|M]F[type] keyValue_changed
关键值域keyValue的类型决定了插补器的类型(例如,OrientationInterpolator的keyValue域的类型是MFFloat).入事件set_fraction接收SFFloat型的事件,插补器随即根据它进行插值,并通过出事件value_changed送出插值结果。
这里我们把时间检测器的fraction_changed事件作为插补器的输入,这个事件是一个[0,1]区间的值,每个时间步都送出一次,表示当前周期内已过去的时间相对于整个周期的比例,是插补器常用的输入源之一。与此对应,我们把插补器关键帧的取值也定义在[0,1]范围内。与0和1这两个关键帧对应的关键值的旋转轴是相同的,只是旋转角度不同(0,3.14159),这样方位插补器输出的旋转值的旋转轴固定不变,旋转角从0递增到3.14159,然后不断重复。
#VRML V2.0 utf8
DEF cube Transform {
rotation 1 1 1 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1 0 0
}
}
geoemtry Box {}
}
DEF TouchS TouchSensor {}
]
}
DEF revolver Script {
eventIn SFTime startRevolving
eventOut SFRotation revolve
field SFFloat angle 0
url "vrmlscript :
function startRevolving () {
revolve[0]=1;
revolve[1]=1;
revolve[2]=1;
revolve[3]=angle;
angle+=0.1;
}"
}
DEF ticker TimeSensor {
cycleInterval 0.1
loop TRUE
enabled FALSE
}
ROUTE TouchS.isOver TO ticker.set_enabled
ROUTE ticker.cycleTime TO revolver.startRevolving
ROUTE revolver.revolve TO cube.set_rotation
DEF ticker TimeSensor {
cleInterval 0.1
loop TRUE
enabled FALSE
}
ROUTE TouchS.isOver TO ticker.set_enabled
ROUTE ticker.cycleTime TO revolver.startRevolving
ROUTE revolver.revolve TO cube.set_rotation
2。时间检测器
为了使方块能够连续旋转,需要引进等间隔连续发送的时间序列,这正是时间检测器的用武之地。时间检测器随着时间推移不断产生事件,可用于多种目的,包括:
a. 驱动连续性的仿真和动画
b. 控制周期性的活动(如每分钟一次)
c. 初始化单独事件,如报警钟
下面是我们要用的时间检测器和修改后的路由关系:
1。接触检测器
作为开始的基本代码是:
#VRML V2.0 utf8
DEF cube Transform {
rotation 1 1 1 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1 0 0
}
}
geometry Box {}
}
DEF TouchS TouchSensor {}
]
}
DEF revolver Script {
eventIn SFBool startRevolving
eventOut SFRotation revolve
field SFFloat angle 0
url "javascript :
function startRevolving () {
revolve[0]=1;
revolve[1]=1;
revolve[2]=1;
revolve[3]=angle;
angle+=0.1;
}"
}
ROUTE TouchS.isOver TO revolver.startRevolving
ROUTE revolver.revolve TO cube.set_rotation
在第二节中我们已经使用过接触检测器,当我们把鼠标指针放到方块(这个几何节点包含接触检测器)上面时,指针形状发生变化,这意味着我们已经进入检测区,如果按下鼠标左钮,则按照我们的定义,当前视点会发生变化。
这一节仍然制作这样一个对接触有反应的方块,只是接触后它会连续不断地转动,动画行为可以用时间检测器(TimeSensor)驱动,而不断变化的旋转值可用脚本节点或朝向插补器(orientationInterpolator)给出。