12_opengl学习

#1  opengl学习资料:

(1.1)百度huachao1001,选择他的专栏,可以看到几篇很好的入门文章!


#2  入门demo:http://www.jianshu.com/p/442682fda917

      再配上这个入门文章,http://blog.csdn.net/jason0539/article/details/9164885

      上面两样东西可以让你很清晰地入门!


       入门之前先看一下View,SurfaceView,GLSurfaceView的概念及区别:http://blog.csdn.net/androidwubo/article/details/60469183


#3  开始绘制第一个图形:三角形

      demo及原理:      http://blog.csdn.net/huachao1001/article/details/52044602


#4   绘制一个3d图形,而且让这个3d图形一直会动!(从网上随便下载一个.stl文件,存到手机sd卡中,然后读取这个.stl文件绘出对应的3d图!)

      demo参考处:    http://blog.csdn.net/huachao1001/article/details/52054334

      自己的代码:


(4.1)布局文件不需要、清单文件中读sd卡权限;

(4.2)Model类:

package com.example.y81022671.a15_opengl_third;

import java.nio.FloatBuffer;

/**
 * Created by y81022671 on 2017/7/4.
 */

public class Model {

    private int facetCount;

    private float[] verts;

    private float[] vnorms;

    private short[] remarks;

    private FloatBuffer vertBuffer;

    private FloatBuffer vnormBuffer;

    float maxX;
    float minX;
    float maxY;
    float minY;
    float maxZ;
    float minZ;

    public Point getCenterPoint() {
        float cx = minX + (maxX - minX) / 2;
        float cy = minY + (maxY - minY) / 2;
        float cz = minZ + (maxZ - minZ) / 2;
        return new Point(cx, cy, cz);
    }

    public float getR() {
        float dx = (maxX - minX);
        float dy = (maxY - minY);
        float dz = (maxZ - minZ);
        float max = dx;
        if (dy > max) {
            max = dy;
        }
        if (dz > max) {
            max = dz;
        }

        return max;
    }

    public float[] getVerts(float[] verts) {
        return verts;
    }

    public void setVerts(float[] verts) {
        this.verts = verts;
        vertBuffer = Util.floatToBuffer(verts);
    }

    public float[] getVnorms(float[] vnorms) {
        return vnorms;
    }

    public void setVnorms(float[] vnorms) {
        this.vnorms = vnorms;
        this.vnormBuffer = Util.floatToBuffer(vnorms);
    }

    public int getFacetCount() {
        return facetCount;
    }

    public void setFacetCount(int facetCount) {
        this.facetCount = facetCount;
    }

    public short[] getRemarks() {
        return remarks;
    }

    public void setRemarks(short[] remarks) {
        this.remarks = remarks;
    }

    public FloatBuffer getVertBuffer() {
        return vertBuffer;
    }

    public FloatBuffer getVnormBuffer() {
        return vnormBuffer;
    }
}

(4.3)Util类:

package com.example.y81022671.a15_opengl_third;

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

/**
 * Created by y81022671 on 2017/7/4.
 */

public class Util {

    public static FloatBuffer floatToBuffer(float[] a) {
        ByteBuffer bb = ByteBuffer.allocateDirect(a.length * 4);
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer buffer = bb.asFloatBuffer();
        buffer.put(a);
        buffer.position(0);
        return buffer;
    }

    //根据stl文件的第81-第84这四个字节,求出该stl文件中有多少个三角面的个数!
    public static int byte4ToInt(byte[] bytes, int offset) {
        int b3 = bytes[offset + 3] & 0xFF;
        int b2 = bytes[offset + 2] & 0xFF;
        int b1 = bytes[offset + 1] & 0xFF;
        int b0 = bytes[offset + 0] & 0xFF;

        return (b3 << 24) | (b2 << 16) | (b1 << 8) | (b0);
    }

    //拿到bytes字节数组,从offset这个下标开始,数4个字节,然后将这4个字节转化成1个float类型的数值!
    public static float byte4ToFloat(byte[] bytes, int offset) {
        return Float.intBitsToFloat(byte4ToInt(bytes, offset));
    }

