//加载后的物体——仅携带顶点信息 public class LoadedObjectVertexOnly { int mProgram;//自定义渲染管线着色器程序id int muMVPMatrixHandle;//总变换矩阵引用 int maPositionHandle; //顶点位置属性引用 String mVertexShader;//顶点着色器代码脚本 String mFragmentShader;//片元着色器代码脚本 FloatBuffer mVertexBuffer;//顶点坐标数据缓冲 int vCount=0; public LoadedObjectVertexOnly(MySurfaceView mv,float[] vertices) { //初始化顶点坐标与着色数据 initVertexData(vertices); //初始化shader initShader(mv); } //初始化顶点坐标的方法 public void initVertexData(float[] vertices) { //顶点坐标数据的初始化================begin============================ vCount=vertices.length/3; //创建顶点坐标数据缓冲 //vertices.length*4是因为一个整数四个字节 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); vbb.order(ByteOrder.nativeOrder());//设置字节顺序 mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲 mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据 mVertexBuffer.position(0);//设置缓冲区起始位置 //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题 //顶点坐标数据的初始化================end============================ } //初始化shader public void initShader(MySurfaceView mv) { //加载顶点着色器的脚本内容 mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_color.sh", mv.getResources()); //加载片元着色器的脚本内容 mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_color.sh", mv.getResources()); //基于顶点着色器与片元着色器创建程序 mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader); //获取程序中顶点位置属性引用 maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); //获取程序中总变换矩阵引用 muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); } public void drawSelf() { //制定使用某套着色器程序 GLES20.glUseProgram(mProgram); //将最终变换矩阵传入着色器程序 GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0); // 将顶点位置数据传入渲染管线 GLES20.glVertexAttribPointer ( maPositionHandle, 3, GLES20.GL_FLOAT, false, 3*4, mVertexBuffer ); //启用顶点位置数据 GLES20.glEnableVertexAttribArray(maPositionHandle); //绘制加载的物体 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount); } }
public class LoadUtil { //从obj文件中加载仅携带顶点信息的物体 public static LoadedObjectVertexOnly loadFromFile(String fname, Resources r,MySurfaceView mv) { LoadedObjectVertexOnly lo=null; ArrayList<Float> alv=new ArrayList<Float>();//原始顶点坐标列表 ArrayList<Float> alvResult=new ArrayList<Float>();//结果顶点坐标列表 try { InputStream in=r.getAssets().open(fname); InputStreamReader isr=new InputStreamReader(in); BufferedReader br=new BufferedReader(isr); String temps=null; while((temps=br.readLine())!=null) { String[] tempsa=temps.split("[ ]+"); if(tempsa[0].trim().equals("v")) {//此行为顶点坐标 alv.add(Float.parseFloat(tempsa[1])); alv.add(Float.parseFloat(tempsa[2])); alv.add(Float.parseFloat(tempsa[3])); } else if(tempsa[0].trim().equals("f")) {//此行为三角形面 int index=Integer.parseInt(tempsa[1].split("/")[0])-1; alvResult.add(alv.get(3*index)); alvResult.add(alv.get(3*index+1)); alvResult.add(alv.get(3*index+2)); index=Integer.parseInt(tempsa[2].split("/")[0])-1; alvResult.add(alv.get(3*index)); alvResult.add(alv.get(3*index+1)); alvResult.add(alv.get(3*index+2)); index=Integer.parseInt(tempsa[3].split("/")[0])-1; alvResult.add(alv.get(3*index)); alvResult.add(alv.get(3*index+1)); alvResult.add(alv.get(3*index+2)); } } //生成顶点数组 int size=alvResult.size(); float[] vXYZ=new float[size]; for(int i=0;i<size;i++) { vXYZ[i]=alvResult.get(i); } //创建物体对象 lo=new LoadedObjectVertexOnly(mv,vXYZ); } catch(Exception e) { Log.d("load error", "load error"); e.printStackTrace(); } return lo; } }