I am making some fairly simple forms in OpenGL-ES based on Apple's sample code. They used an array of points with an array of indices in the first array, and each set of three indices creates a polygon. All this is great, I can make the shapes that I want. To properly shade the shapes, I believe that I need to calculate the normals for each vertex on each polygon. At first the shapes were cubic, so it was very easy, but now I am making (slightly) more complex shapes that I want to create these normals automatically. It seems easy enough if I get vectors for two edges of a polygon (here all policies are triangles) and use their cross-product for each vertex on this polygon. After that, I use the code as shown below to draw the figure.
glEnableVertexAttribArray(GLKVertexAttribPosition); glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices); glEnableVertexAttribArray(GLKVertexAttribColor); glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColours); glEnableVertexAttribArray(GLKVertexAttribNormal); glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, triangleNormals); glDrawArrays(GL_TRIANGLES, 0, 48); glDisableVertexAttribArray(GLKVertexAttribPosition); glDisableVertexAttribArray(GLKVertexAttribColor); glDisableVertexAttribArray(GLKVertexAttribNormal);
I am having trouble understanding, so I have to do it manually. I am sure that there are cases when you need something other than just a vector perpendicular to the surface, but I am also sure that this is the most popular use case today, so there shouldn't be an easier way? Am I missing something obvious? glCalculateNormals () would be great.
// And here is the answer Go to GLKVector3 [], which you want to fill with your normals, another with vertices (each three are grouped into polygons), and then a vertex counter.
- (void) calculateSurfaceNormals: (GLKVector3 *) normals forVertices: (GLKVector3 *)incomingVertices count:(int) numOfVertices { for(int i = 0; i < numOfVertices; i+=3) { GLKVector3 vector1 = GLKVector3Subtract(incomingVertices[i+1],incomingVertices[i]); GLKVector3 vector2 = GLKVector3Subtract(incomingVertices[i+2],incomingVertices[i]); GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vector1, vector2)); normals[i] = normal; normals[i+1] = normal; normals[i+2] = normal; } }