楊安祺, 喬海超, 張杜娟, 賈偉光, 唐 軍
(1.陜西科技大學電氣與信息工程學院, 陜西 西安 710021; 2.西安醫(yī)學院公共課部, 陜西 西安 710021)
隨著計算機技術的不斷發(fā)展,網頁上一些文本、圖片等二維展示途徑已經滿足不了人們的需要,三維建模語言的出現則滿足了人們的這一要求.目前,在房地產開發(fā)等諸多領域,國內外不少公司都已經開始了三維展示的應用,通過三維實體構建模型,將產品的特點生動直觀地展現給用戶,獲得了巨大的成功.以三維建模技術構建的虛擬展廳、虛擬社區(qū),不僅能給出模型的色彩、外觀、結構、紋理等靜態(tài)信息,還能給出模型在運動狀態(tài)所擁有的一些特性,而且用戶可以在其中進行交互式操作,了解到更多的模型在真實世界中的信息[1].
VRML(Virtual Reality Modeling Language,虛擬現實建模語言)是一種開發(fā)于上世紀90年代的三維建模語言,起初只能創(chuàng)建靜態(tài)的三維模型,但隨著計算機圖形學技術和用戶要求的不斷發(fā)展,VRML從2.0版本起支持動態(tài)模型的建立,并且可以添加聲音、腳本,使得它所建立的模型更加生動形象.由于VRML是一種面向WEB、面向對象的三維建模語言,再加上它具有平臺無關性,用戶可以在任意操作系統(tǒng)上瀏覽,所以飛速成為了目前因特網上三維網站制作的主流語言.
在現在的三維圖形建模體系中,存在不少的佼佼者,比如以文件小、交互功能強而著稱的VRML建模,有著高畫質、生動的模型形態(tài)的3D MAX建模,以及純C++或者其他支持圖形繪制的計算機語言建模方式.其中VRML和3D MAX建模比較簡單易學,而純計算機語言比如C++等的建模方式復雜程度較高,掌握起來困難度比較大.3D MAX渲染出來的動畫效果很絢麗,可是僅僅能讓模型按照事先設置的路徑和方式運動起來,雖然也自帶有MAX Script腳本,但不能很好地支持多用戶交互操作.
相對而言,VRML不僅從語言結構上來說比較簡單,而且支持多種不同種類的交互,能夠充分滿足編寫者的設計需要.VRML97標準的建立,使得VRML可以使用諸多的內建傳感器節(jié)點,而且支持VRML Script腳本編程,更令人欣喜的是,VRML還支持引入JAVA、JAVA Script等語言編制的腳本,這些腳本編程交互的加入,將會發(fā)揮編程靈活、控制手段多樣、實現范圍更廣泛的特點,設計出更生動、復雜的場景[2].
從編程的復雜程度上來說,大致可以分為兩類:一類是需要復雜編程的,比如利用VRML Script等腳本語言編寫交互程序;另一類是不需要復雜編程的,比如利用VRML自帶的各種傳感器節(jié)點進行交互.從交互對象上看,又可以分為VRML內部模型編程交互(如上面舉到的兩個例子)和VRML引入對象自帶交互功能,也就是在VRML引入的對象里自己帶有一定的交互功能.
根據以上區(qū)別,我們把VRML內支持的交互功能分為3類:基于VRML內建傳感器的交互、基于腳本語言的交互、引入可交互對象[3,4].
VRML內建了時間傳感器(TimeSensor)、觸摸傳感器(TouchSensor)、接近傳感器(ProximitySensor)、碰撞傳感器(Collision)等多種傳感器節(jié)點.這些傳感器節(jié)點功能不同,分工明確,可以完成最基本的交互功能,滿足用戶最基本的交互需要.VRML當中還內建有多種插值器,這些插值器主要用于實現動畫效果.綜合運用傳感器節(jié)點和插值器節(jié)點,可以使用戶在執(zhí)行某一操作時觸發(fā)某個量變或者形變的動畫,使場景更加生動.
舉個例子,假如我們目前想要設置一個這樣的功能:當用戶走近某個對象時,就可以聽到這個對象的相關介紹,當離開一段距離后聲音就會漸漸減弱到消失.這個功能可以通過接近傳感器(ProximitySensor)節(jié)點去實現.ProximitySensor節(jié)點用來感知某一個坐標區(qū)域內是否有用戶進入和離開,并對用戶的進入和離開還有在該區(qū)域內的停留事件做出響應,其節(jié)點語法如下 :
ProximitySensor {
Enabled TRUE
Center x,y,z
Size a,b,c
isActive
enterTime
exitTime
Position_changed
Orientation_changed
}
其中,Enable域用來控制傳感器的開關,是一個布爾型變量,當它的值為TURE時,傳感器處于打開狀態(tài),才能感知用戶的行為;center域用來設定用于感應的長方體區(qū)域中心點的坐標值;size用來設定用于感應的長方體區(qū)域的大小,a、b、c分別為該區(qū)域在X軸、Y軸、Z軸方向的長度;isActive域是一個布爾型變量,用于標記感應區(qū)域內有沒有用戶存在,如果有,那么它的值為TURE;enterTime域和exitTime域分別用于記錄用戶進入和離開感應區(qū)域的時間;Position_changed域用來記錄用戶在感應區(qū)域內的位置;Orientation_changed域用于記錄用戶在感應區(qū)域內的空間坐標方向.
由于我們需要觸發(fā)的事件是音頻的播放,所以完成該感應機制,還需要設置音響剪輯(AudioClip)節(jié)點.音響剪輯節(jié)點主要用于引入音源信息,它的域值url可以鏈接到網上任意一段音頻,但是僅限于WAV和MIDI格式的文件.該節(jié)點中還包含有startTime域和stopTime域,分別用于設置聲音文件的播放和停止時間.
首先設置接近傳感器節(jié)點的感知區(qū)域,當用戶進入虛擬展廳當中設定好的感知區(qū)域后,接近傳感器的isActive域將會輸出布爾值TRUE,同時接近傳感器enterTime域會把用戶進入感應區(qū)域的事件記錄下來,把接近傳感器enterTime域的時間值傳送到音響剪輯節(jié)點的startTime域,將其激活,這樣在用戶進入感知區(qū)域時,音響剪輯節(jié)點就開始播放聲音;當用戶退出感知區(qū)域時,接近傳感器的isActive域輸出FALSE,關閉該傳感器,同時接近傳感器的exitTime域記錄用戶退出感知區(qū)域的時間,把exitTime域記錄的時間值送到音響剪輯節(jié)點內stopTime域,在這一時刻關閉聲音.這樣,一個感應用戶是否接近對象的交互功能就完成了.
從以上例子可以看出,用戶的一般交互行為,用VRML的內建傳感器節(jié)點綜合其他常用節(jié)點是很容易實現的.由于VRML內建傳感器僅支持一些簡單的交互行為響應,所以基于傳感器節(jié)點的交互技術適用于處理一般情況下常用的用戶交互行為.
用戶在進入虛擬場景之后,有時往往想要進行一些比較復雜的交互,這些交互僅僅利用VRML內建的傳感器節(jié)點是無法滿足的,這時候我們就需要使用腳本編程方式來解決.
腳本編程交互技術是指引入用其他腳本語言比如Java Script或者VRML Script等編寫的程序腳本去執(zhí)行某一項交互操作.由于VRML允許引用的腳本語言種類繁多,而且功能強大,所以利用這一機制基本上可以完成用戶所需要的所有交互行為.
在VRML當中,需要使用腳本節(jié)點(Script)來引入其他語言編寫的腳本.腳本節(jié)點的語法格式如下:
DEF <節(jié)點名稱> Script{
field <域類型> <域名>
eventIn <入事件類型> <入事件名>
eventOut <出事件類型> <出事件名>
url ”<腳本語言聲明>:
腳本語言程序” }
這里的域、入事件、出事件是為了后面腳本語言程序的運行做準備工作的,用于建立腳本程序和VRML場景之間的聯系,沒有個數的限制,也就是說同一事件可以產生多個結果.
下面我們通過一段程序來介紹腳本編程與傳感器節(jié)點相結合使用完成的一項交互功能.在這里,我們制作了一個轉椅,當人們用鼠標點住轉椅的上部時,可以拖動轉椅轉向任意方向.為了實現交互,在轉椅的椅墊以上部分定義了一個繞軸旋轉的圓柱體傳感器(CylinderSensor)節(jié)點,通過將傳感器節(jié)點的輸出路由到Script節(jié)點來引起轉椅的旋轉.當鼠標停在轉椅上就會變成手的形狀可以隨鼠標的轉動而使轉椅繞Y軸進行旋轉.以下是實現該功能的代碼:
DEF SCR Script #定義Script節(jié)點
{
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節(jié)點可以將事件出直接傳給它能聯系上的任意節(jié)點
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)節(jié)點允許包含存儲在網頁上的任何VRML文件,外部原型(EXTERNPROTO)節(jié)點允許調用來自互聯網任意地方的資源來定義新節(jié)點.更一般的情況是,EXTERNPROTO語句使節(jié)點在VRML文件之外定義,這也是VRML最基本的可擴展機制.
目前,基于以上兩種機制,已經有很多種類的的對象可以插入到VRML場景中,而且其中一些對象本身就具有一定的交互性,部分對象還支持腳本編程.在使用VRML構建的虛擬場景中引入這些對象,不僅可以使虛擬場景更加豐富多彩,而且能夠在一定程度上增強虛擬場景的交互性.
以Flash為例,在三維建模語言出現之前,Flash就曾經一度被用于網頁仿三維展示.Flash本身具有強大的動畫功能,而且支持Action Script腳本編輯語言,這些使得Flash在平面表示和交互上具有很大的優(yōu)勢.現在雖然有三維建模語言的支持,但是Flash文件體積小、表現方式多種多樣、交互功能強大的優(yōu)勢依然可以發(fā)揮在目前的三維建模領域.如果我們想在制作的VRML虛擬場景中加入Flash文件,那么在VRML文件的頭文件之后,加入如下代碼就可以支持對Flash文件的調用:
EXTERNPROTO FlashMovie [...]
中間被省略的部分用于設置外部節(jié)點的域和事件,其中域、事件的類型和名稱必須與引用的外部節(jié)點中的定義一樣.
使用外部原型節(jié)點引用的外部對象,其外部節(jié)點的資源定位格式為:
"URL/URN"或["URL/URN","URL/URN",…]
資源定位可以為URL或URN格式,當使用"URL/URN"或["URL/URN","URL/URN",…]的數組形式時,瀏覽器使用數組中第一個正確尋獲的資源.資源的形式也可以寫為:
URL/URN # externProtytypeName
externProtytypeName為引用的外部節(jié)點的名稱,這時候,可以使用與外部節(jié)點定義的名稱不同的節(jié)點名稱.
VRML支持的多種交互技術各有千秋,傳感器交互適用于處理簡單的用戶交互,腳本編程交互適用于處理復雜的用戶交互行為,在VRML中引入具有交互功能的對象更可以為虛擬場景增色不少.如果能在VRML構建的場景中綜合運用這些交互功能,則可以把VRML的交互能力發(fā)揮到極致.
[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.