J2ME Mobile 3D入門教程(一)

首先我要聲明一下該文章,我已經在7月29日發佈到了J2ME DEV網站上了,如果您需要轉載請著名出處

 3D圖形技術在各個領域已經越來越多的被應用了,當然這也包括了J2ME領域。在J2ME中爲我們提供了JSR184這樣一個可選包,該套API實現手機上3D圖形的編程。同時也伴隨着移動設備硬件的發展,現在也出現了越來越的支持該可選包的手機了,例如Sony Ericsson的 K系列、S系列等等。
正巧前一段時間我簡單的學習了一下3D圖形學,所以最近開始對Mobile 3D的學習,在這裏把學習到的東西拿出來與大家共享,希望能對大家有所幫助,也同時希望大家能夠一起來學習JSR184。

        下面言規正傳,首先我們來想象一下在現實生活中,我們是如何觀察這個世界的。我們是通過眼睛來觀察,我們生活在一個3維座標系構成的世界。在Mobile3D中同樣的有World類讓你隨心所欲的構造你想要的世界,當然在這裏專業些,在3D製圖中我們叫它“場景”;另外還有Camera類來作爲你的眼睛,你可以來設置它的位置角度等參數,來顯示出不同的圖像。

        在Mobile 3D中是如何實現3D圖像的顯示呢?首先你要建立或者載入3D模型,然後根據需要設置場景中的環境、渲染方式等一系列的參數,再後生成並設置一架攝影機並且調整好你想要的光線,調整好你所需要的位置和角度。OK還需要什麼呢?按下快門,這一步就是被叫做“渲染”一切就搞定了,這聽起來似乎很簡單其實也並不難,其實這也不難。

        下面我們分步驟的來講解這些步驟:
        首先說模型的建立,在Mobile 3D中和大多數的3D編程API是一樣的有兩種方式:1 及時運算生成;2 外部建模導入。由於外部建模導入會將環境信息同時導入,所以稍候給大家做詳細的介紹,這裏着重要給大家介紹“及時運算生成”的部分,這樣一來有助於大家瞭解Mobile 3D的工作原理
