這章用一個Java
D例子來描述一個
D跳棋
這個例子建立了一個場景
包括
由一個暗綠色和蘭色格相交平鋪的
並帶有標簽的X軸和Z軸形成的平面
一個蘭色背景
一個可以在兩個不同方向浮動的球體
用戶可以通過鼠標來浏覽(拉近放遠)場景
左邊的截圖
顯示最初視圖
右邊的圖是用戶視圖移動一些之後的效果
Figure Initial view and later D跳棋闡述了Java
D編程中一些常用的方法和一些小竅門
例如
D場景使用Canvas
D類來實現顯示(這個類和Swing組件結合使用)
所有的Java
D程序需要一個場景圖
D跳棋說明了如何增加基本圖形
燈光
背景
這些場景圖形成了文件的可視形式
記錄這些場景信息的文本版本通過Daniel Selman的Java
dTree包很容易就能實現
(在這節的最後我會詳細介紹)
地板和球體使用了Java
D的QuadArray
Text
D
and Sphere幾何類
地板是由QuadArray的一系列四邊形組成
標簽是用Text
D對象沿著地板上的主軸形成
用戶通過一個觀察點查看這個
D世界
你將看到如何初始放置觀察點
在使用Java
D的OrbitBehavior 類時候如何移動觀察點
D跳棋類圖 圖
的類圖說明了
D跳棋程序的public和private數據項和方法
Figure Class diagrams for CheckersD Checkers
D 是程序的頂層JFrame
WrapCheckers
D 是場景圖擁有的 JPanel
作為一個Canvas
D 對象
他是可視的
CheckerFloor 建立地板的子圖(例如方格
軸)
with所有同顏色的方格用單獨的ColoredTiles 對象表示
提示
例子的原代碼在Checkers
D/目錄(可能是原書附帶光盤)
Java D和Swing 的結合 就向Swing文本和按紐
Checkers
D 是GUI控制位置的的一個 JFrame
把他放在必要的地方
在這個例子中
他建立一個WrapCheckers
D (一個 JPanel) 實例
並把他放在 BorderLayout 中間
csetLayout( new BorderLayout( ) );
WrapCheckersD wd = new WrapCheckersD( ); // panel for D canvas
cadd(wd BorderLayoutCENTER);
場景中的Canvas
D 視圖建立在WrapCheckers
D 類裡
public WrapCheckersD( )
{
setLayout( new BorderLayout( ) );
// other initialization code
GraphicsConfiguration config =
SimpleUniversegetPreferredConfiguration( );
CanvasD canvasD = new CanvasD(config);
add(Center canvasD);
// other initialization code}
雖然 Canvas
D 是一個重量級的GUI 元素(一個系統產生窗口的輕量層)
還是有一些必須注意的
重量級的組件沒那麼容易與Swing控件組合(Swing是一個輕量組件)
這些控件主要由Java產生
如果 Canvas
D 對象內嵌到一個 JPanel問題就可以消除
並且建立出來的panel可以安全地和Swing程序的其他部分結合
提示: 這是在的一個關於結合 Canvas
D 和Swing的詳細討論
()
相比前幾章
這裡沒有update/draw循環
因為Java
D自身有機制來監視場景和最初視圖的變化
下面以偽代碼給出算法
while(true) {
process user input; //用戶輸入
if (exit request) break;
perform behaviors;
if (scene graph has changed) //場景改變
traverse scene graph and render; //移動場景視圖
}
其中的behaviors是一些影響其他部分圖象的代碼
比如移動的圖形或改變燈光
他們用來監視圖象
傳遞給程序中非
D部分詳情
詳細代碼比例子中的偽代碼更加復雜
Java
D用多線程來並發移動和圖形描述
因此
對這個過程有一個概括了解會對本章其他部分的理解有幫助
場景圖形建立 場景圖形用 WrapCheckers
D的構造函數建立
public WrapCheckersD( )
{
// initialization code
GraphicsConfiguration config =
SimpleUniversegetPreferredConfiguration( );
CanvasD canvasD = new CanvasD(config);
add(Center canvasD);
canvasDsetFocusable(true); // give focus to the canvas
canvasDrequestFocus( );
su = new SimpleUniverse(canvasD);
createSceneGraph( );
initUserPosition( ); // set users viewpoint
orbitControls(canvasD); // controls for moving the viewpoint
suaddBranchGraph( sceneBG );
}
Canvas
D 對象用從getPreferredConfiguration( );獲得的配置來初始化
這個方法能取得硬件的圖形信息
一些老的Java
D程序沒有初始化一個GraphicsConfiguration 對象
而是用null作為 Canvas
D 的構造函數的參數
這種編程可不太好
canvas
D 被設置成焦點
以便鍵盤能傳遞動作給場景圖形
這些動作的觸發通常是按鍵的按壓和彈起
但是他們也能由定時器
幀的改變和由Java
D內部產生的事件觸發
Checkers
D就不需要設置焦點
因為他沒有任何動作
因為在所有的其他程序中我們都會考慮到線條
所以我沒有給出線條的描繪代碼
su SimpleUniverse 對象建立了標准子視圖
場景圖形的VirtualUniverse 和Locale 節點
createSceneGraph( ) 設置了燈光
天空的背景
地板
還有浮動球體
initUserPosition( ) 和 orbitControls( ) 處理用戶視角問題
最後把配置好的 BranchGroup 加入到方法
private void createSceneGraph( )
{
sceneBG = new BranchGroup( );
bounds = new BoundingSphere(new Pointd() BOUNDSIZE);
lightScene( ); // add the lights
addBackground( ); // add the sky
sceneBGaddChild( new CheckerFloor( )getBG( ) ); // add floor
floatingSphere( ); // add the floating sphere
pile( ); // fix the scene
} // end of createSceneGraph( )
使用不同的方法來增加子圖到 sceneBG以建立需要的子視圖
一旦圖形被繪制完畢後
並允許Java
D來優化他
sceneBG 便只被編譯一次
優化包括重排圖形
重新組合編譯節點
例如一連串的包含不同轉換的TransformGroup 節點會被編譯成一個獨立節點
另一個可能的優化是把具有相同顯示屬性的圖形編成組
以便能更快地描繪
bounds是一個 BoundingSphere 類的全局實例
他用來指定環境節點對燈光
背景和OrbitBehavior 對象的影響
跳躍的球體被放在場景的中心
被賦 BOUNDSIZE 單位半徑
並影響場景中所有事件
最後的 WrapCheckers
D( ) 所顯示的場景圖象在圖
中
Floor Branch
節點是我發明出來掩藏一些細節
稍後將會涉及
圖
所缺少的是場景圖形的分支部分
場景燈光 通過 lightScene( )
把一個環境燈光
兩個有向燈光加入到場景中
環境燈光能到達場景中的每個角落
並且強度相同
Colorf white = new Colorf(f f f);
// Set up the ambient light
AmbientLight ambientLightNode = new AmbientLight(white);
ambientLightNodesetInfluencingBounds(bounds);
sceneBGaddChild(ambientLightNode);
代碼設置了燈光的顏色
環境燈光以bounds配置建立
並加入到場景中
類 Color
f( ) 的構造函數設置RGB顏色為
f到
f(
f是全色)
有向燈光模擬的一個從原處照射來的一束燈光
並從特定方向碰上物體表面
有向燈光和環境燈光的區別是有向燈光必須是方向向量
Vectorf lightDirection = new Vectorf(f f f);
// left down backwards
DirectionalLight light = new DirectionalLight(white lightDirection);
lightsetInfluencingBounds(bounds);
sceneBGaddChild(light);
Figure Partial scene graph for CheckersD 方向是介於(
)和(
)的向量
燈光可以想象成是很多從不同方向
不同來源的平行燈光匯聚而成
點光和場光是Java
D燈光的另外一種形式
點光放置在空間中
並向所有方向發射
場光以特定方向朝點光聚焦
場景的背景 場景的背景可以指定為特定的背景(如下所示)
一個靜態圖像或這是一個帶形體的幾何材質
Background back = new Background( );
back
setApplicationBounds( bounds );
back
setColor(
f
f
f); // sky color
sceneBG
addChild( back );
浮動的球體 Sphere 是來自Java
D的 com
sun
j
d
utils
geometry 包的一個工具類
是Primitive 類的一個子類
Primitive 類為帶有 Shape
D 孩子節點的一個 Group 節點
他的幾何特性存儲在Java
D的 TriangleStripArray
這種類把球體看成一組可連接的三角形體
我沒必要校准他的幾何特性
但是他的現實和位置要改變
Appearance 節點是一個包含很多信息的容器
包含顏色
線條
點
多邊形
描繪
透明度和材質特性
ColouringAttributes 確定形體的顏色
而且不受場景燈光影響
如果一個形體需要顏色和燈光的交互作用
就要用到 Material 組件
燈光要影響形體的顏色必須滿足三種情況
; 形體的幾何特性必須是標准的
; 形體的 Appearance 節點必須擁有 Material 組件
; Material 必須用 setLightingEnable( )打開他的光照允許
用工具類 Sphere 能自動制作成標准形體
所以第一種情況容易滿足
形體顏色 Java
D Material 組件控制當一個形體被不同種類的燈光照射後的顏色
Material mat = new Material(ambientColor emissiveColor
diffuseColor specularColor shininess);
環境顏色參數指定當形體被環境燈光照射後的顏色
他給對象統一的顏色
放射性顏色貢獻形體生成的顏色
這個參數經常被設置成黑色(相當於關閉)
當照射的時候
發散顏色就是對象的顏色
他的強度取決於光波照射到形體的角度
提示
發散燈光和環境燈光通常被設置成相同
這與真實世界中的對象被照射時候的顏色一樣
鏡子顏色參數的強度與從形體的光亮區域反射出的多少有關
他由控制reflective highlight尺寸的發光參數組合成
提示
鏡子顏色通常設置成白色
符合真實世界中大部分對象產生的顏色
Checkers
D類中
有兩個不同方向的光
他們在球體頂部建立了兩個不同的光路(如圖
)
地板在他們的顏色未在形體的幾何特性中設置前
是沒有被照射到的
floatingSphere( ) 中處理形體現實的代碼如下
Colorf black = new Colorf(f f f);
Colorf blue = new Colorf(f f f);
Colorf specular = new Colorf(f f f); // near white
Material blueMat= new Material(blue black blue specular f);
blueMatsetLightingEnable(true);
Appearance blueApp = new Appearance( );
blueAppsetMaterial(blueMat);
布置形體 形體放置一般是在TransformGroup 下放置圖形節點
(參見圖
sphere Group)
一個 TransformGroup 用來放置
旋轉和度量旗下節點
他由Java
D Transform
D 對象定義其格式
TransformD td = new TransformD( );
tdset( new Vectorf()); // place at ()
TransformGroup tg = new TransformGroup(td);
tgaddChild(new Sphere(f blueApp));
// set the spheres radius and appearance
// and its normals by default
sceneBGaddChild(tg);
set( ) 方法將形體的中心放置在(
)
重置先前的旋轉和度量
在重置其他格式的時候
set( ) 能用來改變度量和角度
方法setTranslation( )
setScale( )和setRotation( ) 只能對已給格式起作用
與其他
D畫圖程序包不同的是
Java
D中的Y軸是垂直方向
而水平面由xoz決定
如圖
球體的位置被設置為(
)
在XOZ面中心上方
個單位
圖Java D中的坐標系
完請等待Part
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25930.html