  02/02/1997 

             
                  COMMENT PROGRAMMER UN TUNNEL EN 3D ?       
             
                       ... Wondy ... ZEN ...


   Et zou ! Voili-voil un p'tit article pour les coders en herbe !
   Bon c'est le premier article que j'cris concernant un effet...
   Je vais essayer d'tre clair, mais je vous conseille de bien suivre
   parce que j'ai pas l'intention de rpter 50 fois les mmes choses...
   J'ai pas que a  foutre non plus ... ;)

   Bon pour commencer vous avez besoin de 128ko pour les prcalculs...
   Check... ok.

   Ensuite, une jolie image en 256x256 pour la texture du tunnel...
   Check... ok.

   Arf... c'est bien cool tout a, mais je ressens une lgre impatience
   dans l'assistance, l... Venons-en aux faits...

   Bon voyons d'abord comment reprsenter un point 3d sur un cran (en 2d).

   Vous vous souvenez de Thals ? Check... ok.
   Observez la figure ci-dessous :

                  / 
                 /      X,Y,Z = Coordonnes 3d du point
                /   
               /        Xp,Yp = Coordonnes du point projet sur l'cran
              /     
             /          D = Distance oeil-ecran
            /       
           /           P = Plan de projection, ici l'cran.
          /       
         /        
        /          
       /    Yp     Y
      /            
     /            
    /             
   /              
   
    <--D--> P <--Z-->


      Donc suivant Thals, on peut dduire que

         Yp       D
        ----- = -----      Check.. ok.
         Y       D+Z

      C'est  dire (en transposant) :

         Yp      Y
        ---- = -----      Check... ok.
         D      D+Z

     Bon si on simplifie (en multipliant par D) :

               Y*D
         Yp = ------     Check... ok.
               D+Z

    On obtient l'ordonne du point sur l'cran !
    Et voil ! De mme pour calculer l'abscisse du point sur l'cran,
    on fait :
               X*D
         Xp = -----     Check... ok.
               D+Z

   Well en pratique, on peut enlever le D du diviseur...
   Donc
              Y*D                   X*D
        Yp = -----      et    Xp = -----
               Z                     Z

   C'est suffisant pour notre effet de tunnel, et a marche  peu prs
   bien... :)

  Il vous reste  savoir encore deux-trois trucs en trigonomtrie...
  En fait, un tunnel en 3d est juste une infinit de cercles les uns aprs
  les autres.  Notre problme est donc de savoir trouver les coordonnes d'un
  point par rapport au centre d'un cercle.
  Mattez un peu le schma ci-dessous...

     \                  c = rayon du cercle
      \                 a = coordonne y du point
       \ c              b = coordonne x du point
        \           alpha = angle du point dans le cercle
   a     \
          \
           \
       alpha\
     
        b

  Bon tout le monde sait que

      cos(alpha) = b/c
  et  sin(alpha) = a/c       Check... ok.

  Soit en transposant :

      c * cos(alpha) = b
  et  c * sin(alpha) = a         Check... ok.

  Donc dans notre cas :

      x = cos(alpha) * rayon
      y = sin(alpha) * rayon

  Check... ok.
  Ca y est, vous savez  peu prs tout pour pouvoir mettre notre tunnel
  en quation...

  On pose les constantes R et D qui sont respectivement le rayon du tunnel
  et la distance entre l'oeil et l'cran. C'est vous qui dterminez ces
  valeurs, mais je pense qu'un rayon de 100 et une distance de 50 rendent
  assez bien. Ceci dit, amusez-vous  mettre les nombres que vous voulez !

  Avec tout ce qu'on a vu jusqu' maintenant, je pense que vous n'aurez pas
  de mal  comprendre que les coordonnes 2D d'un point par rapport au centre
  de notre tunnel sont :

           COS(alpha) * R * D
     Xp = ---------------------      (coordonne X sur l'cran)
                   Z

           SIN(alpha) * R * D
     Yp = ----------------------     (coordonne Y sur l'cran)
                  Z

  Check... ok.
  Aaah ! nous touchons au but ! Il nous manque plus que le alpha et le Z...

  Well, il suffit de transposer les quations :

       COS(alpha)*R*D
  Xp = --------------       on multiplie par Z...
            Z


  Xp*Z = COS(alpha)*R*D    ...et on divise par Xp


                      
                     COS(alpha)*R*D                 SIN(alpha)*R*D    
      Donc :    Z =  --------------       ou   Z = ----------------   
                           Xp                            Yp           
                      

  Check... ok.
  Et pour l'angle alpha, bah on vient de voir que :

       COS(alpha)*R*D       SIN(alpha)*R*D
      ----------------  =  ----------------
            Xp                   Yp

  Donc :

         COS(alpha)            SIN(alpha)
        ------------    =  ----------------
            Xp                    Yp


         SIN(alpha)             Yp
        ------------    =  ---------------
         COS(alpha)             Xp


  Donc TAN(alpha) = Yp/Xp     Check... ok.

               
                                       
      Soit :    alpha = ATAN( Yp/Xp )  
                                       
               

  Et hop !

 Voil, donc maintenant nous savons calculer, pour chaque point du tunnel,
 sa profondeur et son angle. Etudions maintenant le mapping...

 Le but est d'arriver  "coller" notre image 256x256 sur les murs du tunnel.
 Well, je considre que vous codez dans le mode MCGA 320x200/256c...

 Vous allez aller de -160  160 pour les X
               et de -100  100 pour les Y
 (car le centre de notre tunnel se trouve au centre de l'cran...)

 Et pour chaque point, vous allez calculer son angle :

          alpha = ATAN(Y/X)

 Quand vous calculez a, la fonction Arc tangeante de votre langage prfr
 va vous donner le rsultat TRES prcisment. Mais nous, on a juste besoin de
 256 angles (vous verrez pourquoi apres...)
 Donc il faut convertir le rsultat (qui est donn en radians) en un angle
 allant de 0  256... Bah, simple :

         alpha = ATAN(Y/X)*(256/2)*PI     Check... ok.

 Vous calculez a pour chaque point et vous stockez les valeurs dans une
 table de 64ko, que vous avez allou prcdemment...

 Vous faites de mme pour les profondeurs...
 De -160  160 pour les x, et de -100  100 pour les y, vous calculez pour
 chaque point :
               COS(alpha)*R*D
          Z =  --------------
                    X

 Comme vous venez de calculer l'angle alpha, no problem !
 Bon vous rangez les profondeurs dans une autre table de 64ko...

 Ben maintenant, pour coller notre image au tunnel, il suffit de rflchir
 un peu (ouh la la, dur...) :

 L'angle du point dans le cercle nous donne en fait la coordonne X du point
 de la texture  afficher (c'est pour a qu'on a besoin que des angles de 0 
 256...)
 Et sa profondeur nous donne en fait la coordonne Y dans l'image de texture.
 Tout simplement !

 En incrmentant la coordonne Y, on fera avancer le tunnel. Check... ok.
 Et en incrmentant la coordonne X, on le fera tourner. Check... ok.
 AAAAAAHHHH TOUT S'ECLAIRE !!!! :)

 Donc il n'y a plus qu' afficher le tunnel, de le faire avancer et de le
 faire tourner. Et voil ! Notre super effecto de tunnel (!FAST!) est
 ralis !

 Un exemple en C :

  do
  {
   for(y=0;y<199;y++)
   for(x=0;x<319;x++)
   {
     texture_x = (angles[x+y*320]+x_adder) & 255;
     texture_y = (profondeurs[x+y*320]+y_adder) & 255;
     video_screen[x+y*320] = texture_map[texture_x+texture_y*256];
   }
   x_adder = x_adder + 2 ;
   y_adder = y_adder + 4 ;
  }
  while(!kbhit())


 -  ANGLES et PROFONDEURS sont les tableaux des valeurs prcalcules.
 -  TEXTURE_MAP est le tableau qui contient l'image de texture.
 -  VIDEO_SCREEN est l'cran ou le buffer o afficher le tunnel.
 -  X_ADDER est la variable qui permet de faire tourner le tunnel.
 -  Y_ADDER est la variable qui permet de faire avancer le tunnel.


 Et voil, ENJOY IT !!

 !! ATTENTION !!
    Il peut y avoir des problemes avec la fonction Arc Tangeante des langages
    volus :((
    En C, par exemple, n'utilisez pas  atan(y/x);
                                 mais  atan2(y,x);

    En pascal, la fonction atan2 n'existe pas, donc vous devez calculer
     le premier quart et construire les autres parties de la table par
     symtrie par rapport au point central.
    Baf... C rulezzz :)


 Donc voil bon.
 C'est fini pour aujourd'hui. (OOOOOOOHHHHH)
 Mais je reviendrai ! (AAAAAAAAHHHHHH)

 Pour ceux qui ont rien compris : recommencez depuis le dbut de ce fichier
  et allez-y patiemment (la persvrance est une vertu)

 Pour ceux qui veulent me contacter (on sait jamais...)
  Ben mon snail mail c'est
       WONDY / Zen
       DERRIER Pierre
       267, Rue St Pierre
       73300 St Jean-de-Maurienne

  Sinon vous pouvez me joindre par minitel (suXX da money...)
  sur le 3615 RTEL ou 3614 RTEL2 en bote--lettre "WONDY KAOS"

  n'oublier pas non plus le WHQ de mon groupe ZEN:

  EQUALIZER BBS  :   01.45251923  et  01.45251131

 Allez a++ les coders fous :))

 ...WondY...ZEN...







