Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android應用:3D圓柱體

Android應用:3D圓柱體

編輯:關於Android編程

總共三個類   [java]  package wyf.lgz;      import java.nio.ByteBuffer;   import java.nio.ByteOrder;   import java.nio.FloatBuffer;   import java.util.ArrayList;      import javax.microedition.khronos.opengles.GL10;      public class DrawCylinder   {       private FloatBuffer myVertexBuffer;//頂點坐標緩沖        private FloatBuffer myNormalBuffer;//法向量緩沖       private FloatBuffer myTexture;//紋理緩沖              int textureId;              int vCount;//頂點數量              float length;//圓柱長度       float circle_radius;//圓截環半徑       float degreespan;  //圓截環每一份的度數大小              public float mAngleX;       public float mAngleY;       public float mAngleZ;              public DrawCylinder(float length,float circle_radius,float degreespan,int textureId)       {           this.circle_radius=circle_radius;           this.length=length;           this.degreespan=degreespan;           this.textureId=textureId;                      float collength=(float)length;//圓柱每塊所占的長度           int spannum=(int)(360.0f/degreespan);                      ArrayList<Float> val=new ArrayList<Float>();//頂點存放列表           ArrayList<Float> ial=new ArrayList<Float>();//法向量存放列表                      for(float circle_degree=180.0f;circle_degree>0.0f;circle_degree-=degreespan)//循環行           {                   float x1 =(float)(-length/2);                   float y1=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree)));                   float z1=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree)));                                      float a1=0;                   float b1=y1;                   float c1=z1;                   float l1=getVectorLength(a1, b1, c1);//模長                   a1=a1/l1;//法向量規格化                   b1=b1/l1;                   c1=c1/l1;                                      float x2 =(float)(-length/2);                   float y2=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree-degreespan)));                   float z2=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree-degreespan)));                                      float a2=0;                   float b2=y2;                   float c2=z2;                   float l2=getVectorLength(a2, b2, c2);//模長                   a2=a2/l2;//法向量規格化                   b2=b2/l2;                   c2=c2/l2;                                      float x3 =(float)(length/2);                   float y3=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree-degreespan)));                   float z3=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree-degreespan)));                                      float a3=0;                   float b3=y3;                   float c3=z3;                   float l3=getVectorLength(a3, b3, c3);//模長                   a3=a3/l3;//法向量規格化                   b3=b3/l3;                   c3=c3/l3;                                      float x4 =(float)(length/2);                   float y4=(float) (circle_radius*Math.sin(Math.toRadians(circle_degree)));                   float z4=(float) (circle_radius*Math.cos(Math.toRadians(circle_degree)));                                      float a4=0;                   float b4=y4;                   float c4=z4;                   float l4=getVectorLength(a4, b4, c4);//模長                   a4=a4/l4;//法向量規格化                   b4=b4/l4;                   c4=c4/l4;                                      val.add(x1);val.add(y1);val.add(z1);//兩個三角形,共6個頂點的坐標                   val.add(x2);val.add(y2);val.add(z2);                   val.add(x4);val.add(y4);val.add(z4);                                      val.add(x2);val.add(y2);val.add(z2);                   val.add(x3);val.add(y3);val.add(z3);                   val.add(x4);val.add(y4);val.add(z4);                                      ial.add(a1);ial.add(b1);ial.add(c1);//頂點對應的法向量                   ial.add(a2);ial.add(b2);ial.add(c2);                   ial.add(a4);ial.add(b4);ial.add(c4);                                      ial.add(a2);ial.add(b2);ial.add(c2);                   ial.add(a3);ial.add(b3);ial.add(c3);                   ial.add(a4);ial.add(b4);ial.add(c4);           }                       vCount=val.size()/3;//確定頂點數量                      //頂點           float[] vertexs=new float[vCount*3];           for(int i=0;i<vCount*3;i++)           {               vertexs[i]=val.get(i);           }           ByteBuffer vbb=ByteBuffer.allocateDirect(vertexs.length*4);           vbb.order(ByteOrder.nativeOrder());           myVertexBuffer=vbb.asFloatBuffer();           myVertexBuffer.put(vertexs);           myVertexBuffer.position(0);                      //法向量           float[] normals=new float[vCount*3];           for(int i=0;i<vCount*3;i++)           {               normals[i]=ial.get(i);           }           ByteBuffer ibb=ByteBuffer.allocateDirect(normals.length*4);           ibb.order(ByteOrder.nativeOrder());           myNormalBuffer=ibb.asFloatBuffer();           myNormalBuffer.put(normals);           myNormalBuffer.position(0);                      //紋理           float[] textures=generateTexCoor(spannum);           ByteBuffer tbb=ByteBuffer.allocateDirect(textures.length*4);           tbb.order(ByteOrder.nativeOrder());           myTexture=tbb.asFloatBuffer();           myTexture.put(textures);           myTexture.position(0);       }              public void drawSelf(GL10 gl)       {           gl.glRotatef(mAngleX, 1, 0, 0);//旋轉           gl.glRotatef(mAngleY, 0, 1, 0);           gl.glRotatef(mAngleZ, 0, 0, 1);                      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//打開頂點緩沖           gl.glVertexPointer(3, GL10.GL_FLOAT, 0, myVertexBuffer);//指定頂點緩沖                      gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);//打開法向量緩沖           gl.glNormalPointer(GL10.GL_FLOAT, 0, myNormalBuffer);//指定法向量緩沖                      gl.glEnable(GL10.GL_TEXTURE_2D);           gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);           gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, myTexture);           gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);                      gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vCount);//繪制圖像                      gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//關閉緩沖           gl.glEnable(GL10.GL_TEXTURE_2D);           gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);           gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);       }              //法向量規格化,求模長度       public float getVectorLength(float x,float y,float z)       {           float pingfang=x*x+y*y+z*z;           float length=(float) Math.sqrt(pingfang);           return length;       }              //自動切分紋理產生紋理數組的方法       public float[] generateTexCoor(int bh)       {           float[] result=new float[bh*6*2];            float REPEAT=2;           float sizeh=1.0f/bh;//行數           int c=0;           for(int i=0;i<bh;i++)           {                   //每行列一個矩形,由兩個三角形構成,共六個點,12個紋理坐標                   float t=i*sizeh;                                      result[c++]=0;                   result[c++]=t;                                  result[c++]=0;                   result[c++]=t+sizeh;                                       result[c++]=REPEAT;                   result[c++]=t;                                                  result[c++]=0;                   result[c++]=t+sizeh;                                      result[c++]=REPEAT;                   result[c++]=t+sizeh;                                         result[c++]=REPEAT;                   result[c++]=t;           }           return result;       }   }     [java]  package wyf.lgz;      import android.app.Activity;   import android.content.pm.ActivityInfo;   import android.os.Bundle;   import android.view.Window;   import android.view.WindowManager;      public class Activity_GL_Cylinder extends Activity {       private MyGLSurfaceView mGLSurfaceView;       /** Called when the activity is first created. */       @Override       public void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);                      requestWindowFeature(Window.FEATURE_NO_TITLE);           getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);           setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);                      mGLSurfaceView = new MyGLSurfaceView(this);           setContentView(mGLSurfaceView);           mGLSurfaceView.setFocusableInTouchMode(true);//設置為可觸控           mGLSurfaceView.requestFocus();//獲取焦點       }              @Override       protected void onResume() {           super.onResume();           mGLSurfaceView.onResume();       }          @Override       protected void onPause() {           super.onPause();           mGLSurfaceView.onPause();       }      }     [java]   package wyf.lgz;      import java.io.IOException;   import java.io.InputStream;      import android.opengl.GLSurfaceView;   import android.opengl.GLUtils;      import javax.microedition.khronos.egl.EGLConfig;   import javax.microedition.khronos.opengles.GL10;   import javax.microedition.khronos.opengles.GL11;      import android.content.Context;   import android.graphics.Bitmap;   import android.graphics.BitmapFactory;   import android.view.MotionEvent;      public class MyGLSurfaceView extends GLSurfaceView {       private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度縮放比例       private SceneRenderer mRenderer;//場景渲染器       private float mPreviousY;//上次的觸控位置Y坐標       private float mPreviousX;//上次的觸控位置Y坐標       private int lightAngle=90;//燈的當前角度              public MyGLSurfaceView(Context context) {           super(context);           mRenderer = new SceneRenderer();    //創建場景渲染器           setRenderer(mRenderer);             //設置渲染器                setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//設置渲染模式為主動渲染          }                //觸摸事件回調方法        @Override        public boolean onTouchEvent(MotionEvent e) {           float y = e.getY();           float x = e.getX();           switch (e.getAction()) {           case MotionEvent.ACTION_MOVE:               float dy = y - mPreviousY;//計算觸控筆Y位移               float dx = x - mPreviousX;//計算觸控筆Y位移               mRenderer.cylinder.mAngleX += dy * TOUCH_SCALE_FACTOR;//設置沿x軸旋轉角度               mRenderer.cylinder.mAngleZ += dx * TOUCH_SCALE_FACTOR;//設置沿z軸旋轉角度               requestRender();//重繪畫面           }           mPreviousY = y;//記錄觸控筆位置           mPreviousX = x;//記錄觸控筆位置           return true;       }          private class SceneRenderer implements GLSurfaceView.Renderer        {              int textureId;//紋理名稱ID           DrawCylinder cylinder;//創建圓柱體                      public SceneRenderer()           {              }                      public void onDrawFrame(GL10 gl) {                                 //清除顏色緩存               gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);               //設置當前矩陣為模式矩陣               gl.glMatrixMode(GL10.GL_MODELVIEW);               //設置當前矩陣為單位矩陣               gl.glLoadIdentity();                                         gl.glPushMatrix();//保護變換矩陣現場                              float lx=0; //設定光源的位置               float ly=(float)(7*Math.cos(Math.toRadians(lightAngle)));               float lz=(float)(7*Math.sin(Math.toRadians(lightAngle)));               float[] positionParamsRed={lx,ly,lz,0};               gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionParamsRed,0);                                  initMaterial(gl);//初始化紋理               gl.glTranslatef(0, 0, -10f);//平移               initLight(gl);//開燈               cylinder.drawSelf(gl);//繪制               closeLight(gl);//關燈                              gl.glPopMatrix();//恢復變換矩陣現場           }              public void onSurfaceChanged(GL10 gl, int width, int height) {               //設置視窗大小及位置                gl.glViewport(0, 0, width, height);               //設置當前矩陣為投影矩陣               gl.glMatrixMode(GL10.GL_PROJECTION);               //設置當前矩陣為單位矩陣               gl.glLoadIdentity();               //計算透視投影的比例               float ratio = (float) width / height;               //調用此方法計算產生透視投影矩陣               gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100);           }              public void onSurfaceCreated(GL10 gl, EGLConfig config) {               //關閉抗抖動                gl.glDisable(GL10.GL_DITHER);               //設置特定Hint項目的模式,這裡為設置為使用快速模式               gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);               //設置屏幕背景色黑色RGBA               gl.glClearColor(0,0,0,0);               //設置著色模型為平滑著色                  gl.glShadeModel(GL10.GL_SMOOTH);               //啟用深度測試               gl.glEnable(GL10.GL_DEPTH_TEST);                               textureId=initTexture(gl,R.drawable.stone);//紋理ID               cylinder=new DrawCylinder(10f,2f,18f,textureId);//創建圓柱體                  //            //開啟一個線程自動旋轉光源   //            new Thread()   //            {   //                public void run()   //                {   //                    while(true)   //                    {   //                      lightAngle+=5;//轉動燈   //                      mRenderer.cylinder.mAngleY+=2*TOUCH_SCALE_FACTOR;//球沿Y軸轉動   //                    requestRender();//重繪畫面   //                    try   //                    {   //                        Thread.sleep(50);//休息10ms再重繪   //                    }   //                    catch(Exception e)   //                    {   //                        e.printStackTrace();   //                    }                      //                    }   //                }   //            }.start();           }       }              //初始化白色燈       private void initLight(GL10 gl)       {               gl.glEnable(GL10.GL_LIGHTING);//允許光照               gl.glEnable(GL10.GL_LIGHT1);//打開1號燈                        //環境光設置           float[] ambientParams={0.2f,0.2f,0.2f,1.0f};//光參數 RGBA           gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, ambientParams,0);                                  //散射光設置           float[] diffuseParams={1f,1f,1f,1.0f};//光參數 RGBA           gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseParams,0);                       //反射光設置           float[] specularParams={1f,1f,1f,1.0f};//光參數 RGBA           gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, specularParams,0);        }              //關閉燈       private void closeLight(GL10 gl)       {           gl.glDisable(GL10.GL_LIGHT1);           gl.glDisable(GL10.GL_LIGHTING);       }              //初始化材質       private void initMaterial(GL10 gl)       {           //環境光           float ambientMaterial[] = {248f/255f, 242f/255f, 144f/255f, 1.0f};           gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, ambientMaterial,0);           //散射光           float diffuseMaterial[] = {248f/255f, 242f/255f, 144f/255f, 1.0f};           gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffuseMaterial,0);           //高光材質           float specularMaterial[] = {248f/255f, 242f/255f, 144f/255f, 1.0f};           gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specularMaterial,0);           gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 100.0f);       }              //初始化紋理       public int initTexture(GL10 gl,int drawableId)//textureId       {           //生成紋理ID           int[] textures = new int[1];           gl.glGenTextures(1, textures, 0);               int currTextureId=textures[0];               gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId);           gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR_MIPMAP_NEAREST);           gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR_MIPMAP_LINEAR);           ((GL11)gl).glTexParameterf(GL10.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL10.GL_TRUE);           gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT);           gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);                                            InputStream is = this.getResources().openRawResource(drawableId);           Bitmap bitmapTmp;            try            {               bitmapTmp = BitmapFactory.decodeStream(is);           }            finally            {               try                {                   is.close();               }                catch(IOException e)                {                   e.printStackTrace();               }           }           GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0);           bitmapTmp.recycle();                       return currTextureId;       }   }    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved