gpt4 book ai didi

android - 如何在 OpenGL ES 1.1 中处理索引缓冲区

转载 作者:太空狗 更新时间:2023-10-29 13:25:04 27 4
gpt4 key购买 nike

我想使用适用于 Android 的 OPENGL ES 1.1 渲染从 .obj 文件加载的模型。我有顶点、顶点法线和面。当我使用 GL10.GL_POINTS 渲染模型时,模型看起来不错:

enter image description here

当我使用 GL10.GL_TRIANGLES 时,我会得到像这样的乱七八糟的形状:

same bunny (facing other direction because I applied constant rotation)

这是我的绘图方法。我尝试了 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

最佳答案

也许这会对你有所帮助,我用它来导入一个 .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;
}
}

顶点3

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);
}
}

关于android - 如何在 OpenGL ES 1.1 中处理索引缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22316440/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com