如何使用OpenGL ES 2在Android中加载和显示.obj文件
我正在尝试将一个.obj文件加载到我的Android应用程序中,并使用OpenGL 2显示它 您可以在此处找到该文件:编辑:我删除了该文件,您可以使用包含以下提到的值的任何.obj文件进行测试 关于stackoverflow有很多类似的问题,但我没有找到一个不需要大型库的简单解决方案 该文件仅包含以下值类型:如何使用OpenGL ES 2在Android中加载和显示.obj文件,android,opengl-es,opengl-es-2.0,Android,Opengl Es,Opengl Es 2.0,我正在尝试将一个.obj文件加载到我的Android应用程序中,并使用OpenGL 2显示它 您可以在此处找到该文件:编辑:我删除了该文件,您可以使用包含以下提到的值的任何.obj文件进行测试 关于stackoverflow有很多类似的问题,但我没有找到一个不需要大型库的简单解决方案 该文件仅包含以下值类型: g 五 vt 越南 f 我尝试了libgdx,它工作正常,但对于我所需要的东西来说有点过分了 我试过没有LWJGL的oObjLoader。解析似乎有效,但如何在简单场景中显示值 下一步
- g
- 五
- vt
- 越南
- f
基本的加载和显示工作,现在,如我自己的回答所示 我最后编写了一个新的解析器,它可以像这样用于构建浮动缓冲区,以便在渲染器中使用:
ObjLoader objLoader = new ObjLoader(context, "Mug.obj");
numFaces = objLoader.numFaces;
// Initialize the buffers.
positions = ByteBuffer.allocateDirect(objLoader.positions.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
positions.put(objLoader.positions).position(0);
normals = ByteBuffer.allocateDirect(objLoader.normals.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
normals.put(objLoader.normals).position(0);
textureCoordinates = ByteBuffer.allocateDirect(objLoader.textureCoordinates.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
textureCoordinates.put(objLoader.textureCoordinates).position(0);
下面是解析器:
public final class ObjLoader {
public final int numFaces;
public final float[] normals;
public final float[] textureCoordinates;
public final float[] positions;
public ObjLoader(Context context, String file) {
Vector<Float> vertices = new Vector<>();
Vector<Float> normals = new Vector<>();
Vector<Float> textures = new Vector<>();
Vector<String> faces = new Vector<>();
BufferedReader reader = null;
try {
InputStreamReader in = new InputStreamReader(context.getAssets().open(file));
reader = new BufferedReader(in);
// read file until EOF
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(" ");
switch (parts[0]) {
case "v":
// vertices
vertices.add(Float.valueOf(parts[1]));
vertices.add(Float.valueOf(parts[2]));
vertices.add(Float.valueOf(parts[3]));
break;
case "vt":
// textures
textures.add(Float.valueOf(parts[1]));
textures.add(Float.valueOf(parts[2]));
break;
case "vn":
// normals
normals.add(Float.valueOf(parts[1]));
normals.add(Float.valueOf(parts[2]));
normals.add(Float.valueOf(parts[3]));
break;
case "f":
// faces: vertex/texture/normal
faces.add(parts[1]);
faces.add(parts[2]);
faces.add(parts[3]);
break;
}
}
} catch (IOException e) {
// cannot load or read file
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
//log the exception
}
}
}
numFaces = faces.size();
this.normals = new float[numFaces * 3];
textureCoordinates = new float[numFaces * 2];
positions = new float[numFaces * 3];
int positionIndex = 0;
int normalIndex = 0;
int textureIndex = 0;
for (String face : faces) {
String[] parts = face.split("/");
int index = 3 * (Short.valueOf(parts[0]) - 1);
positions[positionIndex++] = vertices.get(index++);
positions[positionIndex++] = vertices.get(index++);
positions[positionIndex++] = vertices.get(index);
index = 2 * (Short.valueOf(parts[1]) - 1);
textureCoordinates[normalIndex++] = textures.get(index++);
// NOTE: Bitmap gets y-inverted
textureCoordinates[normalIndex++] = 1 - textures.get(index);
index = 3 * (Short.valueOf(parts[2]) - 1);
this.normals[textureIndex++] = normals.get(index++);
this.normals[textureIndex++] = normals.get(index++);
this.normals[textureIndex++] = normals.get(index);
}
}
}
public final class ObjLoader{
公共最终国际货币基金会;
公共最终浮动[]正常值;
公共最终浮动坐标;
公开最终浮动[]职位;
公共对象加载程序(上下文,字符串文件){
向量顶点=新向量();
向量法线=新向量();
向量纹理=新向量();
向量面=新向量();
BufferedReader reader=null;
试一试{
InputStreamReader in=新建InputStreamReader(context.getAssets().open(file));
读卡器=新的缓冲读卡器(in);
//读取文件直到EOF
弦线;
而((line=reader.readLine())!=null){
String[]parts=line.split(“”);
开关(部件[0]){
案例“v”:
//顶点
顶点.add(Float.valueOf(parts[1]);
顶点.add(Float.valueOf(parts[2]);
顶点.add(Float.valueOf(parts[3]);
打破
案例“vt”:
//质地
纹理.add(Float.valueOf(parts[1]);
纹理.add(Float.valueOf(parts[2]);
打破
案例“vn”:
//常态
法线.add(Float.valueOf(parts[1]);
法线.add(Float.valueOf(parts[2]);
法线.add(Float.valueOf(parts[3]);
打破
案例“f”:
//面:顶点/纹理/法线
添加(零件[1]);
添加(零件[2]);
添加(零件[3]);
打破
}
}
}捕获(IOE异常){
//无法加载或读取文件
}最后{
if(读卡器!=null){
试一试{
reader.close();
}捕获(IOE异常){
//记录异常
}
}
}
numface=faces.size();
this.normals=新浮点[numface*3];
纹理坐标=新浮点[numface*2];
位置=新浮动[numface*3];
int positionIndex=0;
int normalIndex=0;
int-textureIndex=0;
用于(字符串面:面){
String[]parts=face.split(“/”);
int index=3*(缩写为valueOf(parts[0])-1);
positions[positionIndex++]=顶点.get(index++);
positions[positionIndex++]=顶点.get(index++);
位置[positionIndex++]=顶点。获取(索引);
索引=2*(简称为(第[1]部分)的值-1);
textureCoordinates[normalIndex++]=textures.get(index++);
//注意:位图得到y反转
textureCoordinates[normalIndex++]=1-textures.get(index);
索引=3*(简称为(第[2]部分)的值-1);
this.normals[textureIndex++]=normals.get(index++);
this.normals[textureIndex++]=normals.get(index++);
this.normals[textureIndex++]=normals.get(索引);
}
}
}
试试这个在Github上找到我的项目。
这是OpenGLES2.0的一个演示。它是一个android应用程序,带有3D引擎,可以加载波前OBJ、STL、DAE和glTF文件。该应用程序基于andresoviedo的项目,该项目可在此处找到,并具有加载和呈现glTF格式的附加功能
本应用程序的目的是学习和分享如何使用OpenGLES和Android进行绘图。因为这是我的第一个android应用程序,所以很可能存在bug;但我会继续改进应用程序并添加更多功能
这个项目是开源的,包含可以解决您的问题的类 感谢@Björn Kechel非常优雅的实现。 我只想添加一个可能导致不良结果的案例。 因为一个面可以有3个以上的顶点,所以我们应该能够处理4个顶点,如下所示
由于您使用的是Android,您的问题很可能针对OpenGL ES 2而不是OpenGL 2。如果是这种情况,我建议更新问题并相应地标记它。嗨,我能得到你的整个ObjLoader文件吗?我有一些问题。非常感谢。我对opengles非常陌生。你能指导我渲染缓冲区吗?多亏了你的代码,我才能够创建缓冲区,但未能重新编写。嗨,你能告诉我如何使用