【附源碼】【Android 3D OpenGL】開發之二——旋轉的三角形【MacroCheng原創】


一、建立三角形的模型

1.1、三角形原理

一般我們建一個三角形需要這麼三個數據:

         索引數組

         頂點座標數組

         頂點對應的顏色數組

三角形就是通過將三個頂點按照索引數組裏給出來的順序畫三個頂點畫出來的。我們來看看我們這裏用的這三個數組:

1.2Triangle.java 三角形的模型類

package com.macrocheng.opengl3d01;

 

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.nio.FloatBuffer;

import java.nio.ShortBuffer;

 

public class Triangle {

    //三角形頂點的Buffer

    private FloatBuffer vertexBuffer;

    public FloatBuffer getVertexBuffer() {

       return vertexBuffer;

    }

 

    public void setVertexBuffer(FloatBuffer vertexBuffer) {

       this.vertexBuffer = vertexBuffer;

    }

 

    //三角形顏色數組的Buffer

    private FloatBuffer colorBuffer;

    public FloatBuffer getColorBuffer() {

       return colorBuffer;

    }

 

    public void setColorBuffer(FloatBuffer colorBuffer) {

       this.colorBuffer = colorBuffer;

    }

 

    //三角形索引值得Buffer

    private ShortBuffer indexBuffer;

   

    public ShortBuffer getIndexBuffer() {

       return indexBuffer;

    }

 

    public void setIndexBuffer(ShortBuffer indexBuffer) {

       this.indexBuffer = indexBuffer;

    }

 

    public Triangle() {

       // TODO Auto-generated constructor stub

       initTriangle();

    }

   

    private int numberOfPoint;

   

    public int getNumberOfPoint() {

       return numberOfPoint;

    }

 

    public void setNumberOfPoint(int numberOfPoint) {

       this.numberOfPoint = numberOfPoint;

    }

 

    //初始化三角形

    private void initTriangle()

    {

       float[] coords = {

              -0.5f,-0.5f,0f,//x1,y1,z1

              0.5f,0.5f,0f,//x2,y2,z2

              0f,0.5f,0f //x3,y3,z3

       };

      

       float[] colors = {

              1f, 0f, 0f, 1f, // point 1

              0f, 1f, 0f, 1f, // point 2

              0f, 0f, 1f, 1f, // point 3

       };

      

       short[] indicesArray = {

              0, 2, 1, // rbg

       };

      

       numberOfPoint = coords.length/3;

      

       //float類型有四個字節,分配內存

       ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length*4);

       vbb.order(ByteOrder.nativeOrder());

       vertexBuffer = vbb.asFloatBuffer();

      

       //short類型有2個字節,分配內存

       ByteBuffer ibb = ByteBuffer.allocateDirect(indicesArray.length*2);

       ibb.order(ByteOrder.nativeOrder());

       indexBuffer = ibb.asShortBuffer();

      

       ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);

       cbb.order(ByteOrder.nativeOrder());

       colorBuffer = cbb.asFloatBuffer();

      

       vertexBuffer.put(coords);

       indexBuffer.put(indicesArray);

       colorBuffer.put(colors);

      

       vertexBuffer.position(0);

       indexBuffer.position(0);

       colorBuffer.position(0);

    }

 

}

1.2.1、三角形的頂點座標數組:

float[] coords = {

  -0.5f,-0.5f,0f,//x1,y1,z1

  0.5f,0.5f,0f,//x2,y2,z2

  0f,0.5f,0f //x3,y3,z3

}

數組裏是三個頂點的座標,其中每個頂點的座標佔三位,x/y/z三個軸

1.2.2、三角形的三個頂點的顏色數組:

float[] colors = {

    1f, 0f, 0f, 1f, // point 1

    0f, 1f, 0f, 1f, // point 2

    0f, 0f, 1f, 1f, // point 3

};

因爲顏色是RGBA,所以每四個元素定義一個顏色值,這其中顏色的順序和上面頂點座標的相對應。

1.2.3、三角形成面的索引值

short[] indicesArray = {

    0, 2, 1, // rbg

};

對於這個數組裏的值其實是座標數組中的索引,0就代表第一個頂點值也就是-0.5f,-0.5f,0f這個頂點。

二、將三角形加入到我們的View裏面去

這個代碼是基於第一講上面的,但是因爲有變動所以我就全部貼出來了:

2.1OpenGLRenderer.java

package com.macrocheng.opengl3d01;

 

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;

 

public class OpenGLRenderer implements GLSurfaceView.Renderer {

         private static final String LOG = OpenGLRenderer.class.getSimpleName();

         private float red = 0.9f;

         private float green = 0.2f;

         private float blue = 0.2f;

        

         private Triangle tr;

        

         private float xAngle;

         private float yAngle;

        

         @Override

         public void onSurfaceCreated(GL10 gl, EGLConfig config) {

                   // TODO Auto-generated method stub

                   tr = new Triangle();

                  

                   /**

                    * 設置OpenGL使用vertex數組來畫

                    */

                   gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

                   /**

                    * 設置顏色來自數組

                    */

                   gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

         }

        

         @Override

         public void onSurfaceChanged(GL10 gl, int width, int height) {

                   // TODO Auto-generated method stub

                   gl.glViewport(0, 0, width, height);

         }

        

         @Override

