ThreeDGl.java

package com.hl.androidopgles;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;

public class ThreeDGl implements Renderer
{
    public ThreeDGl()
    {
        // TODO Auto-generated method stub
        int one = 0x10000;
        int vertices[] = {
                -one, -one, -one,
                one, -one, -one,
                one, one, -one,
                -one, one, -one,
                -one, -one, one,
                one, -one, one,
                one, one, one,
                -one, one, one,
        };

        int colors[] = {
                0, 0, 0, one,
                one, 0, 0, one,
                one, one, 0, one,
                0, one, 0, one,
                0, 0, one, one,
                one, 0, one, one,
                one, one, one, one,
                0, one, one, one,
        };

        byte indices[] = {
                0, 4, 5, 0, 5, 1,
                1, 5, 6, 1, 6, 2,
                2, 6, 7, 2, 7, 3,
                3, 7, 4, 3, 4, 0,
                4, 7, 6, 4, 6, 5,
                3, 0, 1, 3, 1, 2
        };

        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
        vbb.order(ByteOrder.nativeOrder());
        mVertexBuffer = vbb.asIntBuffer();
        mVertexBuffer.put(vertices);
        mVertexBuffer.position(0);

        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
        cbb.order(ByteOrder.nativeOrder());
        mColorBuffer = cbb.asIntBuffer();
        mColorBuffer.put(colors);
        mColorBuffer.position(0);

        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
        mIndexBuffer.put(indices);
        mIndexBuffer.position(0);

        /**
         * @brief Explain
         * 0x10000是出於OPENGL前期內存節約的考慮,以INT型模擬FLOAT型來表示,0x 0001 0000 前面4位表示小數點前,後4位表示小數點後,所以0x10000表示浮點數的1。如果你用的是FloatBuffer,就可以知道此處應該寫1.0。
         * gl.glVertexPointer(3, GL10.GL_FIXED, 0, triggerBuffer);//GL_FIXED,則後面用的是intbuffer。如上面的例子
         * gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triggerBuffer);//則此處那個triggerBuffer用的則是floatBuffer類型。
         */
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        // TODO Auto-generated method stub
        // 清除屏幕和深度緩存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 重置當前的模型觀察矩陣
        gl.glLoadIdentity();

        // 允許設置頂點
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        // 允許設置顏色
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        // 左移1.5單位,並移入屏幕6.0
        gl.glTranslatef(-1.5f, 0.0f, -6.0f);
        //設置和繪制正方形
        gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
        gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);

        // 取消顏色設置
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        // 取消頂點設置
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // TODO Auto-generated method stub
        //設置OpenGL場景的大小
        gl.glViewport(0, 0, width, height);
        //設置投影矩陣
        gl.glMatrixMode(GL10.GL_PROJECTION);
        //重置投影矩陣
        gl.glLoadIdentity();
        // 設置視口的大小
        gl.glFrustumf(-1.5f, 1.5f, -1.5f, 1.5f, 1.0f, 10.0f);
        // 選擇模型觀察矩陣
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        // 重置模型觀察矩陣
        gl.glLoadIdentity();

        /**
         * @brief Explain
         *    小滿(bill man)個人原創,歡迎轉載,轉載請註明地址,小滿(bill man)的專欄地址http://blog.csdn.net/bill_man

         *    在3d世界中投影也是很重要的一部分,openGL ES支持兩種投影方式,正交投影和透視投影。

         *    1.正交投影

         *     正交投影中觀察者的視線是平行的,不產生進大選小的效果,設置正交投影的語句為

         *    gl.glOrthof(-ratio, ratio, -1, 1, 1, 10);

         *    第一個和第二個參數為視口左右側對應的x坐標,第三個和第四個參數為視口上下側對應的y坐標,第五個和第六個坐標為最近端和最遠端的z坐標

         *    OpenGL不支持無限遠的可視區域,視口就是屏幕上指定的矩形區域

         *    設置的方法就是在GLSurfaceView.Renderer類中的onDrawFrame方法中設置這句即可

         *    2.透視投影

         *     透視投影和正交投影不同,如同現實中觀測到的世界一樣,會產生近大遠小的效果,設置的方法和正交投影一樣,也是在GLSurfaceView.Renderer類中的onDrawFrame方法中設置

         *    設置正交的語句為

         *    gl.glFrustumf(-ratio, ratio, -1, 1, 1f, 10);

         *    第一個和第二個參數為視口左右側對應的x坐標,第三個和第四個參數為視口上下側對應的y坐標,第五個和第六個坐標為最近端和最遠端的z坐標

         *    在left,right,top,bottom值不變的情況下,near值越小,視角越大,在開發中對這六個參數的調整非常重要

         *    3.設置視口

         *     在GLSurfaceView.Renderer的onSurfaceChanged方法中調用如下的方法即可

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

         *    前兩個參數為視口矩形在屏幕左上側點的坐標,後兩個參數是寬度和高度

         *    4.近大遠小原理

         *     正交投影的視景體就相當於長方體,沒有近大遠小的效果,所有物體都保留原有的大小和角度,而透視投影則是距離攝像機越遠物體在圖像中看上去就越小,離攝像機越近,則看上去越大。

         *    參考自Android 3d 遊戲開發技術詳解與典型案例,如有錯誤之處,希望大家多多指正


         */
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // TODO Auto-generated method stub
        // 啟用陰影平滑
        gl.glShadeModel(GL10.GL_SMOOTH);
        //黑色背景
        gl.glClearColor(1.0f, 1.0f, 1.0f, 0.7f);
        //設置深度緩沖
        gl.glClearDepthf(1.0f);
        //啟用深度緩沖
        gl.glEnable(GL10.GL_DEPTH_TEST);
        //設置深度測試類型
        gl.glDepthFunc(GL10.GL_LEQUAL);
        //對透視進行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

        /**
         * @brief Explain
         * glHint 用於告訴 OpenGL 我們希望進行最好的透視修正,這會輕微地影響性能,但會使得透視圖更好看。
         * glClearColor 設置清除屏幕時所用的顏色,色彩值的範圍從 0.0f~1.0f 大小從暗到這的過程。
         * glShadeModel 用於啟用陰影平滑度。陰影平滑通過多邊形精細地混合色彩,並對外部光進行平滑。
         *    glDepthFunc 為將深度緩存設想為屏幕後面的層,它不斷地對物體進入屏幕內部的深度進行跟蹤。
         *    glEnable 啟用深度測試。
         */
    }

    private IntBuffer mVertexBuffer;
    private IntBuffer mColorBuffer;
    private ByteBuffer mIndexBuffer;
}
MainActivity.java

package com.hl.androidopgles;

import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {
    Renderer render = new ThreeDGl();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GLSurfaceView gview=new GLSurfaceView(this);
        gview.setRenderer(render);
        setContentView(gview);
                       //---編譯不過、註釋掉-----
        // getActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
             //---編譯不過、註釋掉-----
        // switch (item.getItemId()) {
        // case android.R.id.home:
        // NavUtils.navigateUpFromSameTask(this);
        // return true;
        // }
        return super.onOptionsItemSelected(item);
    }

}
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 愛在屋簷下 的頭像
    愛在屋簷下

    愛在屋簷下的部落格

    愛在屋簷下 發表在 痞客邦 留言(0) 人氣()