【问题标题】:How do I parse .obj files with C++ on OpenGL (e.g. using libobj or another library)?如何在 OpenGL 上使用 C++ 解析 .obj 文件(例如,使用 libobj 或其他库)?
【发布时间】:2011-12-30 17:42:09
【问题描述】:

我正在尝试使用 libobj 解析从 Blender 导出的 .obj 文件。 网站http://people.cs.kuleuven.be/~ares.lagae/libobj/index.html 是我从哪里得到libobjhttp://en.wikipedia.org/wiki/Wavefront_Object_file_format 描述了.obj 文件格式的来龙去脉。 libobj 网站 有一个关于如何解析我在 以下代码。

但是我不确定如何解析面部和渲染 它们在 OpenGL 中。我必须使用顶点列表或服务器端缓冲区对象吗? 如何扩展下面的代码以使其正确渲染人脸?

#include <GL/glut.h>
#include <obj.hpp>
#include <iostream>

    void geometric_vertex_callback(obj::float_type x, obj::float_type y, obj::float_type z)
    {
      std::cout << "v " << x << " " << y << " " << z << "\n";
      glVertex3f(x, y, z);
    }

    void display() {
      glClear(GL_COLOR_BUFFER_BIT);
      obj::obj_parser obj_parser;
      obj_parser.geometric_vertex_callback(geometric_vertex_callback);
      std::cout << std::endl;
      glLoadIdentity();
      gluLookAt(1.0f, 1.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
      glColor3f(1.0f, 1.0f, 1.0f);
      glBegin(GL_POINTS);
      obj_parser.parse("./cube.obj");
      glEnd();
      glFlush();

    }

    void reshape(int h, int w) {

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(-8.0f, 8.0f, -8.0f, 8.0f, -10.0f, 10.0f);
      glViewport(0, 0, w, h);
      glMatrixMode(GL_MODELVIEW);

    }

    int main(int argc, char **argv) {
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_RGB);
      glutCreateWindow("cube");
      glutDisplayFunc(display);
      glutReshapeFunc(reshape);
      glutMainLoop();
      return 0;
    }

编译:g++ -Wall -o main main.cpp -lGL -lGLU -lglut -lobj

