本文介绍了如何使用 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 updateBasic 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 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 16:47