12_opengl学习

来源:互联网 发布:oracle数据库考试 编辑:程序博客网 时间:2024/06/14 12:24

#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

      





原创粉丝点击