Retro-A: Scène et perspective

Description

Bonjour,

Voici une série d'articles "retro" concernant quelques domaines graphiques qui étaient d'actualité au millénaire passé.
Epoque à laquelle l'informaticien devait souvent commencer par "forger ses outils".

Perspective 2D←3D "à la main"

Faut-il encore aujourd'hui proposer un code sur les perspectives "bricolées soi-même" ?
Alors qu'il existe tant de librairies graphiques 3D formidables, rapides et sûres qui font ça mille fois mieux !

Voici quelques avis courants pour ou contre:

Pour:
.. Pas de librairie graphique à installer et à apprendre.
.. Mieux comprendre le "fonctionnement" d'une perspective.
.. Mieux comprendre la composition des transformations.
.. Le plaisir de faire soi-même ou suivre le code.
.. ...

Contre:
.. Programmation "moins sûre".
.. Programmation plus compliquée.
.. Limitation des possibilités graphiques.
.. Utilisation médiocre des "accélérateurs" hardware.
.. ...

Un peu de théorie:

L'image Persp.jpg peut vous servir de guide dans ce qui suit:

Dans un système tridimensionnel traditionnel de coordonnées cartésiennes X·Y·Z, la géométrie des objets sera (principalement) déterminée à l'aide de points 3D de la forme:
    P = (x,y,z)
On s'arrangera pour que tous les points de l'objet se situent "autour" de l'origine 3D.

Définissons, "bien en dehors" de l'objet, sur l'axe -Y, un point ¤ de coordonnées (0,-d,0),
que nous appellerons "œil" ou "caméra" ou "observateur" ou "centre de projection".

Pour un point P = (x,y,z) de l'objet, observons sa projection (U,V) sur le plan 2D U·V "plaqué" sur le plan d'axes X·Z.

En considérant les règles des triangles semblables, on remarque que:
    U/d = x/(d+y) , V/d = z/(d+y) ;
c'est-à-dire:
    U = q·x , V = q·z , avec q = d/(d+y)

Remarques:
.. Comme le centre de projection est "plus loin" que tous les points de l'objet, on a y > -d; ce qui évite une division par zéro !
.. La projection définie est souvent appelée perspective centrale ou perspective conique.

Construction d'une scène interactive

Elle devrait nous permettre de:
.. Tourner un objet librement autour de son axe 3D vertical Z.
.. Basculer l'objet en bas ou en haut (par rapport à l'écran).
.. Déplacer l'œil (sur l'axe -Y) pour modifier l'effet de perspective.
.. Agrandir ou rétrécir l'image 2D projetée (zoom 2D).
.. Déplacer l'image 2d obtenue.
..

Pour la transformation, cela donne en notation matricielle:
Projection 3D->2D:
       Basculement (rotX)         (rotZ)
(x')    (1   0       0   )   (cos(a) -sin(a) 0)   (x)   (       cos(a)       -sin(a)       0)   (x)
(y') =  (0 cos(b) -sin(b)) * (sin(a)  cos(a) 0) * (y) = (cos(b)*sin(a) cos(b)*cos(a) -sin(b)) * (y)
(z')    (0 sin(b)  cos(b))   (  0       0    1)   (z)   (sin(b)*sin(a) sin(b)*cos(a)  cos(b))   (z)

       q = d/(d+y');  U = q*x';  V = q*z';

La transformation 2D->2D (layout, mise en page) sera faite 'in line':
       u = u0 + dil*U; v = v0 + dil*V;

Et voici le code Javascript proposé:
function Persp(D,az,ax) {// az,ax: en degrés (°)
  var rz=az*0.01745329252,rx=ax*-0.01745329252; // en rad
  var sa=Math.sin(rz),ca=Math.cos(rz),sb=Math.sin(rx),cb=Math.cos(rx);
  this.d=D; this.xx=ca; this.xy=-sa;
  this.yx=cb*sa; this.yy=cb*ca; this.yz=-sb;
  this.zx=sb*sa; this.zy=sb*ca; this.zz=cb;
}

 // Projection (x,y,z) --> (U,V) avec p = new Persp(...):
 // var q = p.d/(p.d + p.yx*x + p.yy*y + p.yz*z);

 // U = q*(p.xx*x + p.xy*y);
 // V = q*(p.zx*x + p.zy*y + p.zz*z)};

Traitement

Pour éviter de tout recalculer et redessiner après chaque intervention, le programme est subdivisé en niveaux de traitement:
   ╓─── Traitement(2): modification (ou création) de l'objet
   ║
{x,y,z} coordonnées 3D
   ║
   ╟─── Traitement(1): modification de la perspective
   ║
 {U,V}  coordonnées 2D
   ║
   ╟─── Traitement(0): modification de la mise en page (layout)
   ║
 {u,v}  coordonnées pixels écran (Draw)

Selon le type de l'action interactive, on ne refait que les calculs nécessaires.

Liens:
Coordonnées cartésiennes , Matrice de rotation
Perspective conique

Bonne lecture ...

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.