AndroidDev
AndroidDev

Reputation: 21247

Separate arrays for vertices and normals

I'm trying to draw an object where my vertices are stored in one array and my normals are stored in a separate array. Thus far, I've drawn all of my objects where the vertices and normals have been interleaved in a single data structure, so I'm not sure how to pass in separate arrays. Please scroll down to my init function where you will see that I am trying to pass in both arrays, but am clearly doing something wrong. I can draw this object without normals just fine, but I need to normals for lighting, etc.

Can somebody tell me what I am doing wrong here? Thank you!

    @implementation Camera

    GLfloat cameraVertices[] = {
        0.500000f, -0.350000f, 0.000000f, 0.500000f, -0.350000f, 0.000000f, 0.500000f, -0.350000f, 0.000000f,
        -0.500000f, -0.350000f, 0.000000f, -0.500000f, -0.350000f, 0.000000f,
        -0.500000f, -0.350000f, 0.000000f, -0.500000f, 0.350000f, 0.000000f,
        -0.500000f, 0.350000f, 0.000000f, -0.500000f, 0.350000f, 0.000000f,
       // this goes on for a while...
    };

    GLfloat cameraNormals[] = {
        1.00000f, 0.000000f, 0.000000f, 0.000000f, -1.00000f, 0.000000f, 0.000000f, 0.000000f, -1.00000f,
        -1.00000f, 0.000000f, 0.000000f, 0.000000f, -1.00000f, 0.000000f,
        0.000000f, 0.000000f, -1.00000f, -1.00000f, 0.000000f, 0.000000f,
        0.000000f, 1.00000f, 0.000000f, 0.000000f, 0.000000f, -1.00000f,
        1.00000f, 0.000000f, 0.000000f, 0.000000f, 1.00000f, 0.000000f,
           // this also goes on for a while...
};

    GLint cameraIndices[] = {
        2, 5, 11, 5, 8, 10, 7, 17, 7, 14, 16, 13, 23, 13, 20, 22,
        19, 1, 19, 4, 3, 18, 6, 18, 12, 21, 0, 15, 0, 9, 203, 149,
        204, 147, 204, 152, 204, 155, 204, 158, 204, 161, 204, 164, 204, 167, 204, 170,
        204, 173, 204, 176, 204, 179, 204, 182, 204, 185, 204, 188, 204, 191, 204, 194,
        204, 197, 204, 200, 203, 144, 148, 144, 202, 201, 199, 198, 196, 195, 193, 192,
        190, 189, 187, 186, 184, 183, 181, 180, 178, 177, 175, 174, 172, 171, 169, 168,
        166, 165, 163, 162, 160, 159, 157, 156, 154, 153, 151, 150, 146, 145, 148, 145,
        144, 123, 87, 124, 87, 125, 85, 126, 89, 127, 91, 128, 93, 129, 95, 130,
        97, 131, 99, 132, 101, 133, 103, 134, 105, 135, 107, 136, 109, 137, 111, 138,
        113, 139, 115, 140, 117, 141, 119, 142, 121, 143, 123, 143, 124, 29, 86, 29,
        122, 83, 120, 80, 118, 77, 116, 74, 114, 71, 112, 68, 110, 65, 108, 62,
        106, 59, 104, 56, 102, 53, 100, 50, 98, 47, 96, 44, 94, 41, 92, 38,
        90, 35, 88, 32, 84, 27, 86, 27, 29, 24, 28, 24, 82, 81, 79, 78,
        76, 75, 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 58, 57, 55, 54,
        52, 51, 49, 48, 46, 45, 43, 42, 40, 39, 37, 36, 34, 33, 31, 30,
        26, 25, 28, 25, 24
    };

    - (id) init {

        if (self = [super init]) {

            NSLog(@"new camera!");

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

            glGenBuffers(1, &_vertexBuffer);
            glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
            glBufferData(GL_ARRAY_BUFFER, sizeof(cameraVertices), cameraVertices, GL_STATIC_DRAW);

            glEnableVertexAttribArray(GLKVertexAttribPosition);
            glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, NULL);

            glBufferData(GL_ARRAY_BUFFER, sizeof(cameraNormals), cameraNormals, GL_STATIC_DRAW);
            glEnableVertexAttribArray(GLKVertexAttribNormal);
            glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, NULL);

            glBindVertexArrayOES(0);

        }

        return self;
    }

    - (GLuint) getVertexArray
    {
        return _vertexArray;
    }

    - (void) render
    {
        glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, &cameraIndices[0]);
        glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, &cameraIndices[5]);
        glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, &cameraIndices[10]);
        glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, &cameraIndices[15]);
        glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[20]);
        glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, &cameraIndices[25]);
        glDrawElements(GL_TRIANGLE_STRIP, 39, GL_UNSIGNED_SHORT, &cameraIndices[30]);
        glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_SHORT, &cameraIndices[69]);
        glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_SHORT, &cameraIndices[113]);
        glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_SHORT, &cameraIndices[157]);
        glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_SHORT, &cameraIndices[201]);

    }

    @end

Upvotes: 0

Views: 454

Answers (1)

rickster
rickster

Reputation: 126177

If you have separate arrays, you need separate vertex buffer objects. You're already using glGenBuffers and glBindBuffer to create/bind a VBO for positions -- you need to do it again to create/bind a separate VBO for normals before filling it with glBufferData.

While you're at it, you can also create a buffer of the GL_ELEMENT_ARRAY_BUFFER type to hold your indices array, and attach it to your VAO. This will make your glDrawElements calls faster because they can use data already on the GPU instead of transferring the (sub)array of indices to be drawn on each call. When you do that, you'll need to change the last parameter to your glDrawElements calls -- instead of a pointer to the array in client memory space, it's an offset from the beginning of the buffer.

Upvotes: 1

Related Questions