原文網址:http://tech.it168.com/a2009/0213/265/000000265323.shtml
【IT168 技術文章】Java3D用其自己定義的場景圖和觀察模式等技術構造了3D的上層結構,實現了在Java平臺使用三維技術。本文在原理上着重介紹Java3D特有的兩個重要概念:場景圖(Scene Graph)、觀察模式(View Model)。在接口使用上的介紹分爲兩部分:實例說明如何使用Java3D接口;說明如何將Java3D技術與Java原有的Web技術(JSP、Serverlet)相結合,在網頁上實現三維顯示。
關於Java3D
1.1 Java3D簡介
Java3D API是Sun定義的用於實現3D顯示的接口。3D技術是底層的顯示技術,Java3D提供了基於Java的上層接口。Java3D把OpenGL和DirectX這些底層技術包裝在Java接口中。這種全新的設計使3D技術變得不再繁瑣並且可以加入到J2SE、J2EE的整套架構,這些特性保證了Java3D技術強大的擴展性。
JAVA3D建立在JAVA2(JAVA1.2)基礎之上,JAVA語言的簡單性使JAVA3D的推廣有了可能。它實現了以下三維顯示能夠用到的功能:
生成簡單或複雜的形體(也可以調用現有的三維形體)
使形體具有顏色、透明效果、貼圖。
在三維環境中生成燈光、移動燈光。
生成霧、背景、聲音。
使形體變形、移動、生成三維動畫。
編寫非常複雜的應用程序,用於各種領域如VR(虛擬現實)。
J2SE在其標準開發包中並不提供Java3D的API,Java3D是一個獨立的可選組件,可以單獨下載。Java3D現在(截止到2003年5月)提供的正式版本是1.3.0,可以在 http://java.sun.com/products/java-media/3D/download.html 下載該開發工具包。
Java3D 1.3有7個不同的可下載版本:
Java3D for Windows(DirectX version)SDK for JDK(include Runtime);
Java3D for Windows(OpenGL version)SDK for JDK(include Runtime);
Java3D for Solaris/SPARC Runtime for JDK(include Runtime);
Java3D for Windows(DirectX version)Runtime for JRE;
Java3D for Windows(OpenGL version)Runtime for JRE;
Java3D for Solaris/SPARC SDK for JRE;
Java3D for Solaris Runtime 64 bit support;
其中前三個版本是開發包。第4、5、6個版本是Java3D運行期支持程序包。最後一個是支持Solaris 64 bit操作平臺運行Java3D的程序包。前三個的開發包包含了各自對應的運行期支持包。Java語言本身具有跨平臺特性,無論使用上述哪個版本的開發包,概念和實現代碼都會保持完全一致。這裏我們使用Java3D for Windows(OpenGL version)SDK for JDK(include Runtime);版本作爲我們討論、實現Java3D的工具包。注意在安裝此版本SDK前要保證下列環境:
Java 2 (Runtime or SDK) version 1.3.1 或更後的版本
OpenGL 1.1 或更後的版本,並且是Microsoft支持的顯卡廠商
Windows NT 4.0 only: Service Pack 3 或更後的版本(Window2000、WindowXP)
1.2 Java3D與其他三維技術的比較
JAVA3D可應用在三維動畫、三維遊戲、機械CAD等多個領域。但作爲三維顯示實現技術,它並不是唯一選擇而且是一個新面孔。在Java3D之前已經存在很多三維技術,這些三維技術在實現的技術、使用的語言以及適用的情況上各有不同,我們主要介紹與Java3D又密切關係的三種技術:OpenGL、DIRECT3D、VRML
OpenGL是業界最爲流行也是支持最廣泛的一個底層3D技術,幾乎所有的顯卡廠商都在底層實現了對OpenGL的支持和優化。OpenGL同時也定義了一系列接口用於編程實現三維應用程序,但是這些接口使用C(C++)語言實現並且很複雜。掌握針對OpenGL的編程技術需要花費大量時間精力。
DIRECT3D是Microsoft公司推出的三維圖形編程API,它主要應用於三維遊戲的編程。衆多優秀的三維遊戲都是由這個接口實現。與OpenGL一樣,Direct3D的實現主要使用C++語言。
VRML2.0(VRML97)自1997年12月正式成爲國際標準之後,在網絡上得到了廣泛的應用,這是一種比BASIC、JAVASCRIPT等還要簡單的語言。腳本化的語句可以編寫三維動畫片、三維遊戲、計算機三維輔助教學。它最大的優勢在於可以嵌在網頁中顯示,但這種簡單的語言功能較弱(如目前沒有形體之間的碰撞檢查功能),與JAVA語言等其它高級語言的連接較難掌握,因而逐漸被淹沒在競爭激烈的網絡三維技術中。
表1是Java3D與其它三維技術的比較圖,可以從中直觀的看出他們相互間的區別:
表1:3D技術對招表
技術 | 實現層次 | 開發技術(難度) | 擴展性 | 最適合應用領域 |
Java3D | 中層(JVM) | Java(較易) | J2SE標準擴展(好) | 網上三維顯示實現… |
OpenGL | 底層(顯卡) | C\C++(難) | 各大廠商支持(較好) | 三維設計軟件… |
Direct3D | 底層(操作系統) | C++(較難) | Windows平臺(差) | 三維遊戲… |
VRML | 上層(網頁) | 標記語言(容易) | 安裝插件支持(一般) | 網上虛擬現實… |
Java3D的場景圖結構
Java3D實際上是Java語言在三維圖形領域的擴展,與Java一樣,Java3D有純粹的面向對象結構。Java3D的數據結構採用的是Scene Graphs Structure(場景圖),就是一些具有方向性的不對稱圖形組成的樹狀結構(圖1)。
我們在一個Java3D應用程序看到的逼真三維場景從程序的角度看來,實際就是由Java3D定義的一系列的對象,這些對象不是雜亂無序,對象之間也不是毫無關係。如果想讓三維圖像正常顯示,必須在這兩點上遵循Java3D場景圖的規定。觀察圖1,Java3D場景圖的樹結構由各種各樣的對象組成:
在圖中出現的這些對象都實現了Java3D中有重要的意義的類,從邏輯上我們將它們分爲三類:
根節點(Root):Virtual Universe Object
節點(Node):Local Object、Branch Group Nodes、Behavior Node、Shape3D Node…
葉子節點(Leaf):Appearance、Geomery..
圖1:在應用中的Java3D場景圖
場景圖中線和線的交匯點稱爲節點(Node),這些節點都是Java3D類的實例(Instance of Class),節點之間的線表示各個實例之間的關係。
Virtual Universe是根節點,每一個場景圖的Virtual Universe是唯一的。
在Virtual Universe下面是Locale節點,每個程序可以有一個或多個Locale,但同時只能有一個Locale處於顯示狀態,就好象一個三維世界非常大,有很多個景點,但我們同時只能在一個景點進行觀察。Java3D允許從一個Locale跳到另一個Locale,不過絕大多數程序只有一個Locale。
每一個Locale可以擁有多個BranchGroup節點。所有三維形體的其位置信息(Transform Group Nodes)都建立在BranchGroup節點之上。
TransformGroup Node用來設定Shape3D在Virtual Universe中的位置。
Spape3D Node是三維圖形節點,這個節點的實體放映在最後的顯示畫面中,就是三維世界中的每個形體。包括正方體、球體以及任何形狀和外觀的三維形體。
位於場景圖最下層的是兩個葉子節點:三維體的外觀(Appearance)和幾何信息(Geometry),這兩個節點定義了一個三維體的顯示效果。
View Platform位於圖1的另一個分枝上,與前面所有描述三維體的性質的概念不同,View Platform和View都是用來定義觀察者的信息。
上面所列的概念很多,但是對於建立一個簡單的Java3D程序,我們至少需要了解三個概念:虛擬宇宙(Virtual Universe)、場景(Locale)、座標系統。
2.1 虛擬宇宙(Virtual Universe)
在Java3D中,虛擬宇宙被定義爲結合一系列對象的三維空間。虛擬宇宙被用作最大的聚集體表現單位,同時也可被看作一個數據庫。不管是在物理空間還是邏輯內容,虛擬宇宙都可以很大。實際上在大多數情況下,一個虛擬宇宙就可以滿足一個應用程序所有的需求。
虛擬宇宙是各自獨立的個體,原因是在任何時候一個結點對象都不能在超過一個的虛擬宇宙中存在。同樣的,在一個虛擬宇宙中的結點對象也不能在其他的虛擬宇宙中可見或者與其他的對象結合。
對於一個Java3D應用程序,必須定義一個虛擬宇宙纔可以在這個"宇宙"中顯示三維圖像。
2.2 Java3D的座標系統
默認情況下,Java3D的座標系統是右旋的,用方位語義學來解釋就是:正y方向是本地重力的上,正x方向是水平的右,正z是這對着觀察者的方向。默認的單位是米。
雙精度浮點、單精度浮點甚至是定點來表示的三維座標都足夠來表示和顯示豐富的3D場景。不幸的是,場景不是真實世界,更不必說整個宇宙了。如果使用單精度座標,有可能出現下列情景:
離原點僅有一百公里的距離,被描繪得相當量子化,所能達到的最好效果就是三分之一英寸,在實際應用中這樣的精度比要求的粗糙的多。
如果要縮小到一個很小的尺寸(例如表現集成電路的大小),甚至在離原點很近的地方就會出現同坐標問題。
爲了支持一個大型的鄰接虛擬宇宙,Java3D選擇了有256位的高分辨率座標:
Java3D高分辨率座標由三個256位的定點數組成,分別表示x、y、z。定點被固定在第128位,並且值1.0被定義爲真實的1米。這個座標系統足夠用來描述一個超過幾百萬光年距離的宇宙,也可以定義小於一質子大小(小於一普朗克長度)的對象。
在Java3D中,高分辨率座標僅僅用於將更加傳統的浮點座標系統嵌入更高分辨率的底層系統。用這種方法,可以創造出一個具有任意大小和規模的在視覺上無縫的虛擬宇宙,而且可以不必擔心數字上的精度。(參看表2)
一個256位的定點數還具有能夠直接表示幾乎任何的合理適當的單精度浮點值。
Java3D用有符號的、兩位補碼的256位定點數字來表示高分標率座標。儘管Java3D保持內部高分辨率座標表示的不透明,但用戶用有八個整型變量的數組來表示256位的座標。Java3D把數組中從索引號由0到7分別看作高分辨率座標的從高到底位上的數。第128位上是二進制的小數點,也可以說在索引號爲3和4的整數之間。高分辨率座標的1.0就是1米。
如果是"小"的虛擬宇宙(類似於相對比例的幾百米),在虛擬宇宙對象下的(0.0,0.0,0.0)點建立一個帶有高分辨率座標的Locale作爲根節點就足夠使用了;裝入程序在裝入過程中能自動構建結點,而在高分辨率座標下的點不需要任何外部文件的直接描述。
大一些的虛擬宇宙期待被構建爲有如同計算機文件那樣的層次,這意味着一個根宇宙要包含由外部文件引用的嵌入虛擬宇宙。就這樣,文件引用的對象(用戶指定的Java3D組或高分辨率結點)定義了被讀入現存虛擬宇宙的數據的位置。
表2-1:Java 3D 高分辨率座標
Java 3D 高分辨率座標 | |
2n Meters | Units |
87.29 | Universe (20 billion light years) |
69.68 | Galaxy (100000 light years) |
53.07 | Light year |
43.43 | Solar system diameter |
23.60 | Earth diameter |
10.65 | Mile |
9.97 | Kilometer |
0.00 | Meter |
-19.93 | Micron |
-33.22 | Angstrom |
-115.57 | Planck length |
2.3 場景(Locale)
爲了支持大型虛擬宇宙,Java3D提出了"Locale"的概念。Locale把高分辨率座標作爲起源。把高分辨率座標看作精確的定位,它在高分辨率座標的影響範圍之內使用精度較低的浮點座標指定對象的位置。
一個Locale和與它結合的高分辨率座標一起組成了在虛擬宇宙之下的一個表現層。所有虛擬宇宙包含一個或多個高分辨率Locale。而所有其他的對象都是附加在一個Locale上的。在整個體系中,高分辨率座標扮演的是上層的僅供翻譯的轉換結點。例如,附加到一個特定Locale的所有對象的座標都會與這個Locale位置的高分辨率座標有關。(圖2)
圖2:高分辨率座標指定場景
如果一個虛擬宇宙與傳統的計算機圖像的概念相近,給定的虛擬宇宙可能會變得太大。所以在通常情況下最好把一個場景圖看作是一個高分辨率座標場景的子結點。
構造一個三維場景,程序員必須運行一個Java3D程序。這個Java3D應用程序必須首先創建一個虛擬宇宙對象並且至少把一個Locale對象附加之上。然後,構建出需要的場景圖像,它由一個分支組結點開始並且包括至少一個觀察平臺對象,而場景圖就是附加於這個觀察平臺。當一個包含場景圖的觀察對象被附加於一個虛擬宇宙,Java3D的渲染循環就開始工作。這樣,場景就會和它的觀察對象一起被繪製在畫布上。
2.4 編程實現一個三維世界
這一部分描述怎樣調用VirtualUniverse、Locale和HiResCoord對象的編程接口實現建立一個完整的"三維世界"。注意,這個三維世界有原點、座標,是實現三維顯示程序的第一步。
VirtualUniverse對象有下列構造函數:
1 public VirtualUniverse()
這個函數構造了一個新的VirtualUniverse對象,這個對象可以用來創建Locale對象。
Locale對象有下列構建器:
1public
Locale(VirtualUniverse universe)
2public Locale(VirtualUniverse universe,int x[],int y[], int z[])
3public Locale(VirtualUniverse universe, HiResCoord hiRes)
這三個構建器在指定的VirtualUniverse中創建了一個新的高分辨率Locale對象。其中第一個形成了一個在(0.0,0.0,0.0)的Locale對象。其他的兩個構建器在指定的座標上建立了Locale對象。在第二種形式裏,參數x,y,z是含八個32位整數的數組,這些數組指定了各自的高分辨率座標。
HiResCoord對象定義了一個使用三個高分辨率座標的點,而每一個座標又由三個定點數組成。每個高分辨率座標數共有256位,第128位是二進制小數點。Java3D使用長度爲八的整數數組來定義或提取一個256位的座標值。Java3D用數組內的第一個整數來表示高32位,最後一個整數來表示低32位。
HiResCoord 對象有以下的構建函數:
1 public HiResCoord(int x[],int y[],int z[])
2 public HiResCoord(HiResCoord hc)
3 public HiResCoord()
第一個構造函數從輸入的三個長度爲八的整數數組生成高分辨率座標。整數數組定義了與其同名座標對象的值。第二個構造函數通過複製另外一個座標創建一個新的座標。第三個構造函數創建了一個值爲(0.0,0.0,0.0)的座標。
所有Java3D程序都會首先建立VirtualUniverse和Locale對象,也就是說都會包含表3所示的代碼。爲了方便使用,Java3D爲最原始的VirtualUniverse創建了幾個子類:SimpleUniverse 、ConfiguredUniverse,這些子類保證了可以將三維圖像輕易的在通過Canvas3D的對象在Applet或Frame中顯示。其中最常用到的是SimpleUnivese對象,這個類位於包com.sun.j3d.utils.universe中。
1 u=new SimpleUniverse(v,viewer);
2 u.getViewingPlatform();
3 ViewingPlatform viewingPlatform= u.getViewingPlatform();
Java3D的觀察模式通過完全分離虛擬和現實世界來實現這種多功能性。這種模式區分了以下兩種情況:
一個應用程序通過控制觀察平臺的位置和方向在虛擬宇宙中對一個觀察臺對象(ViewPlatform)定位、定向和設定比例尺;
渲染器使用已知位置和方向計算出要使用的觀察對象,對終端用戶物理環境的描述確定用戶在物理環境中的位置和方向。
3.1 爲什麼使用一個新的模式
在底層的編程接口中可以找到基於照相機的觀察模式,開發者通過它可以控制所有渲染圖的參數。它可以應付處理常規的應用程序,但是處理有更廣闊的適應性的系統的時候就顯得力不從心,這些系統包括:把整個世界作爲一個單元裝入和顯示的觀察器或瀏覽器、可供終端用戶觀察、操縱、顯示、甚至與虛擬世界交互的系統。
基於照相機的觀察模式仿效在虛擬世界中放置一個照相機而不是一個人。開發者必須持續重新配置一個照相機來模擬"在虛擬世界中有一個人"。
Java3D觀察模式直接和跟蹤攝像頭結合。在有攝像頭的情況下,用戶會有好像他們是真實的存在在那個虛擬世界的錯覺,而開發者可以不做任何附加的工作就可以爲用戶帶來這種效果。
在沒有攝像頭並且只是用來表現一個單一的標準顯示的情況下,Java3D觀察模式表現得更像傳統的基於照相機的觀察模式,只是加上了能夠產生立體透視圖的功能。
在一個需要由物理環境規定一些觀察參數的系統中,讓應用程序來控制所有的觀察參數並不合理。
例子就是:一個帶有攝像頭的顯示設備可以用其光系統直接決定應用程序中的觀察領域。不同的設備有不同的光系統,程序開發者硬綁定這樣的參數或允許終端用戶改變這樣的參數都是不合理的。
另外一個例子是:一個可以由用戶當前的頭部位置自動計算出觀察參數的系統。只有一個對世界的說明和一條預先定義的軌跡可能不會嚴密的定義一個終端對象的觀察。對於有攝像頭設備用戶,他們可能會期待在沿着一條固定的路線前進的時候能夠看到他們左右兩旁的物體。就好像在一個遊樂場中,遊客乘坐觀光車按照固定的路線參觀遊樂場,但是在這過程中,遊客可以持續轉動他們的頭。
由於依靠終端用戶的具體物理環境,觀察的各個參數,尤其是觀察和投影的基體變化很大。影響觀察和投影基體的因素包括顯示設備的物理尺寸,顯示設備的安裝方法(在用戶的桌面或用戶的頭頂上),計算機是否知道用戶的頭在三維空間的位置,頭頂裝置真實的觀察領域,顯示設備上每平方英寸的像素數,還有其他類似的參數。
Java3D建立的觀察模式完全可以滿足上述所有的需求。
3.2 分離物理和虛擬
Java3D分離了虛擬環境和物理環境:應用程序在虛擬環境中按照一定關係放置對象,而用戶存在在物理環境之中,看計算機顯示器並操縱輸入設備。
Java3D也定義了用戶所在的物理世界和圖像程序所在的虛擬世界之間最基本的通信。這種"物理到虛擬世界"的通信定義了一個單一的公共空間,在這個空間中用戶的動作影響虛擬世界中的對象,而在虛擬世界中的任何活動都會影響最終用戶的觀察。
虛擬世界是虛擬對象存在的通用空間。虛擬世界的座標系統相對於每個Locale對象的高分辨率座標存在,它定義了所有附加於這個Locale的虛擬世界座標原點。包含當前活動的觀察平臺對象的Local定義了用來繪圖的虛擬世界座標。Java3D最後把所有圖像單元的座標轉換到通用的虛擬世界空間中。
物理世界就是指真實的世界。這是真實的用戶存在和移動他(她)的頭和手的空間。這也是使用任何物理追蹤儀可以定義他們的局部座標和幾個標準的座標系統被描述的空間。
物理世界是一個空間,而不是Java3D不同的程序執行實例之間的通用座標系統。所以當兩個不同的計算機在世界上兩個不同的地方同時運行同一個程序的時候,Java3D中沒有直接來描述它們在物理世界座標系統中相對位置的機制。因爲標準問題,當地的跟蹤系統僅僅定義了特定的Java3D應用程序實例的物理座標系統。
3.3 Java3D中用來定義觀察的對象
Java3D通過幾個對象來發布它的觀察模式。特別是View對象和與它相關的組件對象:PhysicalBody對象、PhysicalEnvironment對象、Canvas3D對象、Screen3D對象。圖3描述了View對象的中心角色和組件對象的輔助角色。
觀察有關的對象都在圖3中,它們起的作用如下:
ViewPlatform(觀察平臺):一個view用一個葉子結點來在場景圖爲自己定位。觀察平臺的起始結點指定了它的位置、方向和在虛擬世界中的比例尺。
View(觀察):主要的觀察對象包含了很多觀察的狀態。
Canvas3D:抽象窗口工具箱中畫布對象的3D版本。它描繪了一個可以讓Java3D在上面畫圖像的窗口。它包括了一個對Screen3D對象的引用和描述一個Canvas3D要用到的尺寸、形狀和位置信息。
Screen3D:一個包含描述顯示熒屏物理屬性信息的對象。Java3D把顯示熒屏信息分別放在單獨的對象中,這樣做可以防止在每一個Canvas3D對象中不同的顯示屏幕信息共享一個屏幕。
PhysicalBody:一個包含刻度信息的對象,它描述了用戶的物理身體。
PhysicalEnvironment:一個包含刻度信息的對象,它描述了物理世界。主要的信息描述了環境的六自由度硬件。
圖3:View和它的組件對象以及它們的相互聯繫
這些對象一起描述觀察的幾何體勝於明白的提供觀察或投影基體。Java3D的表現工具用這個信息來構造適合的觀察和投影基體。這些觀察對象的幾何中心爲產生一個觀察提供了更大的彈性,這種彈性需要支持可以選擇的顯示配置。
3.4 ViewPlatform: 在虛擬世界中的位置
一個Viewplatform結點定義了一個座標系統。這樣,在虛擬世界中就有了一個有原點或參考點的參考系。觀察平臺是一個附加在觀察對象的點並且作爲決定描繪工具觀察的基礎。
圖4表示了一個場景圖的一部分,它包括一個觀察平臺結點。直接在觀察平臺之上的結點決定了它在虛擬世界中的位置和方向。應用程序和或行爲通過修改直接在觀察平臺之上任何與TransformGroup結點結合的Tramsform3D對象可以在虛擬世界中任意移動VierPlatform。一個簡單的應用程序可能直接在一個觀察平臺上定義一個TransformGroup結點。
一個虛擬宇宙可能有很多不同的觀察平臺,但是一個特定的View對象只能附加於一個單一的觀察平臺之上。這樣,每個畫在Canvas3D上的圖畫都是從一個單一的觀察平臺開始。
圖4:包含觀察平臺的一部分場景圖
3.5 如何在虛擬世界中移動
應用程序通過修改觀察平臺的上級TransformGroup在虛擬世界中航行。修改一個觀察平臺的位置和方向的應用程序的例子包括:瀏覽器、提供航行控制的閱讀器、做建築預設計的程序、甚至是搜尋和毀壞遊戲。
控制觀察平臺對象能產生很有趣和有用的結果。我們可以定義一個簡單的場景圖,這個程序的目的是在窗口的正中畫了一個對象並且繞自己的中心轉動。
我們不管在中心的對象,而讓ViewPlatform在虛擬世界中繞圈。如果形體結點包括一個地球模型,這個程序可能產生一個類似於繞地球的遠航員觀察對象。
如果在這個世界中加入更多的對象,這個場景圖允許經由行爲結點來瀏覽整個虛擬世界。
圖5:一個由觀察控制的簡單場景圖
應用程序和動作通過TransformGroup的可訪問方法操縱它。這些方法允許應用程序得到和設置組結點的Transform3D對象。Transform3D結點有setTransform和getTransform兩個方法。
3.6 加載於喜歡的地方
一個場景圖可能包括多個觀察平臺對象。如果用戶把一個觀察對象從一個觀察平臺分離,然後把這個觀察對象附加到另外一個不同的觀察平臺上。顯示屏上的圖像現在就要從新的觀察平臺上的觀察點畫圖了。
在Java3D的繪圖機制中,真實的觀察由當前附加觀察平臺的觀察附加策略決定。觀察平臺定義了設置和得到觀察附加策略的方法:
1 publicvoid setViewAttachPolicy(int policy)
2 publicint getViewAttachPolicy()
View.NOMINAL_HEAD:保證終端用戶在物理世界名義上的眼睛位置對應於在虛擬世界中虛擬眼睛的位置。本質上,這個策略告訴Java3D要用同一種方法把虛擬出射點和觀察平臺原點及物理出射點和物理世界的原點相對放置。物理世界中出射點的方向和位置與原點的背離會產生相應的虛擬出射點的方向和位置在虛擬世界中的背離。
View.NOMINAL_FEET:保證終端用戶的虛擬世界中的腳一直接觸虛擬地面,這個策略告訴Java3D要以這種約束計算物理-虛擬世界的通信。爲達到之一目的,Java3D通過移動終端用戶的眼睛位置和物理高度。Java3D用在PhysicalBody對象中的nominalEyeHeightFromGround參數來執行這個計算。
View.NOMINAL_SCREEN:允許應用程序總是擁有一個和"感興趣的點"保持"可觀察"距離的出射點。這個策略也決定了Java3D計算"物理到虛擬世界"通信的方法。這個方法保證程序根據PhysicalBody對象定義nominalEyeOffsetFromNominalScreen參數來設置虛擬出射點與要表現的點之間的距離。
3.7 在三維世界中建立、移動觀察點
形體移動的實現向來都是三維實現的難點和複雜之處,傳統三維技術的實現多是注重模擬三維物體的真實移動。而Java3D除了提供傳統的方案,還可以在一個存在的三維世界中移動一個觀察點,藉助觀察點的移動模擬物體的移動。如同物理所學的切割磁力線發電,轉子和靜子本來就是一對可以互逆的對象,結果都是把動能轉化爲電能。例2的代碼顯示了在Virtual Universe中建立Viewer、ViewPlatForm、和如何通過綁定OrbitBehavior實現移動ViewPlatform。
例2 建立、移動觀察點代碼
2 Canvas3D c=new Canvas3D(null);
3 add("Center", c);
4 Viewer viewer=new Viewer(c);
5 Vector3d viewpoint=new Vector3d(0.0,0.0,2.41);
6 //初始觀察點位置
7Transform3D t=new Transform3D();
8 t.set(viewpoint);
9 ViewingPlatform v=new ViewingPlatform( );
10 v.getViewPlatformTransform().setTransform(t);
11 u = new SimpleUniverse(v,viewer);
12 u.getViewingPlatform();
13 ViewingPlatform viewingPlatform= u.getViewingPlatform();
14 OrbitBehavior orbit=new OrbitBehavior(c, OrbitBehavior.REVERSE_ALL);
15 BoundingSphere bounds=
16 new BoundiBoundingSpherengSphere(new Point3d(0.0,0.0,0.0),100.0);
17 orbit.setSchedulingBounds(bounds);
18 viewingPlatform.setViewPlatformBehavior(orbit);
同是Java平臺保證Java3D可以在Applet中實現;
Applet使Java3D可以輕易的在網頁中顯示;
JSP、Serverlet技術保證將動態網頁技術用於Java3D顯示;
Serverlet本身就是J2EE平臺的核心技術,這使得Java3D可以搭建於J2EE平臺。更可以使用所有J2EE的其他技術:JDBC、EJB、JMS…
4.1 在網頁上顯示3D圖形
Java3D一個最大的特性是可以使用Applet作爲顯示容器,例3和例4的代碼分別顯示瞭如何在Applet中顯示3D圖形和在網頁文件中(HTML)嵌入該Applet。
例3 Applet實現Java3D
2 private SimpleUniverse u=null;
3 public BranchGroup createSceneGraph() {
4 BranchGroup objRoot=new BranchGroup();
5 ….
6 return objRoot;
7 }
8 publicvoid init() {
9 Canvas3D c=new Canvas3D(config);
10 add("Center", c);
11 ….
12 u.addBranchGraph(scene);
13 }
14 ….
15 }
例4 在網頁嵌入顯示3D Applet
2<HEAD>
3<TITLE>Hello, Universe!</TITLE>
4</HEAD>
5<BODY BGCOLOR="#000000">
6<applet align=middle code="HelloUniverse.class" width=256 height=256>
7</applet>
8</BODY>
9</HTML>
通過Jsp和Serverlet,可以使Java3D在網頁中"動"起來。雖然Java3D本身就有三維動畫的功能,但是這裏的"動"指得是賦予了程序編寫人員對Java3D動態的控制能力。改造上面的HelloUniverse,例5 的jsp代碼可以實現控制旋轉的正方體大小的功能。通過每次Random對象生成的隨機數,立方體的大小也是隨即改變,這段程執行的效果,如圖6、7所示。
例5 實現可以動態調整三位物體大小的jsp代碼
1<%@ page contentType="text/html; charset=GBK"%>
2<HTML>
3<HEAD>
4<TITLE>Hello, Universe!</TITLE>
5</HEAD>
6<BODY BGCOLOR="#000000">
7<%int i=300;%>
8<%float j=i*(new java.util.Random()).nextFloat();%>
9<applet align=middle code="HelloUniverse.class" width=<%=j%> height=<%=j%>>
10</applet>
11</BODY>
12</HTML>
圖6 Jsp顯示效果1
圖6 Jsp顯示效果2
4.3 J2EE平臺對Java3D的支持
上面的例子只是通過動態設定Applet大小來控制Java3D的顯示,實際上可應通過更多的方法實現Jsp、Serverlet對Java3D顯示效果的控制,甚至可以將Java3D置於J2EE平臺的顯示層,實現對EJB、JDBC的調用。
實現Java3D利用J2EE平臺資源的方法很多,甚至可以直接在Java3D的實現類中直接調用EJB。但是從J2EE平臺的設計模式出發,把對EJB調用放到Jsp中,而將返回的結果作爲參數傳入實現Java3D的Applet類中是一個更好的模式。具體代碼見例6。
例6 調用EJB作爲Java3D參數代碼
1<%@ page contentType="text/html; charset=GBK"%>
2<%@ pageimport="javax.ejb.*"%>
3<%@ pageimport="java.rmi.*"%>
4<%@ pageimport="javax.rmi.PortableRemoteObject"%>
5<%@ pageimport="javax.naming.*"%>
6<%@ pageimport="java.util.Properties"%>
7<HTML>
8<HEAD>
9<TITLE>Hello, Universe!</TITLE>
10</HEAD>
11<BODY BGCOLOR="#000000">
12<%try{
13 Properties properties=null;
14 Context context=new InitialContext(properties);
15 Object ref= context.lookup("Customer");
16 EJBHome home= (EJBHome)PortableRemoteObject.narrow(ref,CustomerHome.class);
17 CustomerHome home=(CustomerHome)home;
18 Customer customer= home.findByPrimaryKey("1000000");
19 String data= customer.getData();
20 }
21 catch(Exception e){e.printStackTrace();}
22 %>
23<applet align=middle code="HelloUniverse.class" width=200 height=200>
24<param name="Data" value=<%=data%>>
25</applet>
26</BODY>
27</HTML>
上面的代碼首先訪問JNDI名爲"Customer"的EJB,然後將返回值作爲參數傳入實現Java3D的Applet。
Java3D與J2EE是相互支持的關係:Java3D豐富、強化了J2EE的顯示模式,使略顯枯燥的J2EE客戶端光鮮多彩;J2EE平臺爲Java3D提供了支持,功能強大的Server端處理能力爲三維顯示所需的複雜計算和大數據量提供了有力的支持。
我們可以想象下面的兩幅場景:
通訊衛星將全國所有道路、建築信息錄入大型數據庫;EJB實現應用邏輯並將之部署到AppServer上;所有支持JVM的手機、PDA、車載GPS可以通過調用EJB顯示與真實世界一模一樣的周圍環境。
地震局根據實際勘測到的地表等高線信息繪製二維矢量圖,存爲FDX文件;將二維圖像轉爲三維實現的複雜算法放到EJB中實現;Jsp頁面調用EJB後可以在Appet上實現三維GIS的顯示。
有了Java3D和Java,這一切都不只是夢想。