如何使用OpenGL-ES 2在Android中加载和显示.obj文件 [英] How to load and display .obj file in Android with OpenGL-ES 2

查看:122
本文介绍了如何使用OpenGL-ES 2在Android中加载和显示.obj文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将.obj文件加载到我的Android应用程序中,并使用OpenGL 2显示它.

I am trying to load an .obj file into my Android application and display it using OpenGL 2.

您可以在这里找到文件:我删除了文件,您可以使用包含以下提到的值的任何.obj文件进行测试.

You can find the file here: I removed the file, you can use any .obj file that contains the values mentiones below for testing.

关于stackoverflow也有很多类似的问题,但是我没有找到不需要一些大型库的简单解决方案.

There are a lot of similar questions on stackoverflow but I did not find a simple solution that does not require some large library.

该文件仅包含以下值类型:

The file only contains the following value types:

  • g
  • v
  • vt
  • vn
  • f

我尝试了libgdx,效果很好,但是对于我所需要的来说有点过分了.

I tried libgdx, which worked ok, but it is a bit overkill for what I need.

我尝试了不带LWJGL的oObjLoader https://github.com/seanrowens/oObjLoader .解析似乎有效,但是如何在一个简单的场景中显示这些值?

I tried the oObjLoader https://github.com/seanrowens/oObjLoader without the LWJGL. The parsing seems to work, but how can I display the values in a simple scene?

下一步是将图像作为纹理附加到对象.但是现在我很乐意按原样显示文件.

The next step is to attach an image as a texture to the object. But for now I would be happy to display the file as it is.

我愿意接受诸如预转换文件之类的不同解决方案,因为它在应用程序中永远都是这样.

I am open to different solutions like pre-converting the file, because it will only be this one ever within the application.

谢谢!

状态更新 基本的加载和显示现在可以正常工作,如我自己的答案所示.

Status update Basic loading and displaying works now, as shown in my own answer.

推荐答案

我最终编写了一个新的解析器,它可以像这样用于构建FloatBuffers以在渲染器中使用:

I ended up writing a new parser, it can be used like this to build FloatBuffers to use in your Renderer:

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

这篇关于如何使用OpenGL-ES 2在Android中加载和显示.obj文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