【问题标题】:Problem rendering a mesh from an OBJ file从 OBJ 文件渲染网格时出现问题
【发布时间】:2011-10-17 17:27:57
【问题描述】:

我在调整时遇到问题,或者我猜想理解 OBJ 文件中的顶点/索引/面。我想最终以编程方式解析一个 OBJ 文件,但首先我需要了解如何手动进行。我正在使用对 GLWallpaperService 示例的改编(由网络上的开发人员提供)来执行此操作。

我遇到的问题是,他提供的代码似乎可以正常工作,以生成具有不同颜色面的通用立方体,他必须单独实现和绘制。下面我调整后的代码试图从我从搅拌机导出并插入值的坐标中仅绘制一个基本立方体。

public class GLCube {
private final int _nrOfVertices = 8;

private FloatBuffer _vertexBuffer;
private FloatBuffer _normalBuffer;
private ShortBuffer _indiceBuffer;

public GLCube() {
    this.init();
}

private void init() {
    // 3 is the number of coordinates to each vertex.
    _vertexBuffer = BufferFactory.createFloatBuffer(_nrOfVertices * 3);
    _normalBuffer = BufferFactory.createFloatBuffer(18);
    _indiceBuffer = BufferFactory.createShortBuffer(72);

    // Coordinates for the vertexes of the cube.
    float[] vertexCoords = {
            /*
            1f,  1f,  0f,
            0f,  1f,  0f, 
            0f,  0f,  0f, 
            1f,  0f,  0f, 
            1f,  0f, -1f, 
            1f,  1f, -1f, 
            0f,  1f, -1f, 
            0f,  0f, -1f,
            */
            2.195671f, -0.176713f, -1.292541f,
            2.195671f, -0.176713f,  0.707459f,
            0.195671f, -0.176713f,  0.707459f,
            0.195672f, -0.176713f, -1.292542f,
            2.195672f,  1.823287f, -1.292541f,
            2.195671f,  1.823287f,  0.707460f,
            0.195671f,  1.823287f,  0.707459f,
            0.195671f,  1.823287f, -1.292541f
    };

    short[] indicesArray = {/*
            0, 1, 2,   0, 2, 3,
            3, 4, 0,   4, 5, 0,
            7, 2, 6,   6, 2, 1,
            4, 7, 5,   7, 6, 5,
            1, 0, 6,   6, 0, 5,
            2, 7, 3,   7, 4, 3
            */
            1,1,2, 1,3,1,
            1,1,3, 1,4,1,
            5,2,8, 2,7,2,
            5,2,7, 2,6,2,
            1,3,5, 3,6,3,
            1,3,6, 3,2,3,
            2,4,6, 4,7,4,
            2,4,7, 4,3,4,
            3,5,7, 5,8,5,
            3,5,8, 5,4,5,
            5,6,1, 6,4,6,
            5,6,4, 6,8,6
            };

    //Coordinates for Normal Vector. Used for Lighting calculations
    float[] normalCoords = {/*
             0f, 0f, 1f,   0f, 0f, 1f,   
             0f, 0f, 1f,   0f, 0f, 1f,   
             0f, 0f, 1f,   0f, 0f, 1f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
             1f, 0f, 0f,   1f, 0f, 0f,   
            -1f, 0f, 0f,  -1f, 0f, 0f,  
            -1f, 0f, 0f,  -1f, 0f, 0f,  
            -1f, 0f, 0f,  -1f, 0f, 0f,  
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 0f,-1f,   0f, 0f,-1f,   
             0f, 1f, 0f,   0f, 1f, 0f,   
             0f, 1f, 0f,   0f, 1f, 0f,   
             0f, 1f, 0f,   0f, 1f, 0f,  
             0f,-1f, 0f,   0f,-1f, 0f,   
             0f,-1f, 0f,   0f,-1f, 0f,   
             0f,-1f, 0f,   0f,-1f, 0f   
             */
             0f, -1f,  0f,
             0f,  1f,  0f,
             1f, -0f,  0f,
            -0f, -0f,  1f,
            -1f, -0f, -0f,
             0f,  0f, -1f
    };

    _vertexBuffer.put(vertexCoords);
    _normalBuffer.put(normalCoords);
    _indiceBuffer.put(indicesArray);

    _indiceBuffer.position(0);
    _vertexBuffer.position(0);
    _normalBuffer.position(0);

}

public void draw(GL10 gl) {
    // 3 coordinates in each vertex
    // 0 is the space between each vertex. They are densely packed in the array, so the value is 0
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

    // 0 is the space between each vertex. They are densely packed in the array, so the value is 0
    gl.glNormalPointer(GL10.GL_FLOAT, 0, _normalBuffer);

    gl.glColor4f(1.0f, 0f, 0f, 1f);     //Red
    gl.glDrawElements(GL10.GL_TRIANGLES, 72, GL10.GL_UNSIGNED_SHORT, _indiceBuffer);
}
}

