
3D Lingo
III - Perspectives et faces cachées
Nous avons appris à déplacer
un objet dans l'espace et même à modéliser
des formes complexes. Mais il manque encore deux chose
à notre animation. Un effet de perspective et des
faces cachées
La perspective
Pour simuler la perspective nous allons mobiliser le troisième
point de notre système de coordonnées 3D.
Nous avons en effet tacitement résolu de confondre
l'extrémité de l'axeZ est le lieu d'où
la scËne est regardée. D'autres approches sont
possibles. Notre option est seulement plus simple à
mettre en uvre. De toute façon, et quel que
soit le procédé utilisé, le principe
de la mise en perspective reste inchangé : Les transformations
modifient la distance d'un point donné à l'observateur
et plus cette distance est grande plus les objets semblent
petit. Les points semblent même se confondre à
l'infini, sur la ligne de fuite.
C'est en mesurant cette distance d'un point donné
à l'observateur que nous seront en mesure de simuler
un effet de perspective.
Reformulons ça dans notre langage : Les valeurs
x et y d'un objet sont (paraissent) plus réduites
(plus proches de zéro) à mesure de son éloignement
(position sur l'axe z). Attention toutefois, cette modification
est purement optique ne concerne que l'affichage des objets
sur la scène de Director. En aucun cas, les coordonnées
absolues des objets ne doivent être modifiées !
Nous allons modifier à l'affichage seulement, les
positions horizontales et verticales de chaque coin des
facettes et ce, en fonction de leur position sur l'axe Z.
De notre animation, on reprend le
behavior "facette" et plus particulièrement
le gestionnaire "transformation" :
on transformation me, nouvellesCoordonnŽesDuSystemeLocal
LesQuad = []
if not pOk then exit
origineH = pPosition[1]
origineV = pPosition[2]
unCoin = equivalenceAbsolu (pc1[1] , pc1[2] , pc1[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc1 = unCoin
add LesQuad, point(unCoin[1] + origineH ,unCoin[2]+ origineV
)
-- ajoute dans la liste "LesQuad"
les deux premieres valeurs de pC1
unCoin = equivalenceAbsolu (pc2[1] , pc2[2] , pc2[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc2 = unCoin
add LesQuad, point(unCoin[1] + origineH ,unCoin[2] + origineV)
unCoin = equivalenceAbsolu (pc3[1] , pc3[2] , pc3[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc3 = unCoin
add LesQuad, point(unCoin[1] + origineH ,unCoin[2]+ origineV
)
unCoin = equivalenceAbsolu (pc4[1] , pc4[2] , pc4[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc4 = unCoin
add LesQuad, point(unCoin[1] + origineH ,unCoin[2] + origineV)
the quad of sprite spriteNum = LesQuad
end
Dans ce gestionnaire les coordonnées des coins sont
mémorisées par le sprite-facette dans des
propriétés (pC1, pC2, pC3, pC4). La liste
"lesQuad" utilise immédiatement les deux
premières coordonnées de chaque coin afin
de modifier les quads du sprite. Il nous faut certes CONSERVER
les coordonnées absolues de pC1, pC2, etc. inchangées
mais nous devons aussi infléchir les valeurs avant
de les exploiter pour l'affichage. Nous nous dotons d'un
gestionnaire supplémentaire qui diminue les coordonnée
x et y en fonction de z pour un point donné :
on perspectiveDe unPoint
x = integer(rho[1] * (1 - rho[3]/1000
) )
-- x est égale
à zero si z = 1000 (c'est à dite au point
de fuite)
y = integer(rho[2] * (1 - rho[3]/1000 ) )
-- y est égale à
zero si z = 1000 (c'est à dite au point de fuite)
z = rho[3]
return [x, y , z]
end
NOTA : on peut en augmentant la valeur de division (ici
1000) créer un effet de distorsion ou de focale interessant.
On pourrait par exemple en lieu et place de cette valeur
de 1000, utiliser une variable globale que l'utilisateur
serait libre d'incrémenter. Attention toutefois,
les points éloignés au delà de cette
limite risqueraient de se croiser à force de se rapprocher
!
Nous modifions le gestionnaire "transformation"
de façon à modifier À l'AFFICHAGE les
coordonnées des coins :
on transformation me, nouvellesCoordonnŽesDuSystemeLocal
LesQuad = []
if not pOk then exit
origineH = pPosition[1]
origineV = pPosition[2]
unCoin = equivalenceAbsolu (pc1[1] , pc1[2] , pc1[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc1 = unCoin
-- NOTA : les nouvelles coordonnées
absolues sont d'abord mémorisées dans pC1
-- ce sont les VRAIES coordonnées du coin
unCoin = perspectiveDe(unCoin)
add LesQuad, point(unCoin[1] + origineH ,unCoin[2]+ origineV
)
-- on ajoute dans une liste les
deux premières valeurs infléchies,
-- infléchies pour et seulement pour leur exploitation
à l'affichage
unCoin = equivalenceAbsolu (pc2[1] , pc2[2] , pc2[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc2 = unCoin
unCoin = perspectiveDe(unCoin)
add LesQuad, point(unCoin[1] + origineH ,unCoin[2] + origineV)
unCoin = equivalenceAbsolu (pc3[1] , pc3[2] , pc3[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc3 = unCoin
unCoin = perspectiveDe(unCoin)
add LesQuad, point(unCoin[1] + origineH ,unCoin[2]+ origineV
)
unCoin = equivalenceAbsolu (pc4[1] , pc4[2] , pc4[3],
nouvellesCoordonnŽesDuSystemeLocal)
pc4 = unCoin
unCoin = perspectiveDe(unCoin)
add LesQuad, point(unCoin[1] + origineH ,unCoin[2] + origineV)
the quad of sprite spriteNum = LesQuad
-- la liste LesQuad contient donc
les positions du sprite après rotation ET mise
en perspective
end
Bien vu ! Rappelons-le toutefois ce n'est là qu'une
des options possibles pour simuler la perspective. Notre
choix n'est motivé que par la simplicité de
mise en uvre.
À y bien réfléchir, on épargnerait
bien des efforts inutiles au processeur si l'on s'abstenait
d'afficher les sprites trop éloignés. De même
mais cette fois dans un souci de réalisme, il semblerait
pertinent de ne pas afficher non plus les objets trop proches
(comme s'ils étaient passés derrière
le spectateur). On le voit, la position sur l'axe Z est
sans cesse mobilisée pour construire un monde tri-dimensionnel.
Mais laissons ces retouches accessoires car nous avons maintenant
un problème beaucoup plus important. Que
faire des faces cachées ?
|