我一直在尝试将我之前编写的使用显示列表的 OBJ 解析器转换为使用 VBO,并试图看看我是否可以在没有任何外部帮助的情况下自己解决这个问题,但现在我想我一直在看代码太长,找不到任何错误。
这是一个 Android 应用程序,通过 OpenGLES 2.0,我最终在屏幕上出现了一些三角形,但根本不在正确的位置。我有一种感觉,我尝试根据单个索引列表获取每个面的所有元素是不正确的,我最终只是把所有东西都乱七八糟地扔掉了,但我找不到我的错误。
本质上,由于 OBJ 格式为顶点、纹理坐标和法线向量提供了单独的索引,因此我最终得到了 3 个彼此完全乱序的数据列表,但 VBO 基于单个引用每个部分索引列表。
这是我的代码,以帮助某人帮助我:
OBJ工具包:
public class OBJToolkit {
public static Mesh loadOBJ(String modelLocation) throws FileNotFoundException, IOException
{
Log.d("OBJToolkit", "Location searched for model: " + modelLocation);
ArrayList<Float> allVertices = new ArrayList<Float>();
ArrayList<Float> allTextureCoors = new ArrayList<Float>();
ArrayList<Float> allNormals = new ArrayList<Float>();
ArrayList<Face> faces = new ArrayList<Face>();
BufferedReader reader = new BufferedReader(new FileReader(new File(modelLocation)));
Mesh mesh = new Mesh();
Log.d("OBJToolkit", "About to read the contents of the model");
while (reader.ready())
{
String line = reader.readLine();
if (line == null)
break;
if (line.startsWith("v "))
{
allVertices.add(Float.valueOf(line.split(" ")[1]));
allVertices.add(Float.valueOf(line.split(" ")[2]));
allVertices.add(Float.valueOf(line.split(" ")[3]));
}
if (line.startsWith("vt "))
{
allTextureCoors.add(Float.valueOf(line.split(" ")[1]));
allTextureCoors.add(Float.valueOf(line.split(" ")[2]));
}
if (line.startsWith("vn "))
{
allNormals.add(Float.valueOf(line.split(" ")[1]));
allNormals.add(Float.valueOf(line.split(" ")[2]));
allNormals.add(Float.valueOf(line.split(" ")[3]));
}
if (line.startsWith("f "))
{
Face f = new Face();
String[] lineArray = line.split(" ");
for (int index = 1; index < lineArray.length; index++)
{
String[] valueArray = lineArray[index].split("/");
f.addVertexIndex(Integer.valueOf(valueArray[0]));
if (valueArray.length > 1)
f.addTextureIndex(Integer.valueOf(valueArray[1]));
if (valueArray.length > 2)
f.addNormalIndex(Integer.valueOf(valueArray[2]));
}
faces.add(f);
}
}
reader.close();
ArrayList<Float> verticesInOrder = new ArrayList<Float>();
ArrayList<Integer> indicesInOrder = new ArrayList<Integer>();
ArrayList<Float> textureCoorsInOrder = new ArrayList<Float>();
ArrayList<Float> normalsInOrder = new ArrayList<Float>();
int counter = 0;
Log.d("OBJToolkit", "About to reorganize each point of data");
for (Face f : faces)
{
for (int value : f.vertexIndices)
{
verticesInOrder.add(allVertices.get(value));
}
for (int value : f.textureIndices)
{
textureCoorsInOrder.add(allTextureCoors.get(value));
}
for (int value : f.normalIndices)
{
normalsInOrder.add(allNormals.get(value));
}
indicesInOrder.add(counter);
counter++;
}
Log.d("OBJToolkit", "Vertices");
printFloatArrayList(verticesInOrder);
Log.d("OBJToolkit", "Indices");
printIntegerArrayList(indicesInOrder);
Log.d("OBJToolkit", "Texture Coordinates");
printFloatArrayList(textureCoorsInOrder);
Log.d("OBJToolkit", "Normals");
printFloatArrayList(normalsInOrder);
Log.d("OBJToolkit", "About to create the VBOs");
mesh.createBuffers(floatListToFloatArray(verticesInOrder), integerListToShortArray(indicesInOrder), null, floatListToFloatArray(textureCoorsInOrder));
return mesh;
}
public static void printFloatArrayList(ArrayList<Float> list)
{
String strToPrint = "";
for (float value : list)
{
strToPrint += value + ", ";
}
Log.d("OBJToolkit", strToPrint);
}
public static void printIntegerArrayList(ArrayList<Integer> list)
{
String strToPrint = "";
for (float value : list)
{
strToPrint += value + ", ";
}
Log.d("OBJToolkit", strToPrint);
}
public static float[] floatListToFloatArray(ArrayList<Float> list)
{
Log.d("OBJToolkit", "Converting ArrayList Float");
float[] returnArray = new float[list.size()];
int counter = 0;
for (float i : list)
{
returnArray[counter] = i;
counter++;
}
return returnArray;
}
public static short[] integerListToShortArray(ArrayList<Integer> list)
{
Log.d("OBJToolkit", "Converting ArrayList Integer");
short[] returnArray = new short[list.size()];
int counter = 0;
for (int i : list)
{
returnArray[counter] = (short)i;
counter++;
}
return returnArray;
}
}
网格类:
public class Mesh {
Bitmap bitmap = null;
private FloatBuffer verticesBuffer;
private ShortBuffer indicesBuffer;
private int numOfIndices = -1;
private float[] rgba = new float[] {1.0f, 1.0f, 1.0f, 1.0f};
private FloatBuffer colorBuffer;
private FloatBuffer mTextureBuffer;
private int mTextureId = -1;
private Bitmap mBitmap;
private boolean mShouldLoadTexture = false;
public float x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0;
public Mesh() {
}
public void draw(GL10 gl)
{
//Log.d("Mesh", "About to render mesh");
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
if (colorBuffer != null)
{
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
}
if (mShouldLoadTexture)
{
loadGLTexture(gl);
mShouldLoadTexture = false;
}
if (mTextureId != -1 && mTextureBuffer != null)
{
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
}
gl.glTranslatef(x, y, z);
gl.glRotatef(rx, 1, 0, 0);
gl.glRotatef(ry, 0, 1, 0);
gl.glRotatef(rz, 0, 0, 1);
gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, GL10.GL_UNSIGNED_SHORT, indicesBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
if (mTextureId != -1 && mTextureBuffer != null)
{
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
gl.glDisable(GL10.GL_CULL_FACE);
}
public void setTexture(Bitmap bitmap) {
this.bitmap = bitmap;
}
public void createBuffers(float[] vertices, short[] indices, float[] colors, float[] textureCoords)
{
Log.d("MeshCreateBuffers", "Vertices: " + floatArrayToString(vertices));
setVertices(vertices);
Log.d("MeshCreateBuffers", "Indices: " + shortArrayToString(indices));
setIndices(indices);
if (colors != null)
setColors(colors);
setTextureCoordinates(textureCoords);
Log.d("MeshCreateBuffers", "Texture Coors: " + floatArrayToString(textureCoords));
}
public String floatArrayToString(float[] array)
{
String returnString = "";
for (int i = 0; i < array.length; i++)
{
returnString += array[i];
}
return returnString;
}
public String shortArrayToString(short[] array)
{
String returnString = "";
for (int i = 0; i < array.length; i++)
{
returnString += array[i];
}
return returnString;
}
protected void setVertices(float[] vertices)
{
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
verticesBuffer = vbb.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.position(0);
}
protected void setIndices(short[] indices)
{
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indicesBuffer = ibb.asShortBuffer();
indicesBuffer.put(indices);
indicesBuffer.position(0);
numOfIndices = indices.length;
}
protected void setColor(float red, float green, float blue, float alpha)
{
rgba[0] = red;
rgba[1] = green;
rgba[2] = blue;
rgba[3] = alpha;
}
protected void setColors(float[] colors)
{
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
colorBuffer = cbb.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
}
protected void setTextureCoordinates(float[] textureCoords)
{
ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
mTextureBuffer = byteBuf.asFloatBuffer();
mTextureBuffer.put(textureCoords);
mTextureBuffer.position(0);
}
public void loadBitmap(Bitmap bitmap)
{
this.mBitmap = bitmap;
mShouldLoadTexture = true;
}
private void loadGLTexture(GL10 gl)
{
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureId = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
}
}
我是否在做一些我无法发现的明显错误或过于复杂的事情?
我感谢任何愿意提供意见的人。