<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 5  文章 - 3  trackbacks - 0
    <2008年8月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    常用鏈接

    留言簿(3)

    隨筆檔案

    文章檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    轉帖鏈接:http://bbs.zju.edu.cn/cgi-bin/bbs0an?path=/groups/GROUP_1/Graphics_Image/CAD_ImageProcess/dev/DevLib/java3d 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習資料(一)(轉載) 發信站: 飄渺水云間 (Wed Mar 31 15:58:48 1999), 轉信 PIII、K6-III出來了,在3D編程語言中,JAVA3D也應占有重要的位置。 為此,本人拿出半年多學習及應用JAVA3D的經驗,借國內主要BBS站點,推出JAVA3D編程 指導,并給出大量的例子。 一。如何運行JAVA3D? 只要在WIN95/98上安裝了JDK1.2(JAVA2),再安裝JAVA3D運行環境,就可以運行 JAVA3D,注意,別忘了在autoexec.bat中插入一行: SET PATH=C:\JDK1.2\BIN 目前我們可以從SUN公司的站點獲得最新的JAVA3D,本人擁有的為: java3d1_1-win32-opengl-jdk.exe,大小為3197K。 JAVA3D運行環境中附有許多例子,可用來學習JAVA3D,同時網絡上還有大量的 JAVA3D學習資料,可以用來學習JAVA3D編程。 二。網絡上的JAVA3D學習資料 1.http://www.sun.com/desktop/java3d/collateral/ 這里有SUN公司為我們提供的學習資料。 2.http://www.sdsc.edu/~nadeau/Courses/VR99/java3d.zip 這是一個非常好的JAVA3D學習資料。(12,058K),里面有許多例子。 大家可以從http://www.sdsc.edu/~nadeau/中得到VRML和JAVA3D的許多資料。 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(二)(轉載) 發信站: 飄渺水云間 (Wed Mar 31 16:01:09 1999), 轉信 一。JAVA3D的作用: JAVA3D可用在三維動畫、三維游戲、機械CAD等領域。 1.可以用來編寫三維形體,但和VRML不同,JAVA3D沒有基本形體,不過我們可以利用 JAVA3D所帶的UTILITY生成一些基本形體如立方體、球、圓錐等,我們也可以直接調用 一些軟件如ALIAS、LIGHTWARE、3DS MAX生成的形體,也可以直接調用VRML2.0生成的 形體。 2.可以和VRML一樣,使形體帶有顏色、貼圖。 3.可以產生形體的運動、變化,動態地改變觀測點的位置及視角。 4.可以具有交互作用,如點擊形體時會使程序發出一個信號從而產生一定的變化。 5.可以充分利用JAVA語言的強大功能,編寫出復雜的三維應用程序。 6.JAVA3D具有VRML所沒有的形體碰撞檢查功能(這也是本人目前中意JAVA3D的原因)。 (作為一個高級的三維圖形編程API,JAVA3D給我們帶來了極大的方便,它的作用 可以說,幾乎包含了VRML2.0所提供的所有功能。) 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(三)(轉載) 發信站: 飄渺水云間 (Wed Mar 31 16:02:21 1999), 轉信 二。OPENGL、VRML、DIRECT3D、JAVA3D的比較 由于OPENGL的跨平臺特性,許多人利用OPENGL編寫三維應用程序,不過對于一個非 計算專業的人員來說,利用OPENGL編寫出復雜的三維應用程序是比較困難的,且不說C (C++)語言的掌握需要花費大量時間精力,當我們需要處理復雜問題的時候,我們不得 不自己完成大量非常繁瑣的工作。當然,對于編程高手來說,OPENGL是他們發揮才能的 非常好的工具。 VRML2.0(VRML97)自1997年12月正式成為國際標準之后,在網絡上得到了廣泛的應 用,編寫VRML程序非常方法(VRML語言可以說比BASIC、JAVASCRIPT等語言還要簡 單),同時可以編寫三維動畫片、三維游戲、用于計算機輔助教學,因而其應用前景非 常廣闊尤其適合在中國推廣應用。不過由于VRML語言功能目前還不是很強(如目前沒有 形體之間的碰撞檢查功能),與JAVA語言等其它高級語言的連接較難掌握,因而失去了 一些計算機高手的寵愛。但我們認為,我們可以讓大學里的文理科學生利用VRML編寫多媒 體應用程序,讓學生很快地對編寫程序感興趣,從而使國內的計算機水平得到提高。 DIRECT3D是Microsoft公司推出的三維圖形編程API,它主要應用于三維游戲的編程, 目前相關的學習資料難于獲得,由于它一般需要VC等編程工具進行編程,需要編程人員 具有較高的C++等高級語言的編程功底,因而難以普及。 JAVA3D是建立在JAVA2(JAVA1.2)基礎之上的,JAVA語言的簡單性使JAVA3D的推廣 有了可能。OPENGL和JAVA3D之間的比較可以看成匯編語言與C語言之間的比較,一個是低 級的,一個是高級的(也許這樣比較不太恰當)。JAVA3D給我們編寫三維應用程序提供 了一個非常完善的API,它可以幫助我們: 生成簡單或復雜的形體(也可以直接調用現有的三維形體) 使形體具有顏色、透明效果、貼圖。 可以在三維環境中生成燈光、移動燈光。 可以具有行為(Behavior)的處理判斷能力(鍵盤、鼠標、定時等) 可以生成霧、背景、聲音等。 可以使形體變形、移動、生成三維動畫。 可以編寫非常復雜的應用程序,用于各種領域如VR。 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(四)(轉載) 發信站: 飄渺水云間 (Thu Apr 1 21:45:23 1999), 轉信 在編寫JAVA3D程序之前,我們需要了解一些概念,完成一些準備工作。 一. JAVA3D的數據結構 JAVA3D實際上是JAVA語言在三維圖形領域的擴展,JAVA3D的編程和JAVA一樣, 是面向對象的編程。 JAVA3D的數據結構采用的是Scene Graphs Structure(場景圖),這一靈活 的樹狀結構與顯示列表多少有些相似之處,但運用起來更耐用(More Robust)。 JAVA3D的場景圖是DAG(Directed-acyclic Graph),即具有方向性的不對稱圖形。 場景圖中有許多線和線的交匯點,交匯點稱為節點(Node),不管什么節點, 它都是JAVA3D類的實例(Instance of Class),線(Arc)表示實例之間的關系。 在JAVA3D的場景圖中,最底層(根部)的節點是Virtual Universe,每一個 場景圖只能有一個Virtual Universe。 在Virtual Universe上面,就是Locale節點,每個程序可以有一個或多個 Locale,但同時只能有一個Locale處于顯示狀態,就好象一個三維世界非常大, 有很多個景點,但我們同時只能在一個景點進行觀察。當然我們可以從一個景點 跳到另一個景點,不過絕大多數程序只有一個Locale。 每一個Locale上面擁有一個到多個BranchGroup節點。我們知道,要想建立 我們的三維應用環境,我們必須建立所需要的形體(Shape),給出形體的外觀 (Appearance)及幾何信息(Geometry),再把它們擺放在合適的位置, 這些形體及其擺放位置都建立在BranchGroup節點之上,擺放位置通過另一個節點 TransformGroup來設定。另外,我們在安放好三維形體之后,還需要設定具體的 觀察位置,我們暫時用View Platform代替,它也是建立在TransformGroup節點 之上的。 下面我們用一個示意圖來說明上面我們介紹的JAVA3D的場景圖概念。 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 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(五)(轉載) 發信站: 飄渺水云間 (Sun Apr 4 14:15:43 1999), 轉信 一. 如何安裝JAVA3D 下載JDK1.2及JAVA3D (目前最新的為1.1.1版本)。 在WIN95/98上安裝,先安裝JDK1.2,再安裝JAVA3D, 將JDK安裝到JDK1.2目錄下。 建立一個自己的目錄,在自己的目錄中編寫并運行程序。 注意,安裝JDK1.2時別忘了在autoexec.bat中插入一行: SET PATH=C:\JDK1.2\BIN JDK1.2的大小為20,041KB(jdk12_win32.exe)。 JAVA3D的大小為3,197KB(java3d1_1-win32-opengl-jdk.exe) 安裝時可以選擇所有缺省參數以減收麻煩。 二. 如何編寫JAVA3D源程序 用自己喜愛的文本編輯工具編輯源程序,和其它JAVA程序 一樣,程序后綴為JAVA。 三. 如何運行JAVA3D源程序 用JAVAC編譯源程序,生成class文件。根據文件的類型, 選擇用JAVA或APPLETVIEWER運行程序。 JAVA3D程序可以為APPLICATION程序,也可以為APPLET程序, 因而JAVA3D程序也可以擺放在網頁上,當然這時候我們必須在瀏 覽器上做一些設置工作(以后再介紹)。 四. 一個最簡單的JAVA3D源程序。 下面我們介紹一個最簡單的JAVA3D源程序,進而介紹JAVA3D 為我們提供的各種功能。 程序是一個JAVA的APPLET類型的程序,它的作用是顯示一個 紅色的圓錐,僅此而已。 名為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 在運行applet程序時,我們需要編寫一個HTML文件: 先用javac將JAVA3D源程序編譯成class文件,再用 appletviewer運行HTML文件。 雖然程序是applet程序,但我們也可以將其變成 application程序,這時我們只需將程序頭尾的四個注釋行 的注釋符號去掉即可,這時我們可以用java來運行它: java SimpleCone 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(六)(轉載) 發信站: 飄渺水云間 (Tue Apr 13 19:08:04 1999), 轉信 JAVA3D程序也是JAVA程序,因而我們首先必須對JAVA有所了解,并能 編寫簡單的JAVA程序,了解JAVA編程的基本概念,關于JAVA語言的相關知 識,我們在這里就不一一介紹了,國內這方面的書籍非常豐富。 一. SimpleCone 程序分析 1. SimpleCone.java及其對應的VRML程序 上一節中,我們給出了SimpleCone這個非常簡單的JAVA3D程序,下面 我們來解讀這個程序,進而介紹JAVA3D所提供的API的內容。 第三節中,我們對JAVA3D的場景圖結構作了一個簡單的介紹,從場景圖 我們可以看出,JAVA3D的場景圖和VRML的場景圖非常相似,因而我們可以編 寫類似的VRML程序出來,與JAVA3D程序進行比較。 SimpleCone程序只是顯示一個紅色的圓錐,相類似的VRML程序為: //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程序要簡單的多,并且可以直接在 IE和Netscape瀏覽器上運行,而JAVA3D則要復雜的多。不過幾乎所有的VRML 程序都可以用JAVA3D編寫出來,而稍微復雜一點的JAVA3D的程序則基本上無 法用VRML語言完成。因為VRML幾乎可以看成是一個三維計算機圖形格式,而 JAVA3D則是一個高級計算機語言。 在上面的VRML程序中,只定義了一個三維形體及其材質,背景、燈光、 位置等均為缺省值。 同樣地,SimpleCone.java程序中,我們也只定義了三維形體及其材質, 沒有背景、燈光等,處在缺省的位置上(坐標系原點)。 JAVA3D和VRML一樣,采用的是一個符合右手螺旋法則的三維坐標系。正 X軸向右,正Y軸向上,正Z軸朝外(從計算機屏幕指向我們)。 2. JAVA3D(API)中的類 JAVA3D是SUN公司為我們提供的一個API,里面包含了幾乎所有我們所需 要的編寫JAVA三維多媒體應用程序的基本的類及方法。我們在編程時,只 需調用所需要的類及方法,就可以快速地編寫出復雜的三維多媒體應用程 序。可以說,我們所做的工作只是學會應用JAVA3D的各種類(Objects)及方 法。 JAVA3D為我們提供了100多個存放于javax.media.j3d程序包中的類,它 們被稱為JAVA3D的核心類,除了核心包中的類以外,JAVA3D還提供了一些其 它程序包,其中一個重要的包是com.sun.j3d.utils包(Utility)。 JAVA3D所提供的Utility并不是JAVA3D編譯環境的核心組成部分,我們可以 不用它,不過使用它們會大大提高我們的程序編寫效率。JAVA3D為我們提供的 Utility會不斷增加,例如有可能增加處理NURBS曲線的Utility。目前,JAVA3D 為我們提供了四組Utility,它們是: 用于調用其它三維圖形格式如ALIAS圖形格式的content loader 用于構造場景圖的scene graph construction aids 用于建立一些基本體如圓錐、球的geometry classes 一些其它方便我們編程的convenience utilities 除了JAVA3D的核心包及Utility包之外,每個JAVA3D程序還必需用到下面 兩個包:java.awt和javax.vecmath。java.awt包用來定義一個顯示用的窗口, 而javax.vecmath包則是用來處理調用程序所需要的定義矢量計算所用的類, 處理定義三維形體及其位置時,我們需要用到點、矢量、矩陣及其它一些數學 對象,它也是JAVA3D所提供的一個包,目前它在JAVA3D的編譯環境中,今后則 可能會成為JAVA1.2的核心組成部分。 根據其作用,JAVA3D所提供的類主要有兩種類型:Node、NodeComponent Node類,它含有Group及Leaf兩個子類: Group類 (用于將形體等按一定的組合方式組合在一起), 類似于VRML的組節點。 Leaf 類 (如Light、Sound、Background、shape3d、 Appearance、Texture及其屬性等,還有 ViewPlatform、Sensor、Behavior、Morph、 Link等),類似與VRML的相應節點,是JAVA3D 場景圖的重要組成部分。 NodeComponent類,用于表示Node的屬性,它并不是JAVA3D場景圖 的組成部分,而是被JAVA3D場景圖所引用,如某 一個顏色可以被多個形體所引用。 3. SimpleCone.java程序import語句部分的介紹 根據JAVA3D所提供的類,按照面向對象的編程方式,我們可以編寫出三維 環境中所需要的各個對象。編寫JAVA3D程序的關鍵是學會應用JAVA3D所提供的 各個類,生成自己所需要的對象。 下面我們來看一下SimpleCone.java里的每一個import語句。 我們知道,java程序中。凡是利用到的外部的類均用import語句調用,我 們首先介紹一下程序中的import語句。 第一個import語句表示本程序是Applet程序。 第二個import語句表示窗口環境采用BorderLayout管理方式。 第三個import語句語句在去掉//后就可以使程序既為applet 也為application,為此,使用了JAVA3D所附帶的一個Utility,這是一個名 叫Jef Poskanzer的人所編寫的類。 第四個import語句表示調用生成Cone的一個Utility,這是因為,JAVA3D 和VRML不同,VRML有幾個基本幾何體的節點語句,但JAVA3D的核心部分一個 基本體也沒有定義,但JAVA3D所附帶的Utility為我們提供了一些事先編好的 基本體,我們可以調用這些基本體。 第五個import語句表示我們調用一些設置基本的觀測位置所用的類,如 SimpleUniverse、Viewer、ViewingPlatform等,利用它們,我們可以很方便 地構造JAVA3D場景圖底部的VirtualUniverse、Locale及其上的View分支,進 而使精力主要用在建模及復雜問題的處理上面,當然它們也都是JAVA3D所附帶 的Utility。 第六個import語句表示調用程序所需要的JAVA3D核心類,因而所有JAVA3D 程序都必須帶有這一語句,只有這樣才能在JDK1.2環境中編譯執行JAVA3D程序。 第七個import語句表示調用程序所需要的定義矢量計算所用的類。 3. SimpleCone.java程序的組成 SimpleCone.java程序主要由三個部分組成: createSceneGraph方法的定義 SimpleCone的構造函數 用于生成application應用程序的main函數 4. createSceneGraph方法的定義 我們首先來看一下createSceneGraph方法的定義部分。通過第三講的 JAVA3D場景圖的簡單示意圖,我們知道,為了編寫出一個JAVA3D應用程序, 我們必須編寫出一個擁有三維形體的內容分支,即一個分支組,一個 BranchGroup。我們將我們所需要的形體及其材質定義在里面,由于一般 形體會擺放在三維空間的某一個位置,因而我們還需要先在BranchGroup 分支之上建立一個可用于幾何變換用的TransformGroup,即幾何變換分支 組,再將形體及其材質作為TransformGroup的一個分支給出,當然程序中 如果將形體擺放在坐標原點,也可以不給出一個TransformGroup,如下面 的SimpleCone1程序運行起來和SimpleCone結果完全一樣,它沒有一個 TransformGroup對象: //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有三種運行方式,一種是Immediate Mode,一種是 Retained Mode,一種是Compiled-Retained Mode。 SimpleCone程序中的 objRoot.compile(); 表示程序為Compiled-Retained Mode,在這種模式下,JAVA3D對程序 進行了優化,程序的運行運行速度最快。不過在一些場合,如形體在 程序運行過程中才生成,則不能Compile形體,這說明優化是有條件的。 注意,JAVA3D程序沒有“開始渲染”這一步驟,當一個View被有 效地放入一個Virtual Universe,JAVA3D運行環境就開始不停地渲染 JAVA3D場景圖中的三維形體,從而使屏幕上顯示出三維圖形。 5. SimpleCone的構造函數 SimpleCone的構造函數的作用為 首先設置一個BorderLayout。 生成一個名為c的Canvas--Canvas3D繼承了JDK1.2中的Canvas類, 從而構造了一個圖形環境。 將c放入BorderLayout的中心位置。 生成一個場景圖分支scene,里面定義了形體及其材質(紅色)。 借用JAVA3D的一個Utility,生成了場景圖的Virtual Universe及 Locale、Viewer,和VRML程序有些不同,在缺省情況下, JAVA3D的觀察點為位于(0 , 0 , 2.41),而VRML的觀察點 位于(0 , 0 , 10),因而形體在VRML中看起來比較小, 而在JAVA3D中看起來比較大。我們利用這個Utility生成的 這個u使我們不必考慮生成場景圖中的觀測分支,不過它也 有缺點,即我們不能在Virtual Universe中擁有多個View, 因而也就不能從一個View跳到另一個View。 6. 用于生成application應用程序的main方法 為了使我們的程序既可以為applet程序,又可以為application 程序,我們可以通過編寫一個main方法,利用import語句提供的 MainFrame類,生成一個MainFrame對象,從而使程序變成為 application程序。MainFrame是JAVA3D為我們提供的一個非常有用 的Utility。 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(七)(轉載) 發信站: 飄渺水云間 (Tue Apr 13 19:10:48 1999), 轉信 介紹了一個簡單的JAVA3D程序后,我們開始學習JAVA3D的編程 技術。首席我們介紹三維基本形體的生成。 和VRML不同,JAVA3D沒有基本形體類,因而在程序中無法直接 生成大量應用的基本形體,如BOX、CONE、SPHERE等。我們可以通過 復雜的編程生成這些基本形體,也可以直接調用JAVA3D為我們提供的 geometry classes,利用它生成程序所需要的BOX、COLORCUBE、CONE、 SPHERE、CYLINDER。下面介紹這些基本體的生成方法。 一. BOX UTILITY里BOX的構造函數有: 1. Box() 生成一個各邊尺寸均為2的BOX,要說明的是,BOX、COLORCUBE、 SPHERE的坐標原點均在其中心點,CONE、CYLINDER的則在其軸 線的中點上。 2. Box(float xdim, float ydim, Appearance ap) 生成一個給定尺寸、給定外觀屬性的BOX 例:Box(.5f, .6f, .4f, myApp) 3. Box(float xdim, float ydim, float zdim, int primflags, Appearance ap) 生成一個有特定說明的BOX,例如: Box(.4f,.6f,.3f,Primitive.ENABLE_APPEARANCE_MODIFY, ap) 表示程序在運行時可以改變其外觀屬性。 我們可以在程序中使用的primflags種類可以在JAVA3D所附帶提 供的UTILITY里的Primitive.java中獲得。 二. COLORCUBE UTILITY里COLORCUBE的構造函數有: 1. ColorCube() 生成一個邊長均為2的COLORCUBE 2. ColorCube(double scale) 將邊長均為2的COLORCUBE按比例放大縮小。 三. CONE UTILITY里CONE的構造函數有: 1. public Cone() 生成一個底半徑為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可用來表示圓錐的顯示是高精度 的顯示,或是底精度的顯示,缺省時的中等精度時 xdivision = 15; ydivision = 1; 我們可利用這兩個參數來 改變顯示的效果,使顯示圓錐的三角片更多或更少些。 四. SPHERE UTILITY里SPHERE的構造函數有: 1. Sphere() 生成一個半徑為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的構造函數有: 1. Cylinder() 生成一個底半徑為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) 有了這些基本體的構造函數,我們就可以按SimpleCone.java 程序同樣的方法,編寫出生成BOX、COLORCUBE、CONE、SPHERE、 CYLINDER的JAVA3D程序來。 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(八)(轉載) 發信站: 飄渺水云間 (Tue Apr 13 19:40:39 1999), 轉信 JAVA3D學習系列之7---點的生成 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) ( 在前面(第6部分)我們介紹了如何編寫JAVA3D三維基本形體的) ( 程序,需要指出的是,我們將前面的SimpleCone.java程序修改為) ( 其它形體時,我們需要同時修改import語句的類型,或者干脆將 ) ( 相應的那個import語句修改成: ) ( import com.sun.j3d.utils.geometry.*; )   JAVA3D編程過程中,我們經常要編寫一些點、線、面,JAVA3D所提供 的API中有許多這方面的對象,下面我們開始一一介紹它們的使用方法。 一. 點的生成 我們先用VRML編寫一個帶有不同顏色的六個點的程序。 //Point.wrl ----觀測點在 (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程序中的點非常小,且無法變大。 下面我們改用JAVA3D編寫同樣的程序,不過由于觀測 點不同,觀測效果有差異,VRML程序中的點比較集中,JAVA3D 程序中的點比較分散,程序如下: //Point1.java -----觀測點在( 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 我們來分析一下上面的Point1.java。 我們知道,編寫JAVA3D程序實際上是編寫一個特定的場景圖, 給出了場景圖中帶有形體及其屬性的一個分支(BranchGrou)和 表示觀察位置等數據的另一個分支(View Platform)。一般來說, 表示觀測位置的分支可以用JAVA3D的UTILITY來完成,因而我們可 以看到,在Point1.java中,構造函數Point1和前面介紹的 SimpleCone.java的構造函數SimpleCone內容完全一樣。兩個程序 的不同之處在于形體構造及處理分支,即createSceneGraph方法的 定義。 我們來看一下Point1.java的createScendGraph方法的定義。 在這個方法里,程序先定義了一個分支objRoot,然后用數組 的形式定義了六個頂點坐標vert和六種顏色color,再用PointArray 定義了一組點point,并將頂點坐標及顏色賦值給point,由于JAVA3D 中的PointArray點是Shape3D的子類,它不能直接放入一個BranchGroup, 因而我們還要先定義一個Shape3D對象shape,再將point賦予shape, 這樣point就可以放入BranchGroup類型的對象objRoot中了。 二. PointArray、IndexedPointArray介紹 JAVA3D提供的API中,可用于生成Point的對象有: PointArray IndexedPointArray 1. PointArray PointArray的構造函數為: PointArray( int vertexCount, int vertexFormat ); 這里,vertexCount表示應生成的點的數目, vertexFormat表示所需要的頂點的格式。 點、線、面幾何體所需要的頂點的格式有: COORDINATES 頂點坐標數組 NORMALS 頂點法向數組 COLOR_3 不帶alpha值的顏色數組 COLOR_4 帶alpha值的顏色數組 TEXTURE_COORDINATE_2 二維紋理坐標數組 TEXTURE_COORDINATE_3 三維紋理坐標數組 Point1.java程序用到了COORDINATES和COLOR_3。 2. IndexedPointArray IndexedPointArray的構造函數為: IndexedPointArray( int vertexCount, int vertexFormat, int indexCount ); 利用本函數,我們可以從眾多的點中,選擇特定的點來顯示。 這里,vertexCount表示頂點坐標數組所提供的點的總個數, indexCount表示最終應生成的點的個數。 三. 20像素大小的點的生成 JAVA3D可以生成任意大小的點,并且可以使點為方點或圓點。 下面的程序生成了一個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); //不加這一行,點的顯示效果為正方形 //加了這一行,點的顯示效果為圓形 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編寫的點 下面的程序中,我們用IndexedPointArray生成了四個點。 //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 通過上面的程序,我們來看一下IndexedPointArray 的應用方法。 在定義一個point實例后,我們要給出頂點坐標數組及 對應各個頂點的顏色數組,按下標給出我們的頂點及顏色 的具體選擇方案。從而得以從眾多的點中,選擇特定的點來 顯示并給定顏色。通過setPointSize、setPointAntialiasingEnable 的設定,使顯示的點擁有一定的大小及良好的顯示效果。 ---1--- ---0--- ---3--- ---2--- ---4--- ---5---   程序Point3.java中,我們只選用了六個點中的0、2、3、4 四個點。 五. 主程序比較簡潔的程序Point4.java 前面幾個程序,所有的內容均放置在一個程序中,這對于 閱讀程序來說,增添了一些困難。一般來說,一個具體的例子通常 由幾個JAVA3D程序來完成,一般是將形體生成部分劃為單獨的一個 子程序,下面我們將上面的Point3.java分成兩個程序:子程序 myShape.java用來生成點,主程序Point4.java完成其它設置任務 并調用myShape.java,我們設定兩個程序均位于同一個子目錄下。 //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 六. 能夠旋轉的點 前面介紹的JAVA3D程序,顯示的內容是靜止的,且看不出立體的 效果,為此,我們使程序中的點繞著Y軸旋轉,這樣就可以看到具有 立體效果的點了,當然,其它形體也可以按同樣的方法編程,程序調 用了上面給出的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里,放置的是一個Shape3D對象, 而在Point5.java的objRoot里,放置的是一個Group對象。在 生成對象的createObject() 方法里,為了使得形體能夠產生 旋轉運動,我們首先建立了一個TransformGroup對象和一個 Transform3D對象,通過Capability參數的設置,表示在程序 運行時,objTrans能夠進行幾何變換,并將形體放入objTrans。 JAVA3D之所以能夠使形體運動,是因為JAVA3D擁有類似于 VRML的時間傳感器節點的Alpha對象,和類似于VRML的內插器節 點的各種Interpolator對象,它們在由BoundingSphere等對象 所設定的范圍內在特定的時間內進行幾何坐標變化,因而使形 體產生運動變化的效果。 本程序中,Alpha給出了一個4秒鐘的循環變化時間周期; RotationInterpolator規定了形體每4秒鐘繞著Y軸旋轉 一周。BoundingSphere表示所有距離坐標原點50米之內的形體 均可以旋轉運動,而在這范圍之外的所有形體均不產生運動。 和Point5.java相類似的VRML程序如下,VRML里的點不能夠 改變大小: //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 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(九)(轉載) 發信站: 飄渺水云間 (Tue Apr 13 19:47:27 1999), 轉信 JAVA3D學習系列(8)-----直線的生成 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 我們可以利用JAVA3D的一些對象,生成各種直線。 可以生成直線的對象有: 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對象的定義如下: LineArray(int vertexCount, int vertexFormat) 這里: vertexCount表示頂點的個數(必須為偶數) vertexFormat表示頂點的格式(第七講有介紹) 由下面的程序我們得知,Line1.java和前面介紹的 Point4.java幾乎完全一樣,lineShape1.java和 pointShape.java也相差不多。運行Line1.java我們獲得 了三條直線,由此得知,LineArray的作用是生成多條直線, 頂點坐標數組的每一對數據構成一條直線。 在編寫LineArray生成的直線時,要注意,頂點及顏色 的個數必須相等且為偶數,此數目必須賦值于vertexCount,也即 程序中的vertexCount必須為偶數且不能少于頂點的個數。 -------------------------- 第一條 ---------------- 第二條 -------------------------- 第三條 我們可以根據各種不同的情況,生成不同的直線,如 給定寬度的直線、虛線等。相應的的方法有: setLineWidth(float lineWidth) setLinePattern(int linePattern) setLineAntialiasingEnable(boolean state) 對于線型linePattern有以下數據可選: int PATTERN_SOLID int PATTERN_DASH int PATTERN_DOT int PATTERN_DASH_DOT 這些內容對所有種類的直線都有效。 前面我們利用PointArray生成了六個點,這里,我們 將前面的pointShape.java稍微變化一下,則同樣的六個點生 成了三條直線,所用的兩個程序為: //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可用來生成多條折線段 LineStripArray對象的定義如下: LineStripArray(int vertexCount ,int vertexFormat, int[] stripVertexCounts ) 這里: vertexCount表示頂點的個數(必須為偶數) vertexFormat表示頂點的格式(第七講有介紹) stripVertexCounts為一數組,數組里的每一個數值表示 每條折線段所擁有的頂點數目。 下面我們利用lineShape1.java同樣的頂點坐標數組及 顏色數組,用LineStripArray對象生成直線。程序也是兩個: lineShape2.java、Line2.java,并使生成的直線繞著Y軸旋轉, 直線線型為虛線,線寬為30個像素。 //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這個程序和Point5.java幾乎沒有 什么差別,除了類的名字于調用的外部程序名不同之外,其余 完全相同。 lineShape1.java和lineShape2.java相差不大, lineShape2.java多了一個StripCount數組,它可以用來生成 多個折線段,下面的lineShape3.java程序就將Line2.java生成 的一條折線段分成了兩條折線段:0、1、2三個點構成了一個折 線段,3、4、5構成了另一條折線段,每個折線段的頂點數目就 構成了數組StripCount,StripCount數組的大小等于折線段的 數目。 //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軸旋轉的形體用VRML 程序表示的結果為: #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 ] # 兩個折線段 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對象的定義為: IndexedLineArray(int vertexCount, int vertexFormat, int indexCount ) 這里: vertexCount表示頂點數組里頂點的個數 vertexFormat表示頂點的格式(第七講有介紹) indexCount表示選用的頂點個數,如果一個點用了 幾次,則要把幾次加進去 在上一節里我們介紹了利用IndexedPoint生成點 的程序,和IndexedPoint相類似,我們可以利用 IndexedLineArray生成直線段。 下面的lineShape4.java利用了IndexedLineArray 從六個點中挑選了3個點,生成了2條直線。 從程序中我們可以看到,下標為0的點使用了兩次, 但生成的是兩條線,因而參數VertexCount應為4,即 此處的VertexCount的數值應為直線條數的兩倍。 //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的相應程序為: #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對象的定義如下: IndexedLineStripArray( int vertexCount, int vertexFormat, int indexCount, int stripIndexCounts[]) 這里: vertexCount表示頂點數組里頂點的個數 vertexFormat表示頂點的格式(第七講有介紹) indexCount表示選用的頂點的個數 stripIndexCounts為一數組,數組里的每一個數值表示 每條折線段所擁有的頂點數目。 下面的程序里,我們給出10個頂點, --0-- --1-- --2-- --3-- --4-- --5-- --6-- --7-- --8-- --9-- 然后我們用IndexedLineStripArray生成三個折線段,第一個 折線段為:0 1 3 2,第二個折線段為3、5、4,第三個折線段為 6、7、8、6,最后一個點沒有用到。所有的直線寬度為30像數。 這時我們只用了10個點中的9個點,但有2個點用了兩次,因而程序 中的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 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(十)(轉載) 發信站: 飄渺水云間 (Tue Apr 13 20:00:11 1999), 轉信 JAVA3D學習系列(9)----- 面的生成(上) 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 一. 生成平面的對象及其定義 JAVA3D可通過編程顯示出面來,面有兩種:三角形和四邊形, 相應的對象為Triangle和Quad。 JAVA3D用于生成平面的對象有: 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來生成,利用它可以生成三角片面我們先看一下TriangleArray的定義: TriangleArray (int vertexCount, int vertexFormat ) 這里: vertexCount表示頂點的個數(必須為三的倍數) vertexFormat表示頂點的格式(第七講有介紹) 下面我們看一個利用TriangleArray的例子,例子里有九個點。 --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 從程序運行結果可以得知,TriangleArray將一個頂點數組的 每三個數組合在一個,生成一個面,因而vertexCount的點數必須 為三的倍數。triShape1.java顯示的結果是三個三角形構成的面。 由于對每一個頂點都定義了顏色,因而程序顯示的是色彩變化的 三角形,且只能從正面看到,反面看不到,這和VRML程序生成面 的效果完全一樣。在VRML程序中,為了使一個面的正反方向都可見, 可以在IndexedFaceSet節點中將solid字段設為FALSE。 下面是和triShape1.java相對應的VRML程序,為了使面的正反 都可見,我們將IndexedFaceSet的solid字段設為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顯示的內容從色彩變化及單面顯示 變為每一個面只有一種顏色及雙面顯示? VRML程序中我們可以將IndexedFaceSet節點的 colorPerVertex設為FALSE,并提供一個 colorIndex字段以挑選顏色數組中的顏色。 在JAVA3D程序中我們有一個笨辦法處理顏色問題,即將 每一個面的三個點的顏色均設定為相同的數值,因為 TriangleArray對象沒有 setColorIndices(0,index) 這一方法,故不能從顏色組中選用顏色。 至于雙面顯示問題,我們可以通過設定PolygonAttributes 對象的setCullFace(int cullFace)方法來獲得,cullFace可以為: CULL_NONE CULL_FRONT CULL_BACK 通過選擇其中之一,來獲得前面、后面及雙面的顯示效果,缺省 值為只顯示前面。 另外,我們還可以通過設定PolygonAttributes對象的 setPolygonMode(int polygonMode)方法使面用頂點或端線來代替。 polygonMode有下列三種選擇: POLYGON_POINT POLYGON_LINE POLYGON_FILL 缺省值為POLYGON_FILL。 triShape2.java顯示的是前后都可以看得見的面,每一個面 都有唯一的顏色。 //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); // 增加這一行會使面由線代替 Appearance ap = new Appearance(); ap.setPolygonAttributes(pa); this.setGeometry(tri); this.setAppearance(ap); } } 三. QuadArray生成的面 QuadArray對象的定義如下: QuadArray (int vertexCount, int vertexFormat ) 這里,每一個參數的含義都和TriangleArray里的一樣。 QuadArray可用來生成平面,構成平面的頂點的數目必須為 4的倍數。 下面我們來看一個利用QuadArray的例子,例子里有8個點, 程序運行后生成了兩個長方形面。 //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應用程序時,我們要注意幾個問題。 首先是四點應當共面,如果不共面,程序仍然可以編譯 運行,但顯示的內容為兩個三角面。 其次是四個點組成的面不應有凹點,這有點象VRML程序中 的Extrusion、IndexedFaceSet里的情況,當然,在VRML程序中 四個點構成的面可以有凹點,這時只需要在相應的節點內加上 一個參數: convex TRUE 而在JAVA3D程序中,如果QuadArray生成的面有凹點時, 程序的顯示結果會不正確,例如,當我們將quadShape里的頂點 坐標換為: 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, }; 時,顯示的結果不確定,正面時是一個形狀,轉到反面時是 另一個形狀。 最后一個問題是QuadArray所利用的每四個點,其坐標 位置除了要共面、凸點,四個點的旋轉方向也要注意,如果 點的旋轉方向是逆時針的話,其正面朝外,反之則朝內。當 我們將頂點的坐標換成下面的數據時,我們可以清楚地得出 這一結論。 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對象的定義為: TriangleStripArray ( int vertexCount , int vertexFormat, int[] stripVertexCounts ) 利用TriangleStripArray對象,我們可以生成多組三角片面, 對于每一組三角片面來說,它的頭三個點生成一個面,從第四個點 開始,每一個點都和前兩個點生成一個新的面。 下面的程序中,我們利用一組點,生成了兩組三角片面。程序 中,頂點數組的個數為11,頭一組用了7個頂點,生成了5個相連的 三角片面,后一組用了5個頂點,生成了三個相連的三角片面。 //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對象的定義為: TriangleFanArray ( int vertexCount ,int vetexFormat, int[] stripVertexCounts ) 利用TriangleFanArray對象,我們可以生成多組三角片面,每組 三角片面占用一定數量的頂點,每個組在生成三角片面時,頭三個頂 點構成一個三角片面,其余的頂點和前面的頂點及每組第一個頂點生成 一個三角片面。下面的triShape4.java程序中,我們生成了兩組三角 片面,頭5個點生成了三個相連的三角片面,后6個點生成了四個相連的 三角片面。形狀就像兩把扇子,一大一小。 //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 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(十一)(轉載) 發信站: 飄渺水云間 (Tue Apr 13 20:13:18 1999), 轉信 JAVA3D學習系列(10)----- 面的生成(下) 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 一. IndexedTriangleArray生成的面 IndexedTriangleArray對象的定義為: IndexedTriangleArray (int vertexCount , int vertexFormat, int indexCount) 利用這個對象,我們可以從一個頂點數組中挑選一些頂點生成自己 所需要的三角片面。程序triShape5.java中,有一個10個點的數組,我們 從這個數組中選擇了8個點,生成了三個面,其中有一個點用了兩次,如果 所挑選的點都只用一次,則選擇的點的數目必須為3的倍數。 另外,在編程時,我們要注意點的旋轉順序,逆時針旋轉和順時針 旋轉有時會產生不同的效果。 程序中,vertexCount表示頂點數組頂點的總數,indexCount表示生成 的面的頂點個數,數值為面的個數的三倍,本例中,生成的面為三個,故 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對象的定義為: IndexedQuadArray (int vertexCount , int vertexFormat, int indexCount ) 利用這個對象,我們可以從一個頂點數組中挑選一些頂點生成自己 所需要的四個點所構成的平面。程序quadShape2.java中,有一個10個點 的數組,我們從這個數組中選擇了7個點,生成了兩個面,其中有一個點 用了兩次,如果所挑選的點都只用一次,則選擇的點的數目必須為4的倍數。 這些選中的點構成了數組index。在輸入每一個頂點的坐標及顏色時,我們 用到了下面兩種方法: setCoordinateIndices(0,index); setColorIndices(0,index); 程序中,vertexCount表示頂點數組頂點的總數,indexCount表示生成 的面的頂點個數,數值為面的個數的4倍,本例中,生成的面為兩個,故 vertexCount為8。 編寫IndexedQuadArray應用程序時,我們仍然要注意下面幾個問題。 首先是四點應當共面,如果不共面,程序仍然可以編譯 運行,但顯示的內容為兩個三角面。 其次是四個點組成的面不應有凹點,這有點象VRML程序中 的Extrusion、IndexedFaceSet里的情況,當然,在VRML程序中 四個點構成的面可以有凹點,這時只需要在相應的節點內加上 一個參數: convex TRUE 而在JAVA3D程序中,如果QuadArray生成的面有凹點時, 程序的顯示結果會不正確。 //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對象的定義為: IndexedTriangleStripArray( int vertexCount, int vertexFormat, int indexCount, int stripIndexCounts[]) 利用IndexedTriangleStripArray對象,我們可以生成多組三角片面, 對于每一組三角片面來說,它的頭三個點生成一個面,從第四個點 開始,每一個點都和前兩個點生成一個新的面。這些點可以通過一個數組index 從一個頂點數組中任意選取,它和TriangleStripArray的差別在于 TriangleStripArray對頂點沒有選擇權,而IndexedTriangleStripArray 對頂點具有選擇權,其它的都一樣。 程序triShape6.java給出了一個16個數構成的頂點數組,從中挑選了 兩組數,每一組都有6個頂點構成并生成了相連的四個三角片面。 //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對象的定義為: IndexedTriangleFanArray ( int vertexCount, int vertexFormat, int indexCount, int stripIndexCounts[]) 利用這一對象,我們可以從一組頂點數組中挑選我們所需要的 頂點,生成多組三角片面,每組三角片面占用一定數量的頂點,每個組 在生成三角片面時,頭三個頂點構成一個三角片面,其余的頂點和前面 的頂點及每組第一個頂點生成一個三角片面。下面的triShape7.java程 序中,我們生成了兩組三角片面,頭5個點生成了三個相連的三角片面, 后6個點生成了四個相連的三角片面。形狀就像兩把扇子,一大一小。 程序中所用的數組為20個點的頂點數組。 IndexedTriangleFanArray對象和TriangleFanArray的應用方法很相似, 它們之間的不同在于IndexedTriangleFanArray對象可以從頂點數組中挑選 自己所需要的頂點,而TriangleFanArray對象沒有挑選權,只能被動地使用 頂點數組中的數據。 //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 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(十二)(轉載) 發信站: 飄渺水云間 (Fri Apr 16 13:32:38 1999), 轉信 JAVA3D學習系列(11)---外部復雜形體的調用 (Wavefront的OBJ,Lightwave的LWS和LWO,WRL,DWG,3DS) 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 我們可以利用前面介紹的方法生成我們所需要的基本形體, 生成點、線、平面。但有的時候,我們需要用到其它格式的三 維形體,如VRML2.0格式的圖形文件,AUTOCAD繪出的DWG格式的 三維形體,3DS MAX繪制出的復雜形體。對于這些形體,我們可 以非常方便地將其用到JAVA3D程序中去。下面我們介紹一些圖形 格式在JAVA3D中的應用方法。 一. Wavefront的OBJ格式的圖形文件的調用 1. OBJ格式圖形的簡單調用 JAVA3D編譯環境所帶的UTILITY有兩個LOADER,一個可用來 調用Wavefront軟件的OBJ格式的三維圖形格式文件,一個可用來 調用Lightwave軟件的LWS及LWO格式的三維圖形格式文件。 假設我們有一個OBJ格式的文件(JAVA3D附帶有兩個OBJ,文 件名分別為galleon.obj和p51_mustang.obj,以及調用它們的一 個程序ObjLoad.java)。 我們編寫的第一個程序Obj1.java介紹了OBJ圖形的調用方法。 程序的便宜方法: javac Obj1.java 程序的運行方法(假設圖形在同一目錄): 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 程序運行后我們發現,顯示的效果不太正確,形體只顯示了 一部分,我們將在Obj2.java將其效果修正一下。 我們來看程序,為了使JAVA3D能夠調用Wavefront的OBJ格式 的圖形文件,我們需要用到JAVA3D所附帶的UTILITY。程序的頭 四行import語句就是用來處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.同時調用兩個形體,兩者單獨旋轉。 前面的程序中,形體只有一個,為此,我們編了一個 程序,利用它可以調用兩個OBJ形體,一左一右,它們分別繞 自身的軸旋轉,當然,形體的生成仍然使用上面的 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 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(十三)(轉載) 發信站: 飄渺水云間 (Fri Apr 16 13:38:41 1999), 轉信 JAVA3D學習系列(12)---AUTOCAD的DWG、VRML的WRL及3DS MAX圖形的調用 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 一. VRML2.0(VRML97)圖形文件在JAVA3D中的應用簡介 SUN公司為我們提供了一個VRML97的LOADER,利用它我們可以 在JAVA3D程序中方便地調用VRML圖形。不過由于這個LOADER目前 還不是很完善,因而沒有放入JAVA3D之中,不過隨著它的完善, 最終它會成為JAVA3D的一個組成部分,調用VRML97程序就象調用 Wavefront的OBJ一樣簡單。 我們可以從以下的網址下載(VRML97.ZIP)并安裝,下載的網址為: http://www.vrml.org/WorkingGroups/vrml-java3d/ 從這個網頁上我們需要下載目前大小為283KB的一個ZIP文件, VRML97.ZIP,利用解壓程序將其解成VRML97.JAR,大小目前為310KB, 版本為0.90.2版,利用它可以讓我們在JAVA3D程序中調用 VRML97(VRML2.0)圖形。 *********好消息****************** 為了使國內的JAVA3D愛好者能夠節省時間及開支,本人愿意 向國內的JAVA3D愛好者提供最新的VRML97.JAR,咨詢請發EMAIL。 收到EMAIL后一分鐘內就可將VRML97.JAR發出。 *********好消息****************** 二. VRML97.JAR的安裝 獲得VRML97.JAR后,假設我們的JDK1.2擺放的位置為目錄JDK1.2, 我們應將其放在下面的子目錄中: C:\jdk1.2\lib 并在WINDOWS的AUTOEXEC.BAT文件中寫入下面一行: SET CLASSPATH=%CLASSPATH%;C:\JDK1.2\LIB\vrml97.jar 重新啟動計算機,這樣我們就可以利用它了。 當然,我們可以將VRML97.JAR放在一個目錄中,利用下面的方法 將其解開,不過所獲得的全為CLASS文件。 三. VRML97.JAR的應用 1. 利用VRML971.JAR調用一個VRML文件,使VRML文件中的形體不停地 旋轉,程序如下。 程序的編譯方法: javac Vrml1.java 程序的運行方法(假設圖形在同一目錄): java Vrml1 myShape.wrl 當然,如果所調用的形體非常大或非常小時,需要修改: t3d.setScale(0.3); 中的數值。 //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分解成兩個程序 上面的程序中,用于處理調用問題的部分我們可以提取出來,這樣 我們就可以多次重復使用。 從下面的程序我們可以得知,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. 調用兩個VRML文件并使其放在不同的位置處旋轉 編寫這個程序非常簡單,只需將前面介紹的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中的應用。 在三維圖形生成過程中,國內目前大量使用AUTOCAD及3DS MAX等 軟件。如何將這些軟件生成的三維圖形應用到JAVA3D上去呢? 對于3DS MAX軟件,處理起來非常方便,因為3DS MAX可以將其圖形 直接輸出成VRML97格式,因而可以按本講介紹的方法處理。 對于AUTOCAD R14來說,目前還不太方便,不知AUTOCAD 2000是否 能直接輸出VRML97圖形格式。本人從歐洲捷克一個站點拷得一個文件, 可用來直接將AUTOCAD R14所繪制的三維圖形轉換成VRML97(VRML2.0) 格式,因而AUTOCAD軟件生成的圖形也可以非常方便地應用到JAVA3D上面, 為我們編寫JAVA3D的復雜應用程序打下了良好的基礎。此軟件非常好用 (采用ARX技術編寫)。 **************好消息************** 需要將AUTOCAD R14所生成的圖形轉換成VRML2.0的朋友,可 發一個EMAIL給我,在收到EMAIL一分鐘之內,我將把 AUTOCAD ----> VRML的轉換文件發出,大小為206KB。 **************好消息************** 發信人: cypress (Cypress), 信區: Cad 標 題: Java3D學習系列(十四)(轉載) 發信站: 飄渺水云間 (Sun Apr 18 14:17:51 1999), 轉信 JAVA3D學習系列(13)---形體的組合及幾何坐標變換 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) VRML2.0(VRML97)中,有兩個用來組合各形體的組節點: Transform、Group,其中的Group節點完全可以用Transform 節點來代替。如何在JAVA3D中實現Transform所提供的幾何變換 功能,是我們掌握JAVA3D應用編程的基礎。下面我們對此給以 詳細的介紹。 我們首先來看一下VRML97的Transform節點的定義: Transform節點的定義是: 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程序中,我們可以通過設定 translation、rotation、scale來使形體產生平移、旋轉、 比例變換。如VRML2.0交互式三維圖形編程一書所給出的一個 生成一個小丑的程序Ex4_03.wrl,里面就對形體進行了平移、 旋轉、比例變換。我們先給出Ex4_03.wrl程序(我們對 書中的程序進行了修改,使生成的小丑能夠旋轉),再給出 用JAVA3D編寫出來的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 我們來仔細研究JAVA3D所提供的形體幾何變換功能。 前面我們主要介紹形體生成的方法,其中,編寫自己的形體 用到的是Shape3D對象,VRML97與之對應的是Shape節點。 同樣,JAVA3D對應于VRML97的Transform節點的對象是Transform3D。 VRML97編程中,形體的平移可以通過Transform節點的 translation字段來設置;JAVA3D編程時,形體的平移可以通過 Transform3D的setTranslation方法完成。 VRML97編程中,形體的旋轉可以通過Transform節點的 rotation字段來設置;JAVA3D編程時,形體的旋轉可以通過 Transform3D的setRotation方法完成。 VRML97編程中,形體的比例變化可以通過Transform節點的 scale字段來設置;JAVA3D編程時,形體的比例變化可以通過 Transform3D的setScale方法完成,其中,當擴弧里只有一個雙 精度數時,setScale對所有的方向均采用同一個比例,而當里面 有三個雙精度數時,setScale對不同的方向可以采用不同的比例, 雙精度數后面不加符號,而單精度浮點數后面要加一個f。 我們來看一下程序的主要內容: 程序一開始就定義了一個BranchGroup,后面所有的生成的內容 如形體、形體的變換、背景、燈光都放入其中。 為了使我們生成的圖形有合適的大小,我們定義了一個 TransformGroup對象objScale,通過一個t3d使其按比例縮小,這 相當于我們將視野往后移動。 為了使我們生成的小丑能夠旋轉,我們定義一個TransformGroup 類型的obj,這相當于定義了一個小丑所在的局部坐標系,設定此 坐標系可以旋轉,選轉方式由一個Transform3D類型的temp來確定, 定義obj為objScale的一個子節點。 通過定義rotationAlpha、rotator地定義使得obj能夠產生旋轉。 它們的作用類似于VRML的時間傳感器及方向內插器。 接下來我們在空間中定義了一個定向光、各種材質、形體,并 將燈光、具有一定材質的形體放入objRoot、obj之中,最后我們 還定義了一個背景光。 通過這個程序的編寫,我們掌握了JAVA3D生成復雜形體的最基本 概念,即如何進行形體的幾何坐標變換。掌握了形體幾何坐標變換 方法,我們就具有了編寫JAVA3D復雜應用程序的能力。 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(十五)(轉載) 發信站: 飄渺水云間 (Sun Apr 25 22:16:51 1999), 轉信 JAVA3D學習系列(14)---初始觀察位置的設定 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 一. 初始觀察位置的給定 前面我們介紹的JAVA3D程序,在沒有進行比例變換前,觀察點位于 (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(); 多個語句確定的,在前面的第5講已經對其作了簡單介紹,大多數程序 都利用這些語句定義場景圖中的一個觀察分支。 我們可以將JAVA3D所提供的java3d-utils-src.jar按照下面 的方式解開: jar xvf java3d-utils-src.jar 就可以獲得JAVA3D所有UTILITY的源程序,我們可以從其中的 SimpleUniverse.java、ViewingPlatform.java 程序了解JAVA3D是如何進行觀察點初始位置的設置的。 語句中的u定義了一個SimpleUniverse類型的對象實例。 getViewingPlatform()方法定義在ViewingPlatform.java中, 利用它可以獲得程序所需要的觀察位置,而此方法又通過 ViewingPlatform.java中的setNorminalViewingTransform() 來做進一步的設置。 在沒有用到setNorminalViewingTransform()之前, ViewingPlatform() 給出的缺省觀察位置為坐標原點(0,0,0), 而當我們用到setNorminalViewingTransform()時,由 viewDistance我們得知這時的觀察點的Z坐標移到了 1/tan(math.PI/8),也即2.41。 **************這時的觀察視角為90°**************** 如果要使程序的觀察點為一個可以很方便改動的點,我們就 需要將程序改動,下面是我們將前面介紹的第4講的程序 SimpleCone.java,修改獲得的新程序NewCone.java,兩者的差別 在于,SimpleCone.java的觀察點位于(0,0,2.41), NewCone.java的觀察點坐標位于(0, 0, 10)。我們可以根據需要 設定初始的觀察點的位置,這時只需要方便地將(0,0, 10)改為 我們所需要的任何數值。初始觀察位置改動同樣用到了 SimpleUniverse對象,只是將對象的觀察點坐標變量作了修改。 //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); //初始觀察點位置 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 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(十六)(轉載) 發信站: 飄渺水云間 (Mon Apr 26 11:57:22 1999), 轉信 【 以下文字轉載自 screamer 的信箱 】 【 原文由 screamer 所發表 】 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 1997年底正式成為國際標準的VRML2.0是我們編寫簡單 三維應用程序的一個非常合適的計算機語言,利用它,我們可以 非常方便地編寫三維動畫、交互式的三維游戲,當然,只能 是一些較為簡單的三維動畫及交互式三維游戲。而利用JAVA3D 則可以編寫出較為復雜的三維動畫及交互式三維游戲。 前面我們介紹了JAVA3D的形體生成等方面的知識,JAVA3D 三維應用程序最吸引人之處是它可以用來制作三維動畫、三維 游戲等。為了掌握JAVA3D三維動畫、三維游戲的編程,我們首先 要掌握三維形體在空間的運動控制。 VRML語言有6個內插器節點和7個傳感器節點,同樣地,在 JAVA3D中,也有和VRML內插器節點類似的Interpolator對象,它 們和另一個Alpha類結合在一起,可以編寫出各種類型的三維動畫 程序。 下面我們就介紹這些對象及其應用方法。 一. Alpha類 從VRML的各個內插器節點的定義來看,我們可以看到,每一個 內插器節點都有一個key字段和一個keyValue字段。key字段定義 一個數組,數值從0到1。 所有的內插器節點在使用時都需要與TimeSensor(時間傳感器) 配合使用。TimeSensor把給定的時間周期歸一化,雖然時間的周期 cycleInterval 有給定的秒數,但計算機內部將其處理成從0.0到 1.0,即起始時間為0.0,終止時間為1.0,假如一個時間周期為 20(單位均為秒),則第6秒的歸一化結果是0.3,第10秒的歸一化 結果是0.5,第20秒的歸一化結果是1.0。 JAVA3D里的Alpha類和VRML的key字段的功能類似,它也是用于 輸出歸一化的時間,不過它能夠處理更加復雜的時間安排問題。 Alpha可以輸出從0到1之間的數值給特定的內插對象,當Alpha 輸出的數值為0時,對應的特定內插對象的值為最小;當Alpha輸出 的數值為1時,對應的特定內插對象的值為最大;當Alpha輸出的數 值為0到1之間的數值時,對應的特定內插對象生成和Alpha成相同 比例的數值。假設某一時刻Alpha輸出的數值為0.2,則對應的特定 內插對象的當前值為最小值加上最大最小值之差乘以0.2。 (當前值-最小值)/(最大值-最小值)=0.2 JAVA3D里的各種Interpolator對象和VRML的內插節點的作用 比較類似,可用來旋轉形體、移動形體的坐標、變化形體的顏色等。 假設我們要讓一個形體在規定的時間內按照指定的方式運動, 我們首先要給出時間段的大小,還要指出時間是否要循環。這些內容 都是由Alpha類來完成的。 Alpha類的構造函數定義如下: public Alpha(int loopCount, int mode, long triggerTime, long phaseDelayDuration, long increasingAlphaDuration, long increasingAlphaRampDuration, long alphaAtOneDuration, long decreasingAlphaDuration, long decreasingAlphaRampDuration, long alphaAtZeroDuration) 我們在前面已多次用到Alpha類,基本上我們用它及一個旋轉內 插器RotationInterpolator來使形體繞著其所在的局部坐標系不停 地旋轉。下面是我們眼熟的語句,語句的作用是讓形體以4秒為一周 期,不停地繞著某一個軸旋轉(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構造函數中: loopCount表示循環的次數,例如如果我們將前面介紹的Ex4_03.java 的loopCount設為10,則小丑會旋轉10周,然后停止。不過在一些運行速度 慢的計算機上會出現少幾次的情況,如作者本人使用的一臺機器是 Pentium 586/100的計算機,當loopCount為10時,只看到小丑旋轉了7次, 因為程序從開始運行到出現畫面,需要一段時間。loopCount為-1時表示 無限循環。我們可以利用下面兩個方法設置或獲得loopCount: public void setLoopCount(int loopCount) public int getLoopCount() mode表示Alpha每一周期的運行方式,一共有三種:INCREASING_ENABLE、 DECREASING_ENABLE、INCREASING_ENABLE|DECREASING_ENABLE。第一種 方式表示Alpha的數值從0到1,相對應的內插對象的數值從最小到 最大;第二種方式表示Alpah的數值從1到0,相對應的內插對象的數值 從最大到最小;第三種方式表示Alpah的數值從0到1,然后從1到0, 相對應的內插對象的數值從最小到最大,然后又從最大到最小。 我們前面用到的Alpha,它每一個周期的數值,都是從0到1,對應的內插 對象的數值,在每一個循環周期里,都是從最小到最大。我們可以 利用下面兩個方法,設置或獲得mode: public void setMode(int Mode) public int getMode() triggerTime表示Alpha起作用的時間,它可由外部來觸發,它和后面 的7個參數的單位均為毫秒。 triggerTime參數后面還有7個類型為long的數,我們可以設置 這些數值,來達到我們的各種編程目的。 前面我們介紹了VRML中各內插器節點key字段的作用,在VRML中, key的值只能從0到1。而在JAVA3D中,Alpha輸出的值不僅可以從0到1, 還可以從1到0,甚至可以先從0到1,再從1到0。 VRML程序中各內插器節點的keyValue字段則根據key給定的數值, 輸出相應的數值,計算機在keyValue各個數之間進行線性插值。而 JAVA3D的Alpha則不僅可以對各內插對象的數值進行線性插值,而且 可以利用increasingAlphaRampDuration、decreasingAlphaRampDuration 這兩個參數進行非線性插值,插值曲線可以從SUN公司所提供的JAVA3D的 API中看出,這時又分兩種情況:Ramp大于1/2、Ramp小于1/2。 接下來我們將通過多個JAVA3D動畫程序的編制,介紹Alpha的各個參數。 JAVA3D動畫編程時經常使用的10個內插器對象,它們分別是: PositionInterpolator RotationInterpolator ColorInterpolator ScaleInterpolator SwitchValueInterpolator TransparencyInterpolator PositionPathInterpolator RotPosPathInterpolator RotPosScalePathInterpolator RotationPathInterpolator 二. PositionInterpolator對象 為了編寫一個彩色立方體在空間的運動,我們用到了JAVA3D所提供 的PositionInterpolator對象。 PositionInterpolator對象的定義如下: public PositionInterpolator(Alpha alpha, TransformGroup target, Transform3D axisOfTranslation, float startPosition, float endPosition) 利用這個對象,我們可以在給定的時間內,使某一個局部坐標系 在兩個點之間按照Alpha提供的方式移動位置,它的作用類似于VRML 的PositionInterpolator節點,兩者的名字完全一樣。 PositionInterpolator對象也有多個方法,用于參數的設定,如: 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) 我們先編寫一個VRML程序,使一個形體沿著X軸線左右移動,其實, 形體并沒有移動,移動的只是形體所在的局部坐標系,源程序Pos.wrl 如下,注意,它的觀察點坐標位于(0 ,0 , 10),左右移動一周的時間 為20秒,左右移動的范圍是(-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 -------------------------------------------------------- 我們再利用PositionInterpolator對象編寫類似的JAVA3D應用程序, 同樣,Pos.java的觀察點坐標也位于(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); //初始觀察點位置 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 運行Pos.java后我們發現,JAVA3D、VRML程序運行效果基本一致。 1. PositionInterpolator對象里的參數 我們來看一下Pos.java里定義的PositionInterpolator對象實例 tran里的各個參數。 xtranAlpha表示局部坐標系的變化方式是由xtranAlpha這個Alpha 定義的。 group給出了受影響的局部坐標系的名稱。 tr給出了PositionInterpolator運動變化的方向,缺省時為沿X軸。 -4.f,4.f給出了局部坐標系移動的范圍,表示坐標系的原點在 (-4 , 0 , 0 ) 和 ( 4 , 0 , 0 )之間移動。 2. xtranAlpha里各參數的含義 -1表示無限循環 Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE表示在一個 周期里面,局部坐標系統的位置從(-4, 0 , 0)移到(4 , 0 , 0),再從 (4 , 0 , 0)回到(-4 , 0 , 0),即從最小值到最大值,再從最大值到 最小值。 頭一個10000表示局部坐標系從最小值移到最大值所用的時間,為 10秒。 第二個10000表示局部坐標系從最大值移到最小值所用的時間,也 為10秒,因而一個周期的時間為20秒。 3. 坐標軸的改變。 當然,我們可以改變局部坐標系移動的坐標軸,例如,當我們想 讓局部坐標系沿著Y軸移動時,我們就可以在 Transform3D tr=new Transform3D(); 后面加上一句: tr.rotZ(Math.PI/2) ; 如果我們加的是: tr.rotY(Math.PI/2) ; 則形體沿著Z軸移動。 后面我們在詳細介紹Transform3D時還將詳細介紹坐標系的變換 方法。 三. Alpha構造函數后7個參數的含義 我們再次給出Alpha類的構造函數: public Alpha(int loopCount, int mode, long triggerTime, long phaseDelayDuration, long increasingAlphaDuration, long increasingAlphaRampDuration, long alphaAtOneDuration, long decreasingAlphaDuration, long decreasingAlphaRampDuration, long alphaAtZeroDuration) Alpha構造函數里的頭三個參數我們已經介紹過了,我們在這里介紹 它的后7個參數,它們用于定義各內插對象的周期變化方式。 Alpha將每一個周期分外5個時段: 起始延遲時段 上升時段 高位時段 下降時段 低位時段 ------ / \ / \ / \ ------- ------- 每個周期的時間長度為這5個時段時間長度之和。 每一個Alpha都必須給出這5個時段,當然,其中的任何數都可以為0, 因而我們可以獲得各種各樣的Alpha類型。下面我們給出部分類型: 1. 只有上升時段的類型 / / / / / / / / / / / / 這種類型的Alpha輸出的數值從最小升到最大,然后又從最小升到最大。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,20000, 0, 0,0, 0, 0); 它使形體從左移到右,再將形體跳回到左邊。 2. 只有下降時段的類型 \ \ \ \ \ \ \ \ \ \ \ \ 這種類型的Alpha輸出的數值從最大降到最小,然后又從最大降到最小。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE, 0, 0,0, 0, 0,20000, 0, 0); 它使形體從右移到左,再將形體跳回到右邊。 3. 上升加高位時段的類型 --- --- / / / / / / / / 這種類型的Alpha輸出的數值從最小升到最大,暫停一段時間, 然后又從最小升到最大。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,10000, 0, 10000, 0,0, 0); 它使形體從左移到右,暫停一段時間,再將形體跳回到左邊。 4. 下降加低位時段 \ \ \ \ \ \ ---- ---- 這種類型的Alpha輸出的數值從最大降到最小,暫停一段時間, 然后又從最大降到最小。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE, 0, 0,0, 0, 0, 10000,0, 10000); 它使形體從右移到左,再將形體跳回到右邊。 5. 暫停、上升加高位時段的類型 ---- / / / / ---- 這種類型的Alpha輸出的數值一開始先暫停,然后從最小升到最 大,再暫停一段時間。不過要注意的是,這種類型不能用于 循環方式。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(1, Alpha.INCREASING_ENABLE, 0, 5000,10000, 0, 5000, 0,0, 0); 它使形體暫停一段時間,從左移到右,再暫停一段時間。 6. 暫停、下降加暫停時段的類型 ---- \ \ \ ------ 這種類型的Alpha輸出的數值一開始先暫停,然后從最大升到最 小,再暫停一段時間。不過要注意的是,這種類型也不能用于 循環方式。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(1, Alpha.DECREASING_ENABLE, 0, 0,0, 0, 5000, 10000,0, 5000); 它使形體暫停一段時間,從右移到左,再暫停一段時間。 7. 5種時段均有的類型 ----- / \ / \ / \ ----- ----- 此種類型的Alpha輸出的數值一開始先暫停,然后從最小升到 最大,再暫停一段時間,然后下降到最小,最后再暫停一段時間。 不過要注意的是,這種類型也不能用于循環方式。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(1, Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE, 0, 3000,5000, 0, 3000, 5000,0, 3000); 8. 上升、暫停、下降、暫停類型 ---- ---- / \ / \ / \ / \ / \------/ \----- 本類型和第7種很相似,但沒有上升前的暫停階段,因而可以 用于循環方式。 我們將前面的Pos.java改成這種類型時,生成的Alpha應為: Alpha xtranAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE, 0, 0,5000, 0, 5000, 5000,0, 5000); 9. Alpha的加速 前面介紹的8種類型,可以用于各種場合,如開關門等。但它們 均有一個問題,即形體從靜止到運動的變化是跳躍性的,變化時的 加速度為無窮大。為此,JAVA3D還提供了兩個參數,解決這個問題, 這就是Alpha里的increasingAlphaRampDuration和 decreasingAlphaRampDuration,它們有兩種應用方式:一是設置為 大于或等于0.5,一是設置為小于0.5。 當它們的值為第一種情況時,計算機自動將其轉成0.5,使Alpha 產生的加速度在頭一半時間是均勻加速的,在后一半時間里是均勻 減速的,因而在頭一半時間里,加速度是正數,在后一半時間里, 加速度是相同的負數(請參考JAVA3D的API說明)。 第一種情況在某一時段的速度圖: /\ / \ / \ / \ 下面我們給出這樣一個Alpha的例子: Alpha xtranAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE, 0, 0,5000, (long)0.5, 5000, 5000,(long)0.5, 5000); 當這兩個數小于0.5時,Alpha只在時間段的兩頭產生加速度, 中間的加速度為0,因而中間的速度保持不變。 下面我們給出這樣一個Alpha的例子: Alpha xtranAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE, 0, 0,5000, (long)0.2, 5000, 5000,(long)0.5, 5000); 第二種情況在某一時段的速度圖: -------- / \ / \ / \ m 發信人: screamer (Screamer), 信區: Cad 標 題: Java3D學習系列(十七)(轉載) 發信站: 飄渺水云間 (Sun May 2 18:33:40 1999), 轉信 JAVA3D學習系列(16)--動畫的生成(中) 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 上一講我們已經介紹了一個JAVA3D的內插對象: PositionInterpolator。本講我們將繼續介紹其它的 內插對象。 一. RotationInterpolator對象 RotationInterpolator的構造函數有兩個: 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) 利用這個對象,我們可以在給定的時間內,使某一個局部坐標系 在按照Alpha提供的方式繞著某一個軸旋轉,它的作用類似于VRML 的OrientationInterpolator節點。 RotationInterpolator的前三個參數和我們上一講介紹的 PositionInterpolator對象的前三個參數概念一樣: Alpha為我們提供了旋轉方式。 target為我們提供了需要旋轉的局部坐標系。 axisOfRotation確定了旋轉軸的方位。 1. 第一個構造函數的運行結果 假如我們利用的是第一個構造函數,我們所獲得的最大角度為 2*PI,最小角度為0,坐標系繞著Y軸,按照Alpha給出的旋轉方式 旋轉。 2. 第二個構造函數的運行結果 我們來看一下OrientationInterpolator第二個構造函數的后兩 個參數,它們給出了旋轉的最大最小的角度。 下面的程序Rot.java利用了RotationInterpolator對象,使一個 立方體繞著自己的Y軸不停地旋轉:先正轉180度。停頓幾秒后,又反 轉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); //初始觀察點位置 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 我們給出相應的VRML語言編寫出的程序,由VRML程序的 運行結果可以看出,VRML程序無法使形體的速度漸變,而只 能突變,因而JAVA3D在這一方面功能較強。 #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 如果我們在JAVA3D程序的 Transform3D tr=new Transform3D(); 后面加上一句: tr.rotZ(Math.PI/2) ; 則形體從繞著Y軸旋轉改為繞著X軸旋轉。 二. ColorInterpolator對象 ColorInterpolator的構造函數也有兩個: 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) 利用這個對象,我們可以在給定的時間內,使某一個Material 對象的漫反射光DiffuseColor發生變化。按照Alpha提供的方式變化, 它的作用類似于VRML的ColorInterpolator節點,兩者的名字完全一樣。 1. 第一個構造函數的運行結果 如果我們采用的是第一個構造函數,則startColor為黑色, endColor為白色。本人利用此方法編寫了幾個程序,發現形體的 顏色難以控制,因而建議大家少使用這個方法。 2. 第二個構造函數的運行結果 采用第二個構造函數時,我們需要設定startColor和endColor 這兩個顏色。不過要注意,為了使Material對象的DiffuseColor 產生變化的效果,我們應在空間增加一個對著形體照射的光線, 否則形體顯示的依舊是輻射光EmissiveColor。 但我們經過多次實驗,發現ColorInterpolator對象產生的 效果不是我們所預期的效果,例如,如果我們想使形體的 diffuseColor從顏色a變到顏色b,顯示的結果卻是形體的 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 我們給出程序對應的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對象 ScaleInterpolator對象的構造函數有兩個: 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) 利用這個對象,我們可以在給定的時間內,使某一個局部坐標系 的各個方向按照Alpha提供的方式進行比例變化,它的作用在VRML 程序中可以用PositionInterpolator來代替。 ScaleInterpolator的第一個構造函數為我們提供了缺省的比例數 值,最大為1.0f,最小為0.1f。下面的程序利用第一個構造函數使一 個立方體在一定的時間內按照Alpha給出的變化方式在各個方向上產生 了相同的比例變化,為了比較,我們還給出了相應的VRML語言編寫的程序。 //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的第二個構造函數允許我們設置最大及最小 的比例數值。我們利用它編寫了下面的這個程序,利用它,可以設 置我們所需要的比例數值。 //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對象的構造函數有兩個: 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) 利用這個對象,我們可以在屏幕上在不同的時間分別顯示 不同的形體。例如下面程序里,計算機按循環顯示形體,每一個 周期顯示的內容為:大立方體--球--圓錐--小立方體--圓錐--球。 當然,當我們采用第一個構造函數時,結果和本程序一樣。 當我們將程序中的: SwitchValueInterpolator sv = new SwitchValueInterpolator(scaleAlpha, s,0,4); 改為: SwitchValueInterpolator sv = new SwitchValueInterpolator(scaleAlpha, s,0,3); 時,每一個周期顯示的內容為:大立方體--球--圓錐--球,由此看 來,第四個形體沒有顯示出來。 //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 發信人: screamer (Screamer), 信區: Cad 標 題: Java學習系列(十八)(轉載) 發信站: 飄渺水云間 (Thu May 6 21:06:31 1999), 轉信 JAVA3D學習系列(17)--動畫的生成(下) 汕頭大學機電系 張杰(jzhang@mailserv.stu.edu.cn) 一. TransparnecyInterpolator對象 TransparencyInterpolator對象的構造函數有兩個: 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) 利用這個對象,我們可以在給定的時間內,使某一個形體的透明度 按照Alpha提供的方式在兩個數值之間變化,VRML語言中我們可以用 ScalarInterpolator節點來實現同樣的效果。 如果我們使用的是第一個構造函數,則透明度的最大值為1.0f, 最小值為0.0f。 下面是一個應用此方法的JAVA3D程序和一個相對應的VRML程序。 為了看出透明的效果,我們設定背景為白色。 //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對象 我們在后面將要介紹下面這些對象: PositionPathInterpolator RotPosPathInterpolator RotPosScalePathInterpolator RotationPathInterpolator 它們都是PathInterpolator的子類。為此,我們先介紹一下 PathInterpolator對象的作用。 PathInterpolator是Interpolator類的子類,就好象我們 上面介紹的所有的內插對象是Interpolator類的子類一樣。 PathInterpolator的子類能夠借助于父類的下面的這個方法: computePathInterpolation() 來完成所需要的計算。 PathInterpolator還有以下幾個方法: getArrayLengths() public void setKnot(int index, float knot) public float getKnot(int index) 三. PositionPathInterpolator對象 PositionPathInterpolator對象的構造函數為: 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) 利用這個對象,我們可以對某一個局部坐標系按照指定的路徑、 指定的運動方式進行坐標系的移動。 positions[]給出了指定的路徑。 knots[]、alpha給出了指定的運動方式。 下面我們利用這個對象編寫一個使某個立方體按指定路徑,按 指定運動方式的位移運動。 由程序我們得知,立方體圍繞著由pos[]定義的一個長方形平移。 軌跡的第一個點和最后一個點重合。在從第一個點到最后一個點運動 過程中,每一個點都對應一個knot值,第一個knot值為0.0f,最后一 個knot值為1.0f,knot值必須從小到大排列,它用來給各個點分配由 Alpha對象定義的上升時間段和下降時間段。每一個點的時間可以由 對應的knot的數值算出。 運行JAVA3D程序,我們會看到立方體繞著一個長方形的四個 頂點旋轉。如果我們將程序中的xtranAlpha改寫成下面的內容: Alpha xtranAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE, 0, 0,10000, 0, 2000, 10000, 0, 2000); 則每一個循環的運行結果為:立方體先順時針轉一圈(10秒), 暫停2秒,再逆時針旋轉一圈(10秒),再暫停2秒。 我們可以用VRML語言編寫同樣的處理程序,這時我們應用的節點 是PositionInterpolator。由此可以得知,JAVA3D程序中的knot對應 于VRML程序中PositionInterpolator節點的key字段,而pos對應于 VRML程序中PositionInterpolator節點的keyValue字段。因而我們同時 編寫了一個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對象 RotPosPathInterpolator對象的構造函數為: 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對象可以 使形體按指定的路徑平移,而利用RotPosPathInterpolator 對象則可以在實現平移運動的同時使形體按指定的方式繞特 定的軸旋轉。例如下面的程序就是在Pos.java程序的基礎之 上加了一個Quat4f數組,用來定義形體的旋轉方式。使形體 在每一個knots數值之下都有一個旋轉角度相對應。程序的其 它地方沒有變化。 立方體在順時針或反時針移動時,都要繞著自身先正轉 90度,再反轉90度。 RotPosPathInterpolator對象可以由下面兩個對象代替: 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對象 RotPosScalePathInterpolator對象的構造函數為: 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) 前面我們已經介紹了一個RotationInterpolator對象,利用 它可以使形體按Alpha指定的方式繞著特定的軸旋轉,旋轉的速度 可以由Alpha的一些參數控制,但具體時間的角度無法控制。這時 我們就可以利用RotationPathInterpolator對象,利用quats數組, 控制具體時間的形體旋轉角度。 下面的程序是由上面介紹的Sca.java程序經過一定的處理得來 的,沒有增加什么,只是將用于位移及比例變化的部分去掉了。 //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 -------------------- 相應的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 托托姆 閱讀(4582) 評論(2)  編輯  收藏

    FeedBack:
    # re: Java3D學習系列(轉) 2008-08-01 15:00 mocake
    希望你工作認真點!!
    不要發這樣的帖子!
    ok  回復  更多評論
      
    # re: Java3D學習系列(轉) 2009-06-09 09:28 HAKLF
    發那么多有用沒有呀!能否有點主要點!!!  回復  更多評論
      

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 青草草在线视频永久免费| 中文字幕无码播放免费| 亚洲日韩在线中文字幕第一页| 亚洲阿v天堂在线2017免费| 亚洲乱码国产一区三区| 亚洲精品视频免费在线观看| 亚洲熟妇丰满xxxxx| 亚洲人成色7777在线观看不卡| 久久久久久国产精品免费免费男同| 亚洲一区二区三区深夜天堂| 免费人成在线观看网站品爱网日本| 在线观看免费视频网站色| 亚洲一区二区三区在线观看蜜桃 | 国产成人亚洲精品狼色在线| 免费女人高潮流视频在线观看| 亚洲第一男人天堂| 亚洲日韩精品无码专区网站| 免费涩涩在线视频网| 2021免费日韩视频网| 91成人免费观看| 国产在亚洲线视频观看| 亚洲AV福利天堂一区二区三| 日韩精品视频免费网址| 久久国产精品国产自线拍免费 | 永久免费无码网站在线观看| 18禁免费无码无遮挡不卡网站 | 亚洲精品在线免费观看视频| 亚洲Aⅴ无码一区二区二三区软件 亚洲AⅤ视频一区二区三区 | 97在线视频免费公开视频| 一级特黄录像视频免费| 亚洲国产日韩在线| 亚洲片国产一区一级在线观看| 免费国产成人午夜电影| 免费jjzz在线播放国产| 亚洲国产电影av在线网址| 免费无码A片一区二三区| 国产羞羞的视频在线观看免费| a级在线免费观看| 久久久久免费精品国产| 特级精品毛片免费观看| 亚洲最大免费视频网|