我想使用OPENGL ES 1.1 for Android渲染从.obj文件加载的模型。我有顶点,顶点法线和面。当我使用GL10.GL_POINTS渲染模型时,模型看起来很好:
当我使用GL10.GL_TRIANGLES时,我得到了一堆像这样的形状:
这是我的绘图方法。我尝试了glDrawArrays和glDrawElements,但结果相同。
public void draw(GL10 gl){
gl.glEnable(GL10.GL_CULL_FACE);
gl.glFrontFace(GL10.GL_CCW);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, BYTES_PER_VERTEX, m_vertexBuffer);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(COORDS_PER_VERTEX, BYTES_PER_VERTEX, m_normalBuffer);
gl.glColor4f(m_color[0], m_color[1], m_color[2], m_color[3]);
gl.glScalef(0.1f, 0.1f, 0.1f);
// gl.glDrawArrays(GL10.GL_TRIANGLES, 0, m_numNormals);
gl.glDrawElements(GL10.GL_TRIANGLES, m_numIndices, GL10.GL_UNSIGNED_SHORT, m_indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
以下是.obj文件中的示例行:
v 1.012781 -1.591947 1.752353
...
vn 0.495193 0.342204 0.798517
...
# same indices within pairs
f 14978//14978 14977//14977 22659//22659
...
# different indices
f 34422//34418 34375//34371 34374//34370
面部线条的有趣之处在于,有时v // vn对由相同的索引组成,有时它们不包含。总共有4个法线小于顶点。我怀疑这是造成问题的原因。但是我该怎么处理呢?当我使用glDrawElements时,我应该传递哪些索引?
这是我初始化缓冲区的方法:
public void setVertices(float[] coordinates, int size){
final ByteBuffer bb = ByteBuffer.allocateDirect(size * 4);
bb.order(ByteOrder.nativeOrder());
m_vertexBuffer = bb.asFloatBuffer();
m_vertexBuffer.put(coordinates, 0, size);
m_vertexBuffer.position(0);
m_numVertices = size / COORDS_PER_VERTEX;
}
public void setNormals(float[] coordinates, int size){
final ByteBuffer bb = ByteBuffer.allocateDirect(size * 4);
bb.order(ByteOrder.nativeOrder());
m_normalBuffer = bb.asFloatBuffer();
m_normalBuffer.put(coordinates, 0, size);
m_normalBuffer.position(0);
m_numNormals = size / COORDS_PER_VERTEX;
}
// array contains vertices and normals in the order read from the .obj file
// ie every even index is a vertex, every odd index is a normal
public void setIndices(int[] array, int size){
m_numIndices = size / 2;
final ByteBuffer bb = ByteBuffer.allocateDirect(m_numIndices * 4);
bb.order(ByteOrder.nativeOrder());
m_indexBuffer = bb.asIntBuffer();
for(int i = 0; i < size; i+=2)
m_indexBuffer.put(array[i]);
m_indexBuffer.position(0);
}
你能否给我一个如何初始化和使用索引缓冲区的提示?
编辑:这是模型:bunny.obj
答案 0 :(得分:2)
也许这会帮助你我用它来导入一个.obj文件并且它使用纹理和所有东西,你将不得不挑选它与你的项目相关的什么它绑定到所有这些其他类,如实例GLGame和GLGraphics用于文件输入和获取GL10的实例,祝你好运,希望这有帮助
对象加载器
public class ObjLoader {
public static Vertices3 load(GLGame game, String file) {
InputStream in = null;
try {
in = game.getFileIO().readAsset(file);
List<String> lines = readLines(in);
float[] vertices = new float[lines.size() * 3];
float[] normals = new float[lines.size() * 3];
float[] uv = new float[lines.size() * 2];
int numVertices = 0;
int numNormals = 0;
int numUV = 0;
int numFaces = 0;
int[] facesVerts = new int[lines.size() * 3];
int[] facesNormals = new int[lines.size() * 3];
int[] facesUV = new int[lines.size() * 3];
int vertexIndex = 0;
int normalIndex = 0;
int uvIndex = 0;
int faceIndex = 0;
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (line.startsWith("v ")) {
String[] tokens = line.split("[ ]+");
vertices[vertexIndex] = Float.parseFloat(tokens[1]);
vertices[vertexIndex + 1] = Float.parseFloat(tokens[2]);
vertices[vertexIndex + 2] = Float.parseFloat(tokens[3]);
vertexIndex += 3;
numVertices++;
continue;
}
if (line.startsWith("vn ")) {
String[] tokens = line.split("[ ]+");
normals[normalIndex] = Float.parseFloat(tokens[1]);
normals[normalIndex + 1] = Float.parseFloat(tokens[2]);
normals[normalIndex + 2] = Float.parseFloat(tokens[3]);
normalIndex += 3;
numNormals++;
continue;
}
if (line.startsWith("vt")) {
String[] tokens = line.split("[ ]+");
uv[uvIndex] = Float.parseFloat(tokens[1]);
uv[uvIndex + 1] = Float.parseFloat(tokens[2]);
uvIndex += 2;
numUV++;
continue;
}
if (line.startsWith("f ")) {
String[] tokens = line.split("[ ]+");
String[] parts = tokens[1].split("/");
facesVerts[faceIndex] = getIndex(parts[0], numVertices);
if (parts.length > 2)
facesNormals[faceIndex] = getIndex(parts[2], numNormals);
if (parts.length > 1)
facesUV[faceIndex] = getIndex(parts[1], numUV);
faceIndex++;
parts = tokens[2].split("/");
facesVerts[faceIndex] = getIndex(parts[0], numVertices);
if (parts.length > 2)
facesNormals[faceIndex] = getIndex(parts[2], numNormals);
if (parts.length > 1)
facesUV[faceIndex] = getIndex(parts[1], numUV);
faceIndex++;
parts = tokens[3].split("/");
facesVerts[faceIndex] = getIndex(parts[0], numVertices);
if (parts.length > 2)
facesNormals[faceIndex] = getIndex(parts[2], numNormals);
if (parts.length > 1)
facesUV[faceIndex] = getIndex(parts[1], numUV);
faceIndex++;
numFaces++;
continue;
}
}
float[] verts = new float[(numFaces * 3)
* (3 + (numNormals > 0 ? 3 : 0) + (numUV > 0 ? 2 : 0))];
for (int i = 0, vi = 0; i < numFaces * 3; i++) {
int vertexIdx = facesVerts[i] * 3;
verts[vi++] = vertices[vertexIdx];
verts[vi++] = vertices[vertexIdx + 1];
verts[vi++] = vertices[vertexIdx + 2];
if (numUV > 0) {
int uvIdx = facesUV[i] * 2;
verts[vi++] = uv[uvIdx];
verts[vi++] = 1 - uv[uvIdx + 1];
}
if (numNormals > 0) {
int normalIdx = facesNormals[i] * 3;
verts[vi++] = normals[normalIdx];
verts[vi++] = normals[normalIdx + 1];
verts[vi++] = normals[normalIdx + 2];
}
}
Vertices3 model = new Vertices3(game.getGLGraphics(), numFaces * 3,
0, false, numUV > 0, numNormals > 0);
model.setVertices(verts, 0, verts.length);
return model;
} catch (Exception ex) {
throw new RuntimeException("couldn't load '" + file + "'", ex);
} finally {
if (in != null)
try {
in.close();
} catch (Exception ex) {
}
}
}
static int getIndex(String index, int size) {
int idx = Integer.parseInt(index);
if (idx < 0)
return size + idx;
else
return idx - 1;
}
static List<String> readLines(InputStream in) throws IOException {
List<String> lines = new ArrayList<String>();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null)
lines.add(line);
return lines;
}
}
vertices3
public class Vertices3 {
final GLGraphics glGraphics;
final boolean hasColor;
final boolean hasTexCoords;
final boolean hasNormals;
final int vertexSize;
final IntBuffer vertices;
final int[] tmpBuffer;
final ShortBuffer indices;
public Vertices3(GLGraphics glGraphics, int maxVertices, int maxIndices,
boolean hasColor, boolean hasTexCoords, boolean hasNormals) {
this.glGraphics = glGraphics;
this.hasColor = hasColor;
this.hasTexCoords = hasTexCoords;
this.hasNormals = hasNormals;
this.vertexSize = (3 + (hasColor ? 4 : 0) + (hasTexCoords ? 2 : 0) + (hasNormals ? 3
: 0)) * 4;
this.tmpBuffer = new int[maxVertices * vertexSize / 4];
ByteBuffer buffer = ByteBuffer.allocateDirect(maxVertices * vertexSize);
buffer.order(ByteOrder.nativeOrder());
vertices = buffer.asIntBuffer();
if (maxIndices > 0) {
buffer = ByteBuffer.allocateDirect(maxIndices * Short.SIZE / 8);
buffer.order(ByteOrder.nativeOrder());
indices = buffer.asShortBuffer();
} else {
indices = null;
}
}
public void setVertices(float[] vertices, int offset, int length) {
this.vertices.clear();
int len = offset + length;
for (int i = offset, j = 0; i < len; i++, j++)
tmpBuffer[j] = Float.floatToRawIntBits(vertices[i]);
this.vertices.put(tmpBuffer, 0, length);
this.vertices.flip();
}
public void setIndices(short[] indices, int offset, int length) {
this.indices.clear();
this.indices.put(indices, offset, length);
this.indices.flip();
}
public void bind() {
GL10 gl = glGraphics.getGL();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
vertices.position(0);
gl.glVertexPointer(3, GL10.GL_FLOAT, vertexSize, vertices);
if (hasColor) {
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
vertices.position(3);
gl.glColorPointer(4, GL10.GL_FLOAT, vertexSize, vertices);
}
if (hasTexCoords) {
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
vertices.position(hasColor ? 7 : 3);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, vertexSize, vertices);
}
if (hasNormals) {
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
int offset = 3;
if (hasColor)
offset += 4;
if (hasTexCoords)
offset += 2;
vertices.position(offset);
gl.glNormalPointer(GL10.GL_FLOAT, vertexSize, vertices);
}
}
public void draw(int primitiveType, int offset, int numVertices) {
GL10 gl = glGraphics.getGL();
if (indices != null) {
indices.position(offset);
gl.glDrawElements(primitiveType, numVertices,
GL10.GL_UNSIGNED_SHORT, indices);
} else {
gl.glDrawArrays(primitiveType, offset, numVertices);
}
}
public void unbind() {
GL10 gl = glGraphics.getGL();
if (hasTexCoords)
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
if (hasColor)
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
if (hasNormals)
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
public int getNumIndices() {
return indices.limit();
}
public int getNumVertices() {
return vertices.limit() / (vertexSize / 4);
}
}