Seul gros défaut de notre animation : les facettes sont
toutes visibles ! Nous n'avons jusqu'à présent pas
pris en compte le fait que des faces était cachées
par d'autres et avons repoussé à plus tard ce problème
en utilisant une opacité réduite. Mais outre que cette
solution rend illisible les volumes complexes elle a aussi pour
inconvénient majeur de ralentir gravement les animations.
Nous devons déterminer celles des facettes qui sont le plus
avant et modifier l'affichage en conséquence.
On aborde ici avec la gestion des faces cachées un problème
bien réel et qui n'a pas encore - qu'on se le dise - trouvé
de solution imparable... Encore une fois plusieurs procédés
sont envisageables. Certains fort complexes sont utilisés
par les logiciels de 3D avec de bons résultat. Les procédés
plus simple montrent eux, très vite, leur limite. Voyons
ce que nous pouvons faire simplement. Nous pourrions par exemple
- mais nous ne ferons que le suggérer - tenter de déterminer
celles de facettes qui nous tournent le dos en analysant leurs quads.
Nous pouvons aussi - c'est notre choix - mesurer une distance moyenne
de chaque facette à l'observateur ou plutôt (car nous
avons arbitrairement confondu le point de vue de l'observateur avec
l'extrémité de l'axe Z) une position moyenne de chaque
sprite facette sur l'axe Z.
Cette position moyenne nous est donnée par la troisième
coordonnée de chacun des 4 coins d'une facette (PC1, pC2,
pC3, pC4) , soit pour chaque sprite :
C'est en utilisant cette valeur que nous pourrons redéfinir
pour chaque facette la propriété the LocZ of sprite.
Évidemment cette moyenne risque fort d'être une valeur
décimale ou encore d'être une valeur négative.
On ne pourra donc l'utiliser immédiatement pour la convertir
en LocZ. Nous allons plutôt l'utiliser pour en déduire
un classement des sprites en profondeur.
On utilise un gestionnaire appelé à chaque transformation.
Ce gestionnaire ("faitLeTri") récupère pour
chaque sprite la moyenne des positions des coins sur l'axe Z (via
une liste gLaListeDesSprites renseignée à chaque transformation).
En plaçant ces moyennes dans une liste triée d'avance
(lesMoyennes) on peut connaître leur position dans cette liste
et affecter à chaque sprite sur la scène un locZ fonction
de ce classement.
On ajoute au script d'animation le code suivant :
on faitLeTri
lesMoyennes = []
sort(lesMoyennes)
repeat with n in gLaListeDesSprites
add lesMoyennes, the maMoyenne of n
end repeat
repeat with n in gLaListeDesSprites
the locZ of sprite n.spriteNum = getPos(lesMoyennes,
n.maMoyenne)
-- l'ordre de superposition
sur la scène reprend le classement des moyennes dans la liste
end repeat
gLaListeDesSprites = []
end
Bien sûr, on renseigne la liste globale gLaListeDesSprites
à chaque nouvelle transformation. On obtient cela par cet
ajout que l'on fait à la fin du gestionnaire "transformation"
(script "facette" voir plus haut)
maMoyenne = - ( (pC1[3] + pc2[3] + pC3[3]
+ pC4[3]) /4 )
global gLaListeDesSprites
add gLaListeDesSprites, me
end
Enfin on appelle le gestionnaire faitLeTri après chaque
modification. Exemple ici avec le script associé au bouton
de rotation selon Y:
global angleY
on mouseDown
repeat while the mousedown
angleY = 0.01
nouveauSysteme = rotationSelonAxeYDe (angleY)
sendAllSprites(#transformation, nouveauSysteme)
faitLeTri
go the frame
end repeat
end
Notre procédé est-il acceptable ? Peut-être
pour un univers simplifié mais regardons plutôt le
schéma suivant. Il s'agit tout simplement d'un timbre collé
sur une enveloppe.
Il est évident que la lettre est plus proche que le timbre
et pourtant... c'est lui qui est dessus ! Dans un tel cas notre
gestion des profondeur montrera ses limites...