{----------------------------------------------------------------------} { NOTE D'ALLERGY : CE FICHIER PEUT ETRE ENREGISTRE ET RENOMME EN .PAS } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { J.M. SOLER, (COBALT) } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Dans le détail voila ce que vous trouverez dans ce qui suit: } { } { A/ Mobiles apparents. } { B/ Présentation des paramètres } { du logiciel 'Model6'. } { C/ mobiles cachés. } { } { 1 AFFICHER. } { } { 1.1 LES DEUX ESPACES. } { 1.1.1 2D, l'écran. } { 1.1.2 3D, l'espace derrière l'écran. } { } { 1.2 VOIR. } { 1.2.1 Images VIRTUELLES. } { - optique ? } { - mécanique ? } { - philosophique ? } { 1.2.2 NOTION de point de vue. } { 1.2.2.1 Déterminer le point de vision } { - projection parallèle } { - projection orthogonale } { - projection conique } { - le borgne } { 1.2.2.2 Anaglyphe et vision binoculaire } { } { 1.3 CONSTRUCTION LEGITIME: } { Perspective, Equations et un } { peu d'histoire. } { - portique (quand il faudrait } { dire "fenêtrique"). } { - rayon visuel et bout de ficelle. } { - Albrecht Dürer et les machines } { à dessiner. } { 1.3.1 Schéma du portique } { 1.3.2 Schéma d'une projection 3D>2D dans } { le plan XZ } { ("on voit à l'évidence ...", 1ière partie) } { 1.3.3 Procédure TRANSFERT_ECRAN } { } { 1.4 TRAITEMENT } { 1.4.1 Un peu de rangement: optimiser l'utilisation } { de la mémoire. } { ("on voit à l'évidence ...", 2nd partie) } { 1.4.2 Objet graphique de base } { 1.4.3 Grille de points 3d } { 1.4.4 tableau de triangles } { procedure init_mem } { procedure lib_mem; } { 1.4.5 Equation de la sphère } { 1.4.5.1 Variables diverses } { 1.4.5.2 Variation sur la morphologie sphérique, } { Des patatoïdes. } { } { 1.5 Masquer les faces cachées } { 1.5.1 Tester la visibilité } { 1.5.1.0 Fil de fer } { 1.5.1.1 Faces cachées façon RIXED. } { 1.5.1.2 Pourquoi se compliquer la vie ? } { 1.5.2 Transposer en projection orthogonale } { 1.5.3 Trier avec des bulles } { 1.5.3.1 z-maximal, somme des 'z'. } { 1.5.3.2 tri } { 1.5.3.3 Q-sort } { 1.5.4 Caviarder lourdement } { 1.5.4.1 rappel des touches de commandes } { -'x','y','z','c','p','q','s' } { } { 1.6 Animer, faire varier les angles de vue } { } { 2 SORTIE de données brutes pour POV. } { } { 3 CREUSER LA DOC. } { } { (Ce sommaire est un peu long mais au moins on pourra retrouver } { facilement les parties les plus intéressantes.) } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { A/ MOBILES APPARENTS } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Dans le rep 2 un lecteur ( le nom/pseudo m'échappe) se demandait } { comment dessiner une sphère, sous-entendu:avec un effet réaliste } { de perspective. } { Il aurait été facile de le renvoyer au programme de Hans } { Trapp dans pascalissime 43 de novembre/décembre 1990. Mais il faut } { reconnaître qu'il s'agit d'une méthode (dans son coté algébrique) } { effroyablement longue. Les méthodes exposées ici ne sont pas } { particulièrement rapides, mais elles ont l 'avantage d'être } { efficaces dans la plupart des cas, même pour certains volumes } { concaves et de fournir un fichier texte qui pourra être } { traité par logiciel de rendu d'images comme persistance of vision. } { } { } { Voici donc un programme en pascal qui permet de visualiser une } { sphère (ou un objet dérivé de la sphère car il est très facile de } { la transformer en modifiant un peu les équations que l'on trouvera } { plus loin). } { } { J'entends déjà la critique monter:" ENCORE un programme que } { n'importe quel abruti d'autodidacte va pouvoir tripatouiller et } { comprendre, en un mot : ripper (clin d'oeil à la "scène" quand on } { va parler de scénographie). En pascal, qui plus est, pas la } { moindre instruction en assembleur pour élever les esprits } { encroûtés de la plèbes des programmeurs en herbe au zen de la } { machine, et, certainement par provocation pure: copieusement } { documenté. } { } { Ce n'est même pas un véritable article, cette forme bâtarde ne } { s'est vue nulle part! } { } { Quelle trahison de l'élite éditoriale du reporter!" } { } { Désolé mais je suis plasticien de formation et j'ai besoin } { de voir les choses se produire devant moi au fur à mesure que } { je les forme/qu'elles se forment et qu'elles me forment (je suis } { moi aussi un cochon d'autodidacte). } { } { Vous m'excuserez donc d'utiliser un programme documenté, mais } { j'avais besoin de mettre à l'épreuve au plus vite ce que je } { racontais. Et surtout d'y voir clair (jeu de mots culturel que } { l'honorable lecteur ne pourra comprendre qu'après avoir lu ce } { texte dans sa totalité). } { } { Mais...n'attendez pas de cette présentation qu'elle vous donne } { toutes les astuces pour construire des univers "virtuels" (il } { faudra définir ce mot). Il s'agit simplement de répondre à une } { demande en se faisant plaisir. } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { B/ Présentation des paramètres en ligne de commande. } { à lire impérativement si l'on tient à faire un essai } { avant de comprendre quoi que ce soit. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { les paramètres en ligne de commande possibles : } { } { (1)[(2>)l(<60)] (2)[(2>)c(<60)] (3)[raw,0] (4)[anim] } { (5)[nom de fichier avec extension'.raw'] } { } { 1/ l entre 2 et 60 , lignes. } { 2/ c entre 2 et 60 , colonnes. } { 3/ RAW ou 0, RAW valeurs en virgule fixe: 9 réels. } { pour obtenir un fichier de valeurs brutes sous } { la forme de triplets de réels correspondant aux } { sommets "orientés" des triangles. } { 4/ ANIM permet de faire basculer la forme suivant les } { axes xyz fonctionne si 3/= 0 ou 3/=raw } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { C/ MOBILES CACHES } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { L'idée d'un modeleur me trotte dans la tête depuis 1992. } { } { j'ai réalisé un petit truc, aux alentours du mois de mars, } { qui ressemblait beaucoup à "Worms" mais en beaucoup plus convivial } { et avec beaucoup moins de possibilités au départ. J'en ai envoyé une} { copie à Chip en lui demandant ce qu'il en pensait et ça s'est perdu } { dans les limbes des mois d'été ( Worms est un utilitaire pour pov, } { polyray et vivid qui permet de disposer des sphères dans l'espace). } { } { Ce n'est pas parce que l'on a abandonné un projet que le problème } { qui l'a motivé est résolu. Je reste toujours déçu par les modeleurs } { actuels du marché . Aucun ne permet de retrouver les sensations du } { sculpteurs, la véritable "plasticité" du modelage. } { } { Modeler réellement un plan de triangles et non pas assembler un lot } { de primitives graphiques comme la sphère, le cube, etc. } { } { l'idée: initialiser un mur de triangles et agir sur lui comme un } { sculpteur qui modèle de la glaise en appuyant,en tirant,avec des } { outils/gabarits pour donner des formes, en laissant à "l'intuition" } { toute sa liberté ( 'intuition', au sens de "contact avec"). } { } { Triangle est l'objet de base sur lequel porte toutes les } { modifications. c'est aussi la forme sous laquelle le logiciel } { renvoie des informations en mode texte au format RAW pour être } { traitée par une moulinette qui les transforme en triangles lissés } { ou "Smooth triangles" traité par POV 2.2 } { } { Modification effectuées à l'aide du clavier.... } { ...et en essayant de réinventer le moins possible } { la roue en matière de fonction graphique de base: } {----------------------------------------------------------------------} program modele_triangle_2; uses graph,crt; {----------------------------------------------------------------------} { 1.1 AFFICHER. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.1.1 LES DEUX ESPACES } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.1.1.1 2D, l'écran } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Xv et Yv sont les coordonnées d'affichage VIDEO. } {----------------------------------------------------------------------} type Coord2D = RECORD xv,yv:INTEGER; END; {----------------------------------------------------------------------} { 1.1.1.2 3D, l'espace derrière l'écran } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Pour qu'elle ait un peu d'épaisseur la forme doit apparaître comme } { si elle se trouvait dans l'espace "réel",avec ses trois dimensions } { les triangles qui la composent doivent être initialisés selon les } { trois axes x,y,z } { y } { | z } { | / } { | / } { | / } { |/___________ x } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { X,Y,Z sont les coordonnées de travail dans l'espace 3D. } {----------------------------------------------------------------------} Coord3D = RECORD x,y,z:real; END; {----------------------------------------------------------------------} { 1.2. VOIR } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.2.1 images VIRTUELLES } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { En essayant de faire un peu le point... } { } { Pour l'instant nous n'avons pas encore pu nous débarrasser de } { l'élément le plus pénible de la mise en scène 3D: L'être humain. } { Avant de se présenter comme un problème technique la 3D est un } { problème de perception sensorielle. Désolé de verser dans } { l'obscénité mais on est obligé de référencer l'oeil (donc le } { corps de chair et de sang); j'aurais pu vous éviter ce dur } { rappel en ne parlant que de sa structure en "camera obscura", } { et rester dans le domaine propret de la photographie, } { mais nous aurions perdu la possibilité d'expliquer en quoi les } { images que nous obtiendrons sont réellement "virtuelles". } { Au sens "optique" de la chose la seule image "virtuelle" qui } { existe "réellement" se trouve sur la rétine de l'observateur. } { Sur l'écran l'image n'est "virtuelle" qu'au sens philosophique } { et elle ne trouvera sa réalisation qu'en présence d'un } { spectateur. } { } { Vous me suivez? } { } { Ainsi pour créer cette image philosophiquement virtuelle nous } { avons besoin d'imaginer un observateur et de le modéliser pour } { le faire apparaître dans quelques équations simples. } { Et cet observateur fictif doit croire que l'écran est une } { fenêtre transparente derrière laquelle se trouve l'objet } { représenté. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.2.2 NOTION de POINT de VUE } {----------------------------------------------------------------------} {------------------------------------------} { 1.2.2.1 Déterminer le point de vision: } {----------------------------------------- } {------------------------------------------} { Les points et lignes seront affichés en } { perspective linéaire ou perspective } { des peintres, qui suppose un observateur } { à une distance finie de la scène. } { ----------------------- } { Projection parallèle : } { ----------------------- } { Une perspective axonométrique ou "ca- } { valière" imagine l'observateur situé à } { l'infini et les lignes qui constituent } { les objets sont parallèles... } { -------------------- } { Projection conique: } { -------------------- } { ...alors que la } { perception visuelle nous donne l'impres- } { sion qu'elles se rapprochent. } { } { La seule bonne question: } { à quelle distance de l'écran se } { trouvent vos yeux ? } { Question subsidiaire: } { comment transformer cette dimension } { en valeur/pixel ? } { } {------------------------------------------} {------------------------------------------} { 1.2.2.2 anaglyphe et vision binoculaire } {------------------------------------------} {------------------------------------------} { Un lecteur attentif aura déjà remarqué } { qu'il n'est question que d'UN point de } { vue et que l'image n'est "virtuelle" } { qu'au fond de "l'oeil". } { } { Mais que fait-on de l'autre oeil? } { } { On l'oublie...Et on tache de faire } { croire que l'image "sur" l'écran n'est } { pas plate: affaire de convention. C'est } { fou ce que l'on peut faire admettre à } { notre cerveau, d'ailleurs voir en } { perspective c'est toute une éducation. } { ...Ou bien...On s'équipe un peu: une } { paire de lunettes avec filtres,bleu et } { rouge; on multiplie par deux tous les } { traitements puisqu'il faut prendre } { en compte deux points de vue légèrement } { décalés dans leur coordonnées X (plutôt } { gênant pour la simplicité des calculs, } { l'alternative étant trop lourde à } { gérer). } { } { Ce qui revient, en fin de compte, à } { afficher deux images dont chacune ne } { sera perçue que par l'un des deux yeux. } {------------------------------------------} {------------------------------------------} { Projection sphérique? } {------------------------------------------} {------------------------------------------} { Par ailleurs, puisque nous sommes "dans } { l'oeil" autant prendre en compte } { l'aspect sphérique du globe occulaire, } { l'image virtuelle sur la rétine n'est } { pas "plate" comme dans un appareil photo} { Cette courbure déforme les lignes } { droites qui sont "vues" légèrement } { arrondie. Cependant le cerveau prend } { en charge le "redressement" de ces } { lignes . } { Les amateurs de jeux 3d, Doom par } { exemple, auront certainement remarqué } { que ces même lignes ont tendance à } { s'incurver vers l'extérieur. } {------------------------------------------} { -----------------------------------------} { Les coordonnées 3d de l'observateur sont } { conservées dans la variable PV de type } { coord3d } {------------------------------------------} var point,pv:coord3d; gd,gm:integer; procedure calculpoint_vision(var pv:coord3d); begin {---------------------------------} pv.z:=-1360; { Eloignement vers l'arrière. } pv.y:=0; { Décalage vers le haut ou le bas.} pv.x:=0; { Décalage à droite ou à gauche. } end; {---------------------------------} {----------------------------------------------------------------------} { 1.3 Affiche à l'écran en perspective linéaire... } { (avec un peu d'histoire). } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { le problème de l'affichage de points 3d en 2d est à la portée d'un } { bon élève de collège : c'est tout simplement une question de } { proportionnalité. } { } { soit un point _ dans l'espace, sa localisation sur l'écran va } { se faire à partir de la localisation du point de vision, ou } { "point de vue" qui est lui-même en coordonnées 3d...On imagine } { un "rayon visuel" qui se propagerait de l'objet jusqu'à l'oeil } { de l'observateur situé au point de vision. Ce rayon traverse } { l'écran. Le point 2D est le point d'intersection écran/rayon. } { Cette technique n'a rien de neuf. On peut même dire que les } { premiers fabriquants d'images se sont intéressés à elle (un } { domaine que l'on nomme la skiagraphie, art de la mise en scène, } { elle n'est même pas enfantée par la technique pure, que je sache } { les grecs de l'antiquité n'avaient pas beaucoup de goût pour la } { technique pratique et manuelle, mais par les contingences } { théâtrales). } { } { Albrecht Durer, au XVIième siècle, pour ne citer que lui, imagina} { quelques machines à dessiner: le principe est toujours } { le même: matérialiser le "rayon visuel" par une ficelle et son } { interception par le plan d'une fenêtre qui à l'époque n'avait } { rien de virtuel et se nommait un "portique". Les prémices de la } { géométrie descriptive et projective (quelques siècles pendant } { lesquels la perception de l'espace s'est effacée devant sa } { représentation technique, mais désuète cependant: l'apparition } { du romantisme et de la photographie amenèrent son abandon. Des } { représentations traditionnelles, le XX ième siècle, n'a gardé } { qu'une vague mémoire, les représentations axonométriques } { étant largement plus pratiques aux architectes et autres } { artisans/techniciens; et la Perspective, qui signifie d'ailleurs } { "voir clairement", n'est remise à "l'honneur" que par les } { fabriquants de voiture lorsque monsieur Bezier, le fameux } { inventeur des courbes, leur permet d'avoir des rendus rapides } { et lissés pour modéliser les carrosseries ( on excusera cet } { audacieux raccourci qui oublie au passage la bd et les arts } { appliqués, les publicités BALSEN réalisées par Peter Foldès) . } { } { Aujourd'hui nous dégustons du "virtuel" à toutes les sauces, } { et ce que je viens de vous raconter là n'a rien à voir avec } { l'informatique, me direz-vous... } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.3.1 schéma du portique } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { |\ écran/portique } { | \ } { | \ } { | \ } { | |\ } { | | \ } { | | \ } { |\ | \ } { | \ | \ } { point de vue | \ | \ } { X _________________|______\Y __________|________ X Objet } { | | | | | } { | \ | | | } { | \ | | | } { | \ | | | } { |_________________________\| __________|_________| } { \ | } { \ | } { \ | } { \ | } { \ | } { \| } { } { y= projection de l'objet sur l'écran comme le verrait l'observateur } { à partir du point de vue (ou point de vision). } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.3.2 schéma d'une projection 3D>2D dans le plan XZ } { ("on voit à l'évidence ...", 1ière partie) } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { X point de vue (x,z) } { / | } { / | -z } { / | | } { / | | } { point _.2d / | | } { | / | | 0 } { x <-----------x-------------X---|----- -x écran } { / | | } { / | | } { / | | } { _-> x---------------------x | } { | z } { } { que l'on pourrait traduire par (pv, point de vue): } { _.x.2d= pv.x+(pv.x-_.x)*pv.z/(_.z-pv.z) } { tout à fait équivalent dans le cas de y, } { _.y.2d= pv.y+(pv.y-_.y)*pv.z/(_.z-pv.z) } { } { On se facilite la vie en faisant coïncider pv.x et pv.y avec les } { axes correspondants pv.x:=0 et pv.y:=0 } { } { Et quelques mots magiques comme "on voit à l'évidence que" } { permettent de les réduire encore à leur plus simple expression } { } { _.x.2d= _.x*pv.z/p.z } { _.y.2d= _.y*pv.z/p.z } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Pour affiner un peu le cadre de l'image (surtout pour ne pas } { en perdre 75 %) il vaut mieux ajouter les valeurs du centre de } { l'écran: } {----------------------------------------------------------------------} const gmxx=320; gmxy=240; {-----------} { 1.3.3 } procedure transfert_ecran(p,pv:coord3d; {-----------} var p_ec:coord2d); begin p.z:=pv.z/(p.z+1500); p_ec.xv:=round(-p.x*p.z)+gmxx; p_ec.yv:=round(-p.y*p.z)+gmxy; end; {----------------------------------------------------------------------} { 1.4 TRAITEMENT } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.4.1 Faisons un peu de Rangement: optimiser l'utilisation } { de la mémoire. Le système D avant la 3D. } { ("on voit à l'évidence que...",2nd partie) } {----------------------------------------------------------------------} {--------------------------------------------------------------------} { revenons un peu à nos triangles... } { } { Premièr jet: on crée un tableau de triangles ordonnés de 1 à n. } { Au maximum on range 64500 / 3*3*6 triangles par segment de } { mémoire. Chaque sommet du triangle étant repéré par coordonnées } { 3D sous la forme de 3 "reals", soit 3*3*6 octets . On } { ne dépasse pas 1194 unités. Un peu court: une nappe carrée de } { 34 triangles de cotés. } { } { Après réflexion on arrive à une organisation plus rentable. } { } { Ils seront rangés par lignes de couple. Au départ coïncidants } { avec un carré. Les modifications de localisation d'un point } { a __________c__________ e affectent tous les triangles } { I\ \ | | / /| auxquels ce point appartient. } { | \ \ 2 | | 3 / / | Dans le cas d'un déplacement } { | \ \ | | / / | du point 'd' les triangles } { | 1 \ \ | | / / 4 | 1,2,3,4,5 et 8 sont transformés. } { |________\ \| |/ /________| } { b __________d__________ f questions: comment le logiciel } { I\ \ | | / /| sait-il que ce point appartient } { | \ \ 8 | | 5 / / | à ces 6 triangles? } { | \ \ | | / / | -le concept de triangle } { | 7 \ \ | | / / 6 | et la localisation des points le } { |________\ \| |/ /________| constituant doivent-ils être } { i h g liés dans un même tableau? } { } { Décrire le triangle par ses coordonnées 3d revient à répéter } { jusqu'à six fois les coordonnées de certains points (18*6 octets) } { Il est plus avantageux de travailler sur deux tableaux séparés } { les coordonnées 3d pouvant être rangées sous la forme de lignes et} { de colonnes les sommets des triangles étant/renvoyant à des } { emplacements dans ce tableau: } { } { 1 2 3 4 t[1]=(a,b,c) } { t[2]=(a,c,d) } { 1 a c e . ... } { } { 2 b d f . t[1] vaut 3*2 octets. 65400 div 6 =10900 } { } { 3 i h g . Sur un bloc mémoire de 65400 octets } { on range 10900 triangles. } { 4 . . . . Le problème se pose de savoir combien de } { points sont nécessaires pour repérer ces } { 5 . . formes. } { } { On pose qu'il y aura moitié moins de quadrilatères que de } { triangles (10900/2= 5450. soit racine(5450)*colonne+1 par } { racine(5450*ligne)+1: 73.8249*73.842 73*73= 5329. Trop gros, } { dépasse largement le bloc maximum de points 3638 donne } { 59 colonnes par 59 lignes * 2 = 6962 triangles. } { } {--------------------------------------------------------------------} {--------------------------------------} { Pour se repérer dans un tableau } { dois-je préciser que l=ligne } { et c=colonne? } {--------------------------------------} Type Repere =record l,c:byte end; {----------------------------------------------------------------------} { 1.4.2 Objet graphique de base: } {----------------------------------------------------------------------} {----------------------------------------} { l et c permettent de retrouver } { un point 3d dans le tableau. } { Il en faut trois paires pour } { reconstituer un triangle... } {----------------------------------------} Triangle = ARRAY[1..3] of repere; {----------------------------------------------------------------------} { 1.4.3 Grille de points 3d: } {----------------------------------------------------------------------} {----------------------------------------} { Le tableau de points 3d dans } { lequel l et c permettront de } { circuler... } {----------------------------------------} GrillePtr = ^grille; Grille = ARRAY[1..60,1..60] of Coord3D; {----------------------------------------------------------------------} { 1.4.4 tableau de triangles } {----------------------------------------------------------------------} const n_elem = 4962; type tab_tptr = ^tab_triangle; tab_triangle = array[1..n_elem] of triangle; var gril_ : grilleptr; tab_t, tab_t1 : tab_tptr; {----------------------------------------------------------------------} { 1.4.5 EQUATION DE LA SPHERE } {----------------------------------------------------------------------} {--------------------------------------------} { Pour dessiner une sphère il nous faut } { son équation et de préférence :paramètrée.} { L'équation de la sphère telle que: } { } { x²+y²+z²-1=0 } { } { nous obligerait à essayer toutes les } { valeurs possibles de x,y,z et à ne } { garder que celles qui donnent une } { solution, il est facile d'imaginer que ca } { risque d'être long ....même en assembleur.} {--------------------------------------------} {-----------------------------------------------------------------------} { Or donc l'équation paramétrée de la sphère: } { } { x:=cos(u)*cos(v) } { y:=sin(v)*cos(u) } { z:=sin(u) } { } { u et v en radians et variant pour u de -pi/2 à pi/2 et v de 0 à } { 2*pi. L'idée essentielle est de garder une des deux valeurs v et } { u constante et de faire varier l'autre dans les limites } { } { Imaginons u=-pi/2: } { cos(u):=0; } { sin(u):=-1; } { cela nous donne x:=cos(v)*0= 0 } { y:=sin(v)*0= 0,quelque soit v } { y z=-1 } { } { | z Graphiquement les coordonnées } { | / d'un unique et simple point } { | / (0,0,-1). } { | / } { ___ ______|/______ ___ x } { /| } { / | } { ici---> X | } { / | } { | } { | } { Pour u=0, cos(u)=1 et sin(u)=0, z= 0 et x=cos(v)*1 et y=sin(v)*1 } { exactement l'équation paramétrée d'un cercle dans le plan } { vertical pour peu qu'on fasse varier v de 0 à 2*pi. Une erreur } { ridicule consisterait à choisir un pas} { y de variation trop proche de pi. A } { titre d'exercice essayez d'imaginer } { | z le résultat. c'est la raison pour } { _|__ / laquelle le programme d'exemple qui } { / | X s'imbrique dans cette article } { / | / \ n'acceptera pas de valeurs inférieures} { ___|______|/______|___ x pour le nombre de lignes et colonnes } { | /| | dans lesquelles seront rangés tous } { \ / | / les résultats. } { X __|__ / } { / | } { | } {-----------------------------------------------------------------------} {-----------------------------------------------------------------------} { 1.4.5.1 Variables diverses } {-----------------------------------------------------------------------} {-----------------------------------------------------------------------} { gril_ contient les résultats de ces opérations. } {-----------------------------------------------------------------------} var i,j:byte; {-----------------------------------------------} pec:coord2d; { Pour afficher en 2d à l'écran } max,min, {---* : les points les plus éloignés. } tot,moy:coord3d; { : le point moyen, qui peut être utile si } { on veut ensuite déplacer et manipuler } { des objets "plastiques" sous Pov avec } { commandes ROTATE et TRANSALTE. } u,ic,jc,tn:word; {---* } v,e,w:coord3d; { Pour traiter les coordonnées 3d dans } { triangles et les traduire en 2d et tracer } { avec la procedure drawpoly } vi,ei,wi:coord2d; {-----------------------------------------------} tn2:word; ch:char; {----------------------------------------------------------------------} { } { La procedure init_grille va effectuer plusieurs opérations dont les } { seules vraiment importantes sont de faire tourner deux boucles. La } { première va initialiser une ligne d'entrée dans le tableau grill_ } { et fournir la valeur en radians de u. Toutes les cellules de cette} { ligne contiendrons des valeurs identiques pour z. } { } { La seconde boucle fournit la valeur de v et fait tourner les } { colonnes . } {----------------------------------------------------------------------} procedure init_grille(ic,jc,tn:word); var ud,vd,cosu,sinu,cosv,sinv,r:real; u:word; t:coord3d; alpc,alps,p:real; begin {----------------------------------------------} r:= getmaxy div 2; { pour centrer et ne pas dépasser la dimension } { de l'écran } {----------------------------------------------} max.x:=-10000; max.y:=-10000; max.z:=-10000; min.x:=10000; min.y:=10000; min.z:=10000; {---------------------------------} u:=0; { pour diviser tot et obtenir moy } {---------------------------------} for i:=1 to ic do begin {-----------------------------------} p:=-pi/2+pi/(ic-1)*(i-1); { i-1 car sinon la forme à ce stade } cosu:=cos(p); sinu:=sin(p);{ du projet (une sphere) n'est pas } { correctement fermée, } for j :=1 to jc do { faites un essai sans pour voir! } begin { idem pour j-1,jc et ic! } inc(u); {-----------------------------------} cosv:=cos(2*pi/(jc-1)*(j-1)); sinv:=sin(2*pi/(jc-1)*(j-1)); t.x:=cosu*cosv ; t.y:=sinv*cosu ; t.z:=sinu ; { sphère } {----------------------------------------------------------------------} { 1.4.5.1 Variations sur la morphologie de la sphère } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { Ceci dit , il est possible de s'amuser un peu en modifiant les } { équations de bases. } { } { Quelques exemples de patatoïdes: } { } { t.y:=cosu*cosv; t.z:=sinv; t.x:=sinu; ( ressemble assez à un } { oreiller } { t.y:=cosu*cosv; t.z:=sinv*cosu; t.x:=sinu/2; ( sphère aplatie } { t.y:=cosu*cosv; t.z:=sinv*cosu*cosu; t.x:=sinu;( sphère enfoncée } { t.y:=cosu*cosv;t.z:=sinv*cosu*cosv;t.x:=sinu; ( en grain d'avoine } { t.y:=cosv*cosv; t.z:=sinv*cosv*cosv; t.x:=sinu;( tuyau profilé en } { goutte d'eau } { t.y:=cosu*cosv; t.z:=sinv*cosu*(sinv-1); t.x:=sinu;(façon pois cassé } { t.y:=cosu*sinv; t.z:=sinv*cosu; t.x:=sinu; ( en crêpe } { t.y:=cosu*cosv*sinv-sinv+cosv; t.z:=sinv*cosu; t.x:=sinu; } { t.x:=cosu*(cosv-1); t.y:=sinv*cosu; t.z:=sinu; ( grain de blé } (* t.x:=cosu*cosv-sinv*sinv; t.y:=sinv*cosu*cosv; t.z:=sinu; *) {----------------------------------------------------------------------} {----------------------------------------------------------------------} { t.x:=sinv*(2*sinu/3-1); } { t.y:=sinv*cosv*sinv*cosu; } { t.z:=sinu*sinv*sinv; } { (une certaine idée de l'élégance) } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { t.x:=cosu*cosv; } { t.y:=sinv*cosu*sinu-(cosv*cosv*cosv); } { t.z:=sinu*2-(cosv*cosv*sinv); } { ( un vrai patatoïde) } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { gril_ contient les résultats de ces opérations. } {----------------------------------------------------------------------} gril_^[i,j].y:=t.Y*r; gril_^[i,j].x:=t.X*r; gril_^[i,j].z:=t.Z*r; if max.xt.x then min.x:=t.x; if min.y>t.y then min.y:=t.y; if min.z>t.z then min.z:=t.z; tot.x:=tot.x+t.x; tot.y:=tot.y+t.y; tot.z:=tot.z+t.z; end; end; moy.x:=tot.x/u; moy.y:=tot.y/u; moy.z:=tot.z/u; end; {----------------------------------------------------------------------} { Modification de la version 4: choix de la quantité de } { lignes et de colonnes } { pour les valeurs inférieures à 4 la forme est très aplatie } { et zéro plante. } {----------------------------------------------------------------------} procedure init_lig_col(var ic,jc,tn:word); var errorcode:integer; begin val(paramstr(1),ic,errorcode); val(paramstr(2),jc,errorcode); if ic>60 then begin writeln('trop de lignes: entrez nouvelle valeur < 60 !'); repeat readln(ic) until ((ic<=60) and (ic>1)); end; if ic<4 then begin writeln('pas assez de lignes!! introduisez une valeurs 2> x >60 !!'); repeat readln(ic) until ((ic<=60) and (ic>1)); end; if jc>60 then begin writeln('trop de colonne: entrez nouvelle valeur < 60 !'); repeat readln(jc) until ((jc<=60) and (jc>1)); end; if jc<4 then begin writeln('pas assez de colonnes!! introduisez une valeurs 2> x >60 !!'); repeat readln(jc) until ((jc<=60) and (jc>1)); end; {----------------------------------------------------------------------} { TN correspond au nombre de triangles qu'il est possible de créer } { avec i lignes et j colonnes de points } {----------------------------------------------------------------------} tn:=(ic-1)*(jc-1)*2; end; {----------------------------------------------------------------------} { Initialiser la table des triangles revient à } { Ranger les points des triangles dans le tableau } { en respectant l'ordre qui permettra d'en faire } { des triangles lissés: le sens inverse des } { aiguilles d'une montre. } { } { } { 1 2 3 t[1]=(a,c,d) t[8]=(d,g,f) } { t[2]=(a,d,b) } { 1 a c e t[3]=(c,f,e) } { t[4]=(c,d,f) } { 2 b d f t[5]=(b,i,h) } { t[6]=(b,h,d) } { 3 i h g t[7]=(d,h,g) } { } { La variable "i" correspond aux lignes et "j" aux colonnes. } { le point 'a' sera codé comme (1,1)... } { b=(2,1),c=(1,2),d=(2,2),etc. } {----------------------------------------------------------------------} procedure init_tab_triangle(var ic,jc,tn:word); begin u:=0; i:=1; {---------------------------------} { (i-1,j-1) } for i:=2 to ic do { a ____________ c (i,j-1)} begin { |\ \ | } for j:=2 to jc do { | \ \ | } begin { | \ \ | } if u0 then begin line(vi.xv,vi.yv,ei.xv,ei.yv); line(wi.xv,wi.yv,ei.xv,ei.yv); line(wi.xv,wi.yv,vi.xv,vi.yv); end; end; end; end; setcolor(15); end; {----------------------------------------------------------------------} { 1.5.1.2 Pourquoi se compliquer la vie ! } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Bien plus rapide de faire tourner des points que des ensembles } { de lignes. } {----------------------------------------------------------------------} procedure trace_grille(ic,jc:word); var tp:array[1..4] of pointtype; begin for i:=1 to ic do begin for j:=1 to jc do begin transfert_ecran(gril_^[i,j],pv,pec); putpixel(pec.xv,pec.yv,15); end; end; end; {----------------------------------------------------------------------} { 1.5.2 Transposer en projection orthogonale. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Mais ça m'embête un peu d'appeler la fonction transfert_ecran } { alors que je peux très bien transformer le système de projection } { conique en projection orthogonale par une série d 'équations: } { } { t.x:=d*p.x/(d-p.z) } { t.y:=d*p.y/(d-p.z) } { t.z:=d*p.z/(d-p.z) } { |\ } { avant transformation: | \ } { | \ } { | \ \,__ } { | |\ ___/' \ } { | __|/'\ \ } { |___/' | \ \ } { ____/-X\ | \ \ } { ___/' | \ | \ \ } { _----' | \ 0| \ \ } { _/_________________|______\Y __________|________ X } { \--, d | |0 | | } { \___ \ | | | } { `\___ \ | | | } { `\___ \ | | | } { `----\|_ | | } { X\`---\___ | | } { \ \|__ | } { \ | `\___ | } { \ | `\X } { \ | } { \| } { |\ } { après transformation: | \ } { | \ } { | \ } { | |\ } { | | '\ } { | | \ } { ---------------------X\------|------\-------X } { | \ | \ \ } { | \ | \ \ } { X'_________________|______\Y __________|________ X } { | | | | } { \ | | | } { \ | | | } { \ | | | } { _________________________\| __________|_________| } { \ | } { \ | } { \ | } { \ | } { \ | } { \| } { } { L'intérêt: } { Un observateur impartial reconnaîtra qu'on ne gagne pas grand chose } { en vitesse mais au moins la technique est expliquée et si quelqu'un } { de courageux veut bien se donner la peine de traiter le problème } { des faces cachées avec une méthodes plus élaborée... } { (Et surtout cela me permet d'ajouter une touche PERSONNELLE !) } { Donc: } {----------------------------------------------------------------------} var recto_verso:boolean; procedure ventre_ou_dos(var verso:boolean ; u:integer); var r0:real; begin r0:=pv.z-(gril_^[tab_t^[u][1].l,tab_t^[u][1].c].z); vi.xv:=round(gril_^[tab_t^[u][1].l,tab_t^[u][1].c].x*pv.z/r0); vi.yv:=round(gril_^[tab_t^[u][1].l,tab_t^[u][1].c].y*pv.z/r0); r0:=pv.z-(gril_^[tab_t^[u][2].l,tab_t^[u][2].c].z); ei.xv:=round(gril_^[tab_t^[u][2].l,tab_t^[u][2].c].x*pv.z/r0); ei.yv:=round(gril_^[tab_t^[u][2].l,tab_t^[u][2].c].y*pv.z/r0); r0:=pv.z-(gril_^[tab_t^[u][3].l,tab_t^[u][3].c].z); wi.xv:=round(gril_^[tab_t^[u][3].l,tab_t^[u][3].c].x*pv.z/r0); wi.yv:=round(gril_^[tab_t^[u][3].l,tab_t^[u][3].c].y*pv.z/r0); {----------------------------------------------------------------------} { le signe de N.z } {----------------------------------------------------------------------} if (vi.xv-ei.xv)*(wi.yv-ei.yv)-(wi.xv-ei.xv)*(vi.yv-ei.yv)>0 then verso := true else verso := false; end; {----------------------------------------------------------------------} { 1.5.3 Trier avec des bulles, ou sans bulle. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { 1.5.3.1 z-maximal, somme des s.z } { } { Rappelons le projet: organiser les faces de façon à } { couvrir les plus éloignées par les plus proches. } { première opération trouver la valeur s.z de chaque } { triangle. Le triangle dont la somme des valeurs z sera } { la plus grande à de forte chance d'être le plus éloigné. } { L'intérêt de cette méthode réside dans l'appel au matériel } { le plus élémentaire et dans l'absence de traitement } { géométrique complexe qui obligerait à tester des } { intersections de facettes. En un mot c'est la manière la } { plus SIMPLE ... (que je connaisse; il existerait un bouquin } { traitant du problème: I.E. Sutherland, R.F. Sproull, R.A. } { Schumacker, A Characterization of Ten Hidden-Surface } { Algorithms, ACM Computin Surveys, Vol. 6, N° 1, MARS 1974). } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Créons z_list, constitué de n_elem z_repere pour éviter un } { tas de répétitions. } {----------------------------------------------------------------------} type z_repere= record zl:real; tl:word; end; z_listptr=^z_list; z_list= array[1..n_elem] of z_repere; var z_lip:z_listptr; {----------------------------------------------------------------------} { Pour chaque triangle la somme des valeurs Z est rangée dans } { z_lip^[n].zl qui est un "real". Et numéro de triangle est rangé } { dans z_lip^[n].tl . On évite des sauts de fonctions qui } { ralentissent considérablement le traitement. Et les renvois dans } { des zones exotiques de la mémoire pendant le tri. } {----------------------------------------------------------------------} procedure add_t(t:word); var u0:word; begin for u0:=1 to t do begin z_lip^[u0].zl:=((gril_^[tab_t1^[u0][1].l,tab_t1^[u0][1].c].z)+ (gril_^[tab_t1^[u0][2].l,tab_t1^[u0][2].c].z)+ (gril_^[tab_t1^[u0][3].l,tab_t1^[u0][3].c].z)); z_lip^[u0].tl:=u0; end; end; {----------------------------------------------------------------------} { 1.5.3.2 tri à bulle } { } { seconde opération: trier. } { "bubble" sonne mieux puisqu'on s'occupe de sphère pour } { l'instant ( touche 'p' au clavier ) } {----------------------------------------------------------------------} procedure Bubble(tn2:word); var r,r1:real; bi,bj:word; zp:z_repere; begin for bi:=1 to tn2-1 do begin r:= z_lip^[bi].zl; for bj:=bi+1 to tn2 do begin r1:=z_lip^[bj].zl; if r1=ga) then begin tp:=tableau[ga]; tableau[ga]:=tableau[dr]; tableau[dr]:=tp; inc(ga); dec(dr); end; until ga>dr; if gauche's' then begin for u:=1 to tn do begin ventre_ou_dos(recto_verso,u); if recto_verso then begin inc(tn2); tab_t1^[tn2][1]:=tab_t^[u][1]; tab_t1^[tn2][2]:=tab_t^[u][2]; tab_t1^[tn2][3]:=tab_t^[u][3]; end; end; add_t(tn2); if ch = 'p' then bubble(tn2) else if ch='q' then qsort(z_lip^,1,tn2); end; if ch='s' then begin for u:=1 to tn do tab_t1^[u]:=tab_t^[u]; tn2:=tn; add_t(tn); qsort(z_lip^,1,tn); end; for u:=tn2 downto 1 do begin transfert_ecran(gril_^[tab_t1^[z_lip^[u].tl][1].l, tab_t1^[z_lip^[u].tl][1].c],pv,vi); transfert_ecran(gril_^[tab_t1^[z_lip^[u].tl][2].l, tab_t1^[z_lip^[u].tl][2].c],pv,ei); transfert_ecran(gril_^[tab_t1^[z_lip^[u].tl][3].l, tab_t1^[z_lip^[u].tl][3].c],pv,wi); tria[1]:= vi; tria[2]:= ei; tria[3]:= wi; fillpoly(3,tria); end; end; {----------------------------------------------------------------------} { 1.6 Animer : faire varier les angles de vue } {----------------------------------------------------------------------} {----------------------------------------} const cosl:real=0.994521; { Pour accélérer les rotations d'un } sinl:real=0.104528; { ensemble de points autour d'un axe. } { Les formules qui sont utilisées ne } function rotx(x,y:real):real; { font rien de plus qu'avancer de } begin { 6 malheureux degrés dans le sens de } rotx:=x*cosl-sinl*y; { la rotation choisie chaque fois qu'une } end; { touche est pressée. } {----------------------------------------} function roty(x,y:real):real; begin roty:=x*sinl+y*cosl; end; procedure rotate(x:char); var t:coord3d; begin for i:=1 to ic do for j:=1 to jc do begin t.y:=gril_^[i,j].y; t.x:=gril_^[i,j].x; t.z:=gril_^[i,j].z; case x of 'z': begin gril_^[i,j].y:=roty(t.x,t.y); gril_^[i,j].x:=rotx(t.x,t.y); end; 'y': begin gril_^[i,j].x:=rotx(t.x,t.z); gril_^[i,j].z:=roty(t.x,t.z); end; 'x': begin gril_^[i,j].y:=roty(t.z,t.y); gril_^[i,j].z:=rotx(t.z,t.y); end; end; end; end; procedure anim; begin faces_cachees:=0; trace_triangle(tn); repeat if keypressed then begin ch:=readkey; case ch of 'x','y','z': begin rotate(ch); clearviewport; trace_grille(ic,jc); end; 't' :trace_triangle(tn); '+' : begin pv.z:=pv.z-10; clearviewport; trace_grille(ic,jc); end; '-' : begin pv.z:=pv.z+10; clearviewport; trace_grille(ic,jc); end; 'c' : begin if faces_cachees<>0 then faces_cachees:=0 else faces_cachees:=1; clearviewport; trace_triangle(tn); end; 'p','q','s': trace_face_pleine(tn); end; end; until ch=#27; end; procedure init_mem; begin new(gril_); new(tab_t); new(tab_t1); new(z_lip); end; procedure lib_mem_fichier; begin dispose(z_lip); dispose(tab_t1); end; procedure lib_mem; begin if paramstr(3)='0' then lib_mem_fichier; dispose(tab_t); dispose(gril_); end; {----------------------------------------------------------------------} { 2 Sortie de données brutes pour POV } {----------------------------------------------------------------------} {------------------------------------------------------------------} { N'oublions pas que tout cela est destiné à fournir de la } { matière première à POV pour avoir un rendu d'image } { sophistiqué! } { un triangle est défini de la manière suivante dans POV: } { } (* triangle { , , } *) { } { Mais il est possible d'adoucir la forme en réalisant un } { lissage de PHONG sur chacun des triangles pour cela il } { faut associer la "direction de la forme" (c'est comme ca } { qu'on décrit le vecteur normal dans POV) à chaque sommet. } { } { smooth_triangle } (* { , , *) { , , } (* , } *) { } { } { Pour l'instant je manque un peu de documentation sur la } { manière de calculer ce vecteur normal (1) et je préfère passer } { tous les paramètres sous la forme d'un fichier texte où les } { informations paraissent comme suit: } { } { NAP1 } { -239.0 0.0 0.0 -206.9801 59.7500 103.49 -206.9801 119.5 0.0 } { -239.0 0.0 0.0 -239.0 0.0 0.0000 -206.9801 59.7500 103.4900 } { ... } { } { Ce fichier est traité par le logiciel RAW2POV qui } { se charge de trouver et d'associer les vecteurs normaux; } { il est possible aussi de lui demander de créer une caméra et } { un éclairage adapté à la forme. } { } { (1) notez que la programmation d'un produit vectoriel est } { à la portée du premier venu et faire la moyenne des } { vecteurs normaux des trois triangles qui se partagent } { chaque sommet aussi ... mais je suis très en retard } { pour le numéro courant du REPORTER. } {------------------------------------------------------------------} procedure raw_fichier(tn:word); var f: text; s1,s2,s3,sp,nm:string; begin assign(f,'c:\graphic\util3d\raw\nap2.raw'); rewrite(f); writeln(f,'NAP1'); for u:=1 to tn do begin {-------------------------------} { charge une valeur du tableau } {-------------------------------} v:=gril_^[tab_t^[u][1].l,tab_t^[u][1].c]; e:=gril_^[tab_t^[u][2].l,tab_t^[u][2].c]; w:=gril_^[tab_t^[u][3].l,tab_t^[u][3].c]; str(v.x:4:4,s1); str(v.y:4:4,s2); str(v.z:4:4,s3); sp:=s1+' '+s2+' '+s3; str(e.x:4:4,s1); str(e.y:4:4,s2); str(e.z:4:4,s3); sp:=sp+' '+s1+' '+s2+' '+s3; str(w.x:4:4,s1); str(w.y:4:4,s2); str(w.z:4:4,s3); sp:=sp+' '+s1+' '+s2+' '+s3; writeln(f,sp); end; close(f); outtext('ok'); end; var s1:string; {-----------------------------------------------} { Programme principal . } { On arrive au bout, bientôt la fin, } { courage ! } {-----------------------------------------------} begin init_lig_col(ic,jc,tn); init_mem; init_tab_triangle(ic,jc,tn); {----------------------------------------} { On passe en mode graphique: : } {----------------------------------------} gd:=9; gm:=2; initgraph(gd,gm,''); {----------------------------------------} { Information à l'écran: } {----------------------------------------} setfillstyle(1,0); outtextxy(0,465,'`x`,`y`,`z`;Rotation; `t`:trace ;'+ '`c`,`p`,`q`,`s` face cachées; `esc`:fin` '); {----------------------------------------} { Présenter proprement: } {----------------------------------------} rectangle(1,1,639,460); setviewport(2,2,638,459,true); {----------------------------------------} { Documenter le point de vue: } {----------------------------------------} calculpoint_vision(pv); {----------------------------------------} { Calculer la sphère et la ranger: } {----------------------------------------} init_grille(ic,jc,tn); {----------------------------------------} { Traiter les paramètres en ligne de } { commande: } {----------------------------------------} if paramstr(4)='anim' then anim else begin trace_triangle(tn); outtext('`entrez "anim" pour changer l`angle'); readln(s1); if s1='anim' then anim; end; {----------------------------------------} { Traiter des donner pour POV: } {----------------------------------------} if paramstr(3)='raw' then raw_fichier(tn); {----------------------------------------} { Sortir sans laisser de traces: } {----------------------------------------} closegraph; lib_mem; end. {----------------------------------------} { Fin de la partie active. } {----------------------------------------} {----------------------------------------------------------------------} { } { 2 CREUSER LA DOC } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { On trouvera quelques explications supplémentaires dans : } { } { Dessiner avec l'ordinateur , } { M.Binse et M. Hennart, ed. Cedic/nathan } { ( LA base, le minimum, essentiel malgré } { quelques archaïsmes : programme en LSE} { et LOGO ). } { } { les 7 premiers numéros de PIXEL magazine qui contenaient } { d'excellents cahiers techniques d'initiation } { aux méthodes graphiques de bases. } { } { Infographie et Applications , } { T.Liebling et H.Röthlisberger, ed. MAsson } { ( La partie application est plutôt } { fastidieuse. Pour le reste on trouve } { Les méthodes de Bresenham et une } { technique de transformation de } { projection conique en projection } { orthogonale pratique pour traiter } { rapidement les faces cachées) } { } { Graphisme en turbo pascal, tome 1 } { Thomas Lachand-robert, ed. Sybex 1988 } { ( Pour approfondir si vous n'avez pas } { un niveau en math de première force, ce } { bouquin ne vous expliquera peut-être pas } { tout,mais vous tirera d'embarras bien } { souvent. Le tome 2 traite des repré- } { sentations en volume mais il est } { introuvable. } { } { Graphiques en turbo C (je ne suis pas sectaire!! enfin pas trop) } { Catherine Duval, ed. Eyrolles 1989 } { (en plus c'est une femme mais c'est plutôt } { "patchwork" entre le lissage de courbe et } { la gestion de la mémoire, il y a même } { quelques trucs et astuces pour faire de } { l'animation, et des volumes simples dont } { la sphère. } { Mais c'est quand même plus lisible en } { pascal). } { } { On peut se procurer le programme Raw2pov dont les sources } { (en 'c', berk!) sont livrés, chez DP-tools , } { groupé avec quelques autres utilitaires pour Pov et Vivid. } { } { Si l'histoire de la perspective vous intéresse: } { } { La perspective en jeu, les dessous de l'image } { Philippe Comar,Découvertes gallimard n°138 } { ( Par le concepteur de l'exposition de } { l'exposition permanente, Sténopé, présentée } { à la cité des sciences de la vilette. } { panorama complet de toutes les variations } { sur le thême; vous n'apprendrez pas comment } { construire une pers. centrale ou sphérique, } { mais vous saurez tout de ceux qui les ont } { inventées. Quelques mots sur les machines } { à dessiner, court sur l'ordinateur, mais } { clair sur l'éviction de l'oeil du peintre } { par les mathématiques dès le XVIIième } { siècle. ) } { } { La Perspective comme forme symbolique } { Erwin Panofsky, Le sens commun, } { Les Editions de minuit, 1975. } { (Ce n'est pas le guide microsoft de la } { programmation des cartes graphiques, } { mais on peut y lire des choses très } { fortes comme :"...elle [la perspective] } { crée la distance entre l'homme et les } { choses ("en premier lieu vient l'oeil qui } { voit, en second lieu l'objet qui est vu, } { en troisième la distance intermédiaire") } { [...] Mais elle abolit en retour cette } { distance en faisant en un certain sens } { pénétrer jusque dans l'oeil humain ce } { monde des choses dont l'existence autonome } { s'affirmait en face de l'homme; enfin elle } { ramène le phénomène artistique à des règles } { stables, d'exactitude mathématique } { même[...]". } } { - je ne sais pas si ça rentre dans le } { cadre des courtes citations à titre } { d'exemple . Mais il est bien clairement } { dit aussi que tout cela reste soumis à la } { détermination arbitraire d'un 'point de } { vue' subjectif). } { } { L'Origine de la perspective, } { Hubert Damish, } { Idées et recherches, Flammarion 1987 } { (on doit pouvoir le trouver aussi en } { champs-Flammarion.On y trouve des descriptions } { de perspectives urbinates qui ont autant de } { savoir faire et de "sens" que la plupart des } { "démos" actuelles.) } { } { } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { Conclusion. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { } { Je suis loin d'avoir été exhaustif, par contre certainement } { long, et pas toujours très serieux. Mais je suis ouvert à } { toutes les remarques, suggestions, idées qui auraient pu } { naître à la lecture de tout cela. Donc, n'hésite pas, courageux } { lecteur, à me contacter pour améliorer, préciser, transformer, } { ou simplement pour exprimer ta satisfaction... } { Aux bons soins du Reporter. } {----------------------------------------------------------------------} {----------------------------------------------------------------------} { ..... et pour le compte je ne sais pas sur quoi je ferai porter } { mon article la prochaine fois...à moins que je ne vous parle } { du pavage régulier de la sphère ... } {----------------------------------------------------------------------}