【问题讨论】:

    标签: opengl blender


    【解决方案1】:

    检查参考(http://people.cs.kuleuven.be/~ares.lagae/libobj/obj-0.1/doc/html/classobj_1_1obj__parser.html)。您可以使用多个回调来渲染几何图形。

    .OBJ 是一种非常简单直接的格式。我认为编写解析器并不难,可能是一次有趣的学习经历。

    【讨论】:

    【解决方案2】:

    我知道这不是你问的问题,因为你想使用 libobj,但我发现自己学习如何做某事比使用预制库要好得多。实际上,我刚刚为我的程序实现了一个简单的 .obj 阅读器。我会把它贴在这里让你开始。

    请注意,它包含一些特定于我的实现的代码(即我如何处理我的顶点缓冲区等),它仍然只处理其中包含单个对象的对象文件。 但是希望这会让你走上正轨。

    另外,我遵循了我在网上找到的一个教程(不记得是哪个),所以我不能把所有功劳都归功于这个。

    private class Face{
        public int[] v;
        public int[] vt;
        public int[] vn;
    
        public Face(){
            v = new int[3];
            vt = new int[3];
            vn = new int[3];
            for(int i = 0; i < 3; i++){
                v[i] = vt[i] = vn[i] = -1;
            }
        }
    }
    
    public void readObjFile(String fileName){
        Reader r;
        try{
            r = new FileReader(fileName);
    
            BufferedReader reader = new BufferedReader(r);
            String line = null;
            int lineNo = 0;
            float[] floatTemp = new float[3];
            int[] intTemp = new int[3];
    
            ArrayList<Face> faces = new ArrayList<Face>();
            ArrayList<Vector3> v = new ArrayList<Vector3>();
            ArrayList<Vector2> vt = new ArrayList<Vector2>();
            ArrayList<Vector3> vn = new ArrayList<Vector3>();
    
            while((line = reader.readLine()) != null){
                ++lineNo;
    
                String[] elements = line.split("\\s+");
    
                if(elements.length > 0){
                    if(elements[0].equals("v")){
                        if(elements.length < 4){
                            System.out.println("Something is wrong with the obj loading");
                        }
                        else{
                            //mVertexBuffer.addVertex(new Vector3(Float.parseFloat(elements[1]), Float.parseFloat(elements[2]),Float.parseFloat(elements[3])));
                            v.add(new Vector3(Float.parseFloat(elements[1]), Float.parseFloat(elements[2]),Float.parseFloat(elements[3])));
                        }
                    }
                    else if(elements[0].equals("vt")){
                        if(elements.length < 3){
                            System.out.println("Something is wrong with the obj loading");
                        }
                        else{
                            //mVertexBuffer.addTextureCoord(new Vector2(Float.parseFloat(elements[1]), Float.parseFloat(elements[2])));
                            vt.add(new Vector2(Float.parseFloat(elements[1]), 1.0f - Float.parseFloat(elements[2])));
                        }
                    }
                    else if(elements[0].equals("vn"))
                    {
                        if(elements.length < 4){
                            System.out.println("Something is wrong with the obj loading");
                        }
                        else{
                            //mVertexBuffer.addVertex(new Vector3(Float.parseFloat(elements[1]), Float.parseFloat(elements[2]),Float.parseFloat(elements[3])));
                            vn.add(new Vector3(Float.parseFloat(elements[1]), Float.parseFloat(elements[2]),Float.parseFloat(elements[3])));
                        }
                    }
                    else if(elements[0].equals("f")){
                        if(elements.length != 4){
                            System.out.println("Something is wrong with the obj loading");
                        }
                        else{
                            //if(mIndexBuffer == null){
                            //  mIndexBuffer = new IndexBuffer(mGl);
                            //}
    
                            Face newFace = new Face();
    
                            for (int i = 1; i < 4; i++) {
                                String seg = elements[i];
    
                                if(seg.indexOf("/") > 0) 
                                {
                                    String[] faceOrder = seg.split("/");
    
                                    if (faceOrder.length > 0) {
                                        //mIndexBuffer.addIndex(Integer.valueOf(faceOrder[0]) - 1);
                                        newFace.v[i - 1] = Integer.valueOf(faceOrder[0]) - 1;
                                    }
    
                                    if (faceOrder.length > 1) {
                                        if(faceOrder[1].length() > 0){
                                            //f.uvIndices.add(Integer.valueOf(faceOrder[1]));
                                            newFace.vt[i - 1] = Integer.valueOf(faceOrder[1]) - 1;
                                        }
                                    }
    
                                    if (faceOrder.length > 2) {
                                        //f.normalIndices.add(Integer.valueOf(faceOrder[2]));
                                        newFace.vn[i - 1] = Integer.valueOf(faceOrder[2]) - 1;
                                    }
                                }
                                else 
                                {
                                    if (seg.length() > 0) {
                                        //mIndexBuffer.addIndex(Integer.valueOf(seg) - 1);
                                        newFace.v[i - 1] = Integer.valueOf(seg) - 1;
                                    }
                                }
                            }
    
                            faces.add(newFace);
                        }
                    }
                }
            }
    
            // Now do post process
            for(int i = 0; i < faces.size(); i++){
                mVertexBuffer.addVertex(v.get(faces.get(i).v[0]));
                mVertexBuffer.addVertex(v.get(faces.get(i).v[1]));
                mVertexBuffer.addVertex(v.get(faces.get(i).v[2]));
                if(vt.size() > 0){
                    mVertexBuffer.addTextureCoord(vt.get(faces.get(i).vt[0]));
                    mVertexBuffer.addTextureCoord(vt.get(faces.get(i).vt[1]));
                    mVertexBuffer.addTextureCoord(vt.get(faces.get(i).vt[2]));
                }
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }
    

    【讨论】:

    • 很有趣,但我注意到您使用的是 Java(JOGL?)而不是 C++。我没有得到关于 JOGL 的参考资料,尽管我很快就需要掌握它,因为最终我需要将我的代码移植到 android。现在我正在考虑学习 JOGL 并使用 min3d 库。无论如何,我仍在尝试在 libobj 中编写那个长函数而不犯任何错误,所以我至少没有得到任何编译时错误。
    • 我可以使用 IDE 来为我填写函数吗? obj_parser.face_callbacks( triangular_face_geometric_vertices_callback_type, triangular_face_geometric_vertices_texture_vertices_callback, triangular_face_geometric_vertices_vertex_normals_callback, triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback, 等等。我在复制所有这些时遇到了一些麻烦。我可以使用允许我的 IDE
    • 是的,我正在使用 JOGl,但 obj 加载的原理应该相同。我不确定让 IDE 为您填写函数(如自动完成)或实际创建函数和代码是什么意思?
    • 是的,我的意思是像自动完成。无论如何,我刚刚尝试在 Ubuntu Linux 11.10 上安装 JOGL。我已按照以下页面上的所有说明进行操作:jogamp.org/jogl/doc/HowToBuild.html,我什至无法从 en.wikipedia.org/wiki/Java_OpenGL 编译四边形示例。我不知道我做错了什么。我安装了 OpenJDK 而不是 gcj,所以它应该可以正常工作,但我收到错误:JOGLQuad.java:8: package javax.media.opengl does not exist import javax.media.opengl.GL;关于我做错了什么的任何想法。为什么我不能正确安装 JOGL?
    • 您似乎没有 javax.media.opengl 在您的 java 安装可以找到的位置。尝试确保路径设置正确。我从来没有尝试过用 ubuntu 运行 JOGL,所以在那里我帮不了你太多。我建议提出一个单独的问题来解决这个问题。
    猜你喜欢
    • 2011-12-12
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2019-08-06
    • 2012-01-16
    相关资源
    最近更新 更多