邱龍輝, 葉 琳
(青島科技大學(xué)機(jī)電工程學(xué)院,山東 青島 266061)
工程圖學(xué)虛擬實(shí)驗(yàn)采用Web+Java+VRML平臺(tái),在網(wǎng)絡(luò)中構(gòu)建圖學(xué)學(xué)習(xí)實(shí)踐的空間,優(yōu)化學(xué)生的課內(nèi)和課后實(shí)驗(yàn)和實(shí)踐訓(xùn)練環(huán)境。實(shí)驗(yàn)系統(tǒng)要求能夠?qū)崿F(xiàn):① 三維立體的實(shí)時(shí)變形處理,如截交線實(shí)驗(yàn)中的立體切割;② 立體之間的位置變化處理,如立體相貫實(shí)驗(yàn)和組合體實(shí)驗(yàn)中立體的定位;③ 實(shí)驗(yàn)參數(shù)調(diào)整靈活:可以直接控制模型調(diào)整和通過 Web頁面的界面調(diào)整[1]。但VRML的基本節(jié)點(diǎn)本身并不具備實(shí)現(xiàn)這些目標(biāo)的能力,要實(shí)現(xiàn)上述目標(biāo),必須能夠通過程序方便的控制虛擬實(shí)驗(yàn)系統(tǒng)中虛擬模型,如獲得模型的狀態(tài)數(shù)據(jù)、讀取模型的幾何結(jié)構(gòu)數(shù)據(jù)、程序動(dòng)態(tài)生成模型等,本文研究了使用Java平臺(tái)實(shí)現(xiàn)實(shí)驗(yàn)系統(tǒng)的幾個(gè)關(guān)鍵技術(shù)。
Java程序控制VRML可以通過兩種方式,即通過 SAI (Script Authoring Interface)或 EAI(External Authoring Interface)[2]。SAI方式是通過VRML中的Script接口節(jié)點(diǎn)控制場(chǎng)景,充分利用了VRML原有的事件機(jī)制,但其Java程序類必須是Script類的子類[2-3],也就是說所編寫的Java類都必須繼承自Script類。EAI方式是使用一套針對(duì)VRML瀏覽器的Java類,實(shí)現(xiàn)了Java Applet與 VRML場(chǎng)景的通信。通過 EAI,Java Applet可以訪問當(dāng)前運(yùn)行的 VRML場(chǎng)景,在外部直接操作、控制和修改 VRML內(nèi)部的場(chǎng)景。SAI和EAI相當(dāng)于Java對(duì)VRML場(chǎng)景的內(nèi)部控制和外部控制方法,可以滿足不同實(shí)驗(yàn)的需要。
在系統(tǒng)中欲實(shí)現(xiàn)對(duì) VRML場(chǎng)景的控制,應(yīng)首先在 VRML程序?qū)ζ溟_放的被控制節(jié)點(diǎn)使用DEF命名,建立該節(jié)點(diǎn)被檢索的標(biāo)識(shí),然后在Java程序中通過該名稱獲得對(duì)應(yīng)節(jié)點(diǎn)的Node類實(shí)例。在SAI和EAI中獲得節(jié)點(diǎn)實(shí)例的方法不同,SAI必須在Script節(jié)點(diǎn)中定義域,并使用USE關(guān)鍵詞引用對(duì)應(yīng)的節(jié)點(diǎn),在 Java程序中使用getField()方法通過讀取Script節(jié)點(diǎn)中的域值獲得該實(shí)例。而EAI則相對(duì)靈活,只需使用getNode()方法即可直接獲得。
在虛擬實(shí)驗(yàn)操作過程中,諸如截交線實(shí)驗(yàn)的截平面、組合體實(shí)驗(yàn)中構(gòu)件都需要獲得其空間位置,測(cè)繪實(shí)驗(yàn)中需要獲得坐標(biāo)點(diǎn)數(shù)據(jù),此時(shí)獲得場(chǎng)景中模型當(dāng)前的狀態(tài)數(shù)據(jù)和幾何結(jié)構(gòu)數(shù)據(jù)成為關(guān)鍵環(huán)節(jié)之一,正確讀取相關(guān)數(shù)據(jù)才能進(jìn)行其他的相關(guān)操作。場(chǎng)景中模型的結(jié)構(gòu)數(shù)據(jù)和當(dāng)前的狀態(tài)是由節(jié)點(diǎn)的出事件和外露域的參數(shù)表現(xiàn)的,所以獲得模型的結(jié)構(gòu)數(shù)據(jù)和當(dāng)前的狀態(tài)就是獲得相應(yīng)節(jié)點(diǎn)的出事件和外露域參數(shù)。
使用VRML API時(shí),獲得節(jié)點(diǎn)的出事件和外露域參數(shù)有兩個(gè)途徑:① 使用VRML的ROUTE語句,通過Script節(jié)點(diǎn)的eventIn獲得相關(guān)節(jié)點(diǎn)的狀態(tài)數(shù)據(jù),需要在 VRML文件中添加許多ROUTE語句,但只適用于SAI模式開發(fā);② 直接讀取 VRML節(jié)點(diǎn)的出事件和外露域,SAI和EAI均可以實(shí)現(xiàn)。
如圖1所示,直接讀取VRML節(jié)點(diǎn)出事件和外露域需要如下幾個(gè)步驟:
圖1 讀取出事件
(1)獲得Browser實(shí)例
本步驟需要定義一個(gè) VRML API特有的Browser類,然后使用該類的 getBrowser()方法建立當(dāng)前的Browser類實(shí)例。Browser類實(shí)際上是對(duì)VRML場(chǎng)景的一個(gè)Java封裝,其中包含了獲取當(dāng)前瀏覽環(huán)境信息的各種方法。
(2)獲得節(jié)點(diǎn)(Node)實(shí)例
使用 SAI或 EAI開發(fā)時(shí),獲得節(jié)點(diǎn)實(shí)例的方法不同:SAI必須在關(guān)聯(lián)的Script節(jié)點(diǎn)中定義域,并使用 USE關(guān)鍵詞引用對(duì)應(yīng)的節(jié)點(diǎn),然后在 Java程序中使用 getField()方法通過讀取Script節(jié)點(diǎn)中的域值獲得該實(shí)例;而EAI則相對(duì)靈活,只需使用getNode()方法即可直接獲得。
(3)獲得節(jié)點(diǎn)出事件(eventOut)或外露域(exposedField)實(shí)例
模型的結(jié)構(gòu)數(shù)據(jù)和當(dāng)前的狀態(tài)數(shù)據(jù)是通過該節(jié)點(diǎn)的eventOut或exposedField反映的。所以應(yīng)先獲得該事件的實(shí)例。該實(shí)例的獲得通過Node類的getEventOut()方法實(shí)現(xiàn)。這一步驟需要將getEventOut得到的實(shí)例強(qiáng)制類型轉(zhuǎn)化為EventOut的相應(yīng)子類(如 EventOutMFVec3f),以實(shí)現(xiàn)讀取eventOut事件目的。
(4)讀取模型的狀態(tài)數(shù)據(jù)
通過eventOut實(shí)例的getValue()方法實(shí)現(xiàn)模型的狀態(tài)數(shù)據(jù)的讀取。
按照前述步驟,在虛擬截交線實(shí)驗(yàn)中,采用了 EAI的方式實(shí)時(shí)獲得了切割平面位置。其中須定義變量如下:
在實(shí)驗(yàn)過程中,經(jīng)常需要根據(jù)實(shí)驗(yàn)需求動(dòng)態(tài)的建立模型;當(dāng)針對(duì)實(shí)驗(yàn)?zāi)P瓦M(jìn)行諸如切割、拉伸等操作后,也需要重新生成虛擬模型。因此,使用 Java程序動(dòng)態(tài)地生成虛擬模型成為了虛擬實(shí)驗(yàn)的關(guān)鍵過程。
向VRML場(chǎng)景添加節(jié)點(diǎn),需要以下5個(gè)步驟。
(1)獲得瀏覽器的管理。
(2)獲得父節(jié)點(diǎn)的控制
場(chǎng)景中一般使用Transform節(jié)點(diǎn)作為容納模型形體的父節(jié)點(diǎn),在 VRML文件需要對(duì)相應(yīng)的Transform節(jié)點(diǎn)使用DEF定義名稱,同時(shí)在Java中使用Browser類的getNode()方法獲得該節(jié)點(diǎn)的Node類實(shí)例。
(3)獲得父節(jié)點(diǎn)的eventIn實(shí)例
向Transform節(jié)點(diǎn)中添加模型節(jié)點(diǎn)是通過該節(jié)點(diǎn)的eventIn事件addChildren實(shí)現(xiàn)的。所以必須先獲得該事件的實(shí)例。該實(shí)例的獲得通過Node類的 getEventIn()方法實(shí)現(xiàn)。此處同樣需要注意的是將getEventIn得到的addChildren實(shí)例強(qiáng)制轉(zhuǎn)化為EventIn的子類EventInMFNode。
(4)建立新模型節(jié)點(diǎn)數(shù)據(jù)
模型節(jié)點(diǎn)數(shù)據(jù)生成步驟如下:
1)計(jì)算獲得模型立體的點(diǎn)表和面表數(shù)據(jù);
2)按VRML格式建立坐標(biāo)(coordString)和坐標(biāo)索引(coordindexString)字符串,1)中計(jì)算獲得的點(diǎn)表數(shù)據(jù)是雙精度型,而 VRML模型中數(shù)據(jù)精度不必太高,這里使用Java中Math類的 round()方法保留兩位小數(shù),然后將坐標(biāo)值轉(zhuǎn)換為字符串向坐標(biāo)字符串賦值。同時(shí)注意各坐標(biāo)之間需要加入空格,每組坐標(biāo)后要加入逗號(hào)分隔,以符合VRML格式要求。
3)建立Node類數(shù)組
創(chuàng)建 Node類型的實(shí)例數(shù)組使用 API中Browser類的createVrmlFromString()方法,該方法的參數(shù)是符合 VRML格式的字符串。這里將坐標(biāo)、坐標(biāo)索引字符串與Transform的其他相關(guān)字符串組合。此處的字符串應(yīng)按照 VRML編程時(shí)的格式,分行列出,這樣可以極大地減少程序在運(yùn)行過程中的出錯(cuò)率。
下面以棱柱截交線實(shí)驗(yàn)為例,說明各種方法的應(yīng)用。截交線實(shí)驗(yàn)進(jìn)行中,截平面位置的獲得使用了VRML模型數(shù)據(jù)的獲取技術(shù),如圖2所示;而截切后截?cái)囿w的生成使用了 Java程序生成虛擬模型技術(shù),如圖3所示。
圖2 截平面位置的獲得
圖3 Java程序生成截?cái)囿w
本文針對(duì)工程圖學(xué)虛擬實(shí)驗(yàn)系統(tǒng)在控制虛擬模型方面的需求,研究實(shí)現(xiàn)了 Java程序控制VRML,獲取VRML模型數(shù)據(jù),生成虛擬模型等幾個(gè)實(shí)現(xiàn)模型控制中的關(guān)鍵技術(shù)。解決了虛擬實(shí)驗(yàn)系統(tǒng)開發(fā)中的幾個(gè)難點(diǎn)問題,也為其他VRML虛擬系統(tǒng)提供了開發(fā)基礎(chǔ)。
[1]邱龍輝, 葉 琳. 基于VRML-Java平臺(tái)的工程圖學(xué)網(wǎng)絡(luò)實(shí)驗(yàn)系統(tǒng)研究與實(shí)現(xiàn)[J]. 工程圖學(xué)學(xué)報(bào), 2005,26(5): 155-159.
[2]Rikk Carey, Gavin Bell, Chris Marrin. ISO/IEC 14772-1:1997, Virtual Reality Modeling Language [S].
[3]The Java Tutorial [EB/OL]. http://java.sun.com/docs/books/tutorial