CALCUL DES NORMALES D'UN OBJET 3D

Messages postés
231
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
20 août 2014
- - Dernière réponse : KeniiyK
Messages postés
326
Date d'inscription
vendredi 13 août 2004
Statut
Membre
Dernière intervention
2 novembre 2007
- 2 mars 2005 à 18:35
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/29723-calcul-des-normales-d-un-objet-3d

Afficher la suite 
KeniiyK
Messages postés
326
Date d'inscription
vendredi 13 août 2004
Statut
Membre
Dernière intervention
2 novembre 2007
2 -
Histoire d'être sur de ne pas laisser des trucs en suspend :
Pour calculer les angles :
pour AV00 par exemple, tu prends les vecteurs V0V1 et V0V2 normalisés puis acos(V0V1.V0V2) . étant le Dot Product. Sachant aussi qu'en C/C++, les fonctions trigos cos, sin, acos etc... bossent en radians.

Et pour finir, saches qu'au niveau mathématique, la moyenne "de base" (non pondérée) à un "coefficient de robustesse" de 0.5 c'est à dire qu'elle peut aussi bien donner le bon résultat qu'un mauvais résultat.
KeniiyK
Messages postés
326
Date d'inscription
vendredi 13 août 2004
Statut
Membre
Dernière intervention
2 novembre 2007
2 -
Pour l'histoire du length==0.0, ca depend d'ou proviennent tes normales, si tu es sur que tes normales au faces ne peuvent pas etre nulles alors ok, pas besoin de verifier.
Mais imaginons que tu calcules tes normales au faces et imaginons une face triangulaire (v0,v1,v2) (avec Vi,
i c [0..2] designant un point 3D), si jamais tu as Vi==Vj avec i!=j, i,j c [0..2]² alors (v1-v0)^(v2-v0)=(0.0,0.0,0.0)
(en Counter Clock Wise au sinon faire (v2-v0)^(v1-v0) mais c'est aussi égal au vecteur nul).
(au fait ^ c'est le cross product)
Voila pour l'explication du length==0.0, a toi de voir, mais je pense qu'on est jamais trop prudent :)

Sinon une méthode qui marche bien (voire super bien...) pour le calcul des normales aux sommets c'est de pondérer la moyenne des normales aux faces par l'angle associé au sommet dans la face.
C'est pas clair ?, JE M'EXPLIQUE !!!!! :
(t'inquiètes pas c'est pas long et l'exemple est simple, prends une feuille et un crayon au cas mes explications ne soient pas assez claires).

En tenant compte qu'on est dans un repère direct orthonormé oxyz.

Notons 6 sommets Vi, i c [0..5] :
V0=(0.0,0.0,0.0)
V1=(1.0,0.0,0.0)
V2=(1.0,0.0,1.0)
V3=(0.0,1.0,1.0)
V4=(0.0,0.0,1.0)
V5=(0.0,1.0,0.0)

Notons 5 faces triangulaires (en CCW)
Fj(Vi0,Vi1,Vi2), j c [0..4].
Vik, k c [0..2] un des sommets précedents.
et leurs normales NFj(X,Y,Z).
F0(0,1,2) -> NF0(0.0,-1.0,0.0)
F1(0,2,4) -> NF1(0.0,-1.0,0.0)
F2(0,5,1) -> NF2(0.0,0.0,-1.0)
F3(0,3,5) -> NF3(-1.0,0.0,0.0)
F4(0,4,3) -> NF4(-1.0,0.0,0.0)

Dans le plan oxz on a :

z
|
V4......................V2
| . . NF0 et NF1 pointent vers
| . . toi.
| F1 . .
| . .
| . F0 .
V0------------------V1--x
o

Dans le plan oxy on a :

y
|
V5 .
| . NF2 pointe vers l'ecran
| .
| F2 .
| .
| .
V0------------------V1--x
o

Dans le plan oyz on a :

z
|
V4......................V3
| . . NF3 et NF4 pointent vers
| . . l'ecran.
| F4 . .
| . .
| . F3 .
V0------------------V5--y
o

Calculons maintenant la normale au sommet V0 (qui participe à toutes les faces), si tu visualises bien l'exemple, tu seras d'accord pour dire que la normale a trouvé est NV0=(-1.0,-1.0,-1.0).

Par la moyenne des faces on trouve donc :
NV0=(NF0+NF1+NF2+NF3+NF4)/5=(-2/5,-2/5,-1/5).
Donc ca ne marche pas....

Par la méthode que j'explique (que je tente d'expliquer...)
Notons les angles du sommet V0 dans chaque face Fi
par AV0i l'angle dans la face i
(par exemple AV00 =angle entre V0V1 et V0V2).
AV00=PI/4
AV01=PI/4
AV02=PI/2
AV03=PI/4
AV04=PI/4
avec une moyenne des normales aux faces pondérées par ces angles on a
NV0=NF0*AV00+NF1*AV01+NF2*AV02+NF3*AV03+NF4*AV04=(-2.0*PI/4 , -1.0*PI/2 , -2.0*PI/4)=
(-1.0,-1.0,-1.0) apres normalisation.

J'espère que j'ai été clair et que cela puisse t'aider.

@+, KeniiyK.
cs_erazor
Messages postés
85
Date d'inscription
jeudi 7 février 2002
Statut
Membre
Dernière intervention
8 février 2007
-
"Ta méthode de calcul pour une normale a un sommet c'est quoi exactement ?.
Pour chaque sommet tu fais une moyenne des normales des faces auxquelles il appartient ?. (Si c'est ca il y a mieux...)"

je suis preneur ;-)

par contre je ne vois pas l'utilité de verifier due le lenght ne soit pas nul vue que une normale (0,0,0) n'est pas possible??
cs_erazor
Messages postés
85
Date d'inscription
jeudi 7 février 2002
Statut
Membre
Dernière intervention
8 février 2007
-
"Ta méthode de calcul pour une normale a un sommet c'est quoi exactement ?.
Pour chaque sommet tu fais une moyenne des normales des faces auxquelles il appartient ?. (Si c'est ca il y a mieux...)"

je suis preneur ;-)

par contre je ne vois pas l'utilité de verifier due le lenght ne soit pas nul vue que une normale (0,0,0) n'est pas possible??
KeniiyK
Messages postés
326
Date d'inscription
vendredi 13 août 2004
Statut
Membre
Dernière intervention
2 novembre 2007
2 -
Ta méthode de calcul pour une normale a un sommet c'est quoi exactement ?.
Pour chaque sommet tu fais une moyenne des normales des faces auxquelles il appartient ?. (Si c'est ca il y a mieux...)

Au sinon juste un conseil :
dans ton code tu fais ca :
normx[polya[i]]=normx[polya[i]]/sqrt((normx[polya[i]]*normx[polya[i]])+(normy[polya[i]]*normy[polya[i]])+(normz[polya[i]]*normz[polya[i]]));

normy[polya[i]]=normy[polya[i]]/sqrt((normx[polya[i]]*normx[polya[i]])+(normy[polya[i]]*normy[polya[i]])+(normz[polya[i]]*normz[polya[i]]));

normz[polya[i]]=normz[polya[i]]/sqrt((normx[polya[i]]*normx[polya[i]])+(normy[polya[i]]*normy[polya[i]])+(normz[polya[i]]*normz[polya[i]]));

range plutot dans un float ou un double le diviseur :

float/double length=sqrt((normx[polya[i]]*normx[polya[i]])+(normy[polya[i]]*normy[polya[i]])+(normz[polya[i]]*normz[polya[i]]));

puis faire :
normx[polya[i]]/=length;
normy[polya[i]]/=length;
normz[polya[i]]/=length;

Au moins tu ne calcules qu'une seule fois le length, et il faut aussi verifier qu'il ne soit pas nul.