在Mobile 3D中爲我們提供了VertexArray和VertexBuffer倆個類,這兩個類用來保存3維模型的頂點信息。
其中VertexArray 類用處比較多,也比較靈活,這個類最常用的用法有3個,1 保存頂點座標信息; 2 保存法線信息; 3 保存帖圖信息 。有人也許要問這一個類怎麼管理3種不同的東西呢?那下面我們來分析一下該類,首先該類的構造器有3個參數:1 該實例要包括的元素的數量; 2 每個元素要包括的元素數量; 3每個子元素所佔的字節數。這樣一來似乎清楚很多爲什麼這個類能被使用到3種東西上。另外該類還有一個比較常用的方法set(int index,int length,short[] array0)這個方法是用來向該類的實例對象種存放數據的,第一個參數是指從第幾個元素開始;第二個參數是指要設置多少個;第三個參數就是實際設置的置了。
下面簡單介紹VertexBuffer類,該類纔是真正保存多邊形的框架信息的類。改類通過設置頂點位置、發現、帖圖信息,來建立圖形。其中setPositions(VertexBuffer v,float s,float[]b)是用來設置頂點位置的,在這個方法中你會發現有3個參數,第一個不用說了,是頂點的座標信息,後兩個是用來做座標偏移等操作的,操作是這樣的數學公式v'=v*s+b。還有一個setNormals(vertexBuffer norm)方法來設置法線。還有一個非常重要的方法setTexCoords(int, VertexArray, float, float[])這個方法中參數除第一個以外,後三個和setPositions(VertexBuffer v,float s,float[]b)是一樣的,第一個參數是開始的元素編號。這樣說是不是有些抽象呢?給大家一個例子吧,好讓大家理解。
  short x = 20;

  short y = 20;

  short z = 20;

  short fx = (short) -x;

  short fy = (short) -y;

  short fz = (short) -z;
  
  
  //定點座標
  short[] vert = {x,y,z, fx,y,z, x,fy,z, fx,fy,z, //D

    fx,y,fz, x,y,fz, fx,fy,fz, x,fy,fz, //C

    fx,y,z, fx,y,fz, fx,fy,z, fx,fy,fz, //B

    x,y,fz, x,y,z, x,fy,fz, x,fy,z, //F

    x,y,fz, fx,y,fz, x,y,z, fx,y,z, //A

    x,fy,z, fx,fy,z, x,fy,fz, fx,fy,fz}; //E
  
  try{vertArray=new VertexArray(vert.length/3,3,2);
  vertArray.set(0,vert.length/3,vert);
  }catch(Exception e){System.out.println("vert");}
  
  //發線
  byte[] norm = { 0,0,127, 0,0,127, 0,0,127, 0,0,127,

    0,0,-127, 0,0,-127, 0,0,-127, 0,0,-127,

    -127,0,0, -127,0,0, -127,0,0, -127,0,0,

    127,0,0, 127,0,0, 127,0,0, 127,0,0,

    0,127,0, 0,127,0, 0,127,0, 0,127,0,

    0,-127,0, 0,-127,0, 0,-127,0, 0,-127,0};
  
  try{normArray=new VertexArray(norm.length/3,3,1);
  normArray.set(0,norm.length/3,norm);
  }catch(Exception e){System.out.println("norm");e.printStackTrace();}

  //給出頂點們對應圖片上的點(vert和tex數組是一一對應的)
  short[] tex = { 1, 0, 0, 0, 1, 1, 0, 1,

    1, 0, 0, 0, 1, 1, 0, 1,

    1, 0, 0, 0, 1, 1, 0, 1,

    1, 0, 0, 0, 1, 1, 0, 1,

    1, 0, 0, 0, 1, 1, 0, 1,

    1, 0, 0, 0, 1, 1, 0, 1 };
  
  try{
  texArray=new VertexArray(tex.length/2,2,2);
  texArray.set(0,tex.length/2,tex);
  }catch(Exception e){System.out.println("tex");}

  //建立正方體
  vb=new VertexBuffer();
  vb.setPositions(vertArray,1.0f,null);
  vb.setNormals(normArray);
  vb.setTexCoords(0,texArray,1.0f,null);
  
在上述代碼中我建立一個正方體所需要全部頂點和麪的信息,但大家要注意這裏並沒有生成對應的模型。原因就是我們還沒有設置生成模型所以的其他信息,下面我們來看看TriangleStripArray類,該類是構成面所需要的三角面的信息類,熟悉3D製圖的人都清楚構造3D圖形是通過多個面構造一個3D實體的,而三角面是比較常用的一個方法。具體內容我這裏不詳細說明了。
下面我們還需要設置一些環境和材質信息,這裏要用到的類比較多Appearance、Texture2D、Material。前來看個例子
  appearnce=new Appearance();
 
  //創建帖圖
  Texture2D texture=new Texture2D(image2d);
  texture.setBlendColor(Texture2D.FUNC_DECAL);
  texture.setWrapping(Texture2D.WRAP_REPEAT,Texture2D.WRAP_REPEAT);
  texture.setFiltering(Texture2D.FILTER_NEAREST,Texture2D.FILTER_NEAREST);
  
  material=new Material();
  material.setColor(Material.DIFFUSE, 0xFFFFFFFF);
  material.setColor(Material.SPECULAR, 0xFFFFFFFF);
  material.setShininess(100.0f);
  
  appearnce.setTexture(0,texture);
  appearnce.setMaterial(material);
  
  mesh=new Mesh(vb,tsa,appearnce);
  mesh.setAppearance(0,appearnce);
  
我個人感覺Appearance類有些類似VertexBuffer類,同樣是多種屬性的持有者;在這裏要強調一點,就是Appearance類的設置遠遠不止上述給出的東西,還有很多的設置(例如FOG也就是霧的設置)。Texture2D是帖圖類,用它來設置帖圖的信息,例如帖圖的方式是平鋪等方式。Material物名斯意就是指材質,這裏你可是設置“反光度”、“顏色”等等信息。另外這裏我還要介紹一種設置渲染參數的方法

  //設置poly模式設置
  PolygonMode polygonMode=new PolygonMode();
  polygonMode.setShading(PolygonMode.SHADE_SMOOTH);
  polygonMode.setCulling(PolygonMode.CULL_NONE);
  
  //生成外貌
  appearnce=new Appearance();
  appearnce.setPolygonMode(polygonMode);
