//加载后的物体——仅携带顶点信息
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 alv=new ArrayList();//原始顶点坐标列表
ArrayList alvResult=new ArrayList();//结果顶点坐标列表
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