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...