Android 用java编写.3ds或.obj加载程序
Iv'e将blender中的模型导出为.obj文件。Iv'e成功地创建了一个非常简单的 类,该类将顶点和索引加载到数组。我的问题是我需要纹理坐标(vt)和法线(vn)。例如,我需要4个顶点*6个面,一个简单的立方体才能使用纹理,但我在.obj文件中只得到了8个,而且我不知道如何处理vt的索引,因为我只能有一个数组/缓冲区用于索引,但我在.obj文件中得到了两个不同的v/vtAndroid 用java编写.3ds或.obj加载程序,android,opengl-es,loader,.obj,3ds,Android,Opengl Es,Loader,.obj,3ds,Iv'e将blender中的模型导出为.obj文件。Iv'e成功地创建了一个非常简单的 类,该类将顶点和索引加载到数组。我的问题是我需要纹理坐标(vt)和法线(vn)。例如,我需要4个顶点*6个面,一个简单的立方体才能使用纹理,但我在.obj文件中只得到了8个,而且我不知道如何处理vt的索引,因为我只能有一个数组/缓冲区用于索引,但我在.obj文件中得到了两个不同的v/vt 是否有加载程序只返回顶点、纹理、法线和一个索引数组的数组或类似数组?或者是如何写的例子?到目前为止,我只在完整的3d引擎中
是否有加载程序只返回顶点、纹理、法线和一个索引数组的数组或类似数组?或者是如何写的例子?到目前为止,我只在完整的3d引擎中找到了装载机,这不是我想要的 4个顶点*6个面超出了您的需要。事实上,这是没有效率的。已导出的顶点将使用索引进行优化。使用Opengl es,您可以从何处获取顶点(数组),然后使用另一个数组中的顶点索引绘制顶点。结果是,您得到了8个顶点,而可能只有24个顶点,所以存储所需的内存更少。所以效率是16/24*100%。假设您将拥有一个具有1000个顶点的模型 顶点索引意味着在另一个具有适当偏移量的数组中,GPU将获得一个顶点(顶点的大小_(3个浮点)*索引)和UV坐标的适当偏移量(顶点的大小_(2个浮点)*索引) 此代码适用于opengl ES 2.0,但您可以了解:
GLES20.glUseProgram(programTextured);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
sqTex.getVertexBuffer().position(sqTex.VERT_OFFSET);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(programTextured, "aPosition") 3, GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer()); GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aPosition"));
sqTex.getVertexBuffer().position(sqTex.TEXT_OFFSET);
GLES20.glVertexAttribPointer(
GLES20.glGetAttribLocation(programTextured, "aTextureCoord"), 2,
GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer());
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, sqTex.getIndexBuffer());
sqTEx是TexturedSquare的一个实例:
public class TexturedSquare {
// private float[] vertices=new float[4];
float vertices[] = { -1.0f, -1.0f, 0.0f,0.0f,0.0f, // 0, Top Left //x,y,z,u,v
1.0f, -1.0f, 0.0f,0.0f,1.0f, // 1, Bottom Left
1.0f, 1.0f, 0.0f,1.0f,1.0f, // 2, Bottom Right
-1.0f, 1.0f, 0.0f,1.0f,0.0f, // 3, Top Right
};
public static int VERT_OFFSET=0;
public static int TEXT_OFFSET=3;
short[] indices = { 0, 1, 2, 2, 3, 0 };;
// Our vertex buffer.
private FloatBuffer vertexBuffer;
// Our index buffer.
private ShortBuffer indexBuffer;
public TexturedSquare()
{
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// short is 2 bytes, therefore we multiply the number if
// vertices with 2.
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
FloatBuffer getVertexBuffer(){
return vertexBuffer;
}
ShortBuffer getIndexBuffer(){
return indexBuffer;
}
}
4个顶点*6个面超出了您的需要。事实上,这是没有效率的。已导出的顶点将使用索引进行优化。使用Opengl es,您可以从何处获取顶点(数组),然后使用另一个数组中的顶点索引绘制顶点。结果是,您得到了8个顶点,而可能只有24个顶点,所以存储所需的内存更少。所以效率是16/24*100%。假设您将拥有一个具有1000个顶点的模型 顶点索引意味着在另一个具有适当偏移量的数组中,GPU将获得一个顶点(顶点的大小_(3个浮点)*索引)和UV坐标的适当偏移量(顶点的大小_(2个浮点)*索引) 此代码适用于opengl ES 2.0,但您可以了解:
GLES20.glUseProgram(programTextured);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
sqTex.getVertexBuffer().position(sqTex.VERT_OFFSET);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(programTextured, "aPosition") 3, GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer()); GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aPosition"));
sqTex.getVertexBuffer().position(sqTex.TEXT_OFFSET);
GLES20.glVertexAttribPointer(
GLES20.glGetAttribLocation(programTextured, "aTextureCoord"), 2,
GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer());
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, sqTex.getIndexBuffer());
sqTEx是TexturedSquare的一个实例:
public class TexturedSquare {
// private float[] vertices=new float[4];
float vertices[] = { -1.0f, -1.0f, 0.0f,0.0f,0.0f, // 0, Top Left //x,y,z,u,v
1.0f, -1.0f, 0.0f,0.0f,1.0f, // 1, Bottom Left
1.0f, 1.0f, 0.0f,1.0f,1.0f, // 2, Bottom Right
-1.0f, 1.0f, 0.0f,1.0f,0.0f, // 3, Top Right
};
public static int VERT_OFFSET=0;
public static int TEXT_OFFSET=3;
short[] indices = { 0, 1, 2, 2, 3, 0 };;
// Our vertex buffer.
private FloatBuffer vertexBuffer;
// Our index buffer.
private ShortBuffer indexBuffer;
public TexturedSquare()
{
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// short is 2 bytes, therefore we multiply the number if
// vertices with 2.
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
FloatBuffer getVertexBuffer(){
return vertexBuffer;
}
ShortBuffer getIndexBuffer(){
return indexBuffer;
}
}
看看jPCT(或jPCT AE),它是一个优秀的Java(和/或Android)3D库。它支持3ds/obj开箱即用。看看jPCT(或jPCT AE),它是一个优秀的Java(和/或Android)3D库。它支持3ds/obj开箱即用。感谢您的解释。好的,我得到了一部分,我真的不需要所有这些顶点。然而,我仍然不知道如何处理我得到两个不同的索引数组这一事实。因为我只能在gl.glDrawElement或gl.glDrawArray中引用一个。我知道应该是这样的。但这是否意味着我必须重新排列vt(UV坐标)的顺序,以便如果一个面是(1/4…),我应该将vt:4移动到位置1(vt:1)?——编辑:非常感谢你,尤里,这真的很有帮助!解析obj文件,得到不同的数组,然后有N个面,可以根据obj文件面的索引值创建顶点和uv坐标的数组。这些新创建的数组将有N个元素,每个数组将有N个元素。您可以设置glEnable特定数组,然后调用Draw N Element感谢您的解释。好的,我得到了一部分,我真的不需要所有这些顶点。然而,我仍然不知道如何处理我得到两个不同的索引数组这一事实。因为我只能在gl.glDrawElement或gl.glDrawArray中引用一个。我知道应该是这样的。但这是否意味着我必须重新排列vt(UV坐标)的顺序,以便如果一个面是(1/4…),我应该将vt:4移动到位置1(vt:1)?——编辑:非常感谢你,尤里,这真的很有帮助!解析obj文件,得到不同的数组,然后有N个面,可以根据obj文件面的索引值创建顶点和uv坐标的数组。这些新创建的数组将有N个元素,每个数组将有N个元素。设置glEnable特定数组,然后调用Draw N元素