    public static int byte2ToShort(byte[] bytes, int offset) {
        int b1 = bytes[offset + 1] & 0xFF;
        int b0 = bytes[offset + 0] & 0xFF;
        return (short) ((b1 << 8) | b0);
    }
}

(4.4)STLReader类:

package com.example.y81022671.a15_opengl_third;

import android.content.Context;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by y81022671 on 2017/7/4.
 */

public class STLReader {
    private StlLoadListener stlLoadListener = new StlLoadListener() {
        @Override
        public void onstart() {
            System.out.println("StlLoadListener  onstart");
        }

        @Override
        public void onLoading(int cur, int total) {
            System.out.println("StlLoadListener  onLoading");
        }

        @Override
        public void onFinished() {
            System.out.println("StlLoadListener  onFinished");
        }

        @Override
        public void onFailure(Exception e) {
            System.out.println("StlLoadListener  onFailure");
        }
    };

    public Model parserBinStlInSDCard(String path) throws IOException {
        File file = new File(path);
        FileInputStream fis = new FileInputStream(file);

        return parserBinStl(fis);
    }

    public Model parserBinStlInAssets(Context context, String fileName) throws IOException {
        InputStream is = context.getAssets().open(fileName);

        return parserBinStl(is);
    }

    //根据二进制的stl文件读出它的相关数据!即解析二进制的stl文件
    public Model parserBinStl(InputStream in) throws IOException {
        if (null != stlLoadListener) {
            stlLoadListener.onstart();
        }

        Model model = new Model();
        in.skip(80);

        byte[] bytes = new byte[4];
        in.read(bytes);
        int facetCount = Util.byte4ToInt(bytes, 0);

        model.setFacetCount(facetCount);

        if (facetCount == 0) {
            in.close();
            return model;
        }

        byte[] facetBytes = new byte[50 * facetCount];
        in.read(facetBytes);
        in.close();


        //定义一个新的方法解析后面那些关于三角面的字节
        parseModel(model, facetBytes);

        if (null != stlLoadListener) {
            stlLoadListener.onFinished();
        }

        return model;
    }


    //定义的一个新的方法,它的作用是:解析stl二进制文件的后面那些字节(所有三角面信息的那些字节!)
    private void parseModel(Model model, byte[] facetBytes) {

        int facetCount = model.getFacetCount();

        float[] verts = new float[facetCount * 3 * 3];

        float[] vnorms = new float[facetCount * 3 * 3];

        short[] remarks = new short[facetCount];

        int stlOffset = 0;
        try {
            for (int i = 0; i < facetCount; i++) {
                if (null != stlLoadListener) {
                    stlLoadListener.onLoading(i, facetCount);
                }

                for (int j = 0; j < 4; j++) {
                    float x = Util.byte4ToFloat(facetBytes, stlOffset + 0);
                    float y = Util.byte4ToFloat(facetBytes, stlOffset + 4);
                    float z = Util.byte4ToFloat(facetBytes, stlOffset + 8);
                    stlOffset = stlOffset + 12;

                    if (j == 0) {
                        vnorms[i * 9 + 0] = x;
                        vnorms[i * 9 + 1] = y;
                        vnorms[i * 9 + 2] = z;
                        vnorms[i * 9 + 3] = x;
                        vnorms[i * 9 + 4] = y;
                        vnorms[i * 9 + 5] = z;
                        vnorms[i * 9 + 6] = x;
                        vnorms[i * 9 + 7] = y;
                        vnorms[i * 9 + 8] = z;

                    } else {
                        verts[i * 9 + (j - 1) * 3 + 0] = x;
                        verts[i * 9 + (j - 1) * 3 + 1] = y;
                        verts[i * 9 + (j - 1) * 3 + 2] = z;
                    }

                    if (i == 0 && j == 1) {
                        model.minX = model.maxX = x;
                        model.minY = model.maxY = y;
                        model.minZ = model.maxZ = z;
                    } else {
                        model.minX = Math.min(model.minX, x);
                        model.minY = Math.min(model.minY, y);
                        model.minZ = Math.min(model.minZ, z);

                        model.maxX = Math.max(model.maxX, x);
                        model.maxY = Math.max(model. maxY, y);
                        model.maxZ = Math.max(model.maxZ, z);
                    }
                }

                //stl文件的注释说明部分!
                short r = (short) Util.byte2ToShort(facetBytes, facetCount);
                stlOffset = stlOffset + 2;
                remarks[i] = r;
            }
        } catch (Exception e) {
            if (null != stlLoadListener) {
                stlLoadListener.onFailure(e);
            } else {
                e.printStackTrace();
            }
        }

        model.setVerts(verts);
        model.setVnorms(vnorms);
        model.setRemarks(remarks);

    }