         public void onDrawFrame(GL10 gl) {

                   // TODO Auto-generated method stub

                   /**

                    * 我們通過glClearColor()方法爲底色定義了顏色。

                    * 底色是在我們能看到的所有東西的後面,所以所有在底色後面的東西都是不可見的。

                    * 可以想象這種東西爲濃霧,擋住了所有的東西。

                    */

                   gl.glClearColor(red, green, blue, 1.0f);

                  

                   //清除顏色的Buffer然後讓現實上面我們通過glClearColor來定義的顏色

                   /**

                    * 爲了讓顏色變化可見,我們必須調用glClear()以及顏色緩衝的Mask來清空buffer

                    * 然後爲我們的底色使用新的底色。

                    */

                   gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

                  

                   /**

                    *  重置當前的模型觀察矩陣

                    *  近似於重置。它將所選的矩陣狀態恢復成其原始狀態

                    */

                   gl.glLoadIdentity();

                   /**

                    * 旋轉,四個參數分別是旋轉度、x軸、y軸、z

                    * 後面三個值來決定圍繞那個軸線來旋轉

                    */

                   gl.glRotatef(xAngle, 1f, 0f, 0f);

                   gl.glRotatef(yAngle, 0f, 1f, 0f);

                   /**

                    * 第一個參數是大小,也是頂點的維數。我們使用的是x,y,z三維座標。

                    * 第二個參數,GL_FLOAT定義buffer中使用的數據類型。

                    * 第三個變量是0,是因爲我們的座標是在數組中緊湊的排列的,沒有使用offset

                    * 最後,第四個參數頂點緩衝。

                    */

                   gl.glVertexPointer(3, GL10.GL_FLOAT, 0, tr.getVertexBuffer());

                   /**

                    * 參數4表示RGBA(RGBA剛好是四個值),其餘的幾個參數大家都比較熟悉了。

                    */

                   gl.glColorPointer(4, GL10.GL_FLOAT, 0, tr.getColorBuffer());

                   /**

                    * 將所有這些元素畫出來。第一個參數定義了什麼樣的圖元將被畫出來。

                    * 第二個參數定義有多少個元素,

                    * 第三個是indices使用的數據類型。

                    * 最後一個是繪製頂點使用的索引緩衝。

                    */

                   gl.glDrawElements(GL10.GL_TRIANGLES, tr.getNumberOfPoint(), GL10.GL_UNSIGNED_SHORT, tr.getIndexBuffer());

         }

        

         public float getXAngle() {

                   return xAngle;

         }

 

         public float getYAngle() {

                   return yAngle;

         }

 

         public void setYAngle(float angle) {

                   yAngle = angle;

         }

 

         public void setXAngle(float angle) {

                   xAngle = angle;

         }

 

         /**

          * 設置顏色的值

          * @param r Red值

          * @param g Green值

          * @param b Blue值

          */

         public void setColor(float r,float g,float b)

         {

                   red = r;

                   green = g;

                   blue = b;

         }

        

         /**

          * 設置三角形的旋轉度

          * @param x x軸上的旋轉度

          * @param y y軸上的旋轉度

          */

         public void setAngle(float x,float y)

         {

                   xAngle = x;

                   yAngle = y;

         }

}

代碼中基本都有註釋所以就不單獨做解釋了。

三、讓三角形旋轉起來

因爲要讓三角形旋轉起來我們需要在OpenGLView中來監聽事件然後來設置旋轉度,所以貼出代碼也就不做贅敘了。

3.1OpenGLView.java

package com.macrocheng.opengl3d01;

 

import android.content.Context;

import android.opengl.GLSurfaceView;

import android.view.MotionEvent;

 

public class OpenGLView extends GLSurfaceView {

         private static final String LOG = OpenGLView.class.getSimpleName();

         private OpenGLRenderer or;

        

         private float xAngle;

         private float yAngle;

 

         public OpenGLView(Context context) {

                   super(context);

                   // TODO Auto-generated constructor stub

                   or = new OpenGLRenderer();

                   setRenderer(or);

         }

 

         // 監聽touch事件,用來改變顏色、改變旋轉度

         public boolean onTouchEvent(final MotionEvent event) {

                   if (event.getAction() == MotionEvent.ACTION_MOVE

                                     || event.getAction() == MotionEvent.ACTION_DOWN) {

                            queueEvent(new Runnable() {

                                     public void run() {

                                               or.setColor(event.getX() / getWidth(), event.getY()

                                                                 / getHeight(), 1.0f);

                                     }

                            });

                   }

                   if (event.getAction() == MotionEvent.ACTION_DOWN) {

                            xAngle = event.getX();

                            yAngle = event.getY();

                   }

                   if (event.getAction() == MotionEvent.ACTION_MOVE) {

                            final float xdiff = (xAngle - event.getX());

                            final float ydiff = (yAngle - event.getY());

                            queueEvent(new Runnable() {

                                     public void run() {

                                               or.setXAngle(or.getXAngle() + ydiff);

                                               or.setYAngle(or.getYAngle() + xdiff);

                                     }

                            });

                            xAngle = event.getX();

                            yAngle = event.getY();

                   }

                   return true;

         }

}

3.2、旋轉的關鍵

你應該已經知道了,這裏只是設置了一下旋轉的角度,至於關鍵還是在OpenGLRenderer.java中的倆條語句:

/**

        * 旋轉,四個參數分別是旋轉度、x軸、y軸、z

        * 後面三個值來決定圍繞那個軸線來旋轉

        */

       gl.glRotatef(xAngle, 1f, 0f, 0f);

    gl.glRotatef(yAngle, 0f, 1f, 0f);

就是這兩句,也已經給出了註釋所以不用多做解釋,只是標識出來。

四、效果貼圖

 

 

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