J'ai une classe qui génère une forme 3D basée sur les entrées du code appelant. Les entrées sont des choses comme la longueur, la profondeur, l'arc, etc. Mon code génère parfaitement la géométrie, mais je rencontre des problèmes lors du calcul des normales de surface. Lorsqu'elle est allumée, ma forme a une coloration / texture très bizarre provenant des normales de surface incorrectes qui sont calculées. De toutes mes recherches, je crois que mes calculs sont corrects, il semble que quelque chose ne va pas avec ma technique ou ma méthode.
À un niveau élevé, comment procéder pour calculer par programme les normales de surface d'une forme générée? J'utilise Swift / SceneKit sur iOS pour mon code mais une réponse générique est très bien.
J'ai deux tableaux qui représentent ma forme. L'un est un tableau de points 3D qui représente les sommets qui composent la forme. L'autre tableau est une liste d'index du premier tableau qui mappent les sommets en triangles. J'ai besoin de prendre ces données et de générer un troisième tableau qui est un ensemble de normales de surface qui aident à l'éclairage de la forme. (voir SCNGeometrySourceSemanticNormal
dans SceneKit` )
La liste des sommets et des index est toujours différente en fonction des entrées de la classe, donc je ne peux pas pré-calculer ou coder en dur les normales de surface.
Réponses:
Vous ne voulez tout simplement pas de résultats parfaitement fluides. Alors que la méthode commentée de Nathan Reed: "Calculer chaque sommet pour faire face à la normale, les additionner, normaliser la somme", fonctionne généralement, il échoue parfois de façon spectaculaire. Mais cela n'a pas d'importance ici, nous pouvons utiliser cette méthode en y ajoutant une clause de rejet.
Dans ce cas, vous souhaitez simplement que certaines pièces ne soient pas lissées contre certaines autres pièces. Vous voulez des bords durs sélectifs. Ainsi, par exemple, le haut et le bas plats sont séparés de la bande triangulaire sur le côté, tout comme chaque zone plate.
Image 1 : Le résultat souhaité.
En effet, vous voulez uniquement faire la moyenne des sommets de la zone courbe, tous les autres peuvent utiliser la normale qu'ils obtiennent à partir de leur triangle seul. Il vaut donc mieux considérer le maillage comme 9 régions distinctes qui sont gérées sans les autres.
Image 2 : Image montrant la structure du maillage et les normales.
Vous pouvez certainement déduire cela automatiquement en n'incluant pas les normales qui sont en dehors d'un certain angle par rapport à la normale des sommets primaires. Pseudocode:
Cela fonctionne, mais vous pouvez simplement éviter tout cela au moment de la création, car vous comprenez que les plans séparés fonctionnent différemment. Ainsi, seuls les côtés incurvés doivent fusionner dans le sens normal. Et en fait, vous pouvez simplement les calculer directement à partir de la forme mathématique sous-jacente.
la source
Je vois principalement trois façons de calculer des normales pour une forme générée.
Normales analytiques
Dans certains cas, vous disposez de suffisamment d'informations sur la surface pour générer les normales. Par exemple, la normale de tout point sur une sphère est triviale à calculer. En termes simples, lorsque vous connaissez la dérivée de la fonction, vous connaissez également la normale.
Si votre cas est suffisamment étroit pour vous permettre d'utiliser des normales analytiques, elles donneront probablement le meilleur résultat en termes de précision. Cependant, la technique n'est pas trop évolutive: si vous devez également gérer des cas où vous ne pouvez pas utiliser de normales analytiques, il peut être plus facile de conserver la technique qui gère le cas général et de supprimer complètement le cas analytique.
Normales de sommet
Le produit croisé de deux vecteurs donne un vecteur perpendiculaire au plan auquel ils appartiennent. Il est donc simple d'obtenir la normale d'un triangle:
De plus, dans l'exemple ci-dessus, la longueur du produit croisé est proportionnelle à la zone à l'intérieur de abc . Ainsi, la normale lissée à un sommet partagé par plusieurs triangles peut être calculée en additionnant les produits croisés et en normalisant comme dernière étape, pondérant ainsi chaque triangle par sa surface.
Si vous travaillez avec des quads, il y a une bonne astuce que vous pouvez utiliser: pour un quad abcd , utilisez
crossProduct(c - a, d - b)
et il gérera bien les cas où le quad est en fait un triangle.Iñigo quilez a écrit quelques courts articles sur le sujet: normalisation intelligente d'un maillage , et normale et aire de polygones à n côtés .
Normales dérivées partielles
Les normales peuvent être calculées dans le fragment shader à partir des dérivées partielles. Le calcul derrière est le même, sauf que cette fois, cela se fait dans l'espace écran. Cet article d'Angelo Pesce décrit la technique: des normales sans normales .
la source