看剛剛給出的代碼,似乎比上面的更簡單是吧?其實在PolygonMode中已經替我們做了很多工作。該的設置很類似3D MAX中的Poly的使用。

剛纔的代碼中還給出了一個Mesh類,該類材質最後我們要的模型。

建立模型後,我們要建立Camera。在Camera中我在這裏只簡單介紹兩個方法setParallel(float, float, float, float)和setPerspective(float, float, float, float)。我們首先來看setParallel(float, float, float, float)該方法是設置Camera的視圖方法爲平視圖;第一個參數是設置視角的高度,注意是高度,不是角度,因爲這裏是平視圖;第二個參數是Camera的寬高比例,例如我們的電視是4:3、寬銀幕電影是16:9;第三、四參數分別是最近和最遠渲染的範圍。同樣的setPerspective是設置Camera爲透視圖,這種視圖比較接近我們日常生活中的觀察的角度,而該方法的後三個參數和setParallel的後三個參數是一樣的,而第一個參數是可是角度,這裏你可不要忽視這個角度問題,這個角度是在透視圖中計算投影的一個重要參數。

 

似乎一切都設置好了,其實不然,到目前爲止我們僅僅是把我們所需要的素材都準備好了。下面我們來看看Mobile 3D的管理機制,熟悉3D製圖的人都清楚大部分3D軟件,3D API都是通過樹狀結構來管理素材的,這樣的好處是每個模型、模型組、攝像機等元素作爲節點都可以設置自己的旋轉軸等等屬性,並可以按照自己所設定好的動畫信息進行運動。在Mobile 3D中爲我們規定了該樹狀結構的根節點必須是World類的實例對象,其中攝影機和光線比較特殊,可以不被放置在這個樹中,而是通過Graphics3D類的對象來設置(只是可以不被放到樹中,而不是必須不放到樹中)。
  world=new World();
  //world.addChild(camera);
  world.addChild(mesh);
  //world.setActiveCamera(camera);
  //world.addChild(light);

記得在前面我們提到過模型可以從外部文件導入,這裏要介紹了,你可以通過*.m3g文件導入,導入後你就可以直接獲得World的實例對象,這裏有可能包括各種模型、攝像機、燈光、環境、材質以及三角面的各種信息。也就是說通過*.m3g文件,我們可以直接獲得World的實力化對象。
  Object3D[] roots = Loader.load(“http://www.example.com/m3g/samples/simple.m3g”);
  myWorld = (World)roots[0];

最後在我們建立這棵“參天大樹”後我們終於可以繪製了,這也是最激動人心的時刻嘍……^-^……前看代碼    g.setClip(0,0,getWidth(),getHeight());
  g.drawString("3D demo",2,100,Graphics.LEFT|Graphics.TOP);
  g3d.bindTarget(g,true,Graphics3D.DITHER|Graphics3D.TRUE_COLOR);
  g3d.setViewport(0,0,getWidth(),getHeight());
  g3d.resetLights();
  g3d.clear(background);
  g3d.addLight(light,transform_light);
  
  
  
  transForm.postRotate(angle,1,1,1);
  //transForm.postTranslate(0,0,0);
  transform_camera.postTranslate(0,0,0.02f);
  g3d.setCamera(camera,transform_camera);
  g3d.render(world,transForm);
  //g3d.render(vb,tsa,appearnce,transForm);
  g3d.releaseTarget();
  
這個簡單吧~不用再說什麼了吧?嘿嘿

20050729152706647.jpg

希望上述的內容對你學習有幫助,有什麼問題發郵件到我的信箱[email protected][email protected],當然更歡迎大家一起來探討Moblie 3D

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