【Android】OpenGL ES---图形变换

一、在OpenGL ES中,将一个3D模型显示到2D屏幕中有以下四个过程

1.视角(Viewing)变换

【Android】OpenGL ES---图形变换_第1张图片

2.模型(Modeling)变换

【Android】OpenGL ES---图形变换_第2张图片

3.投影(Projection)变换

【Android】OpenGL ES---图形变换_第3张图片

4.视窗(Viewport)变换

【Android】OpenGL ES---图形变换_第4张图片

二、视角(Viewing)变换和模型(Modeling)变换操作

这两者产生的效果是一样的,具体的有一下三种变换:

  1. -Translate 平移变换
  2. -Rotate 旋转变换
  3. -Scale 缩放变换

1.平移变换

在平移变换之前,调用一下代码

//设置单位矩阵
gl.glLoadIdentity();

调用gl.glTranslatef(float x,float y, float z)方法进行平移

//向右移动0.6个x坐标
gl.glTranslatef(0.6f,0f,0f)

2.旋转变换

调用gl.glRotatef(float angle,float x,float y,float z)

//以经过(0.1f,0.1f)的直线为轴逆时针旋转70度
gl.glRotatef(70,0.1f,0.1f,0f);

3.缩放变化

调用gl.glScalef(float x,float y,float z)

//x、y、z均变为原来的0.5倍
gl.glScalef(0.5f,0.5f,0f)

MainActivity.java

public class MainActivity extends AppCompatActivity {
     
    public static GLSurfaceView glSurfaceView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
     
        super.onCreate(savedInstanceState);
        glSurfaceView = new GLSurfaceView(this);
        glSurfaceView.setRenderer(new MyRenderer());
        glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        setContentView(glSurfaceView);
    }
}

MyRenderer.java

public class MyRenderer implements GLSurfaceView.Renderer {
     
    private float[] mArray = new float[]{
     0f,0f,0f,0.5f,0f,0f,0.25f,-0.5f,0f};
    private int[] colorArray = new int[]{
     
            65535,0,0,0,
            0,65535,0,0,
            65535,655535,0,0};
    private FloatBuffer floatBuffer;
    private IntBuffer intBuffer;
    public MyRenderer(){
     
        floatBuffer = Utils.getFloatBuffer(mArray);
        intBuffer = Utils.getIntBuffer(colorArray);
    }
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
     
        gl.glClearColor(0f,0f,1f,0f);
        gl.glShadeModel(GL10.GL_SMOOTH);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
     
        gl.glViewport(0,0,width,height);
        //平移变换
        //gl.glTranslatef(-0.6f,0.5f,0f);
        //旋转变换
        //gl.glRotatef(70,1f,0f,0f);
        //缩放变化
        //gl.glScalef(0.5f,0.5f,0f);

    }

    @Override
    public void onDrawFrame(GL10 gl) {
     
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT,0,floatBuffer);
        //gl.glColor4f(0,1,0,0);

        //平滑着色
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        gl.glColorPointer(4, GL10.GL_FIXED,0,intBuffer);

        gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    }
}

工具类Utils.java

public class Utils {
     
	//用来将float数组转化为FloatBuffer
    public static FloatBuffer getFloatBuffer(float[] floats){
     
        FloatBuffer floatBuffer;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(floats.length*4);
        byteBuffer.order(ByteOrder.nativeOrder());
        floatBuffer = byteBuffer.asFloatBuffer();
        floatBuffer.put(floats);
        floatBuffer.position(0);
        return floatBuffer;
    }
    //用来将int数组转化为IntBuffer
    public static IntBuffer getIntBuffer(int[] arrays){
     
        IntBuffer intBuffer;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(arrays.length*4);
        byteBuffer.order(ByteOrder.nativeOrder());
        intBuffer = byteBuffer.asIntBuffer();
        intBuffer.put(arrays);
        intBuffer.position(0);
        return  intBuffer;
    }
}

三、投影变换

  1. 先在onSurfaceCreated()中开启深度测量(gl.glEnable(GL10.GL_DEPTH_TEST);),并设置深度缓冲比较函数(gl.glDepthFunc(GL10.GL_LEQUAL))
  2. 在onSurfaceChanged()中转换到投影视图设置投影空间的大小(glFrustumf()或者GLU.gluPerspective)
  3. 在onDrawFrame()中切换到模型视图设置平移和旋转实现3D效果

MainActivity.java

public class MainActivity extends AppCompatActivity {
     
    public static GLSurfaceView glSurfaceView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
     
        super.onCreate(savedInstanceState);
        glSurfaceView = new GLSurfaceView(this);
        glSurfaceView.setRenderer(new MyRenderer());
        //glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        setContentView(glSurfaceView);
    }
}

MyRenderer.java

public class MyRenderer implements GLSurfaceView.Renderer {
     
    private float[] rectData = new float[]{
     
            0.4f,0.4f,0f,
            -0.4f,0.4f,0f,
            0.4f,-0.4f,0f,
            -0.4f,-0.4f,0f};

    private int[] colorArray = new int[]{
     
            65535,0,0,0,
            0,65535,0,0,
            65535,655535,0,0
    };
    private FloatBuffer rectFloatBuffer;
    private IntBuffer rectColorBuffer;
    public MyRenderer(){
     
        rectFloatBuffer = Utils.getFloatBuffer(rectData);
        rectColorBuffer = Utils.getIntBuffer(colorArray);

    }
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
     
        gl.glClearColor(0.5f,0.5f,0.5f,0);
        gl.glClearDepthf(1.0f);
        gl.glShadeModel(GL10.GL_FLAT);

        // 第一步、启用深度测试!!!!!!!
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        //gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);


    }

    @Override
    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;
        //GLU.gluPerspective(gl,);
        //设定透视投影空间大小,两种方法都可以
        //gl.glFrustumf(-ratio,ratio,1f,1f,1f,1000f);
        
        
        /*1.fovy是眼睛上下睁开的幅度,角度值,值越小,视野范围越狭小(眯眼),值越大,视野范围越宽			  阔(睁开铜铃般的大眼);
        2.aspect表示裁剪面的宽w高h比,这个影响到视野的截面有多大。
        3.zNear表示近裁剪面到眼睛的距离,zFar表示远裁剪面到眼睛的距离,注意zNear和zFar不能设置设置为负值
		*/
        GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
                100.0f);
        // 或者用gl.glFrustnum
        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.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        //第三步、转换到模型视图!!!!!!!!!
		gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0f,0f,-2.0f);
        gl.glRotatef(70,0.1f,0.1f,0f);

        gl.glVertexPointer(3,GL10.GL_FLOAT,0,rectFloatBuffer);
        gl.glColorPointer(4, GL10.GL_FIXED,0,rectColorBuffer);

        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);

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

    }
}

工具类Utils.java

public class Utils {
     
	//用来将float数组转化为FloatBuffer
    public static FloatBuffer getFloatBuffer(float[] floats){
     
        FloatBuffer floatBuffer;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(floats.length*4);
        byteBuffer.order(ByteOrder.nativeOrder());
        floatBuffer = byteBuffer.asFloatBuffer();
        floatBuffer.put(floats);
        floatBuffer.position(0);
        return floatBuffer;
    }
    //用来将int数组转化为IntBuffer
    public static IntBuffer getIntBuffer(int[] arrays){
     
        IntBuffer intBuffer;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(arrays.length*4);
        byteBuffer.order(ByteOrder.nativeOrder());
        intBuffer = byteBuffer.asIntBuffer();
        intBuffer.put(arrays);
        intBuffer.position(0);
        return  intBuffer;
    }
}

你可能感兴趣的:(Android开发,android)