在這裡我首先感謝大家對上一篇文章J2ME Mobile 3D入門教程系列文章之一的支持,也正是有了大家的支持,我決定把我的Mobile3D學習過程拿出來和大家共享,希望大家能一起來討論Mobile3D。
在上一次的教程中我為您具體的介紹了,在Moble3D中通過及時運算建立3D圖形,並且對從*.m3g文件中導入模型做了一個簡單的介紹,這次我想在這裡通過*.m3g檔案的使用簡單的介紹一下Mobile3D對動畫的控制,以及對模型的一些操作。
首先我來簡單的說一下m3g檔案的建立,這個其實很簡單,你只需要選擇一種你所熟悉的3D圖形製作軟體,並安裝對應的插件即可,在這裡我使用的軟體是Maya和3DS
MAX,插件使用的是H3T EXPort Plugin,插件有maya和3ds max的,同時還需要下載一個軟體M3G Tools kit。
這些都可以從Sony EriCSSon的網站上找到連結。插件的安裝應該都沒問題吧。插件安裝完成後,就可以建立模型、設定材質貼圖、設定攝影機、設定要害幀等等了,最後只要輸出成H3T檔案即可。然後再打開M3G
Tools kit將h3t檔案輸出成m3g檔案就可以了。在使用m3g檔案之前最好用M3G Tools
kit瀏覽一下該文件,為的是記錄對應的信息,例如userid和該場景的樹狀結構等信息,這些都是非常重要的。假如你這樣做了,你會發現這樣導出的m3g檔案中camera並沒有在world樹下,而是和world樹是平級的。
其實上一篇文章中我也說過,camera和渲染資訊可以不被放在world樹下,但是所有的模型資訊必須被放到樹下。當我們看m3g檔案的時候比較重要的是看清楚world節點所在的位置,以及需要我們操作的模型的userid。
預備工作差不多了,現在來看Mobile3D吧,在上一文章中我說過m3g檔案使用透過javax.microedition.m3g.Loader.load(String url)載入的,而且該方法返回的是javax. microedition.m3g.Object3D的數組,也許有人要問既然world是根節點,那為什麼不直接回傳一個World呢?
剛才讓大家看m3g檔案的結構的時候就已經說明了攝影機和動畫設定等等並沒有被放到World為節點的書中,而是和World節點同級的。而World節點是場景的根節點才對。那我們要如何才正確的取出World節點呢?方法有兩個:
1、遍歷該Object3D數組,並比較每個元素的userid假如正式World節點的useid將該元素取出。
2、遍歷該Object3D數組,並比較每個元素是不是World類別的實例,那麼既然World節點是場景的根節點,那麼在該Object3D數組中也應該只有一個World類別的實例物件。
第一個方法比較簡單,我在這裡只給出第二個方法的片段程式碼。 (其實是一樣的)
PRivate void loadWorld(){
System.out.println("now loading...");
try{
for(int i=0;i if(buffer[i] instanceof World){
world=(World)buffer[i];
return ;
cept } buffer=null;
System.out.println("thorw a exception when loading");
e.printStackTrace();
}
}
〼我們可以對其進行一些基本的設定這裡不細說了。很複雜的,我測試了連桿兩軸的運動可以沒問題,從一些資料上看到的IK反向運動也沒有問題。簡單的說World.animate()來更新動畫訊息,這個方法需要傳進去一個int類型的參數,當你第一次調用該方法的時候,系統會記錄下這個數值,後面每次調用的時候都會和這個數值相比較,然後系統替我們計算出動畫更新到什麼位置,同時該方法會傳回一個int類型的參數,這個參數表示的下一次更新的一個建議的數值(是以毫秒為單位的)。
我們這時就可以讓調用這個方法的線程休眠這個時間,以便下以次更新動畫數據。好消息,但在有很多情況播放的長度、什麼時候播放,都需要我們自己來控制怎麼辦? 這時候我們就需要用到javax.microedition.m3g.AnimationController類了,其實每個動畫中的每個可以動的模型都有自己的AnimationController對象,和模型動畫一樣我們可以通過World.find(int
controllerID)來取得,在該類別中我們可以透過setActiveInterval(int activeTime,int
unactiveTime)來設定動畫在該系統中播放的起始和重點時間,另外透過setPosition(int startTime,int
endTime)方法控制這個動畫需要播放哪一段落。
很抱歉有關兩個方法的時候在這次教程實例中我並沒有使用,不過假如您想了解關於這兩個方法的使用,我建議你看看WTK2.2的那個Demo3D中袋鼠的例子,那裡面寫的挺具體的。這裡呢我給動畫和繪製的程式碼片段吧。
protected void paint(Graphics g) {
startTime= System.currentTimeMillis() - worldStartTime;
. rentTimeMillis();
g .setColor(0x00);
g.fillRect(0,0,getWidth(), getHeight());
g.setClip(0,0,getWidth(]),getHeight); true,Graphics3D.DITHERGraphics3D.TRUE_COLOR);
g3d.setViewport(0,0,getWidth(),getHeight());
g3d.r.
framePor=(int )1000/((int)System.currentTimeMillis()-perFrameTime);
System.out.println("3D demo frame/sn:"+framePor);
if(validity { // The validity too small; allow a minimum of 1ms.
validity = 1;
}
if(validity == 0x7fffff)
if(validity == 0x7fffff)
if(validity == 0x7fffff)
。 if(validity == 0x7fffff)
, valuece.
validity=1000;
}
}
public void run() {
while(isRun){
repaint();
try{🀎 㟀. }
}
這裡假如你不喜歡使用線程的話,你可以換成Timer。個人喜好問題吧,我對線程比較熟悉,所以這裡我使用的是線程。
動畫似乎我現在也只理解到這些,全部和大家共享出來了。下面我想說一說Transformable類別中的幾個方法。首先來介紹Transformable類別吧。 Transformable類別是很重要的一個類,Node就是它的子類,知道它的重要性了吧。
Transformable中有四個方法是今天我要簡單說一下的postRotate(float,
float, float,
float)放是和物體的旋轉有關係的在Mobile3D中默認所有的物體的旋轉軸都在自身的中心,所以對物體進行旋轉操作的話,一定是自轉,而不是繞某個點、或某個軸公轉,這一點一定要弄清楚。也許這樣說有些抽像那麼我換個說法,就是這裡的旋轉只改變物體的朝向,不會改變物體的位置。
這下明白了吧,也許有人要問「這不正是我們需要的嗎?為什麼要強調呢?」原因其實是這樣的,在有的3D引擎中,旋轉是以原點為基礎的。也就是說假如需要做自轉運動,就必須做移動、再旋轉、再移動這樣的操作,其實這樣做的好處是可以方便點的運算,因為點不存在自轉的概念。而我們的Mobile3D在某種程度上說是不可以對點操作的,所以它的最小單位是Mesh,那麼它要如何實現自轉呢?來看個矩陣你就明白了
90,0,0,0
0,0,0,0
0,0,1,0
0,0,0,03,0,1『在Y軸上有90度的旋轉。現在我們回頭來看看postRotate(float
a, float x, float y, float
z)方法,其中有4個參數,第一個就是這次需要旋轉的角度,後三個其實一個這次旋轉的軸,是透過一個向量來表示的,postRotate方法就是在原來的朝向繼續進行新的旋轉,假如用數學公式來表示的話就是用原有的矩陣乘以
a,0,0,0
0,x,0,0
0,0,y,0 0,x,0㟎,z
這個矩陣就是新的方向矩陣。這個方法假如從數學角度聽起來很難理解的話,你只要記住四個參數第一個是這次旋轉的角度,後三個確定旋轉軸。
同postRotate方法類似的是setOrientation(float a, float x, float y, float z)。不同的是這次不再是旋轉了而是直接設定到這個朝向。
說過旋轉再來看看移動,這個似乎就簡單很多了translate(float
x, float y, float z)這個就是指依照指定的向量平移;setTranslation(float x, float y,
float z)這個更簡單了,直接移動到指定的位置。
其實還有一個方法scale(float sx, float sy,
float sz)是用來進行縮放的,同樣還有setScale(float sx, float sy, float
sz)直接設定比例尺,這個六個方法是對物體進行直接的操作的,非常有用,尤其是前四個,在編寫遊戲的時候會經常用到,而後兩個使用的頻率似乎少一些,因為很多時候我們都是直接對攝影機的距離進行操作的(除非有非凡需要)。下面我給個使用前四方法的舉例吧。
public void keyPressed(int keycode){
float[] camerTra;
float x;
break;
case GameCanvas.UP:
break;
case 52:
dir=dir-2;
System.out.println(dir);
x=(float)(3*Math.sin((dir * 3.14159f) 7159f二的內容,更多相關內容請關注PHP中文網(www.php.cn)!