这是 Obj 文件,也许我只是没有将值放入正确的数组中,但我一直在尝试解决这个问题,老实说只是没有任何使用 OpenGL 的背景,所以这是我的第一个项目试图使用它。

# Blender v2.58 (sub 1) OBJ File: ''
# www.blender.org
v 2.195671 -0.176713 -1.292541
v 2.195671 -0.176713 0.707459
v 0.195671 -0.176713 0.707459
v 0.195672 -0.176713 -1.292542
v 2.195672 1.823287 -1.292541
v 2.195671 1.823287 0.707460
v 0.195671 1.823287 0.707459
v 0.195671 1.823287 -1.292541
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 -0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl (null)
s off
f 1//1 2//1 3//1
f 1//1 3//1 4//1
f 5//2 8//2 7//2
f 5//2 7//2 6//2
f 1//3 5//3 6//3
f 1//3 6//3 2//3
f 2//4 6//4 7//4
f 2//4 7//4 3//4
f 3//5 7//5 8//5
f 3//5 8//5 4//5
f 5//6 1//6 4//6
f 5//6 4//6 8//6

对此的任何帮助将不胜感激。我留下了他的价值观评论,所以你可以看到什么有效。我在屏幕上看到的图像是一组完全扭曲的三角形,它似乎试图制作我的立方体,但还没有完全到达那里。

包含要更改的内容的答案会很棒。 -=)

【问题讨论】:

    标签: android opengl-es live-wallpaper cube .obj


    【解决方案1】:

    我认为您以错误的方式解释 .obj 格式。看看at this document

    基本上,您的面在 vertexCoords 中的索引应该是第一个整数。 每个面都由索引定义,格式如下:

    f v1/t1/n1 v2/t2/n2 v3/t3/n3
    

    其中 v 是顶点索引,t 是纹理坐标索引,n 是法线索引。

    所以对于这条线(定义单个面/三角形)

    f 1//1 2//1 3//1
    

    顶点索引为1,2,3,普通索引为1,1,1。 您没有纹理坐标,因此那里没有索引,因此没有双斜线。

    请记住,构成面的顶点的索引和相关法线的索引是不同的。所以你必须创建两组索引。 (请参阅下面关于 glDrawElements 的编辑)

    另一个小细节是要记住 .obj 文件从索引 1 开始计数,尽管这可能是(也可能是)数组中的第 0 个值。所以你必须考虑到这一点(即从所有索引值中减去 1)。

    编辑: 查看您的代码,我发现您正在使用glDrawElements。据我所知(但如果我错了,请纠正我)这不允许您为顶点、texcoords 和法线拥有多组(不同的)索引。因此,您必须更改法线数据以匹配与顶点相同的索引。

    【讨论】:

    • 好的,我已经研究了链接,从你所说的我想我有点明白了,但我仍然没有正确转换大声笑......无论如何你可以修改我的代码以回复我提供的数据告诉我你的意思?如果您修复我的代码,我保证“已回答”-=)
    • 暂时忘记法线。只是您提供的顶点。给定 .obj 索引数组应如下所示:pastebin.com/Sj4sigPq 我无法编译/运行/检查您的代码,但至少索引应该是这样的。你试过了吗?
    • 好吧,有道理!我没有从每个索引中减去 1。这让我对转换有了更多的了解。回答接受。任何更多的解释都会很棒,但你已经超出了我的预期 -=D
    • 实际上,我在 GLWallpaperService 中使用的示例有多个 glDrawElement,每个都有单独的边。有没有更好的方法来做到这一点,而不必为每个形状设置一组单独的索引?
    • 啊,我明白了。他正在画一个有 6 个纯色边的立方体。在这种特殊情况下,顶点的复制是必要的,因为所有属性都是在每个顶点级别上指定的。当然,如果您有一个具有单一颜色/材质或纹理映射的网格,则不需要这样做。
    猜你喜欢
    • 1970-01-01
    • 2011-05-26
    • 2019-08-28
    • 1970-01-01
    • 2013-11-25
    • 2011-01-28
    • 2016-01-25
    • 2013-05-24
    • 2013-07-30
    相关资源
    最近更新 更多