Opengl es 2.0 绘制球体并计算曲面法线

Opengl es 2.0 绘制球体并计算曲面法线,opengl-es-2.0,Opengl Es 2.0,我试图画一个球体并计算它的表面法线。我已经盯着这个看了好几个小时了,但我什么也没得到。下面是这张图所显示的混乱情况的屏幕截图: - (id) init { if (self = [super init]) { glGenVertexArraysOES(1, &_vertexArray); glBindVertexArrayOES(_vertexArray); glGenBuffers(1, &_vertexBuffer)

我试图画一个球体并计算它的表面法线。我已经盯着这个看了好几个小时了,但我什么也没得到。下面是这张图所显示的混乱情况的屏幕截图:

- (id) init
{
    if (self = [super init]) {

        glGenVertexArraysOES(1, &_vertexArray);
        glBindVertexArrayOES(_vertexArray);

        glGenBuffers(1, &_vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);

        GLfloat rad_th, rad_ph;
        GLint th, ph;
        GLint i = 0;

        GLKMatrix3 this_triangle;
        GLKVector3 column0, column1, column2, this_normal;

        for (ph=-90; ph<=90; ph++) {
            for (th=0; th<=360; th+=10) {

                if (i<3) printf("i: %d th: %f  ph: %f\n", i, (float)th, (float)ph);
                rad_th = GLKMathDegreesToRadians( (float) th );
                rad_ph = GLKMathDegreesToRadians( (float) ph);

                _vertices[i][0][0] = sinf(rad_th)*cosf(rad_ph);
                _vertices[i][0][1] = sinf(rad_ph);
                _vertices[i][0][2] = cos(rad_th)*cos(rad_ph);

                rad_th = GLKMathDegreesToRadians( (float) (th) );
                rad_ph = GLKMathDegreesToRadians( (float) (ph+1) );

                _vertices[i+1][0][0] = sinf(rad_th)*cosf(rad_ph);    
                _vertices[i+1][0][1] = sinf(rad_ph);     
                _vertices[i+1][0][2] = cos(rad_th)*cos(rad_ph);

                i+=2;
            }
        }

        // calclate and store the surface normal for every triangle
        i=2;
        for (ph=-90; ph<=90; ph++) {
            for (th=2; th<=360; th++) {
                // note that the first two vertices are irrelevant since it isn't until the third vertex that a triangle is defined.

                column0 = GLKVector3Make(_vertices[i-2][0][0], _vertices[i-2][0][1], _vertices[i-2][0][2]);
                column1 = GLKVector3Make(_vertices[i-1][0][0], _vertices[i-1][0][1], _vertices[i-1][0][2]);
                column2 = GLKVector3Make(_vertices[i-0][0][0], _vertices[i-0][0][1], _vertices[i-0][0][2]);
                this_triangle = GLKMatrix3MakeWithColumns(column0, column1, column2);
                this_normal = [self calculateTriangleSurfaceNormal : this_triangle];
                _vertices[i][1][0] = this_normal.x;
                _vertices[i][1][1] = this_normal.y;
                _vertices[i][1][2] = this_normal.z;                    

                i++;
            }
    i+=2;
        }

        glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices), _vertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(GLKVertexAttribPosition);
        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);
        glEnableVertexAttribArray(GLKVertexAttribNormal);
        glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, (GLubyte*)(sizeof(GLfloat)*3));

        glBindVertexArrayOES(0);

    }

    return self;

}
在我的.h文件中,我定义了_顶点数组,如下所示:

// 360 + 2 = 362 vertices per triangle strip
// 90 strips per hemisphere (one hemisphere has 91)
// 2 hemispheres
// 362 * 90.5 * 2 = 65522
GLfloat _vertices[65522][2][3]; //2 sets (vertex, normal) and 3 vertices in each set

看起来您正在计算三角形条带中三角形的法线,但将这些法线指定给多个三角形共享的顶点。如果您只是使用三角形而不是三角形条带,并为每个三角形的所有三个顶点指定三角形法线,则每个三角形都将具有适当的法线。该值仅适用于三角形的中心。您最好使用顶点法线,正如Christian提到的,在本例中,顶点法线等于顶点。这些顶点可以在三角形上插值。

顶点到底是什么?通常,您不能将3D数组传递给OpenGL,并期望它做任何有意义的事情。我不得不想象,还有其他一些数据类型使3D数组下标在一个线性内存块上工作,而不是执行三级指针间接寻址。我编辑了我的帖子,以展示我是如何存储这种疯狂的数据结构的。我在这方面是个新手,所以我很容易接受更好的方法。这种方法对我来说适用于更小的数据集,但对于这么多的顶点来说却很麻烦。你知道一个球体的法线只是它的标准化顶点,对于一个单位球体,就像你的一样,它们与顶点相等,是吗?@Andon:在C中,因此也是在这个问题中使用的Objective-C,声明具有多个下标的数组是指针乘法,而不是指针间接寻址。声明GLfloat_顶点[65522][2][3]实际上与GLfloat_顶点[65522*2*3]相同,将元素寻址为_顶点[i][j][k]与_顶点[i*2*3+j*3+k]相同。看。这种结构没有什么问题。但是,使用typedefs在语义上组织顶点数据可能会很有用。如果定义typedef struct{GLKVector3 position;GLKVector3 normal;}Vertex,则可以将数组声明为顶点_顶点[65522],将地址元素声明为_顶点[i].position.x、_顶点[i].normal.z等。就GL而言,它仍然是一个很长的glfloat块,但可以使用名称,sizeof和offsetof来跟踪事物,而不是在源代码中到处都是神奇的数字。对不起,这不是你问题的解决方案,而是一个一般性的提示@克里斯蒂安罗的评论应该会有所帮助。
// 360 + 2 = 362 vertices per triangle strip
// 90 strips per hemisphere (one hemisphere has 91)
// 2 hemispheres
// 362 * 90.5 * 2 = 65522
GLfloat _vertices[65522][2][3]; //2 sets (vertex, normal) and 3 vertices in each set