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 répéter 50 fois les mêmes choses... J'ai pas que ça à foutre non plus ... ;) Bon pour commencer vous avez besoin de 128ko pour les précalculs... 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 légère impatience dans l'assistance, là... Venons-en aux faits... Bon voyons d'abord comment représenter un point 3d sur un écran (en 2d). Vous vous souvenez de Thalès ? Check... ok. Observez la figure ci-dessous : / |^ / || X,Y,Z = Coordonnées 3d du point / || / || Xp,Yp = Coordonnées du point projeté sur l'écran / || / || D = Distance oeil-ecran / || / ^ || P = Plan de projection, ici l'écran. / || || / || || / | | / |Yp |Y / | | / || || / || || / |V || ---------+-------'V <--D--> P <--Z--> Donc suivant Thalès, on peut déduire 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'ordonnée du point sur l'écran ! Et voilà ! De même 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 près bien... :) Il vous reste à savoir encore deux-trois trucs en trigonométrie... En fait, un tunnel en 3d est juste une infinité de cercles les uns après les autres. Notre problème est donc de savoir trouver les coordonnées d'un point par rapport au centre d'un cercle. Mattez un peu le schéma ci-dessous... |\ c = rayon du cercle | \ a = coordonnée y du point | \ c b = coordonnée 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 près 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 déterminez 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 coordonnées 2D d'un point par rapport au centre de notre tunnel sont : COS(alpha) * R * D Xp = --------------------- (coordonnée X sur l'écran) Z SIN(alpha) * R * D Yp = ---------------------- (coordonnée 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 considère 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 préféré va vous donner le résultat TRES précisément. Mais nous, on a juste besoin de 256 angles (vous verrez pourquoi apres...) Donc il faut convertir le résultat (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é précédemment... Vous faites de même 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 réfléchir un peu (ouh la la, dur...) : L'angle du point dans le cercle nous donne en fait la coordonnée 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 coordonnée Y dans l'image de texture. Tout simplement ! En incrémentant la coordonnée Y, on fera avancer le tunnel. Check... ok. Et en incrémentant la coordonnée 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 réalisé ! 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 précalculées. - 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 évolués :(( 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 symétrie 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 début de ce fichier et allez-y patiemment (la persévérance 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 boîte-à-lettre "WONDY" ou par e-mail : pderrier@icor.fr ou par tel (si c'est pas occupé ;) : +33-(0)4-795-984-30 Vous pouvez aussi venir voir la Zen'S HomE SwEet Page : http://www.citeweb.net/zenpage Allez a++ les coders fous :)) ...WondY...ZEN...