Question

Je fais des formes assez basiques dans OpenGL-ES basé sur un exemple de code d'Apple. Ils ont utilisé un tableau de points, avec un tableau d'indices dans le premier tableau et chaque ensemble de trois indices crée un polygone. C'est tout grand, je peux faire les formes que je veux. Pour ombrer correctement les formes que je crois que je besoin de calculer Normales pour chaque sommet de chaque polygone. Au début, les formes étaient cuboïde il était très facile, mais maintenant je fais (un peu) des formes plus avancées que je veux créer ces Normales automatiquement. Il semble assez facile si je reçois des vecteurs pour deux bords d'un polygone (tous les polys sont des triangles ici) et d'utiliser leur produit croix pour chaque sommet sur ce polygone. Après que le code I utilisation comme ci-dessous pour dessiner la forme.

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);

Ce que je vais avoir du mal à comprendre pourquoi je dois le faire manuellement. Je suis sûr qu'il ya des cas où vous voudriez autre chose qu'un vecteur perpendiculaire à la surface, mais je suis aussi sûr que ce soit le cas le plus d'usage populaire de loin, ne devrait donc pas y avoir un moyen plus facile? Ai-je manqué quelque chose évidente? glCalculateNormals () serait grande.

// Et voici une réponse Passez dans un GLKVector3 [] que vous souhaitez être rempli de vos Normales, une autre avec les sommets (chaque trois sont regroupés en polygones), puis le comptage des sommets.

- (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;
    }
}
Était-ce utile?

La solution

And again the answer is: OpenGL is neither a scene managment library nor a geometry library, but just a drawing API that draws nice pictures to the screen. For lighting it needs normals and you give it the normals. That's all. Why should it compute normals if this can just be done by the user and has nothing to do with the actual drawing?

Often you don't compute them at runtime anyway, but load them from a file. And there are many many ways to compute normals. Do you want per-face normals or per-vertex normals? Do you need any specific hard edges or any specific smooth patches? If you want to average face normals to get vertex normals, how do you want to average these?

And with the advent of shaders and the removing of the builtin normal attribute and lighting computations in newer OpenGL versions, this whole question becomes obsolete anyway as you can do lighting any way you want and don't neccessarily need traditional normals anymore.

By the way, it sounds like at the moment you are using per-face normals, which means every vertex of a face has the same normal. This creates a very faceted model with hard edges and also doesn't work very well together with indices. If you want a smooth model (I don't know, maybe you really want a faceted look), you should average the face normals of the adjacent faces for each vertex to compute per-vertex normals. That would actually be the more usual use-case and not per-face normals.

So you can do something like this pseudo-code:

for each vertex normal:
    intialize to zero vector

for each face:
    compute face normal using cross product
    add face normal to each vertex normal of this face

for each vertex normal:
    normalize

to generate smooth per-vertex normals. Even in actual code this should result in something between 10 and 20 lines of code, which isn't really complex.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top