Android OpenGL 座標系

計算機中任何繪圖都離不開座標系只是在每種繪圖中座標系形式有些差異,比如平時做android的View,在自定義View中繪製直線,那麼這個時候默認的是採用的是屏幕座標系,即座標原點在屏幕左上角,X軸向右,Y向下:

而在opengl中採用的是3維座標:


座標原點默認在屏幕的中間,即(width/2,height/2)位置上,z軸是從屏幕"內"指向屏幕外,而且還要注意原點和x,y軸平面是在屏幕的"表面",有引號,這個"表面"剛好是人看不到的面,所以如果你要畫一條線,線端點(1,0,0),(0,1,0),直接畫到屏幕上,將看不到顯示,怎麼辦?很簡單,這個座標系是三維空間的,那麼就將座標系沿Z軸的負軸方向移動一點,將X,Y平面稍微向屏幕內部移動一點,就能夠看到直線了,想象一下在三維空間中,將座標系往屏幕裏面推一下,那麼x,y軸形成的平面就在屏幕裏面了,在它上面的直線就可以看見了.後面有例子.


紋理座標系:

一般座標系都自由操作移動(或旋轉).


基本瞭解了座標系,後面就可以開始繪圖了

根據上面的可以通過畫直線畫出OPENGL座標系,這樣就可以被看見了:

<1> : android studio新建PumpKinBasicGL10工程:程序如下:

package org.durian.pumpkinbasicgl10;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

import org.durian.pumpkinbasicgl10.draw2d.PumpKinRenderer;


public class MainActivity extends Activity {

    private GLSurfaceView mSurfaceView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSurfaceView=new GLSurfaceView(this);
        mSurfaceView.setRenderer(new PumpKinRenderer()/*new PumpkinDotRenderer()*//*new PumpKinLineRenderer(this)*//*new PumpKinTriangleRenderer()*//*new PumpKinPyramidRenderer()*/);
        setContentView(mSurfaceView/*R.layout.activity_main*/);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mSurfaceView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSurfaceView.onPause();
    }
}

渲染類:

</pre><pre class="html" name="code">package org.durian.pumpkinbasicgl10.draw2d;

import android.opengl.GLSurfaceView;
import android.opengl.GLU;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by Administrator on 2016/4/28.
 */
public class PumpKinRenderer implements GLSurfaceView.Renderer {

    private PumpKin pumpKin;

    public PumpKinRenderer(){
        pumpKin=new PumpKin();
    }
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
        gl.glClearDepthf(1.0f);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glDisable(GL10.GL_DITHER);

    }

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

        if(height==0){
            height=1;
        }
        float aspect=(float)width/height;

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

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

    }

    @Override
    public void onDrawFrame(GL10 gl) {

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);

        gl.glLoadIdentity();
        gl.glTranslatef(0.0f,0.0f,-2f);
        //gl.glRotatef(45,1.0f,1.0f,1.0f);
        pumpKin.draw(gl);

    }
}

這個渲染類裏面稍微注意將座標系"下沉"-2f單位.這樣方便看到圖形.可以試一下不執行:

gl.glTranslatef(0.0f,0.0f,-2f);
就能夠體會了.

繪圖類:
package org.durian.pumpkinbasicgl10.draw2d;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

/**
 * Created by Administrator on 2016/4/28.
 */
public class PumpKin {

    private FloatBuffer vertexsBuffer;
    private FloatBuffer colorsBuffer;

    private ByteBuffer indicesBuffer;

    private float vertexs[]={
        0.0f,0.0f,0.0f,
            1.0f,0.0f,0.0f,
            0.0f,0.0f,0.0f,
            0.0f,1.0f,0.0f,
            0.0f,0.0f,0.0f,
            0.0f,0.0f,1.0f
    };

    private float colors[]={
            1.0f,0.0f,0.0f,1.0f,
            1.0f,0.0f,0.0f,1.0f,
            0.0f,1.0f,0.0f,1.0f,
            0.0f,1.0f,0.0f,1.0f,
            0.0f,0.0f,1.0f,1.0f,
            0.0f,0.0f,1.0f,1.0f
    };

    private byte indices[]={0,1,2};

    public PumpKin(){

        ByteBuffer vbb=ByteBuffer.allocateDirect(vertexs.length*4);
        vbb.order(ByteOrder.nativeOrder());
        vertexsBuffer=vbb.asFloatBuffer();
        vertexsBuffer.put(vertexs);
        vertexsBuffer.position(0);

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

    }

    public void draw(GL10 gl){

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexsBuffer);
        gl.glColorPointer(4,GL10.GL_FLOAT,0,colorsBuffer);

        gl.glDrawArrays(GL10.GL_LINES,0,vertexs.length/3);

        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    }

}


給線添加顏色:

private float colors[]={
            1.0f,0.0f,0.0f,1.0f,
            1.0f,0.0f,0.0f,1.0f,
            0.0f,1.0f,0.0f,1.0f,
            0.0f,1.0f,0.0f,1.0f,
            0.0f,0.0f,1.0f,1.0f,
            0.0f,0.0f,1.0f,1.0f
    };


colors[0]和colors[1]表示從原點到座標(1,0,0)的顏色,如果[0]和[1]顏色不同,將會產生顏色漸變.

如果加入上面數組改爲:

private float colors[]={
            1.0f,0.0f,0.0f,1.0f,
            1.0f,0.0f,0.0f,1.0f,
            0.0f,1.0f,0.0f,1.0f,
            0.0f,1.0f,0.0f,1.0f
    };

試一下,畫Z會是什麼顏色?

將會是(0.0f,1.0f,0.0f,1.0f),即綠色.

運行結果:

發現只有兩個座標,Z軸沒有發現,其實Z軸目前正垂直於屏幕,指向屏幕外,所以看不見,可以修改程序,讓座標旋轉一下:

@Override
    public void onDrawFrame(GL10 gl) {

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);

        gl.glLoadIdentity();
        gl.glTranslatef(0.0f,0.0f,-2f);
        gl.glRotatef(45,1.0f,1.0f,1.0f);
        pumpKin.draw(gl);

    }

沿着矢量(1.0f,1.0f,1.0f)做右手定則式旋轉,即手握住這個矢量方向,順手指的方向旋轉45度.也可以說做了矩陣變換後得到的.


途中虛線是截圖的問題,實際屏幕是連續的.

紅線 : X軸方向;

綠線: Y軸方向;

藍線: Z軸方向;































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