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{
   buffer=Loader.load("/img/TmpMicroFile.m3g");
   for(int i=0;i<BUFFER.LENGTH;I++){
    if(buffer[i] instanceof World){
     world=(World)buffer[i];
     return ;
    }
   }
  }catch(Exception e){
   buffer=null;
   System.out.println("thorw a exception when loading");
   e.printStackTrace();
  }
 }
然後我們設置攝影機,不同的是,這次我們從World中獲得攝影機信息,獲取後我們可以對其進行一些基本的設置這裏不細說了。下面着重的說一下動畫的部分。
在我們導入這個m3g文件時候我們其實已經有了動畫的信息了,並且這些動畫信息有可能是很複雜的,我測試了連桿兩軸的運動可以沒問題,從一些資料上看到的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;
  validity= world.animate((int)startTime);
  perFrameTime=(int)System.currentTimeMillis();
  
  g.setColor(0x00);
  g.fillRect(0,0,getWidth(), getHeight());
 
  g.setClip(0,0,getWidth(),getHeight());
  g3d.bindTarget(g,true,Graphics3D.DITHER|Graphics3D.TRUE_COLOR);
  g3d.setViewport(0,0,getWidth(),getHeight());

  
  g3d.render(world);
  
  g3d.releaseTarget();
  
  framePor=(int)1000/((int)System.currentTimeMillis()-perFrameTime);
  
  System.out.println("3D demo frame/sn:"+framePor);

  if(validity < 1)
  { // The validity too small; allow a minimum of 1ms.
   validity = 1;
  }

  if(validity == 0x7fffffff)
  { // The validity is infinite; scehdule a refresh in 1 second.
   validity=1000;
  }

 }

 public void run() {
  while(isRun){
   repaint();
   try{
    Thread.sleep(validity);
   }catch(Exception e){}
  }

 }
這裏如果你不喜歡使用線程的話,你可以換成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,0
這個矩陣表示的當前的模型在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,0,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;
  float z;
  switch(keycode){
   case GameCanvas.DOWN:
    break;
   case GameCanvas.UP:
    break;
   case 52:
    dir=dir-2;
    System.out.println(dir);
    x=(float)(3*Math.sin((dir * 3.14159f) / 180.0f));
    z=(float)(3*Math.cos((dir * 3.14159f) / 180.0f));
    camera.setTranslation(x,0,z);
    camera.setOrientation(dir,0,1,0);
    camerTra=new float[3];
    
    camera.getTranslation(camerTra);
    for(int i=0;i<CAMERTRA.LENGTH;I++){
     System.out.print(camerTra[i]+"   ");
    }
    System.out.println();
    camerTra=new float[4];
    camera.getOrientation(camerTra);
    for(int i=0;i<CAMERTRA.LENGTH;I++){
     System.out.print(camerTra[i]+"   ");
    }
    System.out.println();
    break;
    
   case 54:
    dir=dir+2;
    System.out.println(dir);
    x=(float)(3*Math.sin((dir * 3.14159f) / 180.0f));
    z=(float)(3*Math.cos((dir * 3.14159f) / 180.0f));
    camera.setTranslation(x,0,z);
    camera.setOrientation(dir,0,1,0);
    camerTra=new float[3];
    
    camera.getTranslation(camerTra);
    for(int i=0;i<CAMERTRA.LENGTH;I++){
     System.out.print(camerTra[i]+"   ");
    }
    System.out.println();
    camerTra=new float[4];
    camera.getOrientation(camerTra);
    for(int i=0;i<CAMERTRA.LENGTH;I++){
     System.out.print(camerTra[i]+"   ");
    }
    System.out.println();
    break;
    
  }
 }
呵呵……上面簡單的對動畫的播放和設置,以及對物體進行操作的說明,希望對你能有所幫助,其實現在的內容已經可以寫出一個簡單操作人物移動的遊戲了或者是操作遙控汽車的遊戲,還缺少的是碰撞的檢測。不過由於時間的關係,我還沒有寫這樣的東西,稍候一定整理一下寫個遙控車什麼的遊戲,這裏還是前把這次的代碼給大家,另外稍候我會製作一個人物走動的動畫,如果能控制m3g文件在合適的大小我會上傳給大家做個素材吧。

20050810163139769.jpg

源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章