杨安祺, 乔海超, 张杜娟, 贾伟光, 唐 军
(1.陕西科技大学电气与信息工程学院, 陕西 西安 710021; 2.西安医学院公共课部, 陕西 西安 710021)
随着计算机技术的不断发展,网页上一些文本、图片等二维展示途径已经满足不了人们的需要,三维建模语言的出现则满足了人们的这一要求.目前,在房地产开发等诸多领域,国内外不少公司都已经开始了三维展示的应用,通过三维实体构建模型,将产品的特点生动直观地展现给用户,获得了巨大的成功.以三维建模技术构建的虚拟展厅、虚拟社区,不仅能给出模型的色彩、外观、结构、纹理等静态信息,还能给出模型在运动状态所拥有的一些特性,而且用户可以在其中进行交互式操作,了解到更多的模型在真实世界中的信息[1].
VRML(Virtual Reality Modeling Language,虚拟现实建模语言)是一种开发于上世纪90年代的三维建模语言,起初只能创建静态的三维模型,但随着计算机图形学技术和用户要求的不断发展,VRML从2.0版本起支持动态模型的建立,并且可以添加声音、脚本,使得它所建立的模型更加生动形象.由于VRML是一种面向WEB、面向对象的三维建模语言,再加上它具有平台无关性,用户可以在任意操作系统上浏览,所以飞速成为了目前因特网上三维网站制作的主流语言.
在现在的三维图形建模体系中,存在不少的佼佼者,比如以文件小、交互功能强而著称的VRML建模,有着高画质、生动的模型形态的3D MAX建模,以及纯C++或者其他支持图形绘制的计算机语言建模方式.其中VRML和3D MAX建模比较简单易学,而纯计算机语言比如C++等的建模方式复杂程度较高,掌握起来困难度比较大.3D MAX渲染出来的动画效果很绚丽,可是仅仅能让模型按照事先设置的路径和方式运动起来,虽然也自带有MAX Script脚本,但不能很好地支持多用户交互操作.
相对而言,VRML不仅从语言结构上来说比较简单,而且支持多种不同种类的交互,能够充分满足编写者的设计需要.VRML97标准的建立,使得VRML可以使用诸多的内建传感器节点,而且支持VRML Script脚本编程,更令人欣喜的是,VRML还支持引入JAVA、JAVA Script等语言编制的脚本,这些脚本编程交互的加入,将会发挥编程灵活、控制手段多样、实现范围更广泛的特点,设计出更生动、复杂的场景[2].
从编程的复杂程度上来说,大致可以分为两类:一类是需要复杂编程的,比如利用VRML Script等脚本语言编写交互程序;另一类是不需要复杂编程的,比如利用VRML自带的各种传感器节点进行交互.从交互对象上看,又可以分为VRML内部模型编程交互(如上面举到的两个例子)和VRML引入对象自带交互功能,也就是在VRML引入的对象里自己带有一定的交互功能.
根据以上区别,我们把VRML内支持的交互功能分为3类:基于VRML内建传感器的交互、基于脚本语言的交互、引入可交互对象[3,4].
VRML内建了时间传感器(TimeSensor)、触摸传感器(TouchSensor)、接近传感器(ProximitySensor)、碰撞传感器(Collision)等多种传感器节点.这些传感器节点功能不同,分工明确,可以完成最基本的交互功能,满足用户最基本的交互需要.VRML当中还内建有多种插值器,这些插值器主要用于实现动画效果.综合运用传感器节点和插值器节点,可以使用户在执行某一操作时触发某个量变或者形变的动画,使场景更加生动.
举个例子,假如我们目前想要设置一个这样的功能:当用户走近某个对象时,就可以听到这个对象的相关介绍,当离开一段距离后声音就会渐渐减弱到消失.这个功能可以通过接近传感器(ProximitySensor)节点去实现.ProximitySensor节点用来感知某一个坐标区域内是否有用户进入和离开,并对用户的进入和离开还有在该区域内的停留事件做出响应,其节点语法如下 :
ProximitySensor {
Enabled TRUE
Center x,y,z
Size a,b,c
isActive
enterTime
exitTime
Position_changed
Orientation_changed
}
其中,Enable域用来控制传感器的开关,是一个布尔型变量,当它的值为TURE时,传感器处于打开状态,才能感知用户的行为;center域用来设定用于感应的长方体区域中心点的坐标值;size用来设定用于感应的长方体区域的大小,a、b、c分别为该区域在X轴、Y轴、Z轴方向的长度;isActive域是一个布尔型变量,用于标记感应区域内有没有用户存在,如果有,那么它的值为TURE;enterTime域和exitTime域分别用于记录用户进入和离开感应区域的时间;Position_changed域用来记录用户在感应区域内的位置;Orientation_changed域用于记录用户在感应区域内的空间坐标方向.
由于我们需要触发的事件是音频的播放,所以完成该感应机制,还需要设置音响剪辑(AudioClip)节点.音响剪辑节点主要用于引入音源信息,它的域值url可以链接到网上任意一段音频,但是仅限于WAV和MIDI格式的文件.该节点中还包含有startTime域和stopTime域,分别用于设置声音文件的播放和停止时间.
首先设置接近传感器节点的感知区域,当用户进入虚拟展厅当中设定好的感知区域后,接近传感器的isActive域将会输出布尔值TRUE,同时接近传感器enterTime域会把用户进入感应区域的事件记录下来,把接近传感器enterTime域的时间值传送到音响剪辑节点的startTime域,将其激活,这样在用户进入感知区域时,音响剪辑节点就开始播放声音;当用户退出感知区域时,接近传感器的isActive域输出FALSE,关闭该传感器,同时接近传感器的exitTime域记录用户退出感知区域的时间,把exitTime域记录的时间值送到音响剪辑节点内stopTime域,在这一时刻关闭声音.这样,一个感应用户是否接近对象的交互功能就完成了.
从以上例子可以看出,用户的一般交互行为,用VRML的内建传感器节点综合其他常用节点是很容易实现的.由于VRML内建传感器仅支持一些简单的交互行为响应,所以基于传感器节点的交互技术适用于处理一般情况下常用的用户交互行为.
用户在进入虚拟场景之后,有时往往想要进行一些比较复杂的交互,这些交互仅仅利用VRML内建的传感器节点是无法满足的,这时候我们就需要使用脚本编程方式来解决.
脚本编程交互技术是指引入用其他脚本语言比如Java Script或者VRML Script等编写的程序脚本去执行某一项交互操作.由于VRML允许引用的脚本语言种类繁多,而且功能强大,所以利用这一机制基本上可以完成用户所需要的所有交互行为.
在VRML当中,需要使用脚本节点(Script)来引入其他语言编写的脚本.脚本节点的语法格式如下:
DEF <节点名称> Script{
field <域类型> <域名>
eventIn <入事件类型> <入事件名>
eventOut <出事件类型> <出事件名>
url ”<脚本语言声明>:
脚本语言程序” }
这里的域、入事件、出事件是为了后面脚本语言程序的运行做准备工作的,用于建立脚本程序和VRML场景之间的联系,没有个数的限制,也就是说同一事件可以产生多个结果.
下面我们通过一段程序来介绍脚本编程与传感器节点相结合使用完成的一项交互功能.在这里,我们制作了一个转椅,当人们用鼠标点住转椅的上部时,可以拖动转椅转向任意方向.为了实现交互,在转椅的椅垫以上部分定义了一个绕轴旋转的圆柱体传感器(CylinderSensor)节点,通过将传感器节点的输出路由到Script节点来引起转椅的旋转.当鼠标停在转椅上就会变成手的形状可以随鼠标的转动而使转椅绕Y轴进行旋转.以下是实现该功能的代码:
DEF SCR Script #定义Script节点
{
url ”javascript:
function initialize () {
ps = sp.site._parent_site_;
if (ps) {
geom = tr.children [1].children [0];
geom.children = ps.children;
ps.children = new MFNode (tr);
setAxis (axis);
center = ps.center;
tr.translation = center;
geom.translation = geom.rotation.multVec (center.negate ( ));
cortona = Browser.getName ().indexOf (‘Cortona’)! = -1;
}
}
function setAxis (val) {
geom = tr.children [1].children [0];
v = geom.rotation.multVec (axisVectors [val]);
tr.rotation = new SFRotation (axisVectors [1], v);
tr.children [1].rotation = tr.rotation.inverse ();
tr.children [0].offset = 0;
offset = geom.rotation;
}
function rotation (value) {
geom = tr.children [1].children [0];
v = tr.rotation.multVec (axisVectors [1]);
r = new SFRotation (v, value [3]);
geom.rotation = cortona? r.multiply (offset): offset.multiply(r);
geom.translation = geom.rotation.multVec (center.negate ( ));
}
function enable (val) {
tr.children [0].enabled = val;
}”
directOutput TRUE # Script节点可以将事件出直接传给它能联系上的任意节点
field SFNode tr Transform
{
children
[
DEF CS CylinderSensor #定义接触型传感器(转椅绕下面轴旋转)
{
enabled IS Enabled
maxAngle IS $MaxAngle
minAngle IS $MinAngle
isActive IS isActive
}
Transform
{
children
[
Transform
{
rotation IS rotation_changed
}]}]}
field SFNode sp SiteProvider
{
site IS _object_site_}
eventIn SFBool enable IS enable
field SFInt32 axis IS $Axis
eventIn SFInt32 setAxis IS setAxis
eventIn SFRotation rotation
field SFRotation offset 0 1 0 0
field MFVec3f axisVectors [1 0 0, 0 1 0, 0 0 1]
field SFVec3f center 0 0 0
field SFBool cortona TRUE}
ROUTE CS.rotation_changed TO SCR.rotation
}
引入可交互对象的机制,是综合运用其他外部对象的交互资源完成VRML场景内交互功能的方法.从VRML2.0版本开始,有两种方法可以引用外部的.wrl或者其他格式的文件,其中内建(InLine)节点允许包含存储在网页上的任何VRML文件,外部原型(EXTERNPROTO)节点允许调用来自互联网任意地方的资源来定义新节点.更一般的情况是,EXTERNPROTO语句使节点在VRML文件之外定义,这也是VRML最基本的可扩展机制.
目前,基于以上两种机制,已经有很多种类的的对象可以插入到VRML场景中,而且其中一些对象本身就具有一定的交互性,部分对象还支持脚本编程.在使用VRML构建的虚拟场景中引入这些对象,不仅可以使虚拟场景更加丰富多彩,而且能够在一定程度上增强虚拟场景的交互性.
以Flash为例,在三维建模语言出现之前,Flash就曾经一度被用于网页仿三维展示.Flash本身具有强大的动画功能,而且支持Action Script脚本编辑语言,这些使得Flash在平面表示和交互上具有很大的优势.现在虽然有三维建模语言的支持,但是Flash文件体积小、表现方式多种多样、交互功能强大的优势依然可以发挥在目前的三维建模领域.如果我们想在制作的VRML虚拟场景中加入Flash文件,那么在VRML文件的头文件之后,加入如下代码就可以支持对Flash文件的调用:
EXTERNPROTO FlashMovie [...]
中间被省略的部分用于设置外部节点的域和事件,其中域、事件的类型和名称必须与引用的外部节点中的定义一样.
使用外部原型节点引用的外部对象,其外部节点的资源定位格式为:
"URL/URN"或["URL/URN","URL/URN",…]
资源定位可以为URL或URN格式,当使用"URL/URN"或["URL/URN","URL/URN",…]的数组形式时,浏览器使用数组中第一个正确寻获的资源.资源的形式也可以写为:
URL/URN # externProtytypeName
externProtytypeName为引用的外部节点的名称,这时候,可以使用与外部节点定义的名称不同的节点名称.
VRML支持的多种交互技术各有千秋,传感器交互适用于处理简单的用户交互,脚本编程交互适用于处理复杂的用户交互行为,在VRML中引入具有交互功能的对象更可以为虚拟场景增色不少.如果能在VRML构建的场景中综合运用这些交互功能,则可以把VRML的交互能力发挥到极致.
[1] 刘 怡,张洪定,崔 欣.虚拟现实VRML程序设计[M]. 天津:南开大学出版社,2007:1-3.
[2] 翁 蓉,廖小平. 基于VRML和Java的交互式虚拟产品设计[J].计算机工程与设计,2007,12:59-60.
[3] 李晓玲,陆长德,李小莉. 基于网络的交互式虚拟展示技术研究[J]. 计算机工程与应用, 2007,43(3):90-92.
[4] 汪 华,李 莹. VRML与JavaScript结合实现交互式动画[J].福建电脑,2008(3):187.