    public static interface StlLoadListener {
        void onstart();

        void onLoading(int cur, int total);

        void onFinished();

        void onFailure(Exception e);
    }
}

(4.5)MyRenderer类:

package com.example.y81022671.a15_opengl_third;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.os.Environment;

import java.io.File;
import java.io.IOException;

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

/**
 * Created by y81022671 on 2017/7/5.
 */

public class MyRenderer implements GLSurfaceView.Renderer {

    private Model model;

    private float mScalef = 1;
    private Point mCenterPoint;

    private Point eye = new Point(0, 0, -3);
    private Point up = new Point(0, 1, 0);
    private Point center = new Point(0, 0, 0);

    private float mDegree = 0;

    public MyRenderer(Context context) {
        try {
            String name0 = Environment.getExternalStorageDirectory() + "00";
            String name1 = Environment.getExternalStorageDirectory() + File.pathSeparator + "smile.stl";
            String name = new File(Environment.getExternalStorageDirectory() + File.separator + "smile.stl").getAbsolutePath();
            String name2 = new File(Environment.getExternalStorageDirectory() + File.separator + "smile.txt").getName();
            //model = new STLReader().parserBinStlInAssets(context, name);
            //model = new STLReader().parserBinStlInAssets(context, name);
            model = new STLReader().parserBinStlInSDCard(name);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void rotate(float degree) {
        mDegree = degree;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glClearDepthf(1.0f);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        gl.glShadeModel(GL10.GL_SMOOTH);
        float r = model.getR();
        mScalef = 0.5f / r;
        mCenterPoint = model.getCenterPoint();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        GLU.gluPerspective(gl, 45.0f, ((float) width / height), 1f, 100f);

        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();

        GLU.gluLookAt(gl, eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z);

        gl.glRotatef(mDegree, 0, 1, 0);
        gl.glScalef(mScalef, mScalef, mScalef);
        gl.glTranslatef(-mCenterPoint.x, -mCenterPoint.y, -mCenterPoint.z);


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

        gl.glNormalPointer(GL10.GL_FLOAT, 0, model.getVnormBuffer());
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, model.getVertBuffer());

        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, model.getFacetCount() * 3);

        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
    }
}

(4.6) MainActivity类:

package com.example.y81022671.a15_opengl_third;

import android.app.ActivityManager;
import android.content.pm.ConfigurationInfo;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private boolean isSupportsEs2;
    private GLSurfaceView glView;
    private MyRenderer myRenderer;

    private float rotateDegreen = 0;

    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            rotate(rotateDegreen);
        }

    };


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

        checkSupported();

        if (isSupportsEs2) {
            glView = new GLSurfaceView(this);
            myRenderer = new MyRenderer(this);
            glView.setRenderer(myRenderer);
            setContentView(glView);
        } else {
            setContentView(R.layout.activity_main);
            Toast.makeText(this, "当前设备不支持OpenGL ES 2.0!", Toast.LENGTH_SHORT).show();
        }

    }




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

        if (null != glView) {
            glView.onResume();

            new Thread() {

                @Override
                public void run() {
                    while (true) {
                        try {
                            sleep(100);

                            rotateDegreen += 5;
                            handler.sendEmptyMessage(0x001);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }.start();
        }
    }




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

        if (null != glView) {
            glView.onPause();
        }
    }





    private void rotate(float rotateDegreen) {
        myRenderer.rotate(rotateDegreen);
        glView.invalidate();
    }





    private void checkSupported() {
        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
        isSupportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;

        boolean isEmulator = Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
                && (Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.startsWith("unknown")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.MODEL.contains("Android SDK built for x86"));

        isSupportsEs2 = isSupportsEs2 || isEmulator;
    }
}


#5

      





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值