轉(zhuǎn)帖鏈接:http://bbs.zju.edu.cn/cgi-bin/bbs0an?path=/groups/GROUP_1/Graphics_Image/CAD_ImageProcess/dev/DevLib/java3d
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)資料(一)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Wed Mar 31 15:58:48 1999), 轉(zhuǎn)信
PIII、K6-III出來(lái)了,在3D編程語(yǔ)言中,JAVA3D也應(yīng)占有重要的位置。
為此,本人拿出半年多學(xué)習(xí)及應(yīng)用JAVA3D的經(jīng)驗(yàn),借國(guó)內(nèi)主要BBS站點(diǎn),推出JAVA3D編程
指導(dǎo),并給出大量的例子。
一。如何運(yùn)行JAVA3D?
只要在WIN95/98上安裝了JDK1.2(JAVA2),再安裝JAVA3D運(yùn)行環(huán)境,就可以運(yùn)行
JAVA3D,注意,別忘了在autoexec.bat中插入一行:
SET PATH=C:\JDK1.2\BIN
目前我們可以從SUN公司的站點(diǎn)獲得最新的JAVA3D,本人擁有的為:
java3d1_1-win32-opengl-jdk.exe,大小為3197K。
JAVA3D運(yùn)行環(huán)境中附有許多例子,可用來(lái)學(xué)習(xí)JAVA3D,同時(shí)網(wǎng)絡(luò)上還有大量的
JAVA3D學(xué)習(xí)資料,可以用來(lái)學(xué)習(xí)JAVA3D編程。
二。網(wǎng)絡(luò)上的JAVA3D學(xué)習(xí)資料
1.http://www.sun.com/desktop/java3d/collateral/
這里有SUN公司為我們提供的學(xué)習(xí)資料。
2.http://www.sdsc.edu/~nadeau/Courses/VR99/java3d.zip
這是一個(gè)非常好的JAVA3D學(xué)習(xí)資料。(12,058K),里面有許多例子。
大家可以從http://www.sdsc.edu/~nadeau/中得到VRML和JAVA3D的許多資料。
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(二)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Wed Mar 31 16:01:09 1999), 轉(zhuǎn)信
一。JAVA3D的作用:
JAVA3D可用在三維動(dòng)畫、三維游戲、機(jī)械CAD等領(lǐng)域。
1.可以用來(lái)編寫三維形體,但和VRML不同,JAVA3D沒有基本形體,不過我們可以利用
JAVA3D所帶的UTILITY生成一些基本形體如立方體、球、圓錐等,我們也可以直接調(diào)用
一些軟件如ALIAS、LIGHTWARE、3DS MAX生成的形體,也可以直接調(diào)用VRML2.0生成的
形體。
2.可以和VRML一樣,使形體帶有顏色、貼圖。
3.可以產(chǎn)生形體的運(yùn)動(dòng)、變化,動(dòng)態(tài)地改變觀測(cè)點(diǎn)的位置及視角。
4.可以具有交互作用,如點(diǎn)擊形體時(shí)會(huì)使程序發(fā)出一個(gè)信號(hào)從而產(chǎn)生一定的變化。
5.可以充分利用JAVA語(yǔ)言的強(qiáng)大功能,編寫出復(fù)雜的三維應(yīng)用程序。
6.JAVA3D具有VRML所沒有的形體碰撞檢查功能(這也是本人目前中意JAVA3D的原因)。
(作為一個(gè)高級(jí)的三維圖形編程API,JAVA3D給我們帶來(lái)了極大的方便,它的作用
可以說,幾乎包含了VRML2.0所提供的所有功能。)
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(三)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Wed Mar 31 16:02:21 1999), 轉(zhuǎn)信
二。OPENGL、VRML、DIRECT3D、JAVA3D的比較
由于OPENGL的跨平臺(tái)特性,許多人利用OPENGL編寫三維應(yīng)用程序,不過對(duì)于一個(gè)非
計(jì)算專業(yè)的人員來(lái)說,利用OPENGL編寫出復(fù)雜的三維應(yīng)用程序是比較困難的,且不說C
(C++)語(yǔ)言的掌握需要花費(fèi)大量時(shí)間精力,當(dāng)我們需要處理復(fù)雜問題的時(shí)候,我們不得
不自己完成大量非常繁瑣的工作。當(dāng)然,對(duì)于編程高手來(lái)說,OPENGL是他們發(fā)揮才能的
非常好的工具。
VRML2.0(VRML97)自1997年12月正式成為國(guó)際標(biāo)準(zhǔn)之后,在網(wǎng)絡(luò)上得到了廣泛的應(yīng)
用,編寫VRML程序非常方法(VRML語(yǔ)言可以說比BASIC、JAVASCRIPT等語(yǔ)言還要簡(jiǎn)
單),同時(shí)可以編寫三維動(dòng)畫片、三維游戲、用于計(jì)算機(jī)輔助教學(xué),因而其應(yīng)用前景非
常廣闊尤其適合在中國(guó)推廣應(yīng)用。不過由于VRML語(yǔ)言功能目前還不是很強(qiáng)(如目前沒有
形體之間的碰撞檢查功能),與JAVA語(yǔ)言等其它高級(jí)語(yǔ)言的連接較難掌握,因而失去了
一些計(jì)算機(jī)高手的寵愛。但我們認(rèn)為,我們可以讓大學(xué)里的文理科學(xué)生利用VRML編寫多媒
體應(yīng)用程序,讓學(xué)生很快地對(duì)編寫程序感興趣,從而使國(guó)內(nèi)的計(jì)算機(jī)水平得到提高。
DIRECT3D是Microsoft公司推出的三維圖形編程API,它主要應(yīng)用于三維游戲的編程,
目前相關(guān)的學(xué)習(xí)資料難于獲得,由于它一般需要VC等編程工具進(jìn)行編程,需要編程人員
具有較高的C++等高級(jí)語(yǔ)言的編程功底,因而難以普及。
JAVA3D是建立在JAVA2(JAVA1.2)基礎(chǔ)之上的,JAVA語(yǔ)言的簡(jiǎn)單性使JAVA3D的推廣
有了可能。OPENGL和JAVA3D之間的比較可以看成匯編語(yǔ)言與C語(yǔ)言之間的比較,一個(gè)是低
級(jí)的,一個(gè)是高級(jí)的(也許這樣比較不太恰當(dāng))。JAVA3D給我們編寫三維應(yīng)用程序提供
了一個(gè)非常完善的API,它可以幫助我們:
生成簡(jiǎn)單或復(fù)雜的形體(也可以直接調(diào)用現(xiàn)有的三維形體)
使形體具有顏色、透明效果、貼圖。
可以在三維環(huán)境中生成燈光、移動(dòng)燈光。
可以具有行為(Behavior)的處理判斷能力(鍵盤、鼠標(biāo)、定時(shí)等)
可以生成霧、背景、聲音等。
可以使形體變形、移動(dòng)、生成三維動(dòng)畫。
可以編寫非常復(fù)雜的應(yīng)用程序,用于各種領(lǐng)域如VR。
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(四)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Thu Apr 1 21:45:23 1999), 轉(zhuǎn)信
在編寫JAVA3D程序之前,我們需要了解一些概念,完成一些準(zhǔn)備工作。
一. JAVA3D的數(shù)據(jù)結(jié)構(gòu)
JAVA3D實(shí)際上是JAVA語(yǔ)言在三維圖形領(lǐng)域的擴(kuò)展,JAVA3D的編程和JAVA一樣,
是面向?qū)ο蟮木幊獭?
JAVA3D的數(shù)據(jù)結(jié)構(gòu)采用的是Scene Graphs Structure(場(chǎng)景圖),這一靈活
的樹狀結(jié)構(gòu)與顯示列表多少有些相似之處,但運(yùn)用起來(lái)更耐用(More Robust)。
JAVA3D的場(chǎng)景圖是DAG(Directed-acyclic Graph),即具有方向性的不對(duì)稱圖形。
場(chǎng)景圖中有許多線和線的交匯點(diǎn),交匯點(diǎn)稱為節(jié)點(diǎn)(Node),不管什么節(jié)點(diǎn),
它都是JAVA3D類的實(shí)例(Instance of Class),線(Arc)表示實(shí)例之間的關(guān)系。
在JAVA3D的場(chǎng)景圖中,最底層(根部)的節(jié)點(diǎn)是Virtual Universe,每一個(gè)
場(chǎng)景圖只能有一個(gè)Virtual Universe。
在Virtual Universe上面,就是Locale節(jié)點(diǎn),每個(gè)程序可以有一個(gè)或多個(gè)
Locale,但同時(shí)只能有一個(gè)Locale處于顯示狀態(tài),就好象一個(gè)三維世界非常大,
有很多個(gè)景點(diǎn),但我們同時(shí)只能在一個(gè)景點(diǎn)進(jìn)行觀察。當(dāng)然我們可以從一個(gè)景點(diǎn)
跳到另一個(gè)景點(diǎn),不過絕大多數(shù)程序只有一個(gè)Locale。
每一個(gè)Locale上面擁有一個(gè)到多個(gè)BranchGroup節(jié)點(diǎn)。我們知道,要想建立
我們的三維應(yīng)用環(huán)境,我們必須建立所需要的形體(Shape),給出形體的外觀
(Appearance)及幾何信息(Geometry),再把它們擺放在合適的位置,
這些形體及其擺放位置都建立在BranchGroup節(jié)點(diǎn)之上,擺放位置通過另一個(gè)節(jié)點(diǎn)
TransformGroup來(lái)設(shè)定。另外,我們?cè)诎卜藕萌S形體之后,還需要設(shè)定具體的
觀察位置,我們暫時(shí)用View Platform代替,它也是建立在TransformGroup節(jié)點(diǎn)
之上的。
下面我們用一個(gè)示意圖來(lái)說明上面我們介紹的JAVA3D的場(chǎng)景圖概念。
Virtual Universe
|
|----------------------------------|
| |
Locale Locale
|
|
----------------+-----------------
| | | |
| | | |
BG BG BG BG (BG--BranchGroup)
| | | |
| | | | (S---Shape)
S TG TG TG (TG--TransformGroup)
----+--- | | |
| | | | |
A G S S View Platform
| |
| | (A---Appearance)
----+---- ----+---- (G---Geometry)
| | | |
| | | |
A G A G
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(五)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Sun Apr 4 14:15:43 1999), 轉(zhuǎn)信
一. 如何安裝JAVA3D
下載JDK1.2及JAVA3D (目前最新的為1.1.1版本)。
在WIN95/98上安裝,先安裝JDK1.2,再安裝JAVA3D,
將JDK安裝到JDK1.2目錄下。
建立一個(gè)自己的目錄,在自己的目錄中編寫并運(yùn)行程序。
注意,安裝JDK1.2時(shí)別忘了在autoexec.bat中插入一行:
SET PATH=C:\JDK1.2\BIN
JDK1.2的大小為20,041KB(jdk12_win32.exe)。
JAVA3D的大小為3,197KB(java3d1_1-win32-opengl-jdk.exe)
安裝時(shí)可以選擇所有缺省參數(shù)以減收麻煩。
二. 如何編寫JAVA3D源程序
用自己喜愛的文本編輯工具編輯源程序,和其它JAVA程序
一樣,程序后綴為JAVA。
三. 如何運(yùn)行JAVA3D源程序
用JAVAC編譯源程序,生成class文件。根據(jù)文件的類型,
選擇用JAVA或APPLETVIEWER運(yùn)行程序。
JAVA3D程序可以為APPLICATION程序,也可以為APPLET程序,
因而JAVA3D程序也可以擺放在網(wǎng)頁(yè)上,當(dāng)然這時(shí)候我們必須在瀏
覽器上做一些設(shè)置工作(以后再介紹)。
四. 一個(gè)最簡(jiǎn)單的JAVA3D源程序。
下面我們介紹一個(gè)最簡(jiǎn)單的JAVA3D源程序,進(jìn)而介紹JAVA3D
為我們提供的各種功能。
程序是一個(gè)JAVA的APPLET類型的程序,它的作用是顯示一個(gè)
紅色的圓錐,僅此而已。
名為SimpleCone.java。
//SimpleCone.java
import java.applet.Applet;
import java.awt.BorderLayout;
//import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class SimpleCone extends Applet{
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objTrans = new TransformGroup();
objRoot.addChild(objTrans);
Appearance app = new Appearance();
Material material = new Material();
material.setEmissiveColor(new Color3f(1.0f,0.0f,0.0f));
app.setMaterial(material);
Cone cone=new Cone(.5f,1.0f,1,app);
objTrans.addChild(cone);
objRoot.compile();
return objRoot;
}
public SimpleCone() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
// public static void main(String[] args) {
// new MainFrame(new SimpleCone(), 256, 256);
// }
}
//end of Simple.java
在運(yùn)行applet程序時(shí),我們需要編寫一個(gè)HTML文件:
先用javac將JAVA3D源程序編譯成class文件,再用
appletviewer運(yùn)行HTML文件。
雖然程序是applet程序,但我們也可以將其變成
application程序,這時(shí)我們只需將程序頭尾的四個(gè)注釋行
的注釋符號(hào)去掉即可,這時(shí)我們可以用java來(lái)運(yùn)行它:
java SimpleCone
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(六)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Tue Apr 13 19:08:04 1999), 轉(zhuǎn)信
JAVA3D程序也是JAVA程序,因而我們首先必須對(duì)JAVA有所了解,并能
編寫簡(jiǎn)單的JAVA程序,了解JAVA編程的基本概念,關(guān)于JAVA語(yǔ)言的相關(guān)知
識(shí),我們?cè)谶@里就不一一介紹了,國(guó)內(nèi)這方面的書籍非常豐富。
一. SimpleCone 程序分析
1. SimpleCone.java及其對(duì)應(yīng)的VRML程序
上一節(jié)中,我們給出了SimpleCone這個(gè)非常簡(jiǎn)單的JAVA3D程序,下面
我們來(lái)解讀這個(gè)程序,進(jìn)而介紹JAVA3D所提供的API的內(nèi)容。
第三節(jié)中,我們對(duì)JAVA3D的場(chǎng)景圖結(jié)構(gòu)作了一個(gè)簡(jiǎn)單的介紹,從場(chǎng)景圖
我們可以看出,JAVA3D的場(chǎng)景圖和VRML的場(chǎng)景圖非常相似,因而我們可以編
寫類似的VRML程序出來(lái),與JAVA3D程序進(jìn)行比較。
SimpleCone程序只是顯示一個(gè)紅色的圓錐,相類似的VRML程序?yàn)椋?
//SimpleCone.wrl
#VRML V2.0 utf8
Shape{
geometry Cone{ bottomRadius .5 height 1.0}
appearance Appearance{material Material{emissiveColor 1 0 0}}
}
//end of SimpleCone.wrl
可以看到,與JAVA3D程序相比,VRML程序要簡(jiǎn)單的多,并且可以直接在
IE和Netscape瀏覽器上運(yùn)行,而JAVA3D則要復(fù)雜的多。不過幾乎所有的VRML
程序都可以用JAVA3D編寫出來(lái),而稍微復(fù)雜一點(diǎn)的JAVA3D的程序則基本上無(wú)
法用VRML語(yǔ)言完成。因?yàn)閂RML幾乎可以看成是一個(gè)三維計(jì)算機(jī)圖形格式,而
JAVA3D則是一個(gè)高級(jí)計(jì)算機(jī)語(yǔ)言。
在上面的VRML程序中,只定義了一個(gè)三維形體及其材質(zhì),背景、燈光、
位置等均為缺省值。
同樣地,SimpleCone.java程序中,我們也只定義了三維形體及其材質(zhì),
沒有背景、燈光等,處在缺省的位置上(坐標(biāo)系原點(diǎn))。
JAVA3D和VRML一樣,采用的是一個(gè)符合右手螺旋法則的三維坐標(biāo)系。正
X軸向右,正Y軸向上,正Z軸朝外(從計(jì)算機(jī)屏幕指向我們)。
2. JAVA3D(API)中的類
JAVA3D是SUN公司為我們提供的一個(gè)API,里面包含了幾乎所有我們所需
要的編寫JAVA三維多媒體應(yīng)用程序的基本的類及方法。我們?cè)诰幊虝r(shí),只
需調(diào)用所需要的類及方法,就可以快速地編寫出復(fù)雜的三維多媒體應(yīng)用程
序。可以說,我們所做的工作只是學(xué)會(huì)應(yīng)用JAVA3D的各種類(Objects)及方
法。
JAVA3D為我們提供了100多個(gè)存放于javax.media.j3d程序包中的類,它
們被稱為JAVA3D的核心類,除了核心包中的類以外,JAVA3D還提供了一些其
它程序包,其中一個(gè)重要的包是com.sun.j3d.utils包(Utility)。
JAVA3D所提供的Utility并不是JAVA3D編譯環(huán)境的核心組成部分,我們可以
不用它,不過使用它們會(huì)大大提高我們的程序編寫效率。JAVA3D為我們提供的
Utility會(huì)不斷增加,例如有可能增加處理NURBS曲線的Utility。目前,JAVA3D
為我們提供了四組Utility,它們是:
用于調(diào)用其它三維圖形格式如ALIAS圖形格式的content loader
用于構(gòu)造場(chǎng)景圖的scene graph construction aids
用于建立一些基本體如圓錐、球的geometry classes
一些其它方便我們編程的convenience utilities
除了JAVA3D的核心包及Utility包之外,每個(gè)JAVA3D程序還必需用到下面
兩個(gè)包:java.awt和javax.vecmath。java.awt包用來(lái)定義一個(gè)顯示用的窗口,
而javax.vecmath包則是用來(lái)處理調(diào)用程序所需要的定義矢量計(jì)算所用的類,
處理定義三維形體及其位置時(shí),我們需要用到點(diǎn)、矢量、矩陣及其它一些數(shù)學(xué)
對(duì)象,它也是JAVA3D所提供的一個(gè)包,目前它在JAVA3D的編譯環(huán)境中,今后則
可能會(huì)成為JAVA1.2的核心組成部分。
根據(jù)其作用,JAVA3D所提供的類主要有兩種類型:Node、NodeComponent
Node類,它含有Group及Leaf兩個(gè)子類:
Group類 (用于將形體等按一定的組合方式組合在一起),
類似于VRML的組節(jié)點(diǎn)。
Leaf 類 (如Light、Sound、Background、shape3d、
Appearance、Texture及其屬性等,還有
ViewPlatform、Sensor、Behavior、Morph、
Link等),類似與VRML的相應(yīng)節(jié)點(diǎn),是JAVA3D
場(chǎng)景圖的重要組成部分。
NodeComponent類,用于表示Node的屬性,它并不是JAVA3D場(chǎng)景圖
的組成部分,而是被JAVA3D場(chǎng)景圖所引用,如某
一個(gè)顏色可以被多個(gè)形體所引用。
3. SimpleCone.java程序import語(yǔ)句部分的介紹
根據(jù)JAVA3D所提供的類,按照面向?qū)ο蟮木幊谭绞剑覀兛梢跃帉懗鋈S
環(huán)境中所需要的各個(gè)對(duì)象。編寫JAVA3D程序的關(guān)鍵是學(xué)會(huì)應(yīng)用JAVA3D所提供的
各個(gè)類,生成自己所需要的對(duì)象。
下面我們來(lái)看一下SimpleCone.java里的每一個(gè)import語(yǔ)句。
我們知道,java程序中。凡是利用到的外部的類均用import語(yǔ)句調(diào)用,我
們首先介紹一下程序中的import語(yǔ)句。
第一個(gè)import語(yǔ)句表示本程序是Applet程序。
第二個(gè)import語(yǔ)句表示窗口環(huán)境采用BorderLayout管理方式。
第三個(gè)import語(yǔ)句語(yǔ)句在去掉//后就可以使程序既為applet
也為application,為此,使用了JAVA3D所附帶的一個(gè)Utility,這是一個(gè)名
叫Jef Poskanzer的人所編寫的類。
第四個(gè)import語(yǔ)句表示調(diào)用生成Cone的一個(gè)Utility,這是因?yàn)椋琂AVA3D
和VRML不同,VRML有幾個(gè)基本幾何體的節(jié)點(diǎn)語(yǔ)句,但JAVA3D的核心部分一個(gè)
基本體也沒有定義,但JAVA3D所附帶的Utility為我們提供了一些事先編好的
基本體,我們可以調(diào)用這些基本體。
第五個(gè)import語(yǔ)句表示我們調(diào)用一些設(shè)置基本的觀測(cè)位置所用的類,如
SimpleUniverse、Viewer、ViewingPlatform等,利用它們,我們可以很方便
地構(gòu)造JAVA3D場(chǎng)景圖底部的VirtualUniverse、Locale及其上的View分支,進(jìn)
而使精力主要用在建模及復(fù)雜問題的處理上面,當(dāng)然它們也都是JAVA3D所附帶
的Utility。
第六個(gè)import語(yǔ)句表示調(diào)用程序所需要的JAVA3D核心類,因而所有JAVA3D
程序都必須帶有這一語(yǔ)句,只有這樣才能在JDK1.2環(huán)境中編譯執(zhí)行JAVA3D程序。
第七個(gè)import語(yǔ)句表示調(diào)用程序所需要的定義矢量計(jì)算所用的類。
3. SimpleCone.java程序的組成
SimpleCone.java程序主要由三個(gè)部分組成:
createSceneGraph方法的定義
SimpleCone的構(gòu)造函數(shù)
用于生成application應(yīng)用程序的main函數(shù)
4. createSceneGraph方法的定義
我們首先來(lái)看一下createSceneGraph方法的定義部分。通過第三講的
JAVA3D場(chǎng)景圖的簡(jiǎn)單示意圖,我們知道,為了編寫出一個(gè)JAVA3D應(yīng)用程序,
我們必須編寫出一個(gè)擁有三維形體的內(nèi)容分支,即一個(gè)分支組,一個(gè)
BranchGroup。我們將我們所需要的形體及其材質(zhì)定義在里面,由于一般
形體會(huì)擺放在三維空間的某一個(gè)位置,因而我們還需要先在BranchGroup
分支之上建立一個(gè)可用于幾何變換用的TransformGroup,即幾何變換分支
組,再將形體及其材質(zhì)作為TransformGroup的一個(gè)分支給出,當(dāng)然程序中
如果將形體擺放在坐標(biāo)原點(diǎn),也可以不給出一個(gè)TransformGroup,如下面
的SimpleCone1程序運(yùn)行起來(lái)和SimpleCone結(jié)果完全一樣,它沒有一個(gè)
TransformGroup對(duì)象:
//SimpleCone1.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class SimpleCone1 extends Applet{
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Appearance app = new Appearance();
Material material = new Material();
material.setEmissiveColor(new Color3f(1.0f,0.0f,0.0f));
app.setMaterial(material);
Cone cone=new Cone(.5f,1.0f,1,app);
objRoot.addChild(cone);
objRoot.compile();
return objRoot;
}
public SimpleCone1() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new SimpleCone1(), 256, 256);
}
}
//end of SimpleCone1.java
JAVA3D有三種運(yùn)行方式,一種是Immediate Mode,一種是
Retained Mode,一種是Compiled-Retained Mode。
SimpleCone程序中的
objRoot.compile();
表示程序?yàn)镃ompiled-Retained Mode,在這種模式下,JAVA3D對(duì)程序
進(jìn)行了優(yōu)化,程序的運(yùn)行運(yùn)行速度最快。不過在一些場(chǎng)合,如形體在
程序運(yùn)行過程中才生成,則不能Compile形體,這說明優(yōu)化是有條件的。
注意,JAVA3D程序沒有“開始渲染”這一步驟,當(dāng)一個(gè)View被有
效地放入一個(gè)Virtual Universe,JAVA3D運(yùn)行環(huán)境就開始不停地渲染
JAVA3D場(chǎng)景圖中的三維形體,從而使屏幕上顯示出三維圖形。
5. SimpleCone的構(gòu)造函數(shù)
SimpleCone的構(gòu)造函數(shù)的作用為
首先設(shè)置一個(gè)BorderLayout。
生成一個(gè)名為c的Canvas--Canvas3D繼承了JDK1.2中的Canvas類,
從而構(gòu)造了一個(gè)圖形環(huán)境。
將c放入BorderLayout的中心位置。
生成一個(gè)場(chǎng)景圖分支scene,里面定義了形體及其材質(zhì)(紅色)。
借用JAVA3D的一個(gè)Utility,生成了場(chǎng)景圖的Virtual Universe及
Locale、Viewer,和VRML程序有些不同,在缺省情況下,
JAVA3D的觀察點(diǎn)為位于(0 , 0 , 2.41),而VRML的觀察點(diǎn)
位于(0 , 0 , 10),因而形體在VRML中看起來(lái)比較小,
而在JAVA3D中看起來(lái)比較大。我們利用這個(gè)Utility生成的
這個(gè)u使我們不必考慮生成場(chǎng)景圖中的觀測(cè)分支,不過它也
有缺點(diǎn),即我們不能在Virtual Universe中擁有多個(gè)View,
因而也就不能從一個(gè)View跳到另一個(gè)View。
6. 用于生成application應(yīng)用程序的main方法
為了使我們的程序既可以為applet程序,又可以為application
程序,我們可以通過編寫一個(gè)main方法,利用import語(yǔ)句提供的
MainFrame類,生成一個(gè)MainFrame對(duì)象,從而使程序變成為
application程序。MainFrame是JAVA3D為我們提供的一個(gè)非常有用
的Utility。
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(七)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Tue Apr 13 19:10:48 1999), 轉(zhuǎn)信
介紹了一個(gè)簡(jiǎn)單的JAVA3D程序后,我們開始學(xué)習(xí)JAVA3D的編程
技術(shù)。首席我們介紹三維基本形體的生成。
和VRML不同,JAVA3D沒有基本形體類,因而在程序中無(wú)法直接
生成大量應(yīng)用的基本形體,如BOX、CONE、SPHERE等。我們可以通過
復(fù)雜的編程生成這些基本形體,也可以直接調(diào)用JAVA3D為我們提供的
geometry classes,利用它生成程序所需要的BOX、COLORCUBE、CONE、
SPHERE、CYLINDER。下面介紹這些基本體的生成方法。
一. BOX
UTILITY里BOX的構(gòu)造函數(shù)有:
1. Box()
生成一個(gè)各邊尺寸均為2的BOX,要說明的是,BOX、COLORCUBE、
SPHERE的坐標(biāo)原點(diǎn)均在其中心點(diǎn),CONE、CYLINDER的則在其軸
線的中點(diǎn)上。
2. Box(float xdim, float ydim, Appearance ap)
生成一個(gè)給定尺寸、給定外觀屬性的BOX
例:Box(.5f, .6f, .4f, myApp)
3. Box(float xdim, float ydim, float zdim, int primflags,
Appearance ap)
生成一個(gè)有特定說明的BOX,例如:
Box(.4f,.6f,.3f,Primitive.ENABLE_APPEARANCE_MODIFY, ap)
表示程序在運(yùn)行時(shí)可以改變其外觀屬性。
我們可以在程序中使用的primflags種類可以在JAVA3D所附帶提
供的UTILITY里的Primitive.java中獲得。
二. COLORCUBE
UTILITY里COLORCUBE的構(gòu)造函數(shù)有:
1. ColorCube()
生成一個(gè)邊長(zhǎng)均為2的COLORCUBE
2. ColorCube(double scale)
將邊長(zhǎng)均為2的COLORCUBE按比例放大縮小。
三. CONE
UTILITY里CONE的構(gòu)造函數(shù)有:
1. public Cone()
生成一個(gè)底半徑為1,高為2的CONE。
2. Cone (float radius, float height)
3. Cone (float radius, float height, int primflags,
Appearance ap)
4. Cone(float radius, float height, int primflags,
int xdivision, int ydivision, Appearance ap)
這里,xdivision、ydivision可用來(lái)表示圓錐的顯示是高精度
的顯示,或是底精度的顯示,缺省時(shí)的中等精度時(shí)
xdivision = 15; ydivision = 1; 我們可利用這兩個(gè)參數(shù)來(lái)
改變顯示的效果,使顯示圓錐的三角片更多或更少些。
四. SPHERE
UTILITY里SPHERE的構(gòu)造函數(shù)有:
1. Sphere()
生成一個(gè)半徑為1的SPHERE。
2. Sphere (float radius)
3. Sphere (float radius, Appearance ap)
4. Sphere(float radius, int primflags, Appearance ap)
5. Sphere(float radius, int primflags, int divisions)
6. Sphere(float radius, int primflags, int divisions,
Appearance ap)
這里,divisions的作用和圓錐的xdivision、ydivision相似。
五. CYLINDER
UTILITY里CYLINDER的構(gòu)造函數(shù)有:
1. Cylinder()
生成一個(gè)底半徑為1,高為2的CYLINDER。
2. Cylinder (float radius, float height)
3. Cylinder (float radius, float height, Appearance ap)
4. Cylinder (float radius, float height, int primflags,
Appearance ap)
5. Cylinder(float radius, float height, int primflags,
int xdivision, int ydivision, Appearance ap)
有了這些基本體的構(gòu)造函數(shù),我們就可以按SimpleCone.java
程序同樣的方法,編寫出生成BOX、COLORCUBE、CONE、SPHERE、
CYLINDER的JAVA3D程序來(lái)。
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(八)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Tue Apr 13 19:40:39 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列之7---點(diǎn)的生成
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
( 在前面(第6部分)我們介紹了如何編寫JAVA3D三維基本形體的)
( 程序,需要指出的是,我們將前面的SimpleCone.java程序修改為)
( 其它形體時(shí),我們需要同時(shí)修改import語(yǔ)句的類型,或者干脆將 )
( 相應(yīng)的那個(gè)import語(yǔ)句修改成: )
( import com.sun.j3d.utils.geometry.*; )
JAVA3D編程過程中,我們經(jīng)常要編寫一些點(diǎn)、線、面,JAVA3D所提供
的API中有許多這方面的對(duì)象,下面我們開始一一介紹它們的使用方法。
一. 點(diǎn)的生成
我們先用VRML編寫一個(gè)帶有不同顏色的六個(gè)點(diǎn)的程序。
//Point.wrl ----觀測(cè)點(diǎn)在 (0 0 10)
#VRML V2.0 utf8
Shape {
geometry PointSet {
coord Coordinate {
point [.8 .8 .0, -.8, .8 0, .5 0 0,
-.5 0 0, -.8 -.8 0, .8 -.8 0]}
color Color{
color [ .0 .5 1., .5 .0 1, 0 .8 .2,
1 0 .3, 0 1 .3, .3 .8 0 ]}
}}
#end of Point.wrl
由程序可知,VRML程序中的點(diǎn)非常小,且無(wú)法變大。
下面我們改用JAVA3D編寫同樣的程序,不過由于觀測(cè)
點(diǎn)不同,觀測(cè)效果有差異,VRML程序中的點(diǎn)比較集中,JAVA3D
程序中的點(diǎn)比較分散,程序如下:
//Point1.java -----觀測(cè)點(diǎn)在( 0 0 2.41 )
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Point1 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,0.2f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
Shape3D shape = new Shape3D();
PointArray point = new PointArray(6, PointArray.COORDINATES
|PointArray.COLOR_3);
point.setCoordinates(0,vert);
point.setColors(0,color);
shape.setGeometry(point);
objRoot.addChild(shape);
objRoot.compile();
return objRoot;
}
public Point1() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Point1(), 400,400);
}
}
//end of Point1.java
我們來(lái)分析一下上面的Point1.java。
我們知道,編寫JAVA3D程序?qū)嶋H上是編寫一個(gè)特定的場(chǎng)景圖,
給出了場(chǎng)景圖中帶有形體及其屬性的一個(gè)分支(BranchGrou)和
表示觀察位置等數(shù)據(jù)的另一個(gè)分支(View Platform)。一般來(lái)說,
表示觀測(cè)位置的分支可以用JAVA3D的UTILITY來(lái)完成,因而我們可
以看到,在Point1.java中,構(gòu)造函數(shù)Point1和前面介紹的
SimpleCone.java的構(gòu)造函數(shù)SimpleCone內(nèi)容完全一樣。兩個(gè)程序
的不同之處在于形體構(gòu)造及處理分支,即createSceneGraph方法的
定義。
我們來(lái)看一下Point1.java的createScendGraph方法的定義。
在這個(gè)方法里,程序先定義了一個(gè)分支objRoot,然后用數(shù)組
的形式定義了六個(gè)頂點(diǎn)坐標(biāo)vert和六種顏色color,再用PointArray
定義了一組點(diǎn)point,并將頂點(diǎn)坐標(biāo)及顏色賦值給point,由于JAVA3D
中的PointArray點(diǎn)是Shape3D的子類,它不能直接放入一個(gè)BranchGroup,
因而我們還要先定義一個(gè)Shape3D對(duì)象shape,再將point賦予shape,
這樣point就可以放入BranchGroup類型的對(duì)象objRoot中了。
二. PointArray、IndexedPointArray介紹
JAVA3D提供的API中,可用于生成Point的對(duì)象有:
PointArray
IndexedPointArray
1. PointArray
PointArray的構(gòu)造函數(shù)為:
PointArray( int vertexCount, int vertexFormat );
這里,vertexCount表示應(yīng)生成的點(diǎn)的數(shù)目,
vertexFormat表示所需要的頂點(diǎn)的格式。
點(diǎn)、線、面幾何體所需要的頂點(diǎn)的格式有:
COORDINATES 頂點(diǎn)坐標(biāo)數(shù)組
NORMALS 頂點(diǎn)法向數(shù)組
COLOR_3 不帶alpha值的顏色數(shù)組
COLOR_4 帶alpha值的顏色數(shù)組
TEXTURE_COORDINATE_2 二維紋理坐標(biāo)數(shù)組
TEXTURE_COORDINATE_3 三維紋理坐標(biāo)數(shù)組
Point1.java程序用到了COORDINATES和COLOR_3。
2. IndexedPointArray
IndexedPointArray的構(gòu)造函數(shù)為:
IndexedPointArray( int vertexCount, int vertexFormat,
int indexCount );
利用本函數(shù),我們可以從眾多的點(diǎn)中,選擇特定的點(diǎn)來(lái)顯示。
這里,vertexCount表示頂點(diǎn)坐標(biāo)數(shù)組所提供的點(diǎn)的總個(gè)數(shù),
indexCount表示最終應(yīng)生成的點(diǎn)的個(gè)數(shù)。
三. 20像素大小的點(diǎn)的生成
JAVA3D可以生成任意大小的點(diǎn),并且可以使點(diǎn)為方點(diǎn)或圓點(diǎn)。
下面的程序生成了一個(gè)20像素大小的程序。
//Point2.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Point2 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
Shape3D shape = new Shape3D();
PointArray point = new PointArray(6, PointArray.COORDINATES
|PointArray.COLOR_3);
point.setCoordinates(0,vert);
point.setColors(0,color);
PointAttributes pa = new PointAttributes();
pa.setPointSize(20.0f);
pa.setPointAntialiasingEnable(true);
//不加這一行,點(diǎn)的顯示效果為正方形
//加了這一行,點(diǎn)的顯示效果為圓形
Appearance ap = new Appearance();
ap.setPointAttributes(pa);
shape.setGeometry(point);
shape.setAppearance(ap);
objRoot.addChild(shape);
objRoot.compile();
return objRoot;
}
public Point2() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Point2(), 400,400);
}
}
//end of Point2.java
四. IndexedPointArray編寫的點(diǎn)
下面的程序中,我們用IndexedPointArray生成了四個(gè)點(diǎn)。
//Point3.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Point3 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
Shape3D shape = new Shape3D();
int[] index={ 0 , 2 , 3 , 4 };
int VertexCount=4;
IndexedPointArray point = new IndexedPointArray(6,
IndexedPointArray.COORDINATES|
IndexedPointArray.COLOR_3,
VertexCount);
point.setCoordinates(0,vert);
point.setColors(0,color);
point.setCoordinateIndices(0,index);
point.setColorIndices(0,index);
PointAttributes pa = new PointAttributes();
pa.setPointSize(20.0f);
pa.setPointAntialiasingEnable(true);
Appearance ap = new Appearance();
ap.setPointAttributes(pa);
shape.setGeometry(point);
shape.setAppearance(ap);
objRoot.addChild(shape);
objRoot.compile();
return objRoot;
}
public Point3() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Point3(), 400,400);
}
}
//end of Point3.java
通過上面的程序,我們來(lái)看一下IndexedPointArray
的應(yīng)用方法。
在定義一個(gè)point實(shí)例后,我們要給出頂點(diǎn)坐標(biāo)數(shù)組及
對(duì)應(yīng)各個(gè)頂點(diǎn)的顏色數(shù)組,按下標(biāo)給出我們的頂點(diǎn)及顏色
的具體選擇方案。從而得以從眾多的點(diǎn)中,選擇特定的點(diǎn)來(lái)
顯示并給定顏色。通過setPointSize、setPointAntialiasingEnable
的設(shè)定,使顯示的點(diǎn)擁有一定的大小及良好的顯示效果。
---1--- ---0---
---3--- ---2---
---4--- ---5---
程序Point3.java中,我們只選用了六個(gè)點(diǎn)中的0、2、3、4
四個(gè)點(diǎn)。
五. 主程序比較簡(jiǎn)潔的程序Point4.java
前面幾個(gè)程序,所有的內(nèi)容均放置在一個(gè)程序中,這對(duì)于
閱讀程序來(lái)說,增添了一些困難。一般來(lái)說,一個(gè)具體的例子通常
由幾個(gè)JAVA3D程序來(lái)完成,一般是將形體生成部分劃為單獨(dú)的一個(gè)
子程序,下面我們將上面的Point3.java分成兩個(gè)程序:子程序
myShape.java用來(lái)生成點(diǎn),主程序Point4.java完成其它設(shè)置任務(wù)
并調(diào)用myShape.java,我們?cè)O(shè)定兩個(gè)程序均位于同一個(gè)子目錄下。
//pointShape.java
import javax.media.j3d.*;
public class pointShape extends Shape3D {
private float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
public pointShape() {
int[] index={ 0 , 2 , 3 , 4 };
int VertexCount=4;
IndexedPointArray point = new IndexedPointArray(6,
IndexedPointArray.COORDINATES|
IndexedPointArray.COLOR_3,
VertexCount);
point.setCoordinates(0,vert);
point.setColors(0,color);
point.setCoordinateIndices(0,index);
point.setColorIndices(0,index);
PointAttributes pa = new PointAttributes();
pa.setPointSize(20.0f);
pa.setPointAntialiasingEnable(true);
Appearance ap = new Appearance();
ap.setPointAttributes(pa);
this.setGeometry(point);
this.setAppearance(ap);
}
}
//end of pointShape.java
--------------------------------------------
//Point4.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Point4 extends Applet {
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Shape3D shape = new pointShape();
objRoot.addChild(shape);
objRoot.compile();
return objRoot;
}
public Point4() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Point4(), 400,400);
}
}
//end of Point4.java
六. 能夠旋轉(zhuǎn)的點(diǎn)
前面介紹的JAVA3D程序,顯示的內(nèi)容是靜止的,且看不出立體的
效果,為此,我們使程序中的點(diǎn)繞著Y軸旋轉(zhuǎn),這樣就可以看到具有
立體效果的點(diǎn)了,當(dāng)然,其它形體也可以按同樣的方法編程,程序調(diào)
用了上面給出的pointShape.java。
//Point5.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Point5 extends Applet {
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
objRoot.addChild(createObject());
objRoot.compile();
return objRoot;
}
private Group createObject() {
Transform3D t = new Transform3D();
TransformGroup objTrans = new TransformGroup(t);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Shape3D shape = new pointShape();
objTrans.addChild(shape);
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 50.0);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
return objTrans;
}
public Point5() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Point5(), 400,400);
}
}
//end of Point5.java
在Point4.java的objRoot里,放置的是一個(gè)Shape3D對(duì)象,
而在Point5.java的objRoot里,放置的是一個(gè)Group對(duì)象。在
生成對(duì)象的createObject() 方法里,為了使得形體能夠產(chǎn)生
旋轉(zhuǎn)運(yùn)動(dòng),我們首先建立了一個(gè)TransformGroup對(duì)象和一個(gè)
Transform3D對(duì)象,通過Capability參數(shù)的設(shè)置,表示在程序
運(yùn)行時(shí),objTrans能夠進(jìn)行幾何變換,并將形體放入objTrans。
JAVA3D之所以能夠使形體運(yùn)動(dòng),是因?yàn)镴AVA3D擁有類似于
VRML的時(shí)間傳感器節(jié)點(diǎn)的Alpha對(duì)象,和類似于VRML的內(nèi)插器節(jié)
點(diǎn)的各種Interpolator對(duì)象,它們?cè)谟葿oundingSphere等對(duì)象
所設(shè)定的范圍內(nèi)在特定的時(shí)間內(nèi)進(jìn)行幾何坐標(biāo)變化,因而使形
體產(chǎn)生運(yùn)動(dòng)變化的效果。
本程序中,Alpha給出了一個(gè)4秒鐘的循環(huán)變化時(shí)間周期;
RotationInterpolator規(guī)定了形體每4秒鐘繞著Y軸旋轉(zhuǎn)
一周。BoundingSphere表示所有距離坐標(biāo)原點(diǎn)50米之內(nèi)的形體
均可以旋轉(zhuǎn)運(yùn)動(dòng),而在這范圍之外的所有形體均不產(chǎn)生運(yùn)動(dòng)。
和Point5.java相類似的VRML程序如下,VRML里的點(diǎn)不能夠
改變大小:
//Point5.wrl
#VRML V2.0 utf8
DEF T Transform{
children Shape {
geometry PointSet {
coord Coordinate {
point [.8 .8 .0, -.8, .8 0, .5 0 0,
-.5 0 0, -.8 -.8 0, .8 -.8 0]}
color Color{
color [ .0 .5 1., .5 .0 1, 0 .8 .2,
1 0 .3, 0 1 .3, .3 .8 0 ]}
}}}
DEF TS TimeSensor{
cycleInterval 4
loop TRUE}
DEF OI OrientationInterpolator{
key [0 .25 .5 .75 1]
keyValue [0 1 0 1, 0 1 0 1.57, 0 1 0 3.14
0 1 0 4.71 0 1 0 6.28]}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
# end of Point5.wrl
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(九)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Tue Apr 13 19:47:27 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(8)-----直線的生成
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
我們可以利用JAVA3D的一些對(duì)象,生成各種直線。
可以生成直線的對(duì)象有:
1. LineArray
LineArray(int vertexCount, int vertexFormat)
2. LineStripArray
LineStripArray(int vertexCount ,int vertexFormat,
int[] stripVertexCounts )
3. IndexedLineArray
IndexedLineArray(int vertexCount, int vertexFormat,
int indexCount )
4. IndexedLineStripArray
IndexedLineStripArray( int vertexCount, int vertexFormat,
int indexCount, int stripIndexCounts[])
一. 利用LineArray生成直線
LineArray對(duì)象的定義如下:
LineArray(int vertexCount, int vertexFormat)
這里:
vertexCount表示頂點(diǎn)的個(gè)數(shù)(必須為偶數(shù))
vertexFormat表示頂點(diǎn)的格式(第七講有介紹)
由下面的程序我們得知,Line1.java和前面介紹的
Point4.java幾乎完全一樣,lineShape1.java和
pointShape.java也相差不多。運(yùn)行Line1.java我們獲得
了三條直線,由此得知,LineArray的作用是生成多條直線,
頂點(diǎn)坐標(biāo)數(shù)組的每一對(duì)數(shù)據(jù)構(gòu)成一條直線。
在編寫LineArray生成的直線時(shí),要注意,頂點(diǎn)及顏色
的個(gè)數(shù)必須相等且為偶數(shù),此數(shù)目必須賦值于vertexCount,也即
程序中的vertexCount必須為偶數(shù)且不能少于頂點(diǎn)的個(gè)數(shù)。
-------------------------- 第一條
---------------- 第二條
-------------------------- 第三條
我們可以根據(jù)各種不同的情況,生成不同的直線,如
給定寬度的直線、虛線等。相應(yīng)的的方法有:
setLineWidth(float lineWidth)
setLinePattern(int linePattern)
setLineAntialiasingEnable(boolean state)
對(duì)于線型linePattern有以下數(shù)據(jù)可選:
int PATTERN_SOLID
int PATTERN_DASH
int PATTERN_DOT
int PATTERN_DASH_DOT
這些內(nèi)容對(duì)所有種類的直線都有效。
前面我們利用PointArray生成了六個(gè)點(diǎn),這里,我們
將前面的pointShape.java稍微變化一下,則同樣的六個(gè)點(diǎn)生
成了三條直線,所用的兩個(gè)程序?yàn)椋?
//lineShape1.java
import javax.media.j3d.*;
public class lineShape1 extends Shape3D {
private float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
public lineShape1() {
LineArray line = new LineArray(6,
LineArray.COORDINATES|LineArray.COLOR_3);
line.setCoordinates(0,vert);
line.setColors(0,color);
LineAttributes la = new LineAttributes();
la.setLineWidth(5.0f);
la.setLineAntialiasingEnable(true);
Appearance ap = new Appearance();
ap.setLineAttributes(la);
this.setGeometry(line);
this.setAppearance(ap);
}
}
//end of lineShape1.java
------------------------------------
//Line1.java ---using LineArray object
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Line1 extends Applet {
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Shape3D shape = new lineShape1();
objRoot.addChild(shape);
objRoot.compile();
return objRoot;
}
public Line1() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Line1(), 400,400);
}
}
//end of Line1.java
二. 利用LineStripArray生成直線
LineStripArray可用來(lái)生成多條折線段
LineStripArray對(duì)象的定義如下:
LineStripArray(int vertexCount ,int vertexFormat,
int[] stripVertexCounts )
這里:
vertexCount表示頂點(diǎn)的個(gè)數(shù)(必須為偶數(shù))
vertexFormat表示頂點(diǎn)的格式(第七講有介紹)
stripVertexCounts為一數(shù)組,數(shù)組里的每一個(gè)數(shù)值表示
每條折線段所擁有的頂點(diǎn)數(shù)目。
下面我們利用lineShape1.java同樣的頂點(diǎn)坐標(biāo)數(shù)組及
顏色數(shù)組,用LineStripArray對(duì)象生成直線。程序也是兩個(gè):
lineShape2.java、Line2.java,并使生成的直線繞著Y軸旋轉(zhuǎn),
直線線型為虛線,線寬為30個(gè)像素。
//lineShape2.java
import javax.media.j3d.*;
public class lineShape2 extends Shape3D {
int StripCount[] = new int[1];
private float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
public lineShape2() {
StripCount[0] = 6;
LineStripArray line = new LineStripArray(6,
LineStripArray.COORDINATES|
LineStripArray.COLOR_3,StripCount);
line.setCoordinates(0,vert);
line.setColors(0,color);
LineAttributes la = new LineAttributes();
la.setLineWidth(30.0f);
la.setLineAntialiasingEnable(true);
la.setLinePattern(LineAttributes.PATTERN_DASH);
Appearance ap = new Appearance();
ap.setLineAttributes(la);
this.setGeometry(line);
this.setAppearance(ap);
}
}
//end of lineShape2.java
-----------------------------------------
//Line2.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Line2 extends Applet {
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
objRoot.addChild(createObject());
objRoot.compile();
return objRoot;
}
private Group createObject() {
Transform3D t = new Transform3D();
TransformGroup objTrans = new TransformGroup(t);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Shape3D shape = new lineShape2();
objTrans.addChild(shape);
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 50.0);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
return objTrans;
}
public Line2() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Line2(), 400,400);
}
}
//end of Line2.java
由上可知,Line2.java這個(gè)程序和Point5.java幾乎沒有
什么差別,除了類的名字于調(diào)用的外部程序名不同之外,其余
完全相同。
lineShape1.java和lineShape2.java相差不大,
lineShape2.java多了一個(gè)StripCount數(shù)組,它可以用來(lái)生成
多個(gè)折線段,下面的lineShape3.java程序就將Line2.java生成
的一條折線段分成了兩條折線段:0、1、2三個(gè)點(diǎn)構(gòu)成了一個(gè)折
線段,3、4、5構(gòu)成了另一條折線段,每個(gè)折線段的頂點(diǎn)數(shù)目就
構(gòu)成了數(shù)組StripCount,StripCount數(shù)組的大小等于折線段的
數(shù)目。
//lineShape3.java
import javax.media.j3d.*;
public class lineShape3 extends Shape3D {
int StripCount[] = new int[2];
private float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
public lineShape3() {
StripCount[0] = 3;
StripCount[1] = 3;
LineStripArray line = new LineStripArray(6,
LineStripArray.COORDINATES|
LineStripArray.COLOR_3,StripCount);
line.setCoordinates(0,vert);
line.setColors(0,color);
LineAttributes la = new LineAttributes();
la.setLineWidth(30.0f);
la.setLineAntialiasingEnable(true);
la.setLinePattern(LineAttributes.PATTERN_DASH);
Appearance ap = new Appearance();
ap.setLineAttributes(la);
this.setGeometry(line);
this.setAppearance(ap);
}
}
//end of lineShape3.java
將lineShape3.java生成的繞Y軸旋轉(zhuǎn)的形體用VRML
程序表示的結(jié)果為:
#VRML V2.0 utf8
DEF T Transform{
children Shape {
geometry IndexedLineSet {
coord Coordinate {
point [.8 .8 .0, -.8, .8 0, .5 0 0,
-.5 0 0, -.8 -.8 0, .8 -.8 0]}
coordIndex [0 1 2 -1, 3 4 5 ]
# 兩個(gè)折線段
color Color{
color [ .0 .5 1., .5 .0 1, 0 .8 .2,
1 0 .3, 0 1 .3, .3 .8 0 ]}
}}}
DEF TS TimeSensor{
cycleInterval 4
loop TRUE}
DEF OI OrientationInterpolator{
key [0 .25 .5 .75 1]
keyValue [0 1 0 1, 0 1 0 1.57, 0 1 0 3.14
0 1 0 4.71 0 1 0 6.28]}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
#end of lineShape3.wrl
三. 利用IndexedLineArray生成直線
IndexedLineArray對(duì)象的定義為:
IndexedLineArray(int vertexCount, int vertexFormat,
int indexCount )
這里:
vertexCount表示頂點(diǎn)數(shù)組里頂點(diǎn)的個(gè)數(shù)
vertexFormat表示頂點(diǎn)的格式(第七講有介紹)
indexCount表示選用的頂點(diǎn)個(gè)數(shù),如果一個(gè)點(diǎn)用了
幾次,則要把幾次加進(jìn)去
在上一節(jié)里我們介紹了利用IndexedPoint生成點(diǎn)
的程序,和IndexedPoint相類似,我們可以利用
IndexedLineArray生成直線段。
下面的lineShape4.java利用了IndexedLineArray
從六個(gè)點(diǎn)中挑選了3個(gè)點(diǎn),生成了2條直線。
從程序中我們可以看到,下標(biāo)為0的點(diǎn)使用了兩次,
但生成的是兩條線,因而參數(shù)VertexCount應(yīng)為4,即
此處的VertexCount的數(shù)值應(yīng)為直線條數(shù)的兩倍。
//lineShape4.java
import javax.media.j3d.*;
public class lineShape4 extends Shape3D {
int[] index={ 1, 0, 0 , 3, };
int VertexCount=4;
private float vert[] = {
.8f, 0.8f,0.0f,
-0.8f, 0.8f,0.0f,
0.5f, 0.0f,0.0f,
-0.5f, 0.0f,0.0f,
-0.8f,-0.8f,0.0f,
0.8f,-0.8f,0.0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
};
public lineShape4() {
IndexedLineArray line = new IndexedLineArray(6,
IndexedLineArray.COORDINATES|
IndexedLineArray.COLOR_3,VertexCount);
line.setCoordinates(0,vert);
line.setColors(0,color);
line.setCoordinateIndices(0,index);
line.setColorIndices(0,index);
LineAttributes la = new LineAttributes();
la.setLineWidth(30.0f);
la.setLineAntialiasingEnable(true);
la.setLinePattern(LineAttributes.PATTERN_DASH);
Appearance ap = new Appearance();
ap.setLineAttributes(la);
this.setGeometry(line);
this.setAppearance(ap);
}
}
//end of lineShape4.java
將lineShape4.java翻譯成VRML的相應(yīng)程序?yàn)椋?
#VRML V2.0 utf8
DEF T Transform{
children Shape {
geometry IndexedLineSet {
coord Coordinate {
point [.8 .8 .0, -.8, .8 0, .5 0 0,
-.5 0 0, -.8 -.8 0, .8 -.8 0]}
coordIndex [1 0 -1 0 3]
color Color{
color [ .0 .5 1., .5 .0 1, 0 .8 .2,
1 0 .3, 0 1 .3, .3 .8 0 ]}
}}}
DEF TS TimeSensor{
cycleInterval 4
loop TRUE}
DEF OI OrientationInterpolator{
key [0 .25 .5 .75 1]
keyValue [0 1 0 1, 0 1 0 1.57, 0 1 0 3.14
0 1 0 4.71 0 1 0 6.28]}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
四. 利用IndexedLineStripArray生成直線
IndexedLineStripArray對(duì)象的定義如下:
IndexedLineStripArray( int vertexCount, int vertexFormat,
int indexCount, int stripIndexCounts[])
這里:
vertexCount表示頂點(diǎn)數(shù)組里頂點(diǎn)的個(gè)數(shù)
vertexFormat表示頂點(diǎn)的格式(第七講有介紹)
indexCount表示選用的頂點(diǎn)的個(gè)數(shù)
stripIndexCounts為一數(shù)組,數(shù)組里的每一個(gè)數(shù)值表示
每條折線段所擁有的頂點(diǎn)數(shù)目。
下面的程序里,我們給出10個(gè)頂點(diǎn),
--0-- --1--
--2-- --3--
--4-- --5--
--6-- --7--
--8-- --9--
然后我們用IndexedLineStripArray生成三個(gè)折線段,第一個(gè)
折線段為:0 1 3 2,第二個(gè)折線段為3、5、4,第三個(gè)折線段為
6、7、8、6,最后一個(gè)點(diǎn)沒有用到。所有的直線寬度為30像數(shù)。
這時(shí)我們只用了10個(gè)點(diǎn)中的9個(gè)點(diǎn),但有2個(gè)點(diǎn)用了兩次,因而程序
中的vertexCount為11,
程序如下:
//lineShape5.java
import javax.media.j3d.*;
public class lineShape5 extends Shape3D {
int StripCount[] = new int[3];
int[] index={ 0 , 1 , 3 , 2 , 3 , 5 ,
4 , 6 , 7 , 8 , 6 } ;
int vertexCount = 11;
private float vert[] = {
-.3f , .8f , .0f,
.3f , .8f , .0f,
-.3f , .4f , .0f,
.3f , .4f , .0f,
-.3f , .0f , .0f,
.3f , .0f , .0f,
-.3f , -.4f , .0f,
.3f , -.4f , .0f,
-.3f , -.8f , .0f,
.3f , -.8f , .0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f
};
public lineShape5() {
StripCount[0] = 4;
StripCount[1] = 3;
StripCount[2] = 4;
IndexedLineStripArray line = new IndexedLineStripArray(10 ,
IndexedLineStripArray.COORDINATES|
IndexedLineStripArray.COLOR_3, vertexCount , StripCount);
line.setCoordinates(0,vert);
line.setColors(0,color);
line.setCoordinateIndices(0,index);
line.setColorIndices(0,index);
LineAttributes la = new LineAttributes();
la.setLineWidth(30.0f);
la.setLineAntialiasingEnable(true);
la.setLinePattern(LineAttributes.PATTERN_DASH);
Appearance ap = new Appearance();
ap.setLineAttributes(la);
this.setGeometry(line);
this.setAppearance(ap);
}
}
//end of lineShape5.java
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Tue Apr 13 20:00:11 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(9)----- 面的生成(上)
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
一. 生成平面的對(duì)象及其定義
JAVA3D可通過編程顯示出面來(lái),面有兩種:三角形和四邊形,
相應(yīng)的對(duì)象為Triangle和Quad。
JAVA3D用于生成平面的對(duì)象有:
1. TriangleArray
TriangleArray (int vertexCount, int vertexFormat )
2. QuadArray
QuadArray (int vertexCount, int vertexFormat )
3. TriangleStripArray
TriangleStripArray ( int vertexCount , int vertexFormat,
int[] stripVertexCounts )
4. TriangleFanArray
TriangleFanArray ( int vertexCount ,int vetexFormat,
int[] stripVertexCounts )
5. IndexedTriangleArray
IndexedTriangleArray (int vertexCount , int vertexFormat,
int indexCount)
6. IndexedQuadArray
IndexedQuadArray (int vertexCount , int vertexFormat,
int indexCount )
7. IndexedTriangleStripArray
IndexedTriangleStripArray( int vertexCount, int vertexFormat,
int indexCount, int stripIndexCounts[])
8. IndexedTriangleFanArray
IndexedTriangleFanArray ( int vertexCount, int vertexFormat,
int indexCount, int stripIndexCounts[])
二. TriangleArray生成的面
和前面介紹的PointArray、LineArray一樣,面也可以用
TriangleArray來(lái)生成,利用它可以生成三角片面我們先看一下TriangleArray的定義:
TriangleArray (int vertexCount, int vertexFormat )
這里:
vertexCount表示頂點(diǎn)的個(gè)數(shù)(必須為三的倍數(shù))
vertexFormat表示頂點(diǎn)的格式(第七講有介紹)
下面我們看一個(gè)利用TriangleArray的例子,例子里有九個(gè)點(diǎn)。
--1-- --4-- --7--
--0-- --3-- --6--
--2-- --5-- --8--
//triShape1.java
import javax.media.j3d.*;
public class triShape1 extends Shape3D {
private float vert[] = {
-.8f , .0f ,0.0f,
-.4f , .8f ,0.0f,
-.4f , -.8f,0.0f,
-.2f , .0f ,0.0f,
0.2f , .8f ,0.0f,
0.2f , -.8f,0.0f,
0.4f , .0f ,0.0f,
0.8f , .8f ,0.0f,
0.8f , -.8f,0.0f,
};
private float color[] = {
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
1.0f,0.0f,0.3f,
0.0f,1.0f,0.3f,
0.3f,0.8f,0.0f,
0.0f,0.5f,1.0f,
0.5f,0.0f,1.0f,
0.0f,0.8f,2.0f,
};
public triShape1() {
TriangleArray tri = new TriangleArray(9,
TriangleArray.COORDINATES|TriangleArray.COLOR_3);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
this.setGeometry(tri);
}
}
//end of triShape1.java
從程序運(yùn)行結(jié)果可以得知,TriangleArray將一個(gè)頂點(diǎn)數(shù)組的
每三個(gè)數(shù)組合在一個(gè),生成一個(gè)面,因而vertexCount的點(diǎn)數(shù)必須
為三的倍數(shù)。triShape1.java顯示的結(jié)果是三個(gè)三角形構(gòu)成的面。
由于對(duì)每一個(gè)頂點(diǎn)都定義了顏色,因而程序顯示的是色彩變化的
三角形,且只能從正面看到,反面看不到,這和VRML程序生成面
的效果完全一樣。在VRML程序中,為了使一個(gè)面的正反方向都可見,
可以在IndexedFaceSet節(jié)點(diǎn)中將solid字段設(shè)為FALSE。
下面是和triShape1.java相對(duì)應(yīng)的VRML程序,為了使面的正反
都可見,我們將IndexedFaceSet的solid字段設(shè)為FALSE。
#VRML V2.0 utf8
DEF T Transform{
children Shape {
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [ -.8 , .0 ,0.0,
-.4 , .8 ,0.0,
-.4 , -.8,0.0,
-.2 , .0 ,0.0,
0.2 , .8 ,0.0,
0.2 , -.8,0.0,
0.4 , .0 ,0.0,
0.8 , .8 ,0.0,
0.8 , -.8,0.0,]}
coordIndex [0 1 2 -1 3 4 5 -1 6 7 8]
color Color{
color [ 0.0,0.5,1.0,
0.5,0.0,1.0,
0.0,0.8,2.0,
1.0,0.0,0.3,
0.0,1.0,0.3,
0.3,0.8,0.0
0.0,0.5,1.0,
0.5,0.0,1.0,
0.0,0.8,2.0,]}
}}}
DEF TS TimeSensor{
cycleInterval 4
loop TRUE}
DEF OI OrientationInterpolator{
key [0 .25 .5 .75 1]
keyValue [0 1 0 1, 0 1 0 1.57, 0 1 0 3.14
0 1 0 4.71 0 1 0 6.28]}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
如何將triShape1.java顯示的內(nèi)容從色彩變化及單面顯示
變?yōu)槊恳粋€(gè)面只有一種顏色及雙面顯示?
VRML程序中我們可以將IndexedFaceSet節(jié)點(diǎn)的
colorPerVertex設(shè)為FALSE,并提供一個(gè)
colorIndex字段以挑選顏色數(shù)組中的顏色。
在JAVA3D程序中我們有一個(gè)笨辦法處理顏色問題,即將
每一個(gè)面的三個(gè)點(diǎn)的顏色均設(shè)定為相同的數(shù)值,因?yàn)?
TriangleArray對(duì)象沒有
setColorIndices(0,index)
這一方法,故不能從顏色組中選用顏色。
至于雙面顯示問題,我們可以通過設(shè)定PolygonAttributes
對(duì)象的setCullFace(int cullFace)方法來(lái)獲得,cullFace可以為:
CULL_NONE
CULL_FRONT
CULL_BACK
通過選擇其中之一,來(lái)獲得前面、后面及雙面的顯示效果,缺省
值為只顯示前面。
另外,我們還可以通過設(shè)定PolygonAttributes對(duì)象的
setPolygonMode(int polygonMode)方法使面用頂點(diǎn)或端線來(lái)代替。
polygonMode有下列三種選擇:
POLYGON_POINT
POLYGON_LINE
POLYGON_FILL
缺省值為POLYGON_FILL。
triShape2.java顯示的是前后都可以看得見的面,每一個(gè)面
都有唯一的顏色。
//triShape2.java
import javax.media.j3d.*;
public class triShape2 extends Shape3D {
private float vert[] = {
-.8f , .0f ,0.0f,
-.4f , .8f ,0.0f,
-.4f , -.8f,0.0f,
-.2f , .0f ,0.0f,
0.2f , .8f ,0.0f,
0.2f , -.8f,0.0f,
0.4f , .0f ,0.0f,
0.8f , .8f ,0.0f,
0.8f , -.8f,0.0f,
};
private float color[] = {
1.0f,0.0f,0.0f,
1.0f,0.0f,0.0f,
1.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
0.0f,0.0f,1.0f,
};
public triShape2() {
TriangleArray tri = new TriangleArray(9,
TriangleArray.COORDINATES|TriangleArray.COLOR_3);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
//pa.setPolygonMode(PolygonAttributes.POLYGON_LINE);
// 增加這一行會(huì)使面由線代替
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
}
}
三. QuadArray生成的面
QuadArray對(duì)象的定義如下:
QuadArray (int vertexCount, int vertexFormat )
這里,每一個(gè)參數(shù)的含義都和TriangleArray里的一樣。
QuadArray可用來(lái)生成平面,構(gòu)成平面的頂點(diǎn)的數(shù)目必須為
4的倍數(shù)。
下面我們來(lái)看一個(gè)利用QuadArray的例子,例子里有8個(gè)點(diǎn),
程序運(yùn)行后生成了兩個(gè)長(zhǎng)方形面。
//quadShape1.java
import javax.media.j3d.*;
public class quadShape1 extends Shape3D {
private float vert[] = {
-.6f , .8f ,0.0f,
-.6f , -.8f,0.0f,
-0.2f , -.6f,0.0f,
-0.2f , .6f ,0.0f,
0.2f , .8f ,0.0f,
0.6f , .8f, 0.0f,
0.6f , -.8f, 0.0f,
0.2f , -.8f,0.5f,
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
5.0f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
};
public quadShape1() {
QuadArray tri = new QuadArray(8,
QuadArray.COORDINATES|QuadArray.COLOR_3);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
this.setGeometry(tri);
}
}
//end of quadShape1.java
程序的雙面顯示問題及單一顏色問題的處理同上面的
triShape2.java。
編寫QuadArray應(yīng)用程序時(shí),我們要注意幾個(gè)問題。
首先是四點(diǎn)應(yīng)當(dāng)共面,如果不共面,程序仍然可以編譯
運(yùn)行,但顯示的內(nèi)容為兩個(gè)三角面。
其次是四個(gè)點(diǎn)組成的面不應(yīng)有凹點(diǎn),這有點(diǎn)象VRML程序中
的Extrusion、IndexedFaceSet里的情況,當(dāng)然,在VRML程序中
四個(gè)點(diǎn)構(gòu)成的面可以有凹點(diǎn),這時(shí)只需要在相應(yīng)的節(jié)點(diǎn)內(nèi)加上
一個(gè)參數(shù):
convex TRUE
而在JAVA3D程序中,如果QuadArray生成的面有凹點(diǎn)時(shí),
程序的顯示結(jié)果會(huì)不正確,例如,當(dāng)我們將quadShape里的頂點(diǎn)
坐標(biāo)換為:
private float vert[] = {
-.6f , .8f , 0.0f,
-.6f , -.8f , 0.0f,
-0.2f, -.6f , 0.0f,
-0.5f, .0f , 0.0f,
0.2f , .8f , 0.0f,
0.6f , .8f , 0.0f,
0.6f , -.8f , 0.0f,
0.2f , -.8f , 0.5f,
};
時(shí),顯示的結(jié)果不確定,正面時(shí)是一個(gè)形狀,轉(zhuǎn)到反面時(shí)是
另一個(gè)形狀。
最后一個(gè)問題是QuadArray所利用的每四個(gè)點(diǎn),其坐標(biāo)
位置除了要共面、凸點(diǎn),四個(gè)點(diǎn)的旋轉(zhuǎn)方向也要注意,如果
點(diǎn)的旋轉(zhuǎn)方向是逆時(shí)針的話,其正面朝外,反之則朝內(nèi)。當(dāng)
我們將頂點(diǎn)的坐標(biāo)換成下面的數(shù)據(jù)時(shí),我們可以清楚地得出
這一結(jié)論。
private float vert[] = {
-.6f , .8f ,0.0f,
-.6f , -.8f ,0.0f,
-0.2f , -.4f ,0.0f,
-0.2f , .4f ,0.0f,
0.2f , .8f ,0.0f,
0.6f , .8f ,0.0f,
0.6f , -.8f ,0.0f,
0.2f , -.8f ,0.5f,
};
四. TriangleStripArray生成的面
TriangleStripArray對(duì)象的定義為:
TriangleStripArray ( int vertexCount , int vertexFormat,
int[] stripVertexCounts )
利用TriangleStripArray對(duì)象,我們可以生成多組三角片面,
對(duì)于每一組三角片面來(lái)說,它的頭三個(gè)點(diǎn)生成一個(gè)面,從第四個(gè)點(diǎn)
開始,每一個(gè)點(diǎn)都和前兩個(gè)點(diǎn)生成一個(gè)新的面。
下面的程序中,我們利用一組點(diǎn),生成了兩組三角片面。程序
中,頂點(diǎn)數(shù)組的個(gè)數(shù)為11,頭一組用了7個(gè)頂點(diǎn),生成了5個(gè)相連的
三角片面,后一組用了5個(gè)頂點(diǎn),生成了三個(gè)相連的三角片面。
//triShape3.java
import javax.media.j3d.*;
public class triShape3 extends Shape3D {
int StripCount[] = new int[2];
private float vert[] = {
-.6f , .8f , 0.0f,
-.6f , -.8f, 0.2f,
-0.2f , .5f, -.2f,
-0.2f , -.5f , 0.2f,
0.0f , -.5f, -.2f,
0.0f , .5f , .2f,
0.2f , .0f, .0f,
0.2f , .8f , 0.3f,
0.2f , -.8f, -0.3f,
0.6f , .8f, 0.0f,
0.6f , -.8f, 0.5f,
0.8f , 0.0f , .3f
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
5.0f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
};
public triShape3() {
StripCount[0] = 7;
StripCount[1] = 5;
TriangleStripArray tri = new TriangleStripArray(12,
TriangleStripArray.COORDINATES|
TriangleStripArray.COLOR_3 , StripCount);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
this.setGeometry(tri);
}
}
//end of triShape3.java
五. TriangleFanArray生成的面
TriangleFanArray對(duì)象的定義為:
TriangleFanArray ( int vertexCount ,int vetexFormat,
int[] stripVertexCounts )
利用TriangleFanArray對(duì)象,我們可以生成多組三角片面,每組
三角片面占用一定數(shù)量的頂點(diǎn),每個(gè)組在生成三角片面時(shí),頭三個(gè)頂
點(diǎn)構(gòu)成一個(gè)三角片面,其余的頂點(diǎn)和前面的頂點(diǎn)及每組第一個(gè)頂點(diǎn)生成
一個(gè)三角片面。下面的triShape4.java程序中,我們生成了兩組三角
片面,頭5個(gè)點(diǎn)生成了三個(gè)相連的三角片面,后6個(gè)點(diǎn)生成了四個(gè)相連的
三角片面。形狀就像兩把扇子,一大一小。
//triShape4.java
import javax.media.j3d.*;
public class triShape4 extends Shape3D {
int FanCount[] = new int[2];
private float vert[] = {
0.0f , 0.0f , 0.0f,
-0.3f , 0.3f , 0.02f,
-0.1f , 0.4f , -0.02f,
0.1f , 0.4f , 0.02f,
0.3f, 0.3f , -0.02f,
0.0f, -0.8f , 0.0f,
-0.6f, -0.2f, 0.02f,
-0.3f, -0.1f , -0.02f,
.0f, -0.05f, 0.02f,
.3f, -0.1f, -0.02f,
.6f, -0.2f, 0.02f
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
5.0f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
};
public triShape4() {
FanCount[0] = 5;
FanCount[1] = 6;
TriangleFanArray tri = new TriangleFanArray(11,
TriangleFanArray.COORDINATES|
TriangleFanArray.COLOR_3 , FanCount);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
this.setGeometry(tri);
}
}
//end of triShape4.java
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十一)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Tue Apr 13 20:13:18 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(10)----- 面的生成(下)
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
一. IndexedTriangleArray生成的面
IndexedTriangleArray對(duì)象的定義為:
IndexedTriangleArray (int vertexCount , int vertexFormat,
int indexCount)
利用這個(gè)對(duì)象,我們可以從一個(gè)頂點(diǎn)數(shù)組中挑選一些頂點(diǎn)生成自己
所需要的三角片面。程序triShape5.java中,有一個(gè)10個(gè)點(diǎn)的數(shù)組,我們
從這個(gè)數(shù)組中選擇了8個(gè)點(diǎn),生成了三個(gè)面,其中有一個(gè)點(diǎn)用了兩次,如果
所挑選的點(diǎn)都只用一次,則選擇的點(diǎn)的數(shù)目必須為3的倍數(shù)。
另外,在編程時(shí),我們要注意點(diǎn)的旋轉(zhuǎn)順序,逆時(shí)針旋轉(zhuǎn)和順時(shí)針
旋轉(zhuǎn)有時(shí)會(huì)產(chǎn)生不同的效果。
程序中,vertexCount表示頂點(diǎn)數(shù)組頂點(diǎn)的總數(shù),indexCount表示生成
的面的頂點(diǎn)個(gè)數(shù),數(shù)值為面的個(gè)數(shù)的三倍,本例中,生成的面為三個(gè),故
vertexCount為9。
//triShape5.java
import javax.media.j3d.*;
public class triShape5 extends Shape3D {
private float vert[] = {
-.6f , .6f ,.0f ,
-.6f , -.6f, .0f ,
-.3f , .6f ,.0f ,
-.3f , -.6f, .0f ,
-.0f , .6f ,.0f ,
-.0f , -.6f, .0f ,
.3f , .6f ,.0f ,
.3f , -.6f, .0f ,
.6f , .6f ,.0f ,
.6f , -.6f, .0f ,
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
5.0f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
};
public triShape5() {
int[] index={ 0 , 1 , 2 , 4 , 5 , 6 , 6 , 7 , 8 };
int VertexCount=9;
IndexedTriangleArray tri = new IndexedTriangleArray(10,
IndexedTriangleArray.COORDINATES|
IndexedTriangleArray.COLOR_3 , VertexCount);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
tri.setCoordinateIndices(0,index);
tri.setColorIndices(0,index);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
this.setGeometry(tri);
}
}
//end of triShape5.java
二. IndexedQuadArray生成的面
IndexedQuadArray對(duì)象的定義為:
IndexedQuadArray (int vertexCount , int vertexFormat,
int indexCount )
利用這個(gè)對(duì)象,我們可以從一個(gè)頂點(diǎn)數(shù)組中挑選一些頂點(diǎn)生成自己
所需要的四個(gè)點(diǎn)所構(gòu)成的平面。程序quadShape2.java中,有一個(gè)10個(gè)點(diǎn)
的數(shù)組,我們從這個(gè)數(shù)組中選擇了7個(gè)點(diǎn),生成了兩個(gè)面,其中有一個(gè)點(diǎn)
用了兩次,如果所挑選的點(diǎn)都只用一次,則選擇的點(diǎn)的數(shù)目必須為4的倍數(shù)。
這些選中的點(diǎn)構(gòu)成了數(shù)組index。在輸入每一個(gè)頂點(diǎn)的坐標(biāo)及顏色時(shí),我們
用到了下面兩種方法:
setCoordinateIndices(0,index);
setColorIndices(0,index);
程序中,vertexCount表示頂點(diǎn)數(shù)組頂點(diǎn)的總數(shù),indexCount表示生成
的面的頂點(diǎn)個(gè)數(shù),數(shù)值為面的個(gè)數(shù)的4倍,本例中,生成的面為兩個(gè),故
vertexCount為8。
編寫IndexedQuadArray應(yīng)用程序時(shí),我們?nèi)匀灰⒁庀旅鎺讉€(gè)問題。
首先是四點(diǎn)應(yīng)當(dāng)共面,如果不共面,程序仍然可以編譯
運(yùn)行,但顯示的內(nèi)容為兩個(gè)三角面。
其次是四個(gè)點(diǎn)組成的面不應(yīng)有凹點(diǎn),這有點(diǎn)象VRML程序中
的Extrusion、IndexedFaceSet里的情況,當(dāng)然,在VRML程序中
四個(gè)點(diǎn)構(gòu)成的面可以有凹點(diǎn),這時(shí)只需要在相應(yīng)的節(jié)點(diǎn)內(nèi)加上
一個(gè)參數(shù):
convex TRUE
而在JAVA3D程序中,如果QuadArray生成的面有凹點(diǎn)時(shí),
程序的顯示結(jié)果會(huì)不正確。
//quadShape2.java
import javax.media.j3d.*;
public class quadShape2 extends Shape3D {
private float vert[] = {
-.6f , .6f , .0f ,
-.6f , -.6f, .0f ,
-.3f , .6f , .0f ,
-.3f , -.6f, .0f ,
-.0f , .6f , .0f ,
-.0f , -.6f, .0f ,
.3f , .6f , .0f ,
.3f , -.6f, .0f ,
.6f , .6f , .0f ,
.6f , -.6f, .0f ,
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
5.0f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
};
public quadShape2() {
int[] index={ 2 , 1 , 3 , 4 , 4 , 7 , 9 , 6};
int VertexCount=8;
IndexedQuadArray quad = new IndexedQuadArray(10,
IndexedQuadArray.COORDINATES|
IndexedQuadArray.COLOR_3 , VertexCount);
quad.setCoordinates(0,vert);
quad.setColors(0,color);
quad.setCoordinateIndices(0,index);
quad.setColorIndices(0,index);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(quad);
this.setAppearance(ap);
this.setGeometry(quad);
}
}
//end of quadShape2.java
三. IndexedTriangleStripArray生成的面
IndexedTriangleStripArray對(duì)象的定義為:
IndexedTriangleStripArray( int vertexCount, int vertexFormat,
int indexCount, int stripIndexCounts[])
利用IndexedTriangleStripArray對(duì)象,我們可以生成多組三角片面,
對(duì)于每一組三角片面來(lái)說,它的頭三個(gè)點(diǎn)生成一個(gè)面,從第四個(gè)點(diǎn)
開始,每一個(gè)點(diǎn)都和前兩個(gè)點(diǎn)生成一個(gè)新的面。這些點(diǎn)可以通過一個(gè)數(shù)組index
從一個(gè)頂點(diǎn)數(shù)組中任意選取,它和TriangleStripArray的差別在于
TriangleStripArray對(duì)頂點(diǎn)沒有選擇權(quán),而IndexedTriangleStripArray
對(duì)頂點(diǎn)具有選擇權(quán),其它的都一樣。
程序triShape6.java給出了一個(gè)16個(gè)數(shù)構(gòu)成的頂點(diǎn)數(shù)組,從中挑選了
兩組數(shù),每一組都有6個(gè)頂點(diǎn)構(gòu)成并生成了相連的四個(gè)三角片面。
//triShape6.java
import javax.media.j3d.*;
public class triShape6 extends Shape3D {
int StripCount[] = new int[2];
private float vert[] = {
-.6f , .6f , .1f ,
-.6f , .2f , .2f ,
-.6f , -.2f , .1f ,
-.6f , -.6f , .2f ,
-.0f , .6f , -.1f ,
-.0f , .2f , -.2f ,
-.0f , -.2f , -.1f ,
-.0f , -.6f , -.2f ,
.6f , .6f , .1f ,
.6f , .2f , .2f ,
.6f , -.2f , .1f ,
.6f , -.6f , .2f ,
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
5.0f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
};
public triShape6() {
int[] index={ 0 , 1 , 4 , 5 , 8 , 9 , 2 , 3 , 6 , 7 , 10 };
StripCount[0] = 6;
StripCount[1] = 5;
int indexCount=11;
IndexedTriangleStripArray tri = new IndexedTriangleStripArray(12,
IndexedTriangleStripArray.COORDINATES|
IndexedTriangleStripArray.COLOR_3 , indexCount , StripCou
nt);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
tri.setCoordinateIndices(0,index);
tri.setColorIndices(0,index);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
this.setGeometry(tri);
}
}
//end of Shape6.java
四. IndexedTriangleFanArray生成的面
IndexedTriangleFanArray對(duì)象的定義為:
IndexedTriangleFanArray ( int vertexCount, int vertexFormat,
int indexCount, int stripIndexCounts[])
利用這一對(duì)象,我們可以從一組頂點(diǎn)數(shù)組中挑選我們所需要的
頂點(diǎn),生成多組三角片面,每組三角片面占用一定數(shù)量的頂點(diǎn),每個(gè)組
在生成三角片面時(shí),頭三個(gè)頂點(diǎn)構(gòu)成一個(gè)三角片面,其余的頂點(diǎn)和前面
的頂點(diǎn)及每組第一個(gè)頂點(diǎn)生成一個(gè)三角片面。下面的triShape7.java程
序中,我們生成了兩組三角片面,頭5個(gè)點(diǎn)生成了三個(gè)相連的三角片面,
后6個(gè)點(diǎn)生成了四個(gè)相連的三角片面。形狀就像兩把扇子,一大一小。
程序中所用的數(shù)組為20個(gè)點(diǎn)的頂點(diǎn)數(shù)組。
IndexedTriangleFanArray對(duì)象和TriangleFanArray的應(yīng)用方法很相似,
它們之間的不同在于IndexedTriangleFanArray對(duì)象可以從頂點(diǎn)數(shù)組中挑選
自己所需要的頂點(diǎn),而TriangleFanArray對(duì)象沒有挑選權(quán),只能被動(dòng)地使用
頂點(diǎn)數(shù)組中的數(shù)據(jù)。
//triShape7.java
import javax.media.j3d.*;
public class triShape7 extends Shape3D {
int StripCount[] = new int[2];
private float vert[] = {
-.6f , .8f , -.1f ,
-.6f , .4f , -.0f ,
-.6f , .0f , .1f ,
-.6f , -.8f , -.1f ,
-.4f , .8f , .1f ,
-.4f , .4f , .1f ,
-.4f , .0f , -.1f ,
-.4f , -.8f , .1f ,
-.0f , .8f , -.1f ,
-.0f , .4f , -.0f ,
-.0f , .0f , .1f ,
-.0f , -.8f , -.1f ,
.4f , .8f , .1f ,
.4f , .4f , -.05f ,
.4f , .0f , -.1f ,
.4f , -.8f , .1f ,
.6f , .8f , -.1f ,
.6f , .4f , -.0f ,
.6f , .0f , .1f ,
.6f , -.8f , -.1f ,
};
private float color[] = {
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
1.0f,0.8f,0.0f,
0.5f,1.0f,0.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,1.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
0.0f,0.5f,1.0f,
1.0f,0.5f,0.0f,
1.0f,0.0f,0.5f,
0.9f,1.0f,0.0f,
0.5f,0.0f,1.0f,
};
public triShape7() {
int[] index={ 9 , 4 , 8 , 12 , 16 , 11 , 2 , 6 , 10 , 14 , 18};
StripCount[0] = 5;
StripCount[1] = 6;
int indexCount=11;
IndexedTriangleFanArray tri = new IndexedTriangleFanArray(20,
IndexedTriangleFanArray.COORDINATES|
IndexedTriangleFanArray.COLOR_3 , indexCount , StripCount
);
tri.setCoordinates(0,vert);
tri.setColors(0,color);
tri.setCoordinateIndices(0,index);
tri.setColorIndices(0,index);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
Appearance ap = new Appearance();
ap.setPolygonAttributes(pa);
this.setGeometry(tri);
this.setAppearance(ap);
this.setGeometry(tri);
}
}
/end of triShape7.java
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十二)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Fri Apr 16 13:32:38 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(11)---外部復(fù)雜形體的調(diào)用
(Wavefront的OBJ,Lightwave的LWS和LWO,WRL,DWG,3DS)
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
我們可以利用前面介紹的方法生成我們所需要的基本形體,
生成點(diǎn)、線、平面。但有的時(shí)候,我們需要用到其它格式的三
維形體,如VRML2.0格式的圖形文件,AUTOCAD繪出的DWG格式的
三維形體,3DS MAX繪制出的復(fù)雜形體。對(duì)于這些形體,我們可
以非常方便地將其用到JAVA3D程序中去。下面我們介紹一些圖形
格式在JAVA3D中的應(yīng)用方法。
一. Wavefront的OBJ格式的圖形文件的調(diào)用
1. OBJ格式圖形的簡(jiǎn)單調(diào)用
JAVA3D編譯環(huán)境所帶的UTILITY有兩個(gè)LOADER,一個(gè)可用來(lái)
調(diào)用Wavefront軟件的OBJ格式的三維圖形格式文件,一個(gè)可用來(lái)
調(diào)用Lightwave軟件的LWS及LWO格式的三維圖形格式文件。
假設(shè)我們有一個(gè)OBJ格式的文件(JAVA3D附帶有兩個(gè)OBJ,文
件名分別為galleon.obj和p51_mustang.obj,以及調(diào)用它們的一
個(gè)程序ObjLoad.java)。
我們編寫的第一個(gè)程序Obj1.java介紹了OBJ圖形的調(diào)用方法。
程序的便宜方法:
javac Obj1.java
程序的運(yùn)行方法(假設(shè)圖形在同一目錄):
java Obj1 galleon.obj
//Obj1.java
import com.sun.j3d.loaders.objectfile.ObjectFile;
import com.sun.j3d.loaders.ParsingErrorException;
import com.sun.j3d.loaders.IncorrectFormatException;
import com.sun.j3d.loaders.Scene;
import java.io.*;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Obj1 extends Applet {
private String filename = null;
public BranchGroup createSceneGraph(String args[]) {
BranchGroup objRoot = new BranchGroup();
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objRoot.addChild(objTrans);
ObjectFile f = new ObjectFile( );
Scene s = null;
try {
s = f.load(filename);
}
catch (FileNotFoundException e) {
System.err.println(e);
System.exit(1);
}
catch (ParsingErrorException e) {
System.err.println(e);
System.exit(1);
}
catch (IncorrectFormatException e) {
System.err.println(e);
System.exit(1);
}
objTrans.addChild(s.getSceneGroup());
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
objRoot.compile();
return objRoot;
}
public Obj1(String args[]) {
filename = args[0];
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph(args); //與通常的有不同
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Obj1(args), 400,400);
}
}
//end of Obj1.java
程序運(yùn)行后我們發(fā)現(xiàn),顯示的效果不太正確,形體只顯示了
一部分,我們將在Obj2.java將其效果修正一下。
我們來(lái)看程序,為了使JAVA3D能夠調(diào)用Wavefront的OBJ格式
的圖形文件,我們需要用到JAVA3D所附帶的UTILITY。程序的頭
四行import語(yǔ)句就是用來(lái)處nsform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
objRoot.compile();
return objRoot;
}
public Obj3(String args[]) {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Obj3(args), 400,400);
}
}
//end of Obj3.java
--------------------------
//objFile.java
import com.sun.j3d.loaders.objectfile.ObjectFile;
import com.sun.j3d.loaders.ParsingErrorException;
import com.sun.j3d.loaders.IncorrectFormatException;
import com.sun.j3d.loaders.Scene;
import java.io.*;
import javax.media.j3d.*;
public class objFile extends BranchGroup{
private double creaseAngle = 60.0;
public objFile(String filename) {
BranchGroup obj = new BranchGroup( );
int flags = ObjectFile.RESIZE;
ObjectFile f = new ObjectFile(flags,
(float)(creaseAngle * Math.PI / 180.0));
Scene s = null;
try {
s = f.load(filename);
}
catch (FileNotFoundException e) {
System.err.println(e);
System.exit(1);
}
catch (ParsingErrorException e) {
System.err.println(e);
System.exit(1);
}
catch (IncorrectFormatException e) {
System.err.println(e);
System.exit(1);
}
obj.addChild(s.getSceneGroup( ) );
this.addChild(obj);
}
}
//end of objFile.java
4.同時(shí)調(diào)用兩個(gè)形體,兩者單獨(dú)旋轉(zhuǎn)。
前面的程序中,形體只有一個(gè),為此,我們編了一個(gè)
程序,利用它可以調(diào)用兩個(gè)OBJ形體,一左一右,它們分別繞
自身的軸旋轉(zhuǎn),當(dāng)然,形體的生成仍然使用上面的
objFile.java程序。另外,我們還在程序中加了紅色的背景。
//Obj4.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.loaders.Scene;
import com.sun.j3d.loaders.objectfile.ObjectFile;
public class Obj4 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
t3d.setScale(0.3);
objScale.setTransform(t3d);
objRoot.addChild(objScale);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Color3f bgColor = new Color3f(1.05f, 0.00f, 0.0f);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
BranchGroup b1 = new objFile("1.obj");
BranchGroup b2 = new objFile("2.obj");
objScale.addChild(createObject (b1, -1.2f , 0.0f ));
objScale.addChild(createObject (b2, 1.2f , 0.0f ));
objRoot.compile();
return objRoot;
}
private Group createObject (BranchGroup b, float xpos, float ypos ) {
Transform3D t = new Transform3D ( );
t.setTranslation ( new Vector3f ( xpos, ypos, 0.0f ) );
TransformGroup objTrans = new TransformGroup(t);
TransformGroup spin = new TransformGroup();
spin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
spin.addChild(b);
Transform3D yAxis = new Transform3D ( );
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, spin, yAxis,
0.0f, (float) Math.PI*2.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
objTrans.addChild ( spin );
return objTrans ;
}
public Obj4(String args[]) {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Obj4(args), 400,400);
}
}
//end of Obj4.java
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十三)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Fri Apr 16 13:38:41 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(12)---AUTOCAD的DWG、VRML的WRL及3DS MAX圖形的調(diào)用
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
一. VRML2.0(VRML97)圖形文件在JAVA3D中的應(yīng)用簡(jiǎn)介
SUN公司為我們提供了一個(gè)VRML97的LOADER,利用它我們可以
在JAVA3D程序中方便地調(diào)用VRML圖形。不過由于這個(gè)LOADER目前
還不是很完善,因而沒有放入JAVA3D之中,不過隨著它的完善,
最終它會(huì)成為JAVA3D的一個(gè)組成部分,調(diào)用VRML97程序就象調(diào)用
Wavefront的OBJ一樣簡(jiǎn)單。
我們可以從以下的網(wǎng)址下載(VRML97.ZIP)并安裝,下載的網(wǎng)址為:
http://www.vrml.org/WorkingGroups/vrml-java3d/
從這個(gè)網(wǎng)頁(yè)上我們需要下載目前大小為283KB的一個(gè)ZIP文件,
VRML97.ZIP,利用解壓程序?qū)⑵浣獬蒝RML97.JAR,大小目前為310KB,
版本為0.90.2版,利用它可以讓我們?cè)贘AVA3D程序中調(diào)用
VRML97(VRML2.0)圖形。
*********好消息******************
為了使國(guó)內(nèi)的JAVA3D愛好者能夠節(jié)省時(shí)間及開支,本人愿意
向國(guó)內(nèi)的JAVA3D愛好者提供最新的VRML97.JAR,咨詢請(qǐng)發(fā)EMAIL。
收到EMAIL后一分鐘內(nèi)就可將VRML97.JAR發(fā)出。
*********好消息******************
二. VRML97.JAR的安裝
獲得VRML97.JAR后,假設(shè)我們的JDK1.2擺放的位置為目錄JDK1.2,
我們應(yīng)將其放在下面的子目錄中:
C:\jdk1.2\lib
并在WINDOWS的AUTOEXEC.BAT文件中寫入下面一行:
SET CLASSPATH=%CLASSPATH%;C:\JDK1.2\LIB\vrml97.jar
重新啟動(dòng)計(jì)算機(jī),這樣我們就可以利用它了。
當(dāng)然,我們可以將VRML97.JAR放在一個(gè)目錄中,利用下面的方法
將其解開,不過所獲得的全為CLASS文件。
三. VRML97.JAR的應(yīng)用
1. 利用VRML971.JAR調(diào)用一個(gè)VRML文件,使VRML文件中的形體不停地
旋轉(zhuǎn),程序如下。
程序的編譯方法:
javac Vrml1.java
程序的運(yùn)行方法(假設(shè)圖形在同一目錄):
java Vrml1 myShape.wrl
當(dāng)然,如果所調(diào)用的形體非常大或非常小時(shí),需要修改:
t3d.setScale(0.3);
中的數(shù)值。
//Vrml.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.loaders.vrml97.VrmlLoader;
import com.sun.j3d.loaders.Scene;
public class Vrml1 extends Applet {
private String filename = null;
public BranchGroup createSceneGraph(String args[]) {
BranchGroup objRoot = new BranchGroup();
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
t3d.setScale(0.3);
objScale.setTransform(t3d);
objRoot.addChild(objScale);
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objScale.addChild(objTrans);
VrmlLoader loader = new VrmlLoader();
Scene s = null;
try {
s = loader.load(filename);
} catch (Exception e) {
System.err.println(e);
System.exit(1);
}
objTrans.addChild(s.getSceneGroup());
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
objRoot.compile();
return objRoot;
}
public Vrml1(String args[]) {
filename = args[0];
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph(args);
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Vrml1(args), 400,400);
}
}
//end of Vrml.java
可以看出,Vrml1.java和前面介紹的Obj2.java非常相似。
2. 將Vrml.java分解成兩個(gè)程序
上面的程序中,用于處理調(diào)用問題的部分我們可以提取出來(lái),這樣
我們就可以多次重復(fù)使用。
從下面的程序我們可以得知,Vrml2.java和前面介紹的Obj3.java
除了Obj3改為Vrml2,objFile改為vrmlLoad之外,其余什么也沒有改變。
vrmlLoad.java和objFile.java也非常相似。
//Vrml2.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.loaders.Scene;
import com.sun.j3d.loaders.objectfile.ObjectFile;
public class Vrml2 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
t3d.setScale(0.3);
objScale.setTransform(t3d);
objRoot.addChild(objScale);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objScale.addChild(objTrans);
BranchGroup b1 = new vrmlLoad("7.wrl");
objTrans.addChild(b1);
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
objRoot.compile();
return objRoot;
}
public Vrml2(String args[]) {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Vrml2(args), 400,400);
}
}
//end of Vrml2.java
-----------------------------
//vrmlLoad.java
import javax.media.j3d.*;
import java.io.*;
import com.sun.j3d.loaders.vrml97.VrmlLoader;
import com.sun.j3d.loaders.Scene;
public class vrmlLoad extends BranchGroup{
public vrmlLoad(String filename) {
BranchGroup obj = new BranchGroup( );
VrmlLoader loader = new VrmlLoader();
Scene s = null;
try {
s = loader.load(filename);
} catch (Exception e) {
System.err.println(e);
System.exit(1);
}
obj.addChild(s.getSceneGroup( ) );
this.addChild(obj);
}
}
//end of vrmlLoad.java
3. 調(diào)用兩個(gè)VRML文件并使其放在不同的位置處旋轉(zhuǎn)
編寫這個(gè)程序非常簡(jiǎn)單,只需將前面介紹的Obj4.java
稍作修改即可,程序如下:
//Vrml3.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Vrml3 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
t3d.setScale(0.1);
objScale.setTransform(t3d);
objRoot.addChild(objScale);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Color3f bgColor = new Color3f(1.05f, 0.00f, 0.0f);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
BranchGroup b1 = new vrmlLoad("7.wrl");
BranchGroup b2 = new vrmlLoad("8.wrl");
objScale.addChild(createObject (b1, -1.2f , 0.0f ));
objScale.addChild(createObject (b2, 1.2f , 0.0f ));
objRoot.compile();
return objRoot;
}
private Group createObject (BranchGroup b, float xpos, float ypos ) {
Transform3D t = new Transform3D ( );
t.setTranslation ( new Vector3f ( xpos, ypos, 0.0f ) );
TransformGroup objTrans = new TransformGroup(t);
TransformGroup spin = new TransformGroup();
spin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
spin.addChild(b);
Transform3D yAxis = new Transform3D ( );
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, spin, yAxis,
0.0f, (float) Math.PI*2.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
objTrans.addChild ( spin );
return objTrans ;
}
public Vrml3(String args[]) {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Vrml3(args), 400,400);
}
}
//end of Vrml3.java
四. AUTOCAD R14的DWG圖形及3DS MAX圖形在JAVA3D中的應(yīng)用。
在三維圖形生成過程中,國(guó)內(nèi)目前大量使用AUTOCAD及3DS MAX等
軟件。如何將這些軟件生成的三維圖形應(yīng)用到JAVA3D上去呢?
對(duì)于3DS MAX軟件,處理起來(lái)非常方便,因?yàn)?DS MAX可以將其圖形
直接輸出成VRML97格式,因而可以按本講介紹的方法處理。
對(duì)于AUTOCAD R14來(lái)說,目前還不太方便,不知AUTOCAD 2000是否
能直接輸出VRML97圖形格式。本人從歐洲捷克一個(gè)站點(diǎn)拷得一個(gè)文件,
可用來(lái)直接將AUTOCAD R14所繪制的三維圖形轉(zhuǎn)換成VRML97(VRML2.0)
格式,因而AUTOCAD軟件生成的圖形也可以非常方便地應(yīng)用到JAVA3D上面,
為我們編寫JAVA3D的復(fù)雜應(yīng)用程序打下了良好的基礎(chǔ)。此軟件非常好用
(采用ARX技術(shù)編寫)。
**************好消息**************
需要將AUTOCAD R14所生成的圖形轉(zhuǎn)換成VRML2.0的朋友,可
發(fā)一個(gè)EMAIL給我,在收到EMAIL一分鐘之內(nèi),我將把
AUTOCAD ----> VRML的轉(zhuǎn)換文件發(fā)出,大小為206KB。
**************好消息**************
發(fā)信人: cypress (Cypress), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十四)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Sun Apr 18 14:17:51 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(13)---形體的組合及幾何坐標(biāo)變換
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
VRML2.0(VRML97)中,有兩個(gè)用來(lái)組合各形體的組節(jié)點(diǎn):
Transform、Group,其中的Group節(jié)點(diǎn)完全可以用Transform
節(jié)點(diǎn)來(lái)代替。如何在JAVA3D中實(shí)現(xiàn)Transform所提供的幾何變換
功能,是我們掌握J(rèn)AVA3D應(yīng)用編程的基礎(chǔ)。下面我們對(duì)此給以
詳細(xì)的介紹。
我們首先來(lái)看一下VRML97的Transform節(jié)點(diǎn)的定義:
Transform節(jié)點(diǎn)的定義是:
Transform {
eventIn MFNode addChildren
eventIn MFNode removeChildren
exposedField SFVec3f center 0 0 0
exposedField MFNode children []
exposedField SFRotation rotation 0 0 1 0
exposedField SFVec3f scale 1 1 1
exposedField SFRotation scaleOrientation 0 0 1 0
exposedField SFVec3f translation 0 0 0
field SFVec3f bboxCenter 0 0 0
field SFVec3f bboxSize -1 -1 -1
}
由定義我們可以看出,VRML程序中,我們可以通過設(shè)定
translation、rotation、scale來(lái)使形體產(chǎn)生平移、旋轉(zhuǎn)、
比例變換。如VRML2.0交互式三維圖形編程一書所給出的一個(gè)
生成一個(gè)小丑的程序Ex4_03.wrl,里面就對(duì)形體進(jìn)行了平移、
旋轉(zhuǎn)、比例變換。我們先給出Ex4_03.wrl程序(我們對(duì)
書中的程序進(jìn)行了修改,使生成的小丑能夠旋轉(zhuǎn)),再給出
用JAVA3D編寫出來(lái)的Ex4_03.java。
//Ex4_03.wrl
#VRML V2.0 utf8
DEF T Transform{
children[
Transform {
scale 1 1.2 1
children Shape {
appearance Appearance{material Material
{diffuseColor 1 1 0 }}
geometry Sphere{}}}
Transform{
translation .5 .4 .6
scale 1 1 2
children Shape{
appearance Appearance{material Material
{diffuseColor 0 0 1}}
geometry Sphere{radius .2}}}
Transform {
translation -.5 .4 .6
scale 1 1 2
children Shape{
appearance Appearance{material Material
{diffuseColor 0 0 1}}
geometry Sphere {radius .2}}}
Transform{
translation 0 1 0
scale 1.1 .4 1.1
children Shape{
appearance Appearance{material Material
{diffuseColor 1 0 0}}
geometry Cone{}}}
Transform{
translation 1 0 0
scale .2 .4 .2
children Shape{
appearance Appearance{material Material
{diffuseColor 0 1 1}}
geometry Sphere{}}}
Transform{
translation -1 0 0
scale .2 .4 .2
children Shape{
appearance Appearance{material Material
{diffuseColor 0 1 1}}
geometry Sphere{}}}
Transform{
translation 0 0 1
scale .2 .4 .2
rotation 1 0 0 -.5
children Shape{
appearance Appearance{material Material
{diffuseColor 1 0 0}}
geometry Sphere{}}}
Transform{
translation 0 -.5 .9
scale .4 .1 .3
children Shape{
appearance Appearance{material Material
{diffuseColor 1 1 1}}
geometry Sphere{}}}
]}
DEF TS TimeSensor{
cycleInterval 8
loop TRUE}
DEF OI OrientationInterpolator{
key [0 .25 .5 .75 1]
keyValue [0 1 0 0, 0 1 0 1.57, 0 1 0 3.14
0 1 0 4.71 0 1 0 6.28]}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
Background {skyColor 1 1 1}
//end of Ex4_03.wrl
------------------------------
//Ex4_03.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Ex4_03 extends Applet{
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Transform3D t3d = new Transform3D();
t3d.setScale(0.3);
TransformGroup objScale = new TransformGroup();
objScale.setTransform(t3d);
Transform3D temp = new Transform3D();
TransformGroup obj = new TransformGroup();
obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
obj.setTransform(temp);
objScale.addChild(obj);
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, obj, temp,
0.0f, (float) Math.PI*2.0f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
rotator.setSchedulingBounds(bounds);
obj.addChild(rotator);
objRoot.addChild(objScale);
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
Appearance app_red = new Appearance();
Material material1 = new Material();
material1.setDiffuseColor(new Color3f(1.0f,0.0f,0.0f));
app_red.setMaterial(material1);
Appearance app_yellow = new Appearance();
Material material2 = new Material();
material2.setDiffuseColor(new Color3f(1.0f,1.0f,0.0f));
app_yellow.setMaterial(material2);
Appearance app_blue = new Appearance();
Material material3 = new Material();
material3.setDiffuseColor(new Color3f(0.0f,0.0f,1.0f));
app_blue.setMaterial(material3);
Appearance app_cyan = new Appearance();
Material material4 = new Material();
material4.setDiffuseColor(new Color3f(0.0f,1.0f,1.0f));
app_cyan.setMaterial(material4);
Appearance app_white = new Appearance();
Material material5 = new Material();
material5.setDiffuseColor(new Color3f(1.0f,1.0f,1.0f));
app_white.setMaterial(material5);
Cone c = new Cone(1.0f,2.0f,1,app_red);
Primitive s_1 = (Primitive) new Sphere(1.0f,app_yellow);
Primitive s_2 = (Primitive) new Sphere(.2f ,app_blue);
Primitive s_2b = (Primitive) new Sphere(.2f ,app_blue);
Primitive s_3 = (Primitive) new Sphere(1.0f,app_cyan);
Primitive s_3b = (Primitive) new Sphere(1.0f,app_cyan);
Primitive s_4 = (Primitive) new Sphere(1.0f,app_red);
Primitive s_5 = (Primitive) new Sphere(1.0f,app_white);
Transform3D t1 = new Transform3D();
t1.setScale(new Vector3d(1,1.2,1));
TransformGroup objTrans1 = new TransformGroup(t1);
objTrans1.addChild(s_1);
Transform3D t2 = new Transform3D();
t2.setScale(new Vector3d(1,1,2));
t2.setTranslation(new Vector3f(0.5f, 0.4f, 0.6f));
TransformGroup objTrans2 = new TransformGroup(t2);
objTrans2.addChild(s_2);
Transform3D t3 = new Transform3D();
t3.setScale(new Vector3d(1,1,2));
t3.setTranslation(new Vector3f(-0.5f, 0.4f, 0.6f));
TransformGroup objTrans3 = new TransformGroup(t3);
objTrans3.addChild(s_2b);
Transform3D t4 = new Transform3D();
t4.setScale(new Vector3d(1.1,0.4,1.1));
t4.setTranslation(new Vector3f(0.0f, 1.0f, 0.0f));
TransformGroup objTrans4 = new TransformGroup(t4);
objTrans4.addChild(c);
Transform3D t5 = new Transform3D();
t5.setScale(new Vector3d(0.2, 0.4, 0.2));
t5.setTranslation(new Vector3f(1.0f, 0.0f, 0.0f));
TransformGroup objTrans5 = new TransformGroup(t5);
objTrans5.addChild(s_3);
Transform3D t6 = new Transform3D();
t6.setScale(new Vector3d(0.2, 0.4, 0.2));
t6.setTranslation(new Vector3f(-1.0f, 0.0f, 0.0f));
TransformGroup objTrans6 = new TransformGroup(t6);
objTrans6.addChild(s_3b);
Transform3D t7 = new Transform3D();
t7.setScale(new Vector3d(0.2, 0.4, 0.2));
t7.setTranslation(new Vector3f(0.0f, 0.0f, 1.0f));
TransformGroup objTrans7 = new TransformGroup(t7);
objTrans7.addChild(s_4);
Transform3D t8 = new Transform3D();
t8.setScale(new Vector3d(0.4, 0.1, 0.3));
t8.setTranslation(new Vector3f(0.0f, -0.5f, 0.9f));
TransformGroup objTrans8 = new TransformGroup(t8);
objTrans8.addChild(s_5);
Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
obj.addChild(objTrans1);
obj.addChild(objTrans2);
obj.addChild(objTrans3);
obj.addChild(objTrans4);
obj.addChild(objTrans5);
obj.addChild(objTrans6);
obj.addChild(objTrans7);
obj.addChild(objTrans8);
objRoot.compile();
return objRoot;
}
public Ex4_03() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Ex4_03(), 640, 480);
}
}
//end of Ex4_03.java
我們來(lái)仔細(xì)研究JAVA3D所提供的形體幾何變換功能。
前面我們主要介紹形體生成的方法,其中,編寫自己的形體
用到的是Shape3D對(duì)象,VRML97與之對(duì)應(yīng)的是Shape節(jié)點(diǎn)。
同樣,JAVA3D對(duì)應(yīng)于VRML97的Transform節(jié)點(diǎn)的對(duì)象是Transform3D。
VRML97編程中,形體的平移可以通過Transform節(jié)點(diǎn)的
translation字段來(lái)設(shè)置;JAVA3D編程時(shí),形體的平移可以通過
Transform3D的setTranslation方法完成。
VRML97編程中,形體的旋轉(zhuǎn)可以通過Transform節(jié)點(diǎn)的
rotation字段來(lái)設(shè)置;JAVA3D編程時(shí),形體的旋轉(zhuǎn)可以通過
Transform3D的setRotation方法完成。
VRML97編程中,形體的比例變化可以通過Transform節(jié)點(diǎn)的
scale字段來(lái)設(shè)置;JAVA3D編程時(shí),形體的比例變化可以通過
Transform3D的setScale方法完成,其中,當(dāng)擴(kuò)弧里只有一個(gè)雙
精度數(shù)時(shí),setScale對(duì)所有的方向均采用同一個(gè)比例,而當(dāng)里面
有三個(gè)雙精度數(shù)時(shí),setScale對(duì)不同的方向可以采用不同的比例,
雙精度數(shù)后面不加符號(hào),而單精度浮點(diǎn)數(shù)后面要加一個(gè)f。
我們來(lái)看一下程序的主要內(nèi)容:
程序一開始就定義了一個(gè)BranchGroup,后面所有的生成的內(nèi)容
如形體、形體的變換、背景、燈光都放入其中。
為了使我們生成的圖形有合適的大小,我們定義了一個(gè)
TransformGroup對(duì)象objScale,通過一個(gè)t3d使其按比例縮小,這
相當(dāng)于我們將視野往后移動(dòng)。
為了使我們生成的小丑能夠旋轉(zhuǎn),我們定義一個(gè)TransformGroup
類型的obj,這相當(dāng)于定義了一個(gè)小丑所在的局部坐標(biāo)系,設(shè)定此
坐標(biāo)系可以旋轉(zhuǎn),選轉(zhuǎn)方式由一個(gè)Transform3D類型的temp來(lái)確定,
定義obj為objScale的一個(gè)子節(jié)點(diǎn)。
通過定義rotationAlpha、rotator地定義使得obj能夠產(chǎn)生旋轉(zhuǎn)。
它們的作用類似于VRML的時(shí)間傳感器及方向內(nèi)插器。
接下來(lái)我們?cè)诳臻g中定義了一個(gè)定向光、各種材質(zhì)、形體,并
將燈光、具有一定材質(zhì)的形體放入objRoot、obj之中,最后我們
還定義了一個(gè)背景光。
通過這個(gè)程序的編寫,我們掌握了JAVA3D生成復(fù)雜形體的最基本
概念,即如何進(jìn)行形體的幾何坐標(biāo)變換。掌握了形體幾何坐標(biāo)變換
方法,我們就具有了編寫JAVA3D復(fù)雜應(yīng)用程序的能力。
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十五)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Sun Apr 25 22:16:51 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(14)---初始觀察位置的設(shè)定
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
一. 初始觀察位置的給定
前面我們介紹的JAVA3D程序,在沒有進(jìn)行比例變換前,觀察點(diǎn)位于
(0 , 0 , 2.41 ),這是由
setLayout(new BorderLayout());
Canvas3D c = new MyCanvas3D(null);
add("Center",c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNorminalViewingTransform();
多個(gè)語(yǔ)句確定的,在前面的第5講已經(jīng)對(duì)其作了簡(jiǎn)單介紹,大多數(shù)程序
都利用這些語(yǔ)句定義場(chǎng)景圖中的一個(gè)觀察分支。
我們可以將JAVA3D所提供的java3d-utils-src.jar按照下面
的方式解開:
jar xvf java3d-utils-src.jar
就可以獲得JAVA3D所有UTILITY的源程序,我們可以從其中的
SimpleUniverse.java、ViewingPlatform.java
程序了解JAVA3D是如何進(jìn)行觀察點(diǎn)初始位置的設(shè)置的。
語(yǔ)句中的u定義了一個(gè)SimpleUniverse類型的對(duì)象實(shí)例。
getViewingPlatform()方法定義在ViewingPlatform.java中,
利用它可以獲得程序所需要的觀察位置,而此方法又通過
ViewingPlatform.java中的setNorminalViewingTransform()
來(lái)做進(jìn)一步的設(shè)置。
在沒有用到setNorminalViewingTransform()之前,
ViewingPlatform() 給出的缺省觀察位置為坐標(biāo)原點(diǎn)(0,0,0),
而當(dāng)我們用到setNorminalViewingTransform()時(shí),由
viewDistance我們得知這時(shí)的觀察點(diǎn)的Z坐標(biāo)移到了
1/tan(math.PI/8),也即2.41。
**************這時(shí)的觀察視角為90°****************
如果要使程序的觀察點(diǎn)為一個(gè)可以很方便改動(dòng)的點(diǎn),我們就
需要將程序改動(dòng),下面是我們將前面介紹的第4講的程序
SimpleCone.java,修改獲得的新程序NewCone.java,兩者的差別
在于,SimpleCone.java的觀察點(diǎn)位于(0,0,2.41),
NewCone.java的觀察點(diǎn)坐標(biāo)位于(0, 0, 10)。我們可以根據(jù)需要
設(shè)定初始的觀察點(diǎn)的位置,這時(shí)只需要方便地將(0,0, 10)改為
我們所需要的任何數(shù)值。初始觀察位置改動(dòng)同樣用到了
SimpleUniverse對(duì)象,只是將對(duì)象的觀察點(diǎn)坐標(biāo)變量作了修改。
//NewCone.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Cone;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class NewCone extends Applet{
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objTrans = new TransformGroup();
objRoot.addChild(objTrans);
Appearance app = new Appearance();
Material material = new Material();
material.setEmissiveColor(new Color3f(1.0f,0.0f,0.0f));
app.setMaterial(material);
Cone cone=new Cone(.5f,1.0f,1,app);
objTrans.addChild(cone);
objRoot.compile();
return objRoot;
}
public NewCone() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
ViewPlatform viewPlatform;
Viewer viewer = new Viewer(c);
Vector3d viewpoint = new Vector3d(0.0, 0.0, 10.0);
//初始觀察點(diǎn)位置
Transform3D t = new Transform3D();
t.set(viewpoint);
ViewingPlatform v = new ViewingPlatform( );
v.getViewPlatformTransform().setTransform(t);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse( v, viewer);
u.getViewingPlatform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new NewCone(), 256, 256);
}
}
//end of NewCone.java
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十六)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Mon Apr 26 11:57:22 1999), 轉(zhuǎn)信
【 以下文字轉(zhuǎn)載自 screamer 的信箱 】
【 原文由 screamer 所發(fā)表 】
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
1997年底正式成為國(guó)際標(biāo)準(zhǔn)的VRML2.0是我們編寫簡(jiǎn)單
三維應(yīng)用程序的一個(gè)非常合適的計(jì)算機(jī)語(yǔ)言,利用它,我們可以
非常方便地編寫三維動(dòng)畫、交互式的三維游戲,當(dāng)然,只能
是一些較為簡(jiǎn)單的三維動(dòng)畫及交互式三維游戲。而利用JAVA3D
則可以編寫出較為復(fù)雜的三維動(dòng)畫及交互式三維游戲。
前面我們介紹了JAVA3D的形體生成等方面的知識(shí),JAVA3D
三維應(yīng)用程序最吸引人之處是它可以用來(lái)制作三維動(dòng)畫、三維
游戲等。為了掌握J(rèn)AVA3D三維動(dòng)畫、三維游戲的編程,我們首先
要掌握三維形體在空間的運(yùn)動(dòng)控制。
VRML語(yǔ)言有6個(gè)內(nèi)插器節(jié)點(diǎn)和7個(gè)傳感器節(jié)點(diǎn),同樣地,在
JAVA3D中,也有和VRML內(nèi)插器節(jié)點(diǎn)類似的Interpolator對(duì)象,它
們和另一個(gè)Alpha類結(jié)合在一起,可以編寫出各種類型的三維動(dòng)畫
程序。
下面我們就介紹這些對(duì)象及其應(yīng)用方法。
一. Alpha類
從VRML的各個(gè)內(nèi)插器節(jié)點(diǎn)的定義來(lái)看,我們可以看到,每一個(gè)
內(nèi)插器節(jié)點(diǎn)都有一個(gè)key字段和一個(gè)keyValue字段。key字段定義
一個(gè)數(shù)組,數(shù)值從0到1。
所有的內(nèi)插器節(jié)點(diǎn)在使用時(shí)都需要與TimeSensor(時(shí)間傳感器)
配合使用。TimeSensor把給定的時(shí)間周期歸一化,雖然時(shí)間的周期
cycleInterval 有給定的秒數(shù),但計(jì)算機(jī)內(nèi)部將其處理成從0.0到
1.0,即起始時(shí)間為0.0,終止時(shí)間為1.0,假如一個(gè)時(shí)間周期為
20(單位均為秒),則第6秒的歸一化結(jié)果是0.3,第10秒的歸一化
結(jié)果是0.5,第20秒的歸一化結(jié)果是1.0。
JAVA3D里的Alpha類和VRML的key字段的功能類似,它也是用于
輸出歸一化的時(shí)間,不過它能夠處理更加復(fù)雜的時(shí)間安排問題。
Alpha可以輸出從0到1之間的數(shù)值給特定的內(nèi)插對(duì)象,當(dāng)Alpha
輸出的數(shù)值為0時(shí),對(duì)應(yīng)的特定內(nèi)插對(duì)象的值為最小;當(dāng)Alpha輸出
的數(shù)值為1時(shí),對(duì)應(yīng)的特定內(nèi)插對(duì)象的值為最大;當(dāng)Alpha輸出的數(shù)
值為0到1之間的數(shù)值時(shí),對(duì)應(yīng)的特定內(nèi)插對(duì)象生成和Alpha成相同
比例的數(shù)值。假設(shè)某一時(shí)刻Alpha輸出的數(shù)值為0.2,則對(duì)應(yīng)的特定
內(nèi)插對(duì)象的當(dāng)前值為最小值加上最大最小值之差乘以0.2。
(當(dāng)前值-最小值)/(最大值-最小值)=0.2
JAVA3D里的各種Interpolator對(duì)象和VRML的內(nèi)插節(jié)點(diǎn)的作用
比較類似,可用來(lái)旋轉(zhuǎn)形體、移動(dòng)形體的坐標(biāo)、變化形體的顏色等。
假設(shè)我們要讓一個(gè)形體在規(guī)定的時(shí)間內(nèi)按照指定的方式運(yùn)動(dòng),
我們首先要給出時(shí)間段的大小,還要指出時(shí)間是否要循環(huán)。這些內(nèi)容
都是由Alpha類來(lái)完成的。
Alpha類的構(gòu)造函數(shù)定義如下:
public Alpha(int loopCount, int mode, long triggerTime,
long phaseDelayDuration,
long increasingAlphaDuration,
long increasingAlphaRampDuration,
long alphaAtOneDuration,
long decreasingAlphaDuration,
long decreasingAlphaRampDuration,
long alphaAtZeroDuration)
我們?cè)谇懊嬉讯啻斡玫紸lpha類,基本上我們用它及一個(gè)旋轉(zhuǎn)內(nèi)
插器RotationInterpolator來(lái)使形體繞著其所在的局部坐標(biāo)系不停
地旋轉(zhuǎn)。下面是我們眼熟的語(yǔ)句,語(yǔ)句的作用是讓形體以4秒為一周
期,不停地繞著某一個(gè)軸旋轉(zhuǎn)(Y軸):
Alpha rotationAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE,
0, 0,
4000, 0, 0,
0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, obj, temp,
0.0f, (float) Math.PI*2.0f);
從中我們可以看到,Alpha構(gòu)造函數(shù)中:
loopCount表示循環(huán)的次數(shù),例如如果我們將前面介紹的Ex4_03.java
的loopCount設(shè)為10,則小丑會(huì)旋轉(zhuǎn)10周,然后停止。不過在一些運(yùn)行速度
慢的計(jì)算機(jī)上會(huì)出現(xiàn)少幾次的情況,如作者本人使用的一臺(tái)機(jī)器是
Pentium 586/100的計(jì)算機(jī),當(dāng)loopCount為10時(shí),只看到小丑旋轉(zhuǎn)了7次,
因?yàn)槌绦驈拈_始運(yùn)行到出現(xiàn)畫面,需要一段時(shí)間。loopCount為-1時(shí)表示
無(wú)限循環(huán)。我們可以利用下面兩個(gè)方法設(shè)置或獲得loopCount:
public void setLoopCount(int loopCount)
public int getLoopCount()
mode表示Alpha每一周期的運(yùn)行方式,一共有三種:INCREASING_ENABLE、
DECREASING_ENABLE、INCREASING_ENABLE|DECREASING_ENABLE。第一種
方式表示Alpha的數(shù)值從0到1,相對(duì)應(yīng)的內(nèi)插對(duì)象的數(shù)值從最小到
最大;第二種方式表示Alpah的數(shù)值從1到0,相對(duì)應(yīng)的內(nèi)插對(duì)象的數(shù)值
從最大到最小;第三種方式表示Alpah的數(shù)值從0到1,然后從1到0,
相對(duì)應(yīng)的內(nèi)插對(duì)象的數(shù)值從最小到最大,然后又從最大到最小。
我們前面用到的Alpha,它每一個(gè)周期的數(shù)值,都是從0到1,對(duì)應(yīng)的內(nèi)插
對(duì)象的數(shù)值,在每一個(gè)循環(huán)周期里,都是從最小到最大。我們可以
利用下面兩個(gè)方法,設(shè)置或獲得mode:
public void setMode(int Mode)
public int getMode()
triggerTime表示Alpha起作用的時(shí)間,它可由外部來(lái)觸發(fā),它和后面
的7個(gè)參數(shù)的單位均為毫秒。
triggerTime參數(shù)后面還有7個(gè)類型為long的數(shù),我們可以設(shè)置
這些數(shù)值,來(lái)達(dá)到我們的各種編程目的。
前面我們介紹了VRML中各內(nèi)插器節(jié)點(diǎn)key字段的作用,在VRML中,
key的值只能從0到1。而在JAVA3D中,Alpha輸出的值不僅可以從0到1,
還可以從1到0,甚至可以先從0到1,再?gòu)?到0。
VRML程序中各內(nèi)插器節(jié)點(diǎn)的keyValue字段則根據(jù)key給定的數(shù)值,
輸出相應(yīng)的數(shù)值,計(jì)算機(jī)在keyValue各個(gè)數(shù)之間進(jìn)行線性插值。而
JAVA3D的Alpha則不僅可以對(duì)各內(nèi)插對(duì)象的數(shù)值進(jìn)行線性插值,而且
可以利用increasingAlphaRampDuration、decreasingAlphaRampDuration
這兩個(gè)參數(shù)進(jìn)行非線性插值,插值曲線可以從SUN公司所提供的JAVA3D的
API中看出,這時(shí)又分兩種情況:Ramp大于1/2、Ramp小于1/2。
接下來(lái)我們將通過多個(gè)JAVA3D動(dòng)畫程序的編制,介紹Alpha的各個(gè)參數(shù)。
JAVA3D動(dòng)畫編程時(shí)經(jīng)常使用的10個(gè)內(nèi)插器對(duì)象,它們分別是:
PositionInterpolator
RotationInterpolator
ColorInterpolator
ScaleInterpolator
SwitchValueInterpolator
TransparencyInterpolator
PositionPathInterpolator
RotPosPathInterpolator
RotPosScalePathInterpolator
RotationPathInterpolator
二. PositionInterpolator對(duì)象
為了編寫一個(gè)彩色立方體在空間的運(yùn)動(dòng),我們用到了JAVA3D所提供
的PositionInterpolator對(duì)象。
PositionInterpolator對(duì)象的定義如下:
public PositionInterpolator(Alpha alpha,
TransformGroup target,
Transform3D axisOfTranslation,
float startPosition,
float endPosition)
利用這個(gè)對(duì)象,我們可以在給定的時(shí)間內(nèi),使某一個(gè)局部坐標(biāo)系
在兩個(gè)點(diǎn)之間按照Alpha提供的方式移動(dòng)位置,它的作用類似于VRML
的PositionInterpolator節(jié)點(diǎn),兩者的名字完全一樣。
PositionInterpolator對(duì)象也有多個(gè)方法,用于參數(shù)的設(shè)定,如:
public void setStartPosition(float position)
public float getStartPosition()
public void setEndPosition(float position)
public float getEndPosition()
public void setTarget(TransformGroup target)
public TransformGroup getTarget()
public void setAxisOfTranslation(Transform3D axis)
public Transform3D getAxisOfTranslation()
public void processStimulus(Enumeration criteria)
我們先編寫一個(gè)VRML程序,使一個(gè)形體沿著X軸線左右移動(dòng),其實(shí),
形體并沒有移動(dòng),移動(dòng)的只是形體所在的局部坐標(biāo)系,源程序Pos.wrl
如下,注意,它的觀察點(diǎn)坐標(biāo)位于(0 ,0 , 10),左右移動(dòng)一周的時(shí)間
為20秒,左右移動(dòng)的范圍是(-4 , 0 , 0 )到( 4 , 0 , 0):
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{material Material{diffuseColor 1 0 0}}
geometry Box{}
}
}
Background{skyColor 1 1 1}
DEF TS TimeSensor{
loop TRUE
cycleInterval 20}
DEF PI PositionInterpolator{
key [ 0 .5 1]
keyValue[-4 0 0, 4 0 0 ,-4 0 0]
}
ROUTE TS.fraction TO PI.fraction
ROUTE PI.value TO T.translation
#end of Pos.wrl
--------------------------------------------------------
我們?cè)倮肞ositionInterpolator對(duì)象編寫類似的JAVA3D應(yīng)用程序,
同樣,Pos.java的觀察點(diǎn)坐標(biāo)也位于(0 , 0 , 10 ):
//Pos.java
import com.sun.j3d.utils.geometry.ColorCube;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Pos extends Applet {
private BranchGroup createSceneGraph( ) {
BranchGroup objRoot = new BranchGroup();
BoundingSphere bound=new BoundingSphere(
new Point3d(0.0,0.0,0.0),50.);
Transform3D tr=new Transform3D();
TransformGroup group=new TransformGroup(tr);
group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
group.addChild(new ColorCube());
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0,10000, 0, 0,10000, 0, 0);
PositionInterpolator tran =
new PositionInterpolator(xtranAlpha, group, tr,
-4.f,4.f);
tran.setSchedulingBounds(bound);
group.addChild(tran);
Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bound);
objRoot.addChild(bg);
objRoot.addChild(group);
return objRoot;
}
public Pos() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
ViewPlatform viewPlatform;
Viewer viewer = new Viewer(c);
Vector3d viewpoint = new Vector3d(0.0, 0.0, 10.0);
//初始觀察點(diǎn)位置
Transform3D t = new Transform3D();
t.set(viewpoint);
ViewingPlatform v = new ViewingPlatform( );
v.getViewPlatformTransform().setTransform(t);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse( v, viewer);
u.getViewingPlatform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Pos(), 400,400);
}
}
//end of Pos.java
運(yùn)行Pos.java后我們發(fā)現(xiàn),JAVA3D、VRML程序運(yùn)行效果基本一致。
1. PositionInterpolator對(duì)象里的參數(shù)
我們來(lái)看一下Pos.java里定義的PositionInterpolator對(duì)象實(shí)例
tran里的各個(gè)參數(shù)。
xtranAlpha表示局部坐標(biāo)系的變化方式是由xtranAlpha這個(gè)Alpha
定義的。
group給出了受影響的局部坐標(biāo)系的名稱。
tr給出了PositionInterpolator運(yùn)動(dòng)變化的方向,缺省時(shí)為沿X軸。
-4.f,4.f給出了局部坐標(biāo)系移動(dòng)的范圍,表示坐標(biāo)系的原點(diǎn)在
(-4 , 0 , 0 ) 和 ( 4 , 0 , 0 )之間移動(dòng)。
2. xtranAlpha里各參數(shù)的含義
-1表示無(wú)限循環(huán)
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE表示在一個(gè)
周期里面,局部坐標(biāo)系統(tǒng)的位置從(-4, 0 , 0)移到(4 , 0 , 0),再?gòu)?
(4 , 0 , 0)回到(-4 , 0 , 0),即從最小值到最大值,再?gòu)淖畲笾档?
最小值。
頭一個(gè)10000表示局部坐標(biāo)系從最小值移到最大值所用的時(shí)間,為
10秒。
第二個(gè)10000表示局部坐標(biāo)系從最大值移到最小值所用的時(shí)間,也
為10秒,因而一個(gè)周期的時(shí)間為20秒。
3. 坐標(biāo)軸的改變。
當(dāng)然,我們可以改變局部坐標(biāo)系移動(dòng)的坐標(biāo)軸,例如,當(dāng)我們想
讓局部坐標(biāo)系沿著Y軸移動(dòng)時(shí),我們就可以在
Transform3D tr=new Transform3D();
后面加上一句:
tr.rotZ(Math.PI/2) ;
如果我們加的是:
tr.rotY(Math.PI/2) ;
則形體沿著Z軸移動(dòng)。
后面我們?cè)谠敿?xì)介紹Transform3D時(shí)還將詳細(xì)介紹坐標(biāo)系的變換
方法。
三. Alpha構(gòu)造函數(shù)后7個(gè)參數(shù)的含義
我們?cè)俅谓o出Alpha類的構(gòu)造函數(shù):
public Alpha(int loopCount, int mode, long triggerTime,
long phaseDelayDuration,
long increasingAlphaDuration,
long increasingAlphaRampDuration,
long alphaAtOneDuration,
long decreasingAlphaDuration,
long decreasingAlphaRampDuration,
long alphaAtZeroDuration)
Alpha構(gòu)造函數(shù)里的頭三個(gè)參數(shù)我們已經(jīng)介紹過了,我們?cè)谶@里介紹
它的后7個(gè)參數(shù),它們用于定義各內(nèi)插對(duì)象的周期變化方式。
Alpha將每一個(gè)周期分外5個(gè)時(shí)段:
起始延遲時(shí)段
上升時(shí)段
高位時(shí)段
下降時(shí)段
低位時(shí)段
------
/ \
/ \
/ \
------- -------
每個(gè)周期的時(shí)間長(zhǎng)度為這5個(gè)時(shí)段時(shí)間長(zhǎng)度之和。
每一個(gè)Alpha都必須給出這5個(gè)時(shí)段,當(dāng)然,其中的任何數(shù)都可以為0,
因而我們可以獲得各種各樣的Alpha類型。下面我們給出部分類型:
1. 只有上升時(shí)段的類型
/ / /
/ / /
/ / /
/ / /
這種類型的Alpha輸出的數(shù)值從最小升到最大,然后又從最小升到最大。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE,
0, 0,20000, 0, 0,0, 0, 0);
它使形體從左移到右,再將形體跳回到左邊。
2. 只有下降時(shí)段的類型
\ \ \
\ \ \
\ \ \
\ \ \
這種類型的Alpha輸出的數(shù)值從最大降到最小,然后又從最大降到最小。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(-1,
Alpha.DECREASING_ENABLE,
0, 0,0, 0, 0,20000, 0, 0);
它使形體從右移到左,再將形體跳回到右邊。
3. 上升加高位時(shí)段的類型
--- ---
/ /
/ /
/ /
/ /
這種類型的Alpha輸出的數(shù)值從最小升到最大,暫停一段時(shí)間,
然后又從最小升到最大。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE,
0, 0,10000, 0, 10000, 0,0, 0);
它使形體從左移到右,暫停一段時(shí)間,再將形體跳回到左邊。
4. 下降加低位時(shí)段
\ \
\ \
\ \
---- ----
這種類型的Alpha輸出的數(shù)值從最大降到最小,暫停一段時(shí)間,
然后又從最大降到最小。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(-1,
Alpha.DECREASING_ENABLE,
0, 0,0, 0, 0, 10000,0, 10000);
它使形體從右移到左,再將形體跳回到右邊。
5. 暫停、上升加高位時(shí)段的類型
----
/
/
/
/
----
這種類型的Alpha輸出的數(shù)值一開始先暫停,然后從最小升到最
大,再暫停一段時(shí)間。不過要注意的是,這種類型不能用于
循環(huán)方式。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(1,
Alpha.INCREASING_ENABLE,
0, 5000,10000, 0, 5000, 0,0, 0);
它使形體暫停一段時(shí)間,從左移到右,再暫停一段時(shí)間。
6. 暫停、下降加暫停時(shí)段的類型
----
\
\
\
------
這種類型的Alpha輸出的數(shù)值一開始先暫停,然后從最大升到最
小,再暫停一段時(shí)間。不過要注意的是,這種類型也不能用于
循環(huán)方式。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(1,
Alpha.DECREASING_ENABLE,
0, 0,0, 0, 5000, 10000,0, 5000);
它使形體暫停一段時(shí)間,從右移到左,再暫停一段時(shí)間。
7. 5種時(shí)段均有的類型
-----
/ \
/ \
/ \
----- -----
此種類型的Alpha輸出的數(shù)值一開始先暫停,然后從最小升到
最大,再暫停一段時(shí)間,然后下降到最小,最后再暫停一段時(shí)間。
不過要注意的是,這種類型也不能用于循環(huán)方式。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(1,
Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
0, 3000,5000, 0, 3000, 5000,0, 3000);
8. 上升、暫停、下降、暫停類型
---- ----
/ \ / \
/ \ / \
/ \------/ \-----
本類型和第7種很相似,但沒有上升前的暫停階段,因而可以
用于循環(huán)方式。
我們將前面的Pos.java改成這種類型時(shí),生成的Alpha應(yīng)為:
Alpha xtranAlpha = new Alpha(-1,
Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
0, 0,5000, 0, 5000, 5000,0, 5000);
9. Alpha的加速
前面介紹的8種類型,可以用于各種場(chǎng)合,如開關(guān)門等。但它們
均有一個(gè)問題,即形體從靜止到運(yùn)動(dòng)的變化是跳躍性的,變化時(shí)的
加速度為無(wú)窮大。為此,JAVA3D還提供了兩個(gè)參數(shù),解決這個(gè)問題,
這就是Alpha里的increasingAlphaRampDuration和
decreasingAlphaRampDuration,它們有兩種應(yīng)用方式:一是設(shè)置為
大于或等于0.5,一是設(shè)置為小于0.5。
當(dāng)它們的值為第一種情況時(shí),計(jì)算機(jī)自動(dòng)將其轉(zhuǎn)成0.5,使Alpha
產(chǎn)生的加速度在頭一半時(shí)間是均勻加速的,在后一半時(shí)間里是均勻
減速的,因而在頭一半時(shí)間里,加速度是正數(shù),在后一半時(shí)間里,
加速度是相同的負(fù)數(shù)(請(qǐng)參考JAVA3D的API說明)。
第一種情況在某一時(shí)段的速度圖:
/\
/ \
/ \
/ \
下面我們給出這樣一個(gè)Alpha的例子:
Alpha xtranAlpha = new Alpha(-1,
Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
0, 0,5000, (long)0.5, 5000, 5000,(long)0.5, 5000);
當(dāng)這兩個(gè)數(shù)小于0.5時(shí),Alpha只在時(shí)間段的兩頭產(chǎn)生加速度,
中間的加速度為0,因而中間的速度保持不變。
下面我們給出這樣一個(gè)Alpha的例子:
Alpha xtranAlpha = new Alpha(-1,
Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
0, 0,5000, (long)0.2, 5000, 5000,(long)0.5, 5000);
第二種情況在某一時(shí)段的速度圖:
--------
/ \
/ \
/ \
m
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java3D學(xué)習(xí)系列(十七)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Sun May 2 18:33:40 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(16)--動(dòng)畫的生成(中)
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
上一講我們已經(jīng)介紹了一個(gè)JAVA3D的內(nèi)插對(duì)象:
PositionInterpolator。本講我們將繼續(xù)介紹其它的
內(nèi)插對(duì)象。
一. RotationInterpolator對(duì)象
RotationInterpolator的構(gòu)造函數(shù)有兩個(gè):
public RotationInterpolator(Alpha alpha,
TransformGroup target)
public RotationInterpolator(Alpha alpha,
TransformGroup target,
Transform3D axisOfRotation,
float minimumAngle,
float maximumAngle)
RotationInterpolator的方法有:
public void setMinimumAngle(float angle)
public float getMinimumAngle()
public void setMaximumAngle(float angle)
public float getMaximumAngle()
public void setAxisOfRotation(Transform3D axis)
public Transform3D getAxisOfRotation()
public void setTarget(TransformGroup target)
public TransformGroup getTarget()
public void processStimulus(Enumeration criteria)
利用這個(gè)對(duì)象,我們可以在給定的時(shí)間內(nèi),使某一個(gè)局部坐標(biāo)系
在按照Alpha提供的方式繞著某一個(gè)軸旋轉(zhuǎn),它的作用類似于VRML
的OrientationInterpolator節(jié)點(diǎn)。
RotationInterpolator的前三個(gè)參數(shù)和我們上一講介紹的
PositionInterpolator對(duì)象的前三個(gè)參數(shù)概念一樣:
Alpha為我們提供了旋轉(zhuǎn)方式。
target為我們提供了需要旋轉(zhuǎn)的局部坐標(biāo)系。
axisOfRotation確定了旋轉(zhuǎn)軸的方位。
1. 第一個(gè)構(gòu)造函數(shù)的運(yùn)行結(jié)果
假如我們利用的是第一個(gè)構(gòu)造函數(shù),我們所獲得的最大角度為
2*PI,最小角度為0,坐標(biāo)系繞著Y軸,按照Alpha給出的旋轉(zhuǎn)方式
旋轉(zhuǎn)。
2. 第二個(gè)構(gòu)造函數(shù)的運(yùn)行結(jié)果
我們來(lái)看一下OrientationInterpolator第二個(gè)構(gòu)造函數(shù)的后兩
個(gè)參數(shù),它們給出了旋轉(zhuǎn)的最大最小的角度。
下面的程序Rot.java利用了RotationInterpolator對(duì)象,使一個(gè)
立方體繞著自己的Y軸不停地旋轉(zhuǎn):先正轉(zhuǎn)180度。停頓幾秒后,又反
轉(zhuǎn)180度,再停頓幾秒鐘。
//Rot.java
import com.sun.j3d.utils.geometry.ColorCube;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Rot extends Applet {
private BranchGroup createSceneGraph( ) {
float min = 0.0f;
float max = (float) Math.PI;
BranchGroup objRoot = new BranchGroup();
BoundingSphere bound=new BoundingSphere(
new Point3d(0.0,0.0,0.0),50.);
Transform3D tr=new Transform3D();
TransformGroup group=new TransformGroup(tr);
group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
group.addChild(new ColorCube());
Alpha xtranAlpha = new Alpha(-1,
Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
0, 0,5000, (long)0.5, 5000, 5000,(long)0.5, 5000);
RotationInterpolator tran =
new RotationInterpolator(xtranAlpha, group, tr,
min,max);
tran.setSchedulingBounds(bound);
group.addChild(tran);
Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bound);
objRoot.addChild(bg);
objRoot.addChild(group);
return objRoot;
}
public Rot() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
ViewPlatform viewPlatform;
Viewer viewer = new Viewer(c);
Vector3d viewpoint = new Vector3d(0.0, 0.0, 10.0);
//初始觀察點(diǎn)位置
Transform3D t = new Transform3D();
t.set(viewpoint);
ViewingPlatform v = new ViewingPlatform( );
v.getViewPlatformTransform().setTransform(t);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse( v, viewer);
u.getViewingPlatform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Rot(), 400,400);
}
}
//end of Rot.java
我們給出相應(yīng)的VRML語(yǔ)言編寫出的程序,由VRML程序的
運(yùn)行結(jié)果可以看出,VRML程序無(wú)法使形體的速度漸變,而只
能突變,因而JAVA3D在這一方面功能較強(qiáng)。
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{material Material{diffuseColor 1 0 .5}}
geometry Box{}}
}
DEF TS TimeSensor{
loop TRUE
cycleInterval 20}
DEF OI OrientationInterpolator{
key [ 0 .25 .5 .75 1]
keyValue[0 1 0 0 ,0 1 0 3.14,0 1 0 3.14, 0 1 0 0, 0 1 0 0]
}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
#end of Rot.wrl
如果我們?cè)贘AVA3D程序的
Transform3D tr=new Transform3D();
后面加上一句:
tr.rotZ(Math.PI/2) ;
則形體從繞著Y軸旋轉(zhuǎn)改為繞著X軸旋轉(zhuǎn)。
二. ColorInterpolator對(duì)象
ColorInterpolator的構(gòu)造函數(shù)也有兩個(gè):
public ColorInterpolator(Alpha alpha, Material target)
public ColorInterpolator(Alpha alpha, Material target,
Color3f startColor,
color3f endColor)
ColorInterpolator的方法有:
public void setStartColor(Color3f color)
public void getStartColor(Color3f color)
public void setEndColor(Color3f color)
public void getEndColor(Color3f color)
public void setTarget(Material target)
public Material getTarget()
public void processStimulus(Enumeration criteria)
利用這個(gè)對(duì)象,我們可以在給定的時(shí)間內(nèi),使某一個(gè)Material
對(duì)象的漫反射光DiffuseColor發(fā)生變化。按照Alpha提供的方式變化,
它的作用類似于VRML的ColorInterpolator節(jié)點(diǎn),兩者的名字完全一樣。
1. 第一個(gè)構(gòu)造函數(shù)的運(yùn)行結(jié)果
如果我們采用的是第一個(gè)構(gòu)造函數(shù),則startColor為黑色,
endColor為白色。本人利用此方法編寫了幾個(gè)程序,發(fā)現(xiàn)形體的
顏色難以控制,因而建議大家少使用這個(gè)方法。
2. 第二個(gè)構(gòu)造函數(shù)的運(yùn)行結(jié)果
采用第二個(gè)構(gòu)造函數(shù)時(shí),我們需要設(shè)定startColor和endColor
這兩個(gè)顏色。不過要注意,為了使Material對(duì)象的DiffuseColor
產(chǎn)生變化的效果,我們應(yīng)在空間增加一個(gè)對(duì)著形體照射的光線,
否則形體顯示的依舊是輻射光EmissiveColor。
但我們經(jīng)過多次實(shí)驗(yàn),發(fā)現(xiàn)ColorInterpolator對(duì)象產(chǎn)生的
效果不是我們所預(yù)期的效果,例如,如果我們想使形體的
diffuseColor從顏色a變到顏色b,顯示的結(jié)果卻是形體的
emissiveColor到diffuseColor的變化。程序如下:
//Color.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Color extends Applet {
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
objRoot.addChild(createObject());
Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
Background bg = new Background(bgColor);
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
Color3f light1Color = new Color3f(1.0f, 1.0f, 1.0f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
objRoot.compile();
return objRoot;
}
private Group createObject() {
Transform3D t = new Transform3D();
TransformGroup objTrans = new TransformGroup(t);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Appearance ap=new Appearance();
ap.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
ap.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
Material mat = new Material( );
mat.setCapability(Material.ALLOW_COMPONENT_WRITE);
Color3f emissive = new Color3f(0.0f, 1.0f, 0.0f);
Color3f diffuse = new Color3f(0.0f, 0.0f, 1.0f);
mat.setEmissiveColor(emissive);
mat.setDiffuseColor(diffuse);
ap.setMaterial(mat);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
ap.setPolygonAttributes(pa);
ColoringAttributes ca = new ColoringAttributes( );
ca.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE);
ap.setColoringAttributes( ca);
Alpha alpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0, 8000, 0, 0, 8000, 0, 0);
ColorInterpolator ci = new ColorInterpolator(alpha, mat,
new Color3f(1.0f,0.0f, 1.0f), new Color3f(0.0f, 0.0f, 1.0
f));
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
ci.setSchedulingBounds(bounds);
Shape3D shape = new myShape();
shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
shape.setAppearance(ap);
objTrans.addChild(shape);
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0, 4000, 0, 0, 0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
return objTrans;
}
public Color() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Color(), 540,361);
}
}
//end of Color.java
----------------------
//myShape.java
import javax.media.j3d.*;
import javax.vecmath.*;
public class myShape extends Shape3D {
private float vert[] = {
-.3f,-.3f,0.0f,
-.3f,.3f,0.0f,
-.1f,-.3f,0.0f,
-.1f,.3f,0.0f,
.1f,-.3f,0.0f,
.1f,.3f,0.0f,
.3f,-.3f,0.0f,
.3f,.3f,0.0f,
.4f,.4f,0.0f, };
public myShape() {
int i, face;
TriangleArray shape = new TriangleArray(9,
TriangleArray.COORDINATES|TriangleArray.NORMALS);
shape.setCoordinates(0,vert);
Vector3f normal = new Vector3f();
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
Point3f [] pts = new Point3f[3];
for (i=0;i<3;i++) pts[i] = new Point3f();
for(face =0; face<3; face++) {
shape.getCoordinates(face*3,pts);
v1.sub(pts[1],pts[0]);
v2.sub(pts[2],pts[0]);
normal.cross(v1,v2);
normal.normalize();
for (i=0;i<3;i++) {
shape.setNormal((face*3+i), normal);
}
}
this.setGeometry(shape);
}
}
//end of myShape.java
我們給出程序?qū)?yīng)的VRML程序color.wrl
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{
material DEF M Material{diffuseColor 0 1 0}}
geometry IndexedFaceSet{
coord Coordinate{point [-0.3 -0.3 0,-0.3 0.3 0,
-0.1 -0.3 0,-0.1 0.3 0,
0.1 -0.3 0, 0.1 0.3 0,
0.3 -0.3 0, 0.3 0.3 0,
0.4 0.4 0]}
coordIndex[0 3 1 -1, 2 5 4 -1, 6 8 7]
solid FALSE
}
}
}
DEF TS TimeSensor{
loop TRUE
cycleInterval 8}
DEF CI ColorInterpolator{
key[0 .5 1]
keyValue[ 0 1 0, 0 0 1 , 0 1 0]
}
DEF OI OrientationInterpolator{
key[0 .5 1]
keyValue[ 0 1 0 0 , 0 1 0 3.14, 0 1 0 6.28]
}
Viewpoint {
position 0 .3 1
orientation 1 0 0 -.3}
Background{skyColor 1 1 1}
ROUTE TS.fraction TO CI.fraction
ROUTE TS.fraction TO OI.fraction
ROUTE CI.value TO M.diffuseColor
ROUTE OI.value TO T.rotation
#end of color.wrl
三. ScaleInterpolator對(duì)象
ScaleInterpolator對(duì)象的構(gòu)造函數(shù)有兩個(gè):
public ScaleInterpolator(Alpha alpha,
TransformGroup target)
public ScaleInterpolator(Alpha alpha,
TransformGroup target,
Transform3D axisOfScale,
float minimumScale,
float maximumScale)
ScaleInterpolator的方法有:
public void setMinimumScale(float scale)
public float getMinimumScale()
public void setMaximumScale(float scale)
public float getMaximumScale()
public void setAxisOfScale(Transform3D axis)
public Transform3D getAxisOfScale()
public void setTarget(TransformGroup target)
public TransformGroup getTarget()
public void processStimulus(Enumeration criteria)
public void updateNodeReferences(NodeReferenceTable
referenceTable)
利用這個(gè)對(duì)象,我們可以在給定的時(shí)間內(nèi),使某一個(gè)局部坐標(biāo)系
的各個(gè)方向按照Alpha提供的方式進(jìn)行比例變化,它的作用在VRML
程序中可以用PositionInterpolator來(lái)代替。
ScaleInterpolator的第一個(gè)構(gòu)造函數(shù)為我們提供了缺省的比例數(shù)
值,最大為1.0f,最小為0.1f。下面的程序利用第一個(gè)構(gòu)造函數(shù)使一
個(gè)立方體在一定的時(shí)間內(nèi)按照Alpha給出的變化方式在各個(gè)方向上產(chǎn)生
了相同的比例變化,為了比較,我們還給出了相應(yīng)的VRML語(yǔ)言編寫的程序。
//Scale1.java
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Scale1 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Transform3D tran3d=new Transform3D();
tran3d.rotX(0.4);
TransformGroup objTrans = new TransformGroup(tran3d);
objRoot.addChild(objTrans);
Transform3D t =new Transform3D();
t.rotX(0.4);
TransformGroup obj = new TransformGroup(t);
objTrans.addChild(obj);
obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
obj.addChild(new ColorCube(0.4));
Alpha scaleAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0, 4000, 0, 0, 4000, 0, 0);
ScaleInterpolator scale =
new ScaleInterpolator(scaleAlpha, obj);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
scale.setSchedulingBounds(bounds);
obj.addChild(scale);
objRoot.compile();
return objRoot;
}
public Scale1() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Scale1(),400,400);
}
}
//end of Scale1.java
----------------------Scale1.wrl----------
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{material Material{diffuseColor 1 0 .5}}
geometry Box{}}
}
DEF TS TimeSensor{
loop TRUE
cycleInterval 8}
EF PI PositionInterpolator{
key [ 0 .5 1]
keyValue[1 1 1, 0.1 0.1 0.1 1 1 1]
}
ROUTE TS.fraction TO PI.fraction
ROUTE PI.value TO T.scale
#end of Scale1.wrl
ScaleInterpolator的第二個(gè)構(gòu)造函數(shù)允許我們?cè)O(shè)置最大及最小
的比例數(shù)值。我們利用它編寫了下面的這個(gè)程序,利用它,可以設(shè)
置我們所需要的比例數(shù)值。
//Scale2.java
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Scale2 extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Transform3D tran3d=new Transform3D();
tran3d.rotX(0.4);
TransformGroup objTrans = new TransformGroup(tran3d);
objRoot.addChild(objTrans);
Transform3D t =new Transform3D();
t.rotX(0.4);
TransformGroup obj = new TransformGroup(t);
objTrans.addChild(obj);
obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
obj.addChild(new ColorCube(0.4));
Alpha scaleAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0, 4000, 0, 0, 4000, 0, 0);
ScaleInterpolator scale =
new ScaleInterpolator(scaleAlpha, obj,t,1.0f,0.4f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
scale.setSchedulingBounds(bounds);
obj.addChild(scale);
objRoot.compile();
return objRoot;
}
public Scale2() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Scale2(),400,400);
}
}
//end of Scale2.java
四. SwitchValueInterpolator
SwitchValueInterpolator對(duì)象的構(gòu)造函數(shù)有兩個(gè):
public SwitchValueInterpolator(Alpha alpha,
Switch target)
public SwitchValueInterpolator(Alpha alpha,
Switch target,
int firstChildIndex,
int lastChildIndex)
SwitchValueInterpolator的方法有:
public void setFirstChildIndex(int firstIndex)
public int getFirstChildIndex()
public void setLastChildIndex(int lastIndex)
public int getLastChildIndex()
public void setTarget(Switch target)
public Switch getTarget()
public void processStimulus(Enumeration criteria)
利用這個(gè)對(duì)象,我們可以在屏幕上在不同的時(shí)間分別顯示
不同的形體。例如下面程序里,計(jì)算機(jī)按循環(huán)顯示形體,每一個(gè)
周期顯示的內(nèi)容為:大立方體--球--圓錐--小立方體--圓錐--球。
當(dāng)然,當(dāng)我們采用第一個(gè)構(gòu)造函數(shù)時(shí),結(jié)果和本程序一樣。
當(dāng)我們將程序中的:
SwitchValueInterpolator sv =
new SwitchValueInterpolator(scaleAlpha, s,0,4);
改為:
SwitchValueInterpolator sv =
new SwitchValueInterpolator(scaleAlpha, s,0,3);
時(shí),每一個(gè)周期顯示的內(nèi)容為:大立方體--球--圓錐--球,由此看
來(lái),第四個(gè)形體沒有顯示出來(lái)。
//mySwitch.java
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class mySwitch extends Applet {
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
Transform3D tran3d=new Transform3D();
tran3d.rotX(0.4);
TransformGroup objTrans = new TransformGroup(tran3d);
objRoot.addChild(objTrans);
Transform3D t =new Transform3D();
t.rotX(0.4);
TransformGroup obj = new TransformGroup(t);
Switch s = new Switch( );
s.addChild(new ColorCube(0.4));
s.addChild(new Sphere( ));
s.addChild(new Cone( ));
s.addChild(new ColorCube(0.2));
s.setCapability(Switch.ALLOW_SWITCH_WRITE);
objTrans.addChild(obj);
obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
obj.addChild(s);
Alpha scaleAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0, 4000, 0, 4000, 4000, 0, 4000);
SwitchValueInterpolator sv =
new SwitchValueInterpolator(scaleAlpha, s,0,4);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
sv.setSchedulingBounds(bounds);
obj.addChild(sv);
Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
objRoot.compile();
return objRoot;
}
public mySwitch() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new mySwitch(),400,400);
}
}
//end of mySwitch.java
發(fā)信人: screamer (Screamer), 信區(qū): Cad
標(biāo) 題: Java學(xué)習(xí)系列(十八)(轉(zhuǎn)載)
發(fā)信站: 飄渺水云間 (Thu May 6 21:06:31 1999), 轉(zhuǎn)信
JAVA3D學(xué)習(xí)系列(17)--動(dòng)畫的生成(下)
汕頭大學(xué)機(jī)電系 張杰(jzhang@mailserv.stu.edu.cn)
一. TransparnecyInterpolator對(duì)象
TransparencyInterpolator對(duì)象的構(gòu)造函數(shù)有兩個(gè):
public TransparencyInterpolator(Alpha alpha,
TransparencyAttributes target)
public TransparencyInterpolator(Alpha alpha,
TransparencyAttributes target,
float minimumTransparency,
float maximumTransparency)
它的方法有:
public void setMinimumTransparency(float transparency)
public float getMinimumTransparency()
public void setMaximumTransparency(float transparency)
public float getMaximumTransparency()
public void setTarget(TransparencyAttributes target)
public TransparencyAttributes getTarget()
public void processStimulus(Enumeration criteria)
利用這個(gè)對(duì)象,我們可以在給定的時(shí)間內(nèi),使某一個(gè)形體的透明度
按照Alpha提供的方式在兩個(gè)數(shù)值之間變化,VRML語(yǔ)言中我們可以用
ScalarInterpolator節(jié)點(diǎn)來(lái)實(shí)現(xiàn)同樣的效果。
如果我們使用的是第一個(gè)構(gòu)造函數(shù),則透明度的最大值為1.0f,
最小值為0.0f。
下面是一個(gè)應(yīng)用此方法的JAVA3D程序和一個(gè)相對(duì)應(yīng)的VRML程序。
為了看出透明的效果,我們?cè)O(shè)定背景為白色。
//Tra.java
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Tra extends Applet {
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
objRoot.addChild(createObject());
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0
);
Background bg=new Background(new Color3f(1.0f,1.0f,1.0f));
bg.setApplicationBounds(bounds);
objRoot.addChild(bg);
objRoot.compile();
return objRoot;
}
private Group createObject() {
Transform3D t = new Transform3D();
TransformGroup objTrans = new TransformGroup(t);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Appearance ap=new Appearance();
Color3f ambient=new Color3f(1.0f,0.0f,0.0f);
Color3f emissive = new Color3f(0.8f,0.2f,0.2f);
Color3f diffuse=new Color3f(1.f,1.f,0.f);
Color3f specular = new Color3f(1.0f,1.0f,1.0f);
ap.setMaterial(new Material(ambient,emissive,diffuse,specular,100.0f));
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
ap.setPolygonAttributes(pa);
TransparencyAttributes ta=new TransparencyAttributes();
ta.setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);
ta.setTransparencyMode(ta.BLENDED);
ta.setTransparency(.0f);
ap.setTransparencyAttributes(ta);
Alpha alpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0, 8000, 0, 0, 8000, 0, 0);
TransparencyInterpolator transparency=
new TransparencyInterpolator(alpha,ta,.0f,1.f);
BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0
);
transparency.setSchedulingBounds(bounds);
Shape3D shape = new myShape();
shape.setAppearance(ap);
objTrans.addChild(shape);
objTrans.addChild(transparency);
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
0, 0, 4000, 0, 0, 0, 0, 0);
RotationInterpolator rotator =
new RotationInterpolator(rotationAlpha, objTrans, yAxis,
0.0f, (float) Math.PI*2.0f);
rotator.setSchedulingBounds(bounds);
objTrans.addChild(rotator);
return objTrans;
}
public Tra() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Tra(), 540,361);
}
}
//end of Tra.java
---------
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{material DEF M Material{diffuseColor 0 1 0}}
geometry IndexedFaceSet{
coord Coordinate{point [-0.3 -0.3 0,-0.3 0.3 0,
-0.1 -0.3 0,-0.1 0.3 0,
0.1 -0.3 0, 0.1 0.3 0,
0.3 -0.3 0, 0.3 0.3 0,
0.4 0.4 0]}
coordIndex[0 3 1 -1, 2 5 4 -1, 6 8 7]
solid FALSE
}
}
}
DEF TS TimeSensor{
loop TRUE
cycleInterval 8}
DEF SI ScalarInterpolator{
key[0 .5 1]
keyValue[ 1, 0, 1]
}
DEF OI OrientationInterpolator{
key[0 .5 1]
keyValue[ 0 1 0 0 , 0 1 0 3.14, 0 1 0 6.28]
}
Viewpoint {
position 0 .3 1
orientation 1 0 0 -.3}
Background{skyColor 1 1 1}
ROUTE TS.fraction TO SI.fraction
ROUTE TS.fraction TO OI.fraction
ROUTE SI.value TO M.transparency
ROUTE OI.value TO T.rotation
#end of tra.wrl
二. PathInterpolator對(duì)象
我們?cè)诤竺鎸⒁榻B下面這些對(duì)象:
PositionPathInterpolator
RotPosPathInterpolator
RotPosScalePathInterpolator
RotationPathInterpolator
它們都是PathInterpolator的子類。為此,我們先介紹一下
PathInterpolator對(duì)象的作用。
PathInterpolator是Interpolator類的子類,就好象我們
上面介紹的所有的內(nèi)插對(duì)象是Interpolator類的子類一樣。
PathInterpolator的子類能夠借助于父類的下面的這個(gè)方法:
computePathInterpolation()
來(lái)完成所需要的計(jì)算。
PathInterpolator還有以下幾個(gè)方法:
getArrayLengths()
public void setKnot(int index, float knot)
public float getKnot(int index)
三. PositionPathInterpolator對(duì)象
PositionPathInterpolator對(duì)象的構(gòu)造函數(shù)為:
public PositionPathInterpolator(Alpha alpha,
TransformGroup target,
Transform3D axisOfTranslation,
float knots[],
Point3f positions[])
它的方法有:
public void setPosition(int index, Point3f position)
public void getPosition(int index, Point3f position)
public void setAxisOfTranslation(Transform3D axis)
public Transform3D getAxisOfTranslation()
public void setTarget(TransformGroup target)
public TransformGroup getTarget()
public void processStimulus(Enumeration criteria)
利用這個(gè)對(duì)象,我們可以對(duì)某一個(gè)局部坐標(biāo)系按照指定的路徑、
指定的運(yùn)動(dòng)方式進(jìn)行坐標(biāo)系的移動(dòng)。
positions[]給出了指定的路徑。
knots[]、alpha給出了指定的運(yùn)動(dòng)方式。
下面我們利用這個(gè)對(duì)象編寫一個(gè)使某個(gè)立方體按指定路徑,按
指定運(yùn)動(dòng)方式的位移運(yùn)動(dòng)。
由程序我們得知,立方體圍繞著由pos[]定義的一個(gè)長(zhǎng)方形平移。
軌跡的第一個(gè)點(diǎn)和最后一個(gè)點(diǎn)重合。在從第一個(gè)點(diǎn)到最后一個(gè)點(diǎn)運(yùn)動(dòng)
過程中,每一個(gè)點(diǎn)都對(duì)應(yīng)一個(gè)knot值,第一個(gè)knot值為0.0f,最后一
個(gè)knot值為1.0f,knot值必須從小到大排列,它用來(lái)給各個(gè)點(diǎn)分配由
Alpha對(duì)象定義的上升時(shí)間段和下降時(shí)間段。每一個(gè)點(diǎn)的時(shí)間可以由
對(duì)應(yīng)的knot的數(shù)值算出。
運(yùn)行JAVA3D程序,我們會(huì)看到立方體繞著一個(gè)長(zhǎng)方形的四個(gè)
頂點(diǎn)旋轉(zhuǎn)。如果我們將程序中的xtranAlpha改寫成下面的內(nèi)容:
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0,10000, 0, 2000, 10000, 0, 2000);
則每一個(gè)循環(huán)的運(yùn)行結(jié)果為:立方體先順時(shí)針轉(zhuǎn)一圈(10秒),
暫停2秒,再逆時(shí)針旋轉(zhuǎn)一圈(10秒),再暫停2秒。
我們可以用VRML語(yǔ)言編寫同樣的處理程序,這時(shí)我們應(yīng)用的節(jié)點(diǎn)
是PositionInterpolator。由此可以得知,JAVA3D程序中的knot對(duì)應(yīng)
于VRML程序中PositionInterpolator節(jié)點(diǎn)的key字段,而pos對(duì)應(yīng)于
VRML程序中PositionInterpolator節(jié)點(diǎn)的keyValue字段。因而我們同時(shí)
編寫了一個(gè)VRML程序。
//Pos.java
import com.sun.j3d.utils.geometry.ColorCube;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Pos extends Applet {
float knot[] = {0.0f,0.25f,0.5f,0.75f,1.0f};
Point3f pos[] = {
new Point3f(-.8f,-.6f,0.0f),
new Point3f(-.8f,.6f, 0.0f),
new Point3f(.8f, .6f, 0.0f),
new Point3f(.8f, -.6f,0.0f),
new Point3f(-.8f,-.6f,0.0f), };
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objTran=new TransformGroup();
objTran.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D t3d=new Transform3D();
t3d.setScale(.3);
objTran.setTransform(t3d);
objRoot.addChild(objTran);
BoundingSphere bound=new BoundingSphere(
new Point3d(0.0,0.0,0.0),50.);
Transform3D tr=new Transform3D();
TransformGroup translation=new TransformGroup(tr);
translation.addChild(new ColorCube(.2));
objTran.addChild(translation);
translation.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE,
0, 0,10000, 0, 0, 0, 0, 0);
PositionPathInterpolator tran =
new PositionPathInterpolator(xtranAlpha, translation, tr,
knot,pos);
tran.setSchedulingBounds(bound);
translation.addChild(tran);
return objRoot;
}
public Pos() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Pos(), 640,480);
}
}
//end of Pos.java
------------------------------
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{
material Material{diffuseColor 1 0 0}}
geometry Box{}}}
DEF TS TimeSensor{
loop TRUE
cycleInterval 10}
DEF PI PositionInterpolator{
key[0 .25 .5 .75 1]
keyValue[-.8 -.6 0 , -.8 .6 0,
.8 .6 0, .8 -.6 0, -.8 -.6 0]}
ROUTE TS.fraction TO PI.fraction
ROUTE PI.value TO T.translation
Background{skyColor 1 1 1}
Viewpoint{
position 0 2 8
orientation 1 0 0 -.3}
#end of Pos.wrl
四. RotPosPathInterpolator對(duì)象
RotPosPathInterpolator對(duì)象的構(gòu)造函數(shù)為:
public RotPosPathInterpolator(Alpha alpha,
TransformGroup target,
Transform3D axisOfRotPos,
float knots[],
Quat4f quats[],
Point3f positions[])
它的方法有:
public void setQuat(int index, Quat4f quat)
public void getQuat(int index, Quat4f quat)
public void setPosition(int index, Point3f position)
public void getPosition(int index, Point3f position)
public void setAxisOfRotPos(Transform3D axisOfRotPos)
public Transform3D getAxisOfRotPos()
public void setTarget(TransformGroup target)
public TransformGroup getTarget()
public void processStimulus(Enumeration criteria)
我們上面介紹的PositionPathInterpolator對(duì)象可以
使形體按指定的路徑平移,而利用RotPosPathInterpolator
對(duì)象則可以在實(shí)現(xiàn)平移運(yùn)動(dòng)的同時(shí)使形體按指定的方式繞特
定的軸旋轉(zhuǎn)。例如下面的程序就是在Pos.java程序的基礎(chǔ)之
上加了一個(gè)Quat4f數(shù)組,用來(lái)定義形體的旋轉(zhuǎn)方式。使形體
在每一個(gè)knots數(shù)值之下都有一個(gè)旋轉(zhuǎn)角度相對(duì)應(yīng)。程序的其
它地方?jīng)]有變化。
立方體在順時(shí)針或反時(shí)針移動(dòng)時(shí),都要繞著自身先正轉(zhuǎn)
90度,再反轉(zhuǎn)90度。
RotPosPathInterpolator對(duì)象可以由下面兩個(gè)對(duì)象代替:
PositionPathInterpolator
RotationInterpolator
//Rot.java
import com.sun.j3d.utils.geometry.ColorCube;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Rot extends Applet {
float knot[] = {0.0f,0.25f,0.5f,0.75f,1.0f};
Point3f pos[] = {
new Point3f(-.8f,-.6f,0.0f),
new Point3f(-.8f,.6f, 0.0f),
new Point3f(.8f, .6f, 0.0f),
new Point3f(.8f, -.6f,0.0f),
new Point3f(-.8f,-.6f,0.0f), };
Quat4f quat[ ] = {
new Quat4f( 0.0f ,1.0f ,0.0f ,0.0f),
new Quat4f(0.0f ,1.0f ,0.0f ,0.78f ),
new Quat4f(0.0f ,1.0f, 0.0f , 1.57f ),
new Quat4f(0.0f, 1.0f ,0.0f, 0.78f ),
new Quat4f( 0.0f ,1.0f, 0.0f, 0.0f ) };
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objTran=new TransformGroup();
objTran.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D t3d=new Transform3D();
t3d.setScale(.3);
objTran.setTransform(t3d);
objRoot.addChild(objTran);
BoundingSphere bound=new BoundingSphere(
new Point3d(0.0,0.0,0.0),50.);
Transform3D tr=new Transform3D();
TransformGroup translation=new TransformGroup(tr);
translation.addChild(new ColorCube(.2));
objTran.addChild(translation);
translation.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0,10000, 0, 2000, 10000, 0, 2000);
RotPosPathInterpolator tran =
new RotPosPathInterpolator(xtranAlpha, translation, tr,
knot,quat , pos);
tran.setSchedulingBounds(bound);
translation.addChild(tran);
return objRoot;
}
public Rot() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Rot(), 640,480);
}
}
//end of Rot.java
我們將Rot.java變成VRML程序Rot.wrl
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{
material Material{diffuseColor 1 0 0}}
geometry Box{size .5 .5 .5}}
}
DEF TS TimeSensor{
loop TRUE
cycleInterval 10}
DEF PI PositionInterpolator{
key[0 .125 .25 .375 .5 .625 .75 .875 1]
keyValue[-.8 -.6 0 , -.8 .6 0,
.8 .6 0, .8 -.6 0, -.8 -.6 0
.8 -.6 0, .8 .6 0, -.8 .6 0
-.8 -.6 0]}
DEF OI OrientationInterpolator{
key[0 .125 .25 .375 .5 .625 .75 .875 1]
keyValue[0 1 0 0,0 1 0 .78,0 1 0 1.57, 0 1 0 0.78,
0 1 0 0, 0 1 0 0.78, 0 1 0 1.57, 0 1 0 0.78
0 1 0 0]}
ROUTE TS.fraction TO PI.fraction
ROUTE PI.value TO T.translation
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
Background{skyColor 1 1 1}
Viewpoint{
position 0 2 8
orientation 1 0 0 -.3}
# end of Rot.wrl
五. RotPosScalePathInterpolator對(duì)象
RotPosScalePathInterpolator對(duì)象的構(gòu)造函數(shù)為:
public RotPosScalePathInterpolator(Alpha alpha,
TransformGroup target,
Transform3D axisOfRotPosScale,
float knots[],
Quat4f quats[],
Point3f positions[],
float scales[])
它的方法有:
public void setScale(int index, float scale)
public float getScale(int index)
public void setQuat(int index, Quat4f quat)
前面我們已經(jīng)介紹了一個(gè)RotationInterpolator對(duì)象,利用
它可以使形體按Alpha指定的方式繞著特定的軸旋轉(zhuǎn),旋轉(zhuǎn)的速度
可以由Alpha的一些參數(shù)控制,但具體時(shí)間的角度無(wú)法控制。這時(shí)
我們就可以利用RotationPathInterpolator對(duì)象,利用quats數(shù)組,
控制具體時(shí)間的形體旋轉(zhuǎn)角度。
下面的程序是由上面介紹的Sca.java程序經(jīng)過一定的處理得來(lái)
的,沒有增加什么,只是將用于位移及比例變化的部分去掉了。
//Rot2.java
import com.sun.j3d.utils.geometry.ColorCube;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Rot2 extends Applet {
float knot[] = {0.0f,0.25f,0.5f,0.75f,1.0f};
Quat4f quat[ ] = {
new Quat4f( 0.0f ,1.0f ,0.0f ,0.0f),
new Quat4f(0.0f ,1.0f ,0.0f ,0.78f ),
new Quat4f(0.0f ,1.0f, 0.0f , 1.57f ),
new Quat4f(0.0f, 1.0f ,0.0f, 0.78f ),
new Quat4f( 0.0f ,1.0f, 0.0f, 0.0f )};
private BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
TransformGroup objTran=new TransformGroup();
objTran.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D t3d=new Transform3D();
t3d.setScale(.3);
objTran.setTransform(t3d);
objRoot.addChild(objTran);
BoundingSphere bound=new BoundingSphere(
new Point3d(0.0,0.0,0.0),50.);
Transform3D tr=new Transform3D();
TransformGroup translation=new TransformGroup(tr);
translation.addChild(new ColorCube(.2));
objTran.addChild(translation);
translation.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Alpha xtranAlpha = new Alpha(-1,
Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
0, 0,10000, 0, 2000, 10000, 0, 2000);
RotationPathInterpolator tran =
new RotationPathInterpolator(xtranAlpha, translation, tr,
knot,quat);
tran.setSchedulingBounds(bound);
translation.addChild(tran);
return objRoot;
}
public Rot2() {
setLayout(new BorderLayout());
Canvas3D c = new Canvas3D(null);
add("Center", c);
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new Rot2(), 640,480);
}
}
//end of Rot2.java
--------------------
相應(yīng)的VRML程序如下:
#VRML V2.0 utf8
DEF T Transform{
children Shape{
appearance Appearance{
material Material{diffuseColor 1 0 0}}
geometry Box{ }}
}
DEF TS TimeSensor{
loop TRUE
cycleInterval 10}
DEF OI OrientationInterpolator{
key[0 .125 .25 .375 .5 .625 .75 .875 1]
keyValue[0 1 0 0,0 1 0 .78,0 1 0 1.57, 0 1 0 0.78,
0 1 0 0, 0 1 0 0.78, 0 1 0 1.57, 0 1 0 0.78
0 1 0 0]}
Background{skyColor 1 1 1}
Viewpoint{
position 0 2 8
orientation 1 0 0 -.3}
ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
# end of Rot2.wrl
posted on 2007-06-19 13:37
托托姆 閱讀(4586)
評(píng)論(2) 編輯 收藏