_______________________________________________________________________________________________________________________________________ /*************************************************************************************************************************************/ /* */ /* F O N C T I O N S D E B A S E P O U R L A M I S E E N M O N T A G N E S : */ /* */ /* */ /* Definition : */ /* */ /* Ce fichier contient toutes les fonctions */ /* necessaires a mettre une image en "montagnes"... */ /* */ /* */ /* Author of '$xiii/montagnes$FON' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 19870000000000). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* A I D E A U C A D R A G E A U T O M A T I Q U E V E R T I C A L D E S M O N T A G N E S : */ /* */ /*************************************************************************************************************************************/ #define PLUS_GRANDE_ORDONNEE_SUR_LA_MONTAGNE \ F_MOINS_L_INFINI \ /* Valeur initiale de 'Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_montagne' et */ \ /* de 'Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_last_ligne_de_la_montagne' */ /* au debut de chaque generation. */ DEFV(Common,DEFV(Float,ZINT(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_montagne,PLUS_GRANDE_ORDONNEE_SUR_LA_MONTAGNE))); /* Donne (dans [0,1]) la plus grande ordonnee rencontree lors du trace de tous les */ /* vecteurs verticaux composant une montagne. */ DEFV(Common,DEFV(Float,ZINT(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_last_ligne_de_la_montagne ,PLUS_GRANDE_ORDONNEE_SUR_LA_MONTAGNE ) ) ); /* Donne (dans [0,1]) la plus grande ordonnee rencontree lors du trace de la derniere */ /* ligne de vecteurs verticaux composant une montagne. */ /* */ /* ......................................................... */ /* :@-* -- . */ /* :--o@** o-@@o plus grande */ /* -:.+-@@o@+-*+@+@*o ordonnee sur */ /* o -:.:+@-*+o:o-**o:*+ la montagne */ /* o*.--*-@-@@@-*-o*oo*@* - o */ /* @@*@:-:-*o++@+*o-*+*@**oo. :+-*-- */ /* @@-@o-:-*--****+o+*o@++*+o++@ +* .+@++:- */ /* +*oo@*.:--*+*@*o-o-@@o*-o**-+@@@@ +@@@@:+@*+* o -+**+.-: */ /* *@o-@*-:+-o+@+@@o@-o@@@-o@*-o*+-:-:-++:@o*@o**o*oo+*++-@@@+o-:*: */ /* --@@@@@*oo*o:+-@o@*o+@@o**+o+*+-+.**:o+@@--:o--@+:@:-++o:*oo:@:- */ /* o-@@@+o+@*@@--**oo@*o*@@o**+++::::--+-o*:@@+o*-*++*---++o*@++o:- */ /* o+@-o@o@o*@*-**o*oo*o*@o@@oo*o:..:o---*-:-@ooooo:o*-@:o*oo@:@**: */ /* *+o@@@-@-**+oo@****@-*o@@--*oo.:.:-.+++-+***o*o+o:o*-*+o+*@:+-:+ */ /* @@**@@@+@@@+***@*-++****o@+*o:::.-::.o+++---*:::--@-***+o++++-+@ */ /* **@@+@:-@**+--@oo@-o+*+-@*@+---::::.-----:@:o-.--*@@*@:-@@++:+o: */ /* o+@o*-*+*ooo*+*@o*@*o**+-@*o+:::..-:-+-o@:o-::--:o**o+**+*-*@:@- */ /* o*@*@+@*o@*@o**@@-*@@-*@:@@*-::..+::-@++:::::-.-:*+:**+*:--o-+o@ */ /* +++*@@@@o+*@*+o+*++*@o@*@@*@:.+*oo:o@*-++-::.-:--*ooo@*+..+:o@@- */ /* o++o@@@*@@@@*o@@o:+o*@+*-@o*--:-+@:.::*-o+-@::-+++o:@@+**::*o@+o */ /* o+o:*o@o-@*--*@+-::+@**oo+@+-.:+o@.@-@+@@***++:@-o-*o:-+-:+@-o++ */ /* o+o-o***@@+@*-*@-:+@o@*o@---::-.+o++*o**o-*@-.+@:::*-:-o:+-@*o+: */ /* **.*-o@@o*@**-:-@-@@@@@@o+:+.....++++o*@@:*-*+@oo.::.+.+-:o*+o*+ */ /* o+oo:@@**@@o:@*@-*@o@o@***+::...-:o+:-@@:**+*-@+o+-:.:.-.-+o+@** */ /* @oo-:--*@+.-*@*@:-***oo*@+::...:++o:-oo@:*oo@-@*-::.....:o+o@oo: */ /* @o---.+:+@@**o:oo@:--@*+oo-*+:.@-@*--+-*@*o:@*oo:-:::...::+-@+o@ */ /* +@*:--:@+:+@-:*@-@*o@@-o@+:*::o*o-@*:-+@@*-@o++o--::@@+:-::+@**+ */ /* -*:*-*o-o@*-:-+:-+*@@o:@*-@@o@***@o@@.-*o@@ ........................... */ /* +o:----++*o--@+o@o:-+o@*@@@**+@@*+@*o-:@ +:o-@-::-+::+*oo@@ plus grande */ /* -...--o.@**--@o*-@@@*@-o@*o-+-*@*o+*-- @+:@**:++::o*:oo+ ordonnee sur */ /* *o+-+@o+-o+o*.+:.+o-@@@*@o@o*:-o@+*@: @@@+---:-*++*@: la 'last' */ /* ligne de la */ /* montagne */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M I S E E N M O N T A G N E S D ' U N E I M A G E : */ /* */ /* */ /* Definition : */ /* */ /* Cette fonction genere une repre- */ /* sentation 3D d'une image 2D, en */ /* utilisant la valeur de chaque point */ /* comme troisieme dimension ; le calcul */ /* est fait pour tout le champ {X,Y}, mais */ /* le trace n'a lieu que la ou l'image */ /* n'est pas masquee. */ /* */ /* Le 'Z-Buffer' est correcte- */ /* ment mis a jour afin de pouvoir */ /* integrer cette montagne a d'autres */ /* objets 3D. */ /* */ /* */ /* */ /* * */ /* ..@ .@ */ /* .* *.@ .@.@ */ /* ...@ . ..*@@@@ */ /* *@ .. .. .. .**@@@* */ /* @ .** . .*.@*@ **.. . . *@@@@@.@ .@ */ /* @****@.. @. **.*@ **.. .@.. .@.. .. ...@*@*@.*.@* */ /* .*.@@@*. .**.*@@.@. .*. . .@. @... .... . .@.** ..@@@* */ /* @.@@.@. *..**** @@@ .. * ** **.. . . .. . *.@ *..@@@@* .@ */ /* @*. @@.. @ @.@ ..@. .. .*@*@. ..@@@. ...*..****.. ...@*@@@**** */ /* . .**@..@@ @*. *@@..*. * @.**@.@@. ** ..*@@.@**. .@@@.*@ *@@ */ /* . . ** ..@@*@. *@****@. .***@..@@*.... @.*@ * .. .**.****@.. */ /* .... **.@@@@*. .*@**... .@.*.@ .*@ . .**@@.... **.@*@*@** */ /* *.... .@*@*...*.. @.@... .**@.@*@. **.. ***@.. * @*@.@ */ /* *.... .***.*@.* ..**.@..@. @*.*@@ *.* ..... .*@@... ..* @. ... */ /* @.. .*.@.**** ..@***@@@* *@. *.@@.*..*.**. @*@@ . * ** ... */ /* @@. . .@.* *.**. *.*@**@.*@@*@..@.@@@.*......@@.@.. ....... . */ /* @@ *. @.*@ **@.....@@*@.*@@*@*.@* *@ @@*.****.**. ..... .* */ /* @.@ @@*.@@ .@ .* @ .@@*@**@@*@@* * *.**. . ..... ... ....@. */ /* *@*..@*.** @* * *@@*@**@@@*.. .. .*.... ... .. . . . . .*. */ /* .@*@@**. .*.**@*@@@@*.@@@**. .. *@*....... . ..... . */ /* @@@..* **. . @.**@*@@@.@@@... *.**.... .@... . ... @... */ /* @**. ** . *.@@.@**@@ *.*@@* ** *.@.*.@@@. @*** .. @@* . */ /* @. . . . @@..***@ @* ..@* *. * .@*@*. .*@* . ... *@ .** */ /* @* .... .... .** *@@*@ .. @.** *.*. @@*.... @@@@ @*..* . @@* */ /* @ .**. *@*@@..*@..**. . * *..@ @ * @...*... @@@*****.... .*** */ /* */ /* */ /* Definition des lignes : */ /* */ /* */ /* Ymax .................................. | */ /* . | */ /* . (lignes non tracees) | AVANT */ /* . | */ /* Yfirst .................................. v */ /* Yfirst_trace ---------------------------------- */ /* . */ /* . */ /* . (lignes tracees) */ /* . */ /* . */ /* Ylast_trace ---------------------------------- */ /* Ylast .................................. ^ */ /* . | */ /* . (lignes non tracees) | ARRIERE */ /* . | */ /* Ymin .................................. | */ /* */ /* */ /*************************************************************************************************************************************/ #ifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : avec 'VERSION_01'. */ DEFV(Common,DEFV(Logical,_____TYPE_DE_imageA_surface_VERSION_01)); #Aifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : avec 'VERSION_01'. */ #Eifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : avec 'VERSION_01'. */ #ifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : avec 'VERSION_02'. */ DEFV(Common,DEFV(Logical,_____TYPE_DE_imageA_surface_VERSION_02)); #Aifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : avec 'VERSION_02'. */ #Eifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : avec 'VERSION_02'. */ DEFV(Common,DEFV(Logical,ZINT(Imontagnes_precises_____compatibilite_20090202,FAUX))); /* Le 20090202103137 en essayant de corriger le probleme de "tricherie" du 20090130181639, */ /* je me suis rendu compte que les definitions de 'Yfirst' et de 'Ylast' pouvaient etre */ /* plus "strictes"... */ /* */ /* Le 20090203162610, au test 'IL_FAUT(Imontagnes_precises_____compatibilite_20090203)' fut */ /* ajoute celui de 'IL_NE_FAUT_PAS(vue_d_avion)' car en effet, il semble que l'absence de */ /* compatibilite deteriore le traitement "anti-aliasing" des lignes de crete d'arriere-plan */ /* (le plus lointain...). */ DEFV(Common,DEFV(Logical,ZINT(Imontagnes_precises_____compatibilite_20090203,FAUX))); /* Meme remarque le 20090203154615 concernant 'Yfirst_trace' et 'Ylast_trace'... */ /* */ /* Le 20090203162610, au test 'IL_FAUT(Imontagnes_precises_____compatibilite_20090203)' fut */ /* ajoute celui de 'IL_NE_FAUT_PAS(vue_d_avion)' car en effet, il semble que l'absence de */ /* compatibilite deteriore le traitement "anti-aliasing" des lignes de crete d'arriere-plan */ /* (le plus lointain...). */ DEFV(Common,DEFV(Logical,ZINT(Imontagnes_precises_____compatibilite_20210928,FAUX))); DEFV(Common,DEFV(Logical,ZINT(Imontagnes_precises_____compatibilite_20211001,FAUX))); /* Le 20210928134325 j'ai decouvert une anomalie dans 'ARRIERE(...)' et 'AVANT(...)' dans */ /* lesquels 'SUCY(...)' et 'PREY(...)' pouvait faire sortir l'ordonnee 'y' de [Ymin,Ymax]. */ /* Ceci a ete mis en evidence a cette date sur '$LACT1B', ou 'v $xci/montagne.01$K' a partir */ /* du format 'Suq' donnait : */ /* */ /* Segmentation fault (core dumped) */ /* */ /* pour (avec le format 'Suq'...) : */ /* */ /* X=126 Y=0 */ /* */ /* et c'est ce "Y=0" qui a attire mon attention... */ /* */ /* Le 20211001175847, cela fut complete par l'utilisation de la procedure d'acces aux */ /* champs... */ /* */ /* Le 20211002110514, on notera un phenomene tres curieux. L'usage des options : */ /* */ /* compatibilite_20210928=VRAI */ /* */ /* et/ou : */ /* */ /* compatibilite_20211001=VRAI */ /* */ /* ne re-provoque pas la "Segmentation fault", contrairement a toute attente. De plus les */ /* images alors generees SANS et AVEC ces options semblent identiques... Par contre si les */ /* procedures en cause sont redefinies ainsi : */ /* */ /* #define vPREX(x) \ */ /* PREX(x) */ /* #define vSUCX(x) \ */ /* SUCX(x) */ /* */ /* #define vPREY(y) \ */ /* PREY(y) */ /* #define vSUCY(y) \ */ /* SUCY(y) */ /* */ /* #define VloadF_point(imageA,X,Y) \ */ /* loadF_point(imageA,X,Y) */ /* */ /* la "Segmentation fault" revient... Peut-etre cela change-t-il l'implantation memoire... */ #define vPREX(x) \ COND(IL_FAUT(Imontagnes_precises_____compatibilite_20210928),NEUT(PREX(x)),TROX(PREX(x))) #define vSUCX(x) \ COND(IL_FAUT(Imontagnes_precises_____compatibilite_20210928),NEUT(SUCX(x)),TROX(SUCX(x))) #define vPREY(y) \ COND(IL_FAUT(Imontagnes_precises_____compatibilite_20210928),NEUT(PREY(y)),TROY(PREY(y))) #define vSUCY(y) \ COND(IL_FAUT(Imontagnes_precises_____compatibilite_20210928),NEUT(SUCY(y)),TROY(SUCY(y))) #define vNEUT(x_ou_y) \ NEUT(x_ou_y) /* Definitions introduites le 20210928135900, 'vNEUT(...)' etant destine uniquement a */ /* assurer de belles tabulations... */ #define VloadF_point(imageA,X,Y) \ OPC3(IL_FAUT(Imontagnes_precises_____compatibilite_20211001),loadF_point,loadF_point_valide,imageA,X,Y) \ /* Definition introduite le 20211001175847... */ #define ARRIERE(y) \ vSUCY(y) \ /* Definition de la fonction de retour arriere. */ #define AVANT(y) \ vPREY(y) \ /* Definition de la fonction de marche en avant. */ #define Xlast \ SUCX(Xmin) \ /* Definition de la derniere colonne calculee ; la colonne 'Xmin' sera */ \ /* obtenue par duplication de celle-ci... */ #define Yfirst \ OPC1(IFOU(IL_NE_FAUT_PAS(vue_d_avion),IL_FAUT(Imontagnes_precises_____compatibilite_20090202)),AVANT,NEUT,Ymax) \ /* Definition de la premiere ligne de la matrice argument a generer en relief sans tracer ; */ \ /* la definition de 'Yfirst' est l'inverse de 'z_point_precedent(...)'. */ #define Yfirst_trace \ OPC1(IFOU(IL_NE_FAUT_PAS(vue_d_avion),IL_FAUT(Imontagnes_precises_____compatibilite_20090203)),AVANT,NEUT,Yfirst) \ /* Definition de la premiere ligne de la matrice argument a visualiser. */ #define Ylast \ OPC1(IFOU(IL_NE_FAUT_PAS(vue_d_avion),IL_FAUT(Imontagnes_precises_____compatibilite_20090202)),ARRIERE,NEUT,Ymin) \ /* Definition de la derniere ligne de la matrice argument avant la premiere visualisee ; */ \ /* la definition de 'Ylast' est l'inverse de 'z_point_suivant(....)'. */ #define Ylast_trace \ OPC1(IFOU(IL_NE_FAUT_PAS(vue_d_avion),IL_FAUT(Imontagnes_precises_____compatibilite_20090203)),ARRIERE,NEUT,Ylast) \ /* Definition de la derniere ligne de la matrice argument a etre visualisee (tracee) ; */ \ /* la definition de 'Ylast_trace' est l'inverse de 'z_point_suivant_suivant(...)'. */ #define DECALAGE_VERTICAL(y) \ INTE(MUL2(Imontagnes_precises_____importance_du_decalage_vertical,FLOT(y))) \ /* Decalage vertical de la composante 'y' lors de la reconstitution de la */ \ /* montagne tranche par tranche... */ DEFV(Common,DEFV(Logical,ZINT(Imontagnes_precises_____verification_de_la_correction_perspective,FAUX))); /* Introduit le 20170413103352... */ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____facteur_de_correction_perspective,FZERO))); /* Facteur de correction perspective (la valeur nulle implicite permet d'assurer la */ /* compatibilite avec les versions anterieures...) ; plus cette valeur est grande, plus */ /* l'effet est accentue... ATTENTION, il ne s'agit pas d'une vraie perspective : l'effet */ /* consiste a translater verticalement les vecteurs traces d'une quantite qui est fonction */ /* croissante de la coordonnee 'y' dans 'EQUATION_DE_LA_SURFACE(...)' ; une coordonnee 'z' */ /* est donc remplacee par : */ /* */ /* z - k.y */ /* */ /* (ou 'k' designe 'Imontagnes_precises_____facteur_de_correction_perspective'). */ /* */ /* Ainsi, ce sont a la fois l'origine et l'extremite de chaque vecteurs qui sont translatees */ /* d'une meme quantite alors que pour bien faire, seule l'extremite devrait l'etre... */ /* Malheureusement, on ne peut pas mieux faire, car cela vient des affectations du type */ /* suivant : */ /* */ /* ASD2(vecteur_vertical,origine,y) = z_point_suivant(X,Y) */ /* ASD2(vecteur_vertical,extremite,y) = z_point_courant(X,Y) */ /* */ /* et des definitions des deux fonctions 'z_point_suivant(...)' et 'z_point_courant(...)' */ /* qui se font via 'EQUATION_DE_LA_SURFACE(...)'. */ /* */ /* ATTENTION, l'experience montre qu'avec une image 'standard=FAUX' il est important qu'elle */ /* soit "relativement normalisee" (donc dans [0,1]) si l'on souhaite pouvoir "jouer" */ /* facilement avec 'Imontagnes_precises_____facteur_de_correction_perspective'. */ /* En particulier, lors de la mise au point de la sequence : */ /* */ /* xivPdf 10 2 / 013313_013824 */ /* */ /* il y a eu une difficulte car toutes les images 'imageA_surface' etaient approximativement */ /* dans [1,16] ; il a donc fallu leur apporter une renormalisation globale. Cela s'est vu de */ /* nouveau aux environs du 20150112125523 lors de la generation 'v $xiirv/CHAR.12$M'... */ /* */ /* On notera que 'Imontagnes_precises_____facteur_de_correction_perspective' intervient */ /* dans la definition de 'EQUATION_DE_LA_SURFACE(x,y)'. Or cette equation est elle-meme */ /* multipliee par 'facteur_d_echelle' dans les definitions du type 'z_point_precedent(x,y)' */ /* (et toutes celles qui lui sont similaires...). Ainsi donc, 'facteur_d_echelle' et */ /* et 'Imontagnes_precises_____facteur_de_correction_perspective' interferent l'un avec */ /* l'autre. Le 20020211111705, j'ai remarque que les deux parametres 'facteur_d_echelle' */ /* et 'Imontagnes_precises_____facteur_de_correction_perspective' devaient etre de meme */ /* signe... */ #define LAMBDA_DE_CORRECTION_PERSPECTIVE(y) \ MUL2(MEME_SIGNE_QUE \ (facteur_d_echelle \ ,Imontagnes_precises_____facteur_de_correction_perspective \ ) \ ,_____cNORMALISE_OY(y) \ ) \ /* Definition introduite le 20170413095025 afin de permettre de valider initialement les */ \ /* differents parametres... */ #ifdef TYPE_DE_imageA_surface_VERSION_01 # define EQUATION_DE_LA_SURFACE(x,y) \ F__cDENORMALISE_OY(SOUS(MUL2(facteur_d_ajustement_de_l_equation_de_la_surface \ ,______NORMALISE_NIVEAU(load_point(imageA_surface,x,y)) \ ) \ ,BARY(COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ,LAMBDA_DE_CORRECTION_PERSPECTIVE(y) \ ) \ ) \ ) \ /* Definition de l'equation de la surface a partir de l'image 'imageA_surface'. On notera */ \ /* les deux facteurs multiplicatifs : */ \ /* */ \ /* 1-facteur_d_ajustement_de_l_equation_de_la_surface : qui permet de prendre en compte le */ \ /* le fait que l'intervalle [NOIR,BLANC] ne change jamais, alors que [Ymin,Ymax] lui depend */ \ /* du format de l'image. */ \ /* */ \ /* 2-Imontagnes_precises_____facteur_de_correction_perspective : qui permet de simuler */ \ /* une vue perspective en reduisant l'altitude de la surface proportionnellement a */ \ /* l'eloignement par rapport a l'observateur (ATTENTION, voir les commentaires de */ \ /* 'Imontagnes_precises_____facteur_de_correction_perspective'). */ \ /* */ \ /* ATTENTION, l'ecriture : */ \ /* */ \ /* SOUS(F__cDENORMALISE_OY(...)) */ \ /* . */ \ /* /|\ */ \ /* | */ \ /* | */ \ /* */ \ /* Y */ \ /* */ \ /* referencant 'Y' et non pas 'Z' n'est pas fausse, et vient du fait que la coordonnee 'Z' */ \ /* de la surface est materialisee suivant l'axe 'OY' de l'image generee... */ \ /* */ \ /* Le 'MEME_SIGNE_QUE(...)' a ete introduit le 20020211111705... */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 # define EQUATION_DE_LA_SURFACE(x,y) \ F__cDENORMALISE_OY(SOUS(MUL2(facteur_d_ajustement_de_l_equation_de_la_surface \ ,VloadF_point(imageA_surface,x,y) \ ) \ ,BARY(COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ,LAMBDA_DE_CORRECTION_PERSPECTIVE(y) \ ) \ ) \ ) \ /* Definition de l'equation de la surface a partir de l'image 'imageA_surface'. On notera */ \ /* les deux facteurs multiplicatifs : */ \ /* */ \ /* 1-facteur_d_ajustement_de_l_equation_de_la_surface : qui permet de prendre en compte le */ \ /* le fait que l'intervalle [NOIR,BLANC] ne change jamais, alors que [Ymin,Ymax] lui depend */ \ /* du format de l'image. */ \ /* */ \ /* 2-Imontagnes_precises_____facteur_de_correction_perspective : qui permet de simuler */ \ /* une vue perspective en reduisant l'altitude de la surface proportionnellement a */ \ /* l'eloignement par rapport a l'observateur (ATTENTION, voir les commentaires de */ \ /* 'Imontagnes_precises_____facteur_de_correction_perspective'). */ \ /* */ \ /* ATTENTION, l'ecriture : */ \ /* */ \ /* SOUS(F__cDENORMALISE_OY(...)) */ \ /* . */ \ /* /|\ */ \ /* | */ \ /* | */ \ /* */ \ /* Y */ \ /* */ \ /* referencant 'Y' et non pas 'Z' n'est pas fausse, et vient du fait que la coordonnee 'Z' */ \ /* de la surface est materialisee suivant l'axe 'OY' de l'image generee... */ \ /* */ \ /* Le 'MEME_SIGNE_QUE(...)' a ete introduit le 20020211111705... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #define z_point_precedent(x,y) \ MUL2(facteur_d_echelle,EQUATION_DE_LA_SURFACE(x,ARRIERE(y))) #define z_point_courant(x,y) \ MUL2(facteur_d_echelle,EQUATION_DE_LA_SURFACE(x,y)) \ /* 'z_point_courant' donne l'extremite (le "haut") du vecteur vertical courant. */ #define z_point_suivant(x,y) \ MUL2(facteur_d_echelle,COND(IFOU(IL_FAUT(vue_d_avion) \ ,IFGT(Y,Ylast_trace) \ ) \ ,EQUATION_DE_LA_SURFACE(x,AVANT(y)) \ ,FLOT(Zmin) \ ) \ ) \ /* 'z_point_suivant' donne l'origine (le "bas") du vecteur vertical courant ; de */ \ /* plus lorsqu'on est au bord inferieur de l'image, et qu'une vue d'avion n'est */ \ /* pas demandee, on force le 'Zmin' afin de creer une falaise verticale artificielle */ \ /* terminant correctement la visualisation... */ #define z_point_suivant_suivant(x,y) \ MUL2(facteur_d_echelle,COND(IFOU(IL_FAUT(vue_d_avion) \ ,IFGT(Y,Ylast_trace) \ ) \ ,EQUATION_DE_LA_SURFACE(x,AVANT(AVANT(y))) \ ,FLOT(Zmin) \ ) \ ) #define texture_courante(x,y,z) \ FLOT(NIVR(load_point(imageA_texture,x,y))) \ /* Definition de la texture a appliquer au point {x,y,z} de la montagne, mais on notera */ \ /* que dans la version actuelle, la cote 'z' n'est pas utilisee, mais ouvre la porte a un */ \ /* texturage tri-dimensionnel... */ #define CLIPPING_INTENSITE \ FLOT(NIVR(NOIR_CLIPPING)) \ /* Niveau lumineux a utiliser pour marquer la "falaise" avant d'une montagne, */ \ /* lorsqu'une vue d'avion n'est pas demandee... */ #define MIN_INTENSITE \ FLOT(NIVR(ADD2(NOIR_CLIPPING,pas_entre_CLIPPING_INTENSITE_et_MIN_INTENSITE))) \ /* Niveau lumineux plancher a ne pas depasser ; on prend un niveau suivant celui */ \ /* de marquage de la falaise, afin de pouvoir le distinguer visuellement... */ #define MAX_NIVEAU_LUMINEUX \ FLOT(NIVR(BLANC)) \ /* Donne le niveau lumineux maximum. */ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____facteur_d_attenuation_a_l_ombre,FDU))); /* Facteur d'attenuation des points a l'ombre. Plus la valeur est proche de 1, plus */ /* l'attenuation est forte, et inversement, plus elle est proche de 0 et plus elle est */ /* faible... */ #define ATTENUATION_A_L_OMBRE(niveau_Relatif) \ MUL2(Imontagnes_precises_____facteur_d_attenuation_a_l_ombre,FLOT(niveau_Relatif)) \ /* Donne la fonction d'attenuation a l'ombre ; plus sa valeur est proche de 'niveau', */ \ /* plus l'attenuation est forte, et inversement, plus elle est proche de '0', moins les */ \ /* effets de l'ombre se font sentir (tout cela vient du 'NEGA()' fait sur cette fonction). */ \ /* On notera que l'argument est un niveau Relatif (de type 'NIVR(...)'), ce qui est en */ \ /* accord avec le fait que cette procedure n'est utilisee qu'avec 'MAX_NIVEAU_LUMINEUX' */ \ /* (qui est de ce type...). */ #define TRACE_VECTEUR_VERTICAL(image,vecteur,Yf_origine,Yf_extremite,X,Y,Zf,c_est_la_phase_d_anti_aliasing) \ Bblock \ CALS(Itrace_segment_vertical(image \ ,vue_d_avion \ ,ADRESSE(vecteur),Yf_origine,Yf_extremite \ ,X,Y,Zf \ ,intensite_origine,intensite_extremite \ ,Zf_extremite \ ,c_est_la_phase_d_anti_aliasing \ ,anti_aliasing \ ) \ ); \ Eblock \ /* Trace le vecteur vertical courant. */ #define C_EST_LA_PHASE_D_ANTI_ALIASING \ VRAI \ /* Indique pour 'Itrace_segment_vertical' que c'est la phase d'anti-aliasing. */ #define CE_N_EST_PAS_LA_PHASE_D_ANTI_ALIASING \ NOTL(C_EST_LA_PHASE_D_ANTI_ALIASING) \ /* Indique pour 'Itrace_segment_vertical' que ce n'est pas la phase d'anti-aliasing. */ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____importance_du_decalage_vertical,FU))); /* Importance relative (dans [0,1]) du decalage vertical applique a chaque */ /* tranche verticale qui compose la montagne ; avec '1' on obtient le */ /* decalage "standard", et avec '0' aucun decalage. */ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____inclinaison_de_la_source_lumineuse,FZERO))); /* Importance relative (dans [0,1]) de la composante selon l'axe 'OY' du */ /* rayon lumineux : '0' correspond a l'etat anterieur ou cette composante */ /* etait completement negligee, et '1' ou elle prend toute son importance. */ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____source_lumineuse_Z,DOUB(FU)))); /* En fait, on introduit ici une troisieme composante a la position de la source */ /* lumineuse afin de resoudre le probleme des grandes facettes verticales */ /* paralleles au plan de projection ; les deux degres de liberte laisses a */ /* l'utilisateur ('X' et 'Y') sont suffisants. Enfin, le calcul des ombres portees */ /* demeure bi-dimensionnel... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* T R A C E D ' U N S E G M E N T V E R T I C A L : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Common,DEFV(Logical,SINT(Imontagnes_precises_____compatibilite_20061220,FAUX))); /* Le 20061220094855 la correction d'anti-alisaing a ete introduite sur l'ensemble des */ /* lignes de crete (et non plus sur celles de l'arriere-plan comme cela avait ete rappele */ /* le 20061220094638 ci-apres...). Cet indicateur permet donc d'assuer, si besoin est, la */ /* compatibilite anterieure... */ DEFV(Common,DEFV(Logical,SINT(Imontagnes_precises_____compatibilite_20090130,FAUX))); /* Le 20090130181639 un dispositif permettant d'inhiber la tricherie concernant les lignes */ /* [Ymin,Ylast] et [Yfirst,Ymax]. Par defaut ce dispositif n'est pas actif (contrairement */ /* a ce qui se fait habituellement pour les '..._____compatibilite_...'). */ /* */ /* Le 20090203133525 la valeur par defaut et passee de 'VRAI' a 'FAUX' car c'est en effet */ /* moins dangereux de voir le defaut (deux lignes NOIRes, une en bas et une en haut) que */ /* de le corriger en trichant et en oubliant ensuite qu'il y a eut cette correction... */ /* A compter du 20090203154615 le defaut a ete reduit a une seule ligne NOIRe (en haut)... */ DEFV(Common,DEFV(Logical,SINT(Imontagnes_precises_____interpoler_les_lignes_de_crete_sur_la_montagne,VRAI))); /* Afin d'inhiber la correction des lignes de crete ci-apres... */ /* */ /* ATTENTION : je note le 20061220094638 qu'il ne s'agit pas alors de toutes les lignes */ /* crete de la montagne, mais uniquement de celles qui correspondent a l'arriere-plan, */ /* c'est-a-dire a 'Yfirst_trace' et a 'Ylast_trace'. C'est pourquoi le 20061220094855 */ /* fut introduit l'interpolation suivante sur toutes les lignes de crete... */ DEFV(Common,DEFV(Float,SINT(Imontagnes_precises_____facteur_profondeur_toutes_lignes_de_crete,GRO3(FRA2(FU))))); /* Facteur destine a la profondeur d'une ligne de crete par rapport a l'arriere-plan */ /* (introduit le 20061220155451). */ DEFV(Common,DEFV(Float,SINT(Imontagnes_precises_____facteur_1_interpolation_toutes_lignes_de_crete,FZERO))); DEFV(Common,DEFV(Float,SINT(Imontagnes_precises_____facteur_2_interpolation_toutes_lignes_de_crete,FDU))); /* Facteur de ponderation introduit le 20061220115138 pour anti-aliaser l'integralite des */ /* lignes de crete. L'interpolation utilisee est la suivante : */ /* */ /* [(1-f1).(1-f2).IntensiteCourante] + */ /* [(1-f1).(f2-0).IntensiteArrierePlan] + */ /* [(f1-0).(1-f2).NOIR] + */ /* [(f1-0).(f2-0).BLANC] */ /* */ /* avec quatre utilisations extremes : */ /* */ /* f1=0 f2=0 IntensiteCourante (et donc compatibilite */ /* anterieure au 20061220094855), */ /* */ /* f1=0 f2=1 IntensiteArrierePlan */ /* */ /* f1=1 f2=0 NOIR */ /* */ /* f1=1 f2=1 BLANC */ /* */ /* les valeurs par defaut (f1=f2=1/2) assurant le moyennage de 'IntensiteCourante' et */ /* de 'IntensiteArrierePlan'. */ DEFV(Common,DEFV(Logical,SINT(Imontagnes_precises_____visualiser_la_falaise_avant_de_la_montagne,FAUX))); /* Afin de visualiser la falaise situee a l'avant de la montagne ('VRAI') ou bien de */ /* l'estomper ('FAUX'). */ DEFV(Common,DEFV(Logical,SINT(Imontagnes_precises_____interpoler_le_Z_Buffer_lors_de_l_anti_aliasing,VRAI))); /* Afin de choisir entre l'ancien mode ('FAUX', anterieur au 20011226142146) et le nouveau */ /* mode ('VRAI') dans 'TRACE_POINT_3D(...)'. Ce dernier mode doit etre utilise lorsque le */ /* 'Z-Buffer' va etre memorise et utilise par exemple pour generer un effet de brume. */ /* Il conviendra alors que 'v $xiii/mono_image$FON Z_Buffer_____valeur_initiale' soit */ /* initialise a 0 (introduit le 20011226142146). Renoncant a la compatibilite, cette */ /* option est immediatement passe a 'VRAI' le 20011226165021... */ /* */ /* ATTENTION : le 20011227172915 j'ai note une propriete tres importante de cette */ /* interpolation du 'Z'. En effet les segments traces pour lesquels il y a interpolation */ /* sont verticaux et donc a 'Z' constant. L'interpolation du 'Z' ne donnent donc pas les */ /* 'Z' des points de ces segments, mais uniquement quelque chose destine a "anti-aliaser" */ /* des effets de brume... */ /* */ /* ATTENTION : on notera que lorsque le 'Z-Buffer' est genere pour etre utilise pour sa */ /* nature tridimensionnelle ('v $xci/merge_3D.01$K ImoveM_3D_volume_avec_marquage'), il */ /* est essentiel que cette option soit 'FAUX'... */ #define ARRONDI_NIVEAU(niveau) \ TRNP(ARRI(niveau)) \ /* A compter du 19980605181852, la fonction 'NEUT(...)' a ete remplacee par 'ARRI(...)' */ \ /* afin de reduire certains effets de "rebonds" des niveaux qui accentuaient les bandes */ \ /* de Mach... */ #define visualiser_la_falaise_avant_de_la_montagne \ Imontagnes_precises_____visualiser_la_falaise_avant_de_la_montagne \ /* Pour reduire plus loin la longueur d'une ligne... */ #define TRACE_POINT_3D(c_est_la_phase_d_anti_aliasing) \ Bblock \ DEFV(Int,INIT(abscisse_courante,ASI2(vecteur_vertical,origine,x))); \ DEFV(genere_Float,INIT(Zf_courant,_____cNORMALISE_OZ(ADD2(Yfirst_trace,SOUS(Ylast_trace,Y))))); \ /* Coordonnees 'x' et 'z' courantes. ATTENTION, il est impossible de donner, si besoin est */ \ /* (c'est-a-dire si a la fois 'EST_VRAI(c_est_la_phase_d_anti_aliasing)' */ \ /* et 'IL_FAUT(Imontagnes_precises_____interpoler_le_Z_Buffer_lors_de_l_anti_aliasing)'), */ \ /* a 'Zf_courant' la valeur 'Zf_courant_vecteur_vertical' sous peine d'artefacts genants, */ \ /* par exemple dans le cas ou l'interpolation du 'Z' (si elle est demandee) se fait avec */ \ /* un point du fond et donc en quelque sorte a l'infini ; ainsi les segments, qui sont dans */ \ /* un plan parallele au plan de l'image (donc a 'Z' constants), se retrouveraient inclines */ \ /* vers l'arriere, puisque leurs 'Z' sont interpoles. Moralite, la mise a jour du 'Z-Buffer' */ \ /* avec 'Zf_courant_vecteur_vertical' ne peut se faire qu'apres l'appel a */ \ /* 'TEST_Z_Buffer_(...)' et donc en fait a l'interieur meme de 'TEST_Z_Buffer_(...)'. */ \ \ Test(IFEXff(intensite_courante,FLOT__NOIR,FLOT__BLANC)) \ /* Test introduit le 20100220184023 car il est tout a fait justifie (en particulier a */ \ /* cause des 'GENP(...)'s qui suivent...). */ \ Bblock \ PRINT_ERREUR("le niveau calcule est mauvais"); \ CAL1(Prer1("niveau calcule.................=%f\n",intensite_courante)); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ TEST_Z_Buffer_(abscisse_courante \ ,ordonnee_courante \ ,Zf_courant \ ,BLOC(DEFV(genere_p,INIT(intensite_courante_utilisee,GENP(ARRONDI_NIVEAU(intensite_courante)))); \ /* Niveau a utiliser a priori... */ \ \ Test(IFET(IL_FAUT(Imontagnes_precises_____interpoler_les_lignes_de_crete_sur_la_montagne) \ ,I3ET(IFOU(IFEQ(Y,Yfirst_trace) \ ,IFEQ(Y,Ylast_trace) \ ) \ ,IFEQ(ENTE(Yf_extremite),ASI2(vecteur_vertical,extremite,y)) \ ,IFEQ(ordonnee_courante,ASI2(vecteur_vertical,extremite,y)) \ ) \ ) \ ) \ Bblock \ DEFV(genere_p,INIT(intensite_anterieure \ ,loadS_point_valide(imageAR \ ,abscisse_courante \ ,ordonnee_courante \ ) \ ) \ ); \ DEFV(Float,INIT(parametre_d_interpolation \ ,SOUS(Yf_extremite \ ,FLOT(ASI2(vecteur_vertical,extremite,y)) \ ) \ ) \ ); \ \ EGAL(intensite_courante_utilisee \ ,GENP(NIVA(ARRONDI_NIVEAU(BARY(FLOT(NIVR(intensite_anterieure)) \ ,NIVR(intensite_courante) \ ,parametre_d_interpolation \ ) \ ) \ ) \ ) \ ); \ /* Niveau a utiliser ; dans le cas ou l'on se situe a l'extremite du vecteur, on applique */ \ /* une correction dependant de la position exacte par rapport a la "grille" des points */ \ /* d'une image... */ \ \ Test(IFOU(IFEXff(parametre_d_interpolation \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ) \ ,NINCff(intensite_courante_utilisee \ ,intensite_anterieure \ ,GENP(ARRONDI_NIVEAU(intensite_courante)) \ ) \ ) \ ) \ Bblock \ PRINT_ERREUR("l'interpolation des niveaux est incorrecte"); \ CAL1(Prer4("segment........................={{%d,%d},{%d,%d}}\n" \ ,abscisse_courante,ASI2(vecteur_vertical,origine,y) \ ,ASI2(vecteur_vertical,extremite,x),ASI2(vecteur_vertical,extremite,y) \ ) \ ); \ CAL1(Prer1("ordonnee precise de l'origine..=%f\n",Yf_origine)); \ CAL1(Prer1("ordonnee precise de l'extremite=%f\n",Yf_extremite)); \ CAL1(Prer1("parametre d'interpolation......=%f\n",parametre_d_interpolation)); \ CAL1(Prer1("niveau anterieur...............=%d\n",intensite_anterieure)); \ CAL1(Prer1("niveau calcule.................=%f\n",intensite_courante)); \ CAL1(Prer1("niveau interpole...............=%f\n",intensite_courante_utilisee)); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ Test(I3ET(IL_FAUT(anti_aliasing) \ ,IFEQ(ordonnee_courante \ ,MAX2(ASI2(vecteur_vertical,origine,y) \ ,ASI2(vecteur_vertical,extremite,y) \ ) \ ) \ ,IL_NE_FAUT_PAS(Imontagnes_precises_____compatibilite_20061220) \ ) \ ) \ Bblock \ Test(IFGT(SOUA(loadF_point_valide(Z_Buffer,abscisse_courante,vSUCY(ordonnee_courante)) \ ,Zf_courant \ ) \ ,MUL2(Imontagnes_precises_____facteur_profondeur_toutes_lignes_de_crete \ ,_____cNORMALISE_OZ(pasY) \ ) \ ) \ ) \ Bblock \ /* Cas ou il semble que l'arriere-plan est un peu plus loin que la distance definie par */ \ /* 'pasY' : on considere qu'on est donc sur une ligne de crete... */ \ /* */ \ /* On notera que l'on utilise 'SUCY(ordonnee_courante)' et non pas 'ordonnee_courante' */ \ /* (qui serait en fait la valeur logique...) a cause de 'C_EST_LA_PHASE_D_ANTI_ALIASING' */ \ /* car, en effet, celle-ci consiste en un trace d'un vecteur situe a l'abscisse 'SUCX(X)' */ \ /* ce qui fait que l'on modifie alors le 'Z' du point {SUCX(X),Y}. Or celui-ci sera teste */ \ /* de nouveau lors de 'CE_N_EST_PAS_LA_PHASE_D_ANTI_ALIASING' suivante avec les coordonnees */ \ /* {X,Y} courante et alors le 'Z' anterieur ne sera plus celui de l'arriere-plan, mais du */ \ /* vecteur "degrade" trace lors de 'C_EST_LA_PHASE_D_ANTI_ALIASING' precedent. On triche */ \ /* donc en regardant un point au-dessus... */ \ EGAL(intensite_courante_utilisee \ ,BAR4(intensite_courante_utilisee \ ,loadS_point_valide(imageAR \ ,abscisse_courante \ ,ordonnee_courante \ ) \ ,NOIR \ ,BLANC \ ,Imontagnes_precises_____facteur_1_interpolation_toutes_lignes_de_crete \ ,Imontagnes_precises_____facteur_2_interpolation_toutes_lignes_de_crete \ ) \ ); \ /* Le 20061220094855 la correction d'anti-aliasing a ete introduite sur toutes les */ \ /* lignes de crete. Elle consiste en une interpolation simple (par une moyenne) avec */ \ /* le niveau d'arriere-plan (deja trace puisque l'on va d'arriere en avant...). */ \ /* */ \ /* Le 20061220115138, 'MOYE(...)' a ete remplace par 'BARY(...)' plus general, soit : */ \ /* */ \ /* (1-facteur).IntensiteCourante + (facteur-0).IntensiteArrierePlan */ \ /* */ \ /* puis remplace le 20061220134021 par 'BAR4(...)' encore plus general : */ \ /* */ \ /* [(1-f1).(1-f2).IntensiteCourante] + */ \ /* [(1-f1).(f2-0).IntensiteArrierePlan] + */ \ /* [(f1-0).(1-f2).NOIR] + */ \ /* [(f1-0).(f2-0).BLANC] */ \ /* */ \ /* puisqu'il permet de marquer les lignes de crete (en NOIR, en BLANC,...). */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ store_point_valide(GENP(COND(I3ET(IL_NE_FAUT_PAS(visualiser_la_falaise_avant_de_la_montagne) \ ,IFEQ(Y,Ylast_trace) \ ,IFNE(ordonnee_courante,ASI2(vecteur_vertical,extremite,y)) \ ) \ ,CLIPPING_INTENSITE \ ,MAX2(intensite_courante_utilisee \ ,MIN_INTENSITE \ ) \ ) \ ) \ ,imageAR \ ,abscisse_courante \ ,ordonnee_courante \ ,FVARIABLE \ ); \ /* Rangement du point courant... */ \ \ Test(IFET(EST_VRAI(c_est_la_phase_d_anti_aliasing) \ ,IL_FAUT(Imontagnes_precises_____interpoler_le_Z_Buffer_lors_de_l_anti_aliasing) \ ) \ ) \ Bblock \ EGAL(Zf_courant,Zf_courant_vecteur_vertical); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ /* Maintenant que 'Zf_courant' a ete utilise precedemment pour tester le 'Z-Buffer' */ \ /* on va le mettre a jour avec 'Zf_courant_vecteur_vertical' et non avec 'Zf_courant'. En */ \ /* effet si on avait donne des le debut de 'TEST_Z_Buffer_(...)' a 'Zf_courant' */ \ /* la valeur 'Zf_courant_vecteur_vertical' les points du segment "anti-aliase" courant */ \ /* aurait pu se trouver memorise avec des 'Z' incoherents : c'est le cas ou l'interpolation */ \ /* du 'Z' a lieu avec un point du fond qui est donc en quelque sorte a l'infini... */ \ ) \ ); \ Eblock \ /* Trace du point 3D de coordonnees : */ \ /* */ \ /* x = ASI2(vecteur_vertical,origine,x), */ \ /* y = ordonnee_courante, */ \ /* z = _____cNORMALISE_OZ(ADD2(Yfirst_trace,SOUS(Ylast_trace,Y))). */ \ /* */ \ /* On notera qu'autrefois on utilisait (ce qui donnait une montagne situee du */ \ /* cote des 'Z' negatifs, c'est-a-dire a l'oppose de l'observateur) : */ \ /* */ \ /* z = _____cNORMALISE_OZ(SOUS(Ylast_trace,Y)), */ \ /* */ \ /* maintenant, on translate de 'Yfirst_trace'... */ \ /* */ \ /* Le 19970116144453, la mise en place de 'CLIPPING_INTENSITE' a ete inhibe meme lorsque */ \ /* 'Y' vaut 'Ylast_trace' et ce lorsque l'on est a l'extremite du vecteur vertical courant. */ DEFV(Common,DEFV(Float,SINT(Imontagnes_precises_____translation_de_la_coordonnee_Z_lors_d_une_vue_d_avion,FZERO))); /* Introduit le 20080214130808 lors de la regeneration de 'v $xiirf/PAYS.R5$M' pour laquelle */ /* 'facteur_d_echelle' est negatif ce qui provoquait alors des 'Zf' tous negatifs ci-apres */ /* dans 'TRACE_POINT_3D_VUE_D_AVION(...)' et donc des points invisibles... */ #define TRACE_POINT_3D_VUE_D_AVION(X,Y,Zf) \ Bblock \ TEST_Z_Buffer_(X,Y,ADD2(Zf,Imontagnes_precises_____translation_de_la_coordonnee_Z_lors_d_une_vue_d_avion) \ ,BLOC(store_point_valide(GENP(MAX2(ARRONDI_NIVEAU(intensite_extremite) \ ,MIN_INTENSITE \ ) \ ) \ ,imageAR \ ,X \ ,Y \ ,FVARIABLE \ ); \ ) \ ); \ Eblock \ /* Trace du point 3D de coordonnees (X,Y,z) vu d'avion. ATTENTION, il y a eu pendant */ \ /* longtemps ici : */ \ /* */ \ /* TEST_Z_Buffer_(X,Y,_____cNORMALISE_OZ(ASI2(vecteur_vertical,extremite,y)) */ \ /* */ \ /* ce qui donnait en fait un 'Z' incorrect (par definition du vecteur a tracer, et en */ \ /* particulier de 'ASI2(vecteur_vertical,extremite,y)'), d'ou l'introduction de la veritable */ \ /* coordonnee 'z' le 1996053000. */ DEFV(Common,DEFV(Logical,SINT(Imontagnes_precises_____compatibilite_20100223,FAUX))); /* Le 20100223170213 une variante a ete introduite lors des tests du probleme */ /* 'v $xiii/montagnes$FON 20100220204800'. En activant cette option (impliquant un */ /* comportement d'ailleurs plus logique) on y perd en anti-aliasing sur les pentes de */ /* droite des montagnes... */ #define NOMBRE_DE_PAS_D_INTERPOLATION_DE_L_INTENSITE(origine,extremite) \ OPC1(IL_FAUT(Imontagnes_precises_____compatibilite_20100223) \ ,TRMU \ ,TRPU \ ,LENG(origine,extremite) \ ) \ /* Calcul du nombre de pas d'interpolation necessaires au calcul de l'intensite courante. On */ \ /* verra avec interet le commentaire relatif a 'DEFV(Int,INIT(longueur_pour_intensite,...))' */ \ /* un peu plus loin... */ \ /* */ \ /* Avant le 20100223102733 le 'TRMU(...)' etait un 'TRPU(...)' et l'une des causes */ \ /* principales du probleme 'v $xiii/montagnes$FON 20100220204800'... */ #define NOMBRE_DE_PAS_D_INTERPOLATION_DE_LA_PROFONDEUR(origine,extremite) \ TRMU(LENG(origine,extremite)) \ /* Calcul du nombre de pas d'interpolation necessaires au calcul de la profondeur courante. */ DEFV(Common,DEFV(Logical,SINT(Itrace_segment_vertical_____editer_la_coordonnee_Z_d_un_point,FAUX))); DEFV(Common,DEFV(Int,SINT(Itrace_segment_vertical_____coordonnee_X_du_point_dont_on_veut_la_coordonnee_Z,k___Xmin))); DEFV(Common,DEFV(Int,SINT(Itrace_segment_vertical_____coordonnee_Y_du_point_dont_on_veut_la_coordonnee_Z,k___Ymin))); /* Introduit le 20240330120041 a des fins de test... */ DEFV(Local,DEFV(FonctionI,Itrace_segment_vertical(imageAR ,vue_d_avion ,ARGUMENT_POINTERs(vecteur_vertical),Yf_origine,Yf_extremite ,X,Y,Zf ,intensite_origine,intensite_extremite ,Zf_extremite ,c_est_la_phase_d_anti_aliasing ,anti_aliasing ) ) ) DEFV(Argument,DEFV(image,imageAR)); /* Image a la fois Argument et Resultat... */ DEFV(Argument,DEFV(Logical,vue_d_avion)); /* Indique le mode de representation : vue d'avion ('VRAI') ou vue de cote ('FAUX'). */ DEFV(Argument,DEFV(vectorI_2D,POINTERs(vecteur_vertical))); DEFV(Argument,DEFV(Float,Yf_origine)); DEFV(Argument,DEFV(Float,Yf_extremite)); /* Vecteur vertical argument. */ DEFV(Argument,DEFV(Int,X)); DEFV(Argument,DEFV(Int,Y)); DEFV(Argument,DEFV(Float,Zf)); /* Coordonnees (X,Y,Zf) dans le champ ; ces arguments ne sont utilises que pour les vues */ /* d'avion... */ DEFV(Argument,DEFV(Float,intensite_origine)); /* Intensite lumineuse du point bas ("origine") du vecteur, */ DEFV(Argument,DEFV(Float,intensite_extremite)); /* Intensite lumineuse du point haut ("extremite") du vecteur. */ DEFV(Argument,DEFV(Float,Zf_extremite)); /* Coordonnee 'Z' du point haut ("extremite") du vecteur. */ DEFV(Argument,DEFV(Logical,c_est_la_phase_d_anti_aliasing)); /* Indique si c'est la phase d'anti-aliasing ('VRAI') ou pas ('FAUX') */ /* sur le vecteur courant. */ DEFV(Argument,DEFV(Logical,anti_aliasing)); /* Indique s'il faut faire ('VRAI') ou pas ('FAUX') de l'anti-aliasing */ /* sur l'image Resultat. Ceci fut introduit le 20061220094855 suite a l'usage qui en */ /* est fait dorenavant dans 'TRACE_POINT_3D(...)'. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock INIT_ERROR; /* ATTENTION : 'INIT_ERROR' est mis en tete des variables locales au cas ou des couples */ /* ('BDEFV','EDEFV') suivraient... */ DEFV(Int,INIT(ordonnee_courante,UNDEF)); /* Ordonnee courante lors du marquage du vecteur vertical. */ DEFV(Float,INIT(intensite_courante ,COND(IFNE(ASI2(vecteur_vertical,origine,y),ASI2(vecteur_vertical,extremite,y)) ,NEUT(intensite_extremite) ,MOYE(intensite_origine,intensite_extremite) ) ) ); /* Intensite lumineuse courante lors du marquage du vecteur. */ DEFV(Float,INIT(pas_intensite,SOUS(intensite_origine,intensite_extremite))); /* Pas de passage de l'intensite "haute" a l'intensite "basse". */ DEFV(Float,INIT(Zf_courant_vecteur_vertical,COND(EST_VRAI(c_est_la_phase_d_anti_aliasing),Zf_extremite,FLOT__UNDEF))); /* Coordonnee 'Z' courante lors du marquage du vecteur. */ DEFV(Float,INIT(pas_Zf ,COND(EST_VRAI(c_est_la_phase_d_anti_aliasing) ,SOUS(_____cNORMALISE_OZ(ADD2(Yfirst_trace,SOUS(Ylast_trace,Y))),Zf_extremite) ,FLOT__UNDEF ) ) ); /* Pas de passage de la coordonnee 'Z' "haute" a la coordonnee 'Z' "basse". */ DEFV(Int,INIT(longueur_pour_intensite,NOMBRE_DE_PAS_D_INTERPOLATION_DE_L_INTENSITE(ASI2(vecteur_vertical,origine,y) ,ASI2(vecteur_vertical,extremite,y) ) ) ); /* Longueur du vecteur a tracer plus deux unites afin de generer correctement les niveaux */ /* d'un vecteur reduit a un point. En particulier, on notera le 'TRPU(LENG(...))' qui, par */ /* exemple, permet la chose suivante : */ /* */ /* soit un vecteur reduit a un point (extremite=origine) ; d'apres la formule ci-dessus, */ /* on a : */ /* */ /* longueur = 2. */ /* */ /* imaginons de plus que : */ /* */ /* intensite_origine = NOIR, */ /* intensite_extremite = BLANC, */ /* */ /* le pas d'interpolation de l'intensite reellement utilise sera donc : */ /* */ /* BLANC - NOIR */ /* pas_intensite = -------------- */ /* 2 */ /* */ /* le seul point du vecteur sera donc marque en GRIS, ce qui represente le bon intermediaire */ /* entre la basse et la haute intensite... */ DEFV(Int,INIT(longueur_pour_profondeur,NOMBRE_DE_PAS_D_INTERPOLATION_DE_LA_PROFONDEUR(ASI2(vecteur_vertical,origine,y) ,ASI2(vecteur_vertical,extremite,y) ) ) ); /* Longueur fictive du vecteur a tracer afin de generer correctement les profondeurs... */ /*..............................................................................................................................*/ PUSH_MASQUE; /* Sauvegarde de l'etat de masquage avant le trace, */ DEMASQUE_IMAGES; /* Et on le desactive ; car en effet, le masque correspond au champ, et donc */ /* au "sol" de la montagne, et non pas a sa projection sur l'ecran... */ Test(IL_FAUT(vue_d_avion)) Bblock TRACE_POINT_3D_VUE_D_AVION(X,Y,Zf); /* Lors d'une vue d'avion, il n'y a pas de translation ; malgre cela, */ /* on genere simultanement le Z_Buffer, qui en fait ne sert a rien au niveau */ /* de l'elimination des lignes cachees de la montagne (vu le principe de */ /* construction), mais qui permet ensuite d'integrer une structure 3D autour */ /* de la montagne (par exemple en graphique). */ Test(IL_FAUT(Imontagnes_precises_____compatibilite_20090130)) /* Test introduit le 20090130181639... */ Bblock Test(IFEQ(Y,Ylast_trace)) /* Lorsque l'on est sur la ligne 'Ylast_trace', etant donne que les lignes [Ymin,Ylast] */ /* qui la precedent ne seront jamais traitees "normalement", on les remplit ci-apres */ /* arbitrairement par duplication du niveau courant 'intensite_extremite' via la procedure */ /* 'TRACE_POINT_3D_VUE_D_AVION(...)'. */ Bblock begin_colonneQ(DoIn,Ymin,Ylast,pasY) Bblock TRACE_POINT_3D_VUE_D_AVION(X,Y,Zf); Eblock end_colonneQ(EDoI) /* Lors d'une vue d'avion, on triche un peu en dupliquant afin de remplir les lignes */ /* non generees [Ymin,AVANT(Ylast)] et [Yfirst,Ymax]. */ Eblock ATes Bblock Eblock ETes Test(IFEQ(Y,Yfirst_trace)) /* Lorsque l'on est sur la ligne 'Yfirst_trace', etant donne que les lignes [Yfirst,Ymax] */ /* qui la suivent ne seront jamais traitees "normalement", on les remplit ci-apres */ /* arbitrairement par duplication du niveau courant 'intensite_extremite' via la procedure */ /* 'TRACE_POINT_3D_VUE_D_AVION(...)'. */ Bblock begin_colonneQ(DoDe,Yfirst,Ymax,pasY) Bblock TRACE_POINT_3D_VUE_D_AVION(X,Y,Zf); Eblock end_colonneQ(EDoD) /* Lors d'une vue d'avion, on triche un peu en dupliquant afin de remplir les lignes */ /* non generees [Ymin,AVANT(Ylast)] et [Yfirst,Ymax]. */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Test(IFNE(ASI2(vecteur_vertical,origine,x),ASI2(vecteur_vertical,extremite,x))) Bblock PRINT_ERREUR("les abscisses argument sont mauvaises"); CAL1(Prer1("X(origine) =%d\n",ASI2(vecteur_vertical,origine,x))); CAL1(Prer1("Y(origine) =%d\n",ASI2(vecteur_vertical,origine,y))); CAL1(Prer1("X(extremite)=%d\n",ASI2(vecteur_vertical,extremite,x))); CAL1(Prer1("Y(extremite)=%d\n",ASI2(vecteur_vertical,extremite,y))); Eblock ATes Bblock Eblock ETes Test(IFET(IFGT(ASI2(vecteur_vertical,origine,y),ASI2(vecteur_vertical,extremite,y)) ,EST_INACTIF(EnTete_de_sauvegardM ## Masque_____etat) ) ) Bblock PRINT_ERREUR("les ordonnees argument sont mauvaises"); CAL1(Prer1("X(origine) =%d\n",ASI2(vecteur_vertical,origine,x))); CAL1(Prer1("Y(origine) =%d\n",ASI2(vecteur_vertical,origine,y))); CAL1(Prer1("X(extremite)=%d\n",ASI2(vecteur_vertical,extremite,x))); CAL1(Prer1("Y(extremite)=%d\n",ASI2(vecteur_vertical,extremite,y))); Eblock ATes Bblock Eblock ETes EGAL(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_montagne ,MAX2(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_montagne ,_____cNORMALISE_OY(MAX2(ASI2(vecteur_vertical,origine,y) ,ASI2(vecteur_vertical,extremite,y) ) ) ) ); /* Recherche de la plus grande ordonnee dans [0,1] sur l'ensemble de la montagne. */ Test(IFEQ(Y,Ylast_trace)) Bblock EGAL(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_last_ligne_de_la_montagne ,MAX2(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_last_ligne_de_la_montagne ,_____cNORMALISE_OY(MAX2(ASI2(vecteur_vertical,origine,y) ,ASI2(vecteur_vertical,extremite,y) ) ) ) ); /* Recherche de la plus grande ordonnee dans [0,1] sur la 'last' ligne de la montagne. */ Eblock ATes Bblock Eblock ETes Test(IFET(IZGT(longueur_pour_intensite) ,IFGE(longueur_pour_intensite,NOMBRE_DE_PAS_D_INTERPOLATION_DE_L_INTENSITE(UNDEF,UNDEF)) ) ) Bblock EGAL(pas_intensite,DIVI(pas_intensite,FLOT(longueur_pour_intensite))); /* On ramene le pas de l'intensite au nombre de points a marquer... */ Eblock ATes Bblock CLIR(pas_intensite); Eblock ETes Test(EST_VRAI(c_est_la_phase_d_anti_aliasing)) Bblock Test(IZGT(longueur_pour_profondeur)) Bblock EGAL(pas_Zf,DIVI(pas_Zf,FLOT(longueur_pour_profondeur))); /* On ramene le pas de la coordonnee 'Z' au nombre de points a marquer... */ Eblock ATes Bblock CLIR(pas_Zf); Eblock ETes Eblock ATes Bblock Eblock ETes Test(IL_FAUT(Itrace_segment_vertical_____editer_la_coordonnee_Z_d_un_point)) /* Possibilite introduite le 20240330120041... */ Bblock Test(IFET(IFEQ(X,Itrace_segment_vertical_____coordonnee_X_du_point_dont_on_veut_la_coordonnee_Z) ,IFEQ(Y,Itrace_segment_vertical_____coordonnee_Y_du_point_dont_on_veut_la_coordonnee_Z) ) ) /* On notera qu'il est fort possible que ce test soit toujours FAUX pour un champ donne... */ Bblock CAL3(Prme2("Y(OrigineVecteur)=%d Y(ExtremiteVecteur)=%d\n" ,ASI2(vecteur_vertical,origine,y) ,ASI2(vecteur_vertical,extremite,y) ) ); CAL3(Prme3("X=%d Y=%d Z=%d\n" ,X ,Y ,MAX2(ASI2(vecteur_vertical,origine,y),ASI2(vecteur_vertical,extremite,y)) ) ); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Test(IFLE(ASI2(vecteur_vertical,origine,y),ASI2(vecteur_vertical,extremite,y))) Bblock /* Trace des vecteurs des faces "avant", c'est-a-dire les vecteurs qui sont */ /* toujours visibles (jusqu'a ce qu'une eventuelle face placee plus pres de */ /* l'observateur vienne ulterieurement le masquer...) : */ /* */ /* * extremite */ /* /|\ */ /* | */ /* | */ /* | */ /* | */ /* * origine */ /* */ DoDe(ordonnee_courante,ASI2(vecteur_vertical,origine,y),ASI2(vecteur_vertical,extremite,y),pasY) Bblock Test(IL_NE_FAUT_PAS(Imontagnes_precises_____compatibilite_20100223)) Bblock INCR(intensite_courante,pas_intensite); /* Dans ce cas ('compatibilite_20100223=FAUX') lors de l'interpolation entre les niveaux */ /* 'N1' et 'N2', en fait les niveaux marques seront dans [N1+k,N2-k] (en supposant N1<N2), */ /* ce qui assure un bon anti-aliasing sur les pentes a droite. */ Eblock ATes Bblock Eblock ETes TRACE_POINT_3D(c_est_la_phase_d_anti_aliasing); /* On genere simultanement le Z_Buffer, qui en fait ne sert a rien au niveau */ /* de l'elimination des lignes cachees de la montagne (vu le principe de */ /* construction), mais qui permet ensuite d'integrer une structure 3D autour */ /* de la montagne (par exemple en graphique). */ Test(IL_FAUT(Imontagnes_precises_____compatibilite_20100223)) Bblock INCR(intensite_courante,pas_intensite); /* Dans ce cas ('compatibilite_20100223=VRAI') lors de l'interpolation entre les niveaux */ /* 'N1' et 'N2', les niveaux marques seront bien dans [N1,N2] ce qui provoque des defauts */ /* d'aliasing sur les pentes a droite. */ Eblock ATes Bblock Eblock ETes INCR(Zf_courant_vecteur_vertical,pas_Zf); Eblock EDoD Eblock ATes Bblock /* Trace des vecteurs des faces "arriere", c'est-a-dire les vecteurs qui sont */ /* theoriquement invisibles, sauf a travers des "trous" crees par l'effet du */ /* Masque : */ /* */ /* * origine */ /* /|\ */ /* | */ /* | */ /* | */ /* | */ /* * extremite */ /* */ DoIn(ordonnee_courante,ASI2(vecteur_vertical,extremite,y),ASI2(vecteur_vertical,origine,y),pasY) Bblock Test(IL_NE_FAUT_PAS(Imontagnes_precises_____compatibilite_20100223)) Bblock INCR(intensite_courante,pas_intensite); /* Dans ce cas ('compatibilite_20100223=FAUX') lors de l'interpolation entre les niveaux */ /* 'N1' et 'N2', en fait les niveaux marques seront dans [N1+k,N2-k] (en supposant N1<N2), */ /* ce qui assure un bon anti-aliasing sur les pentes a droite. */ Eblock ATes Bblock Eblock ETes TRACE_POINT_3D(c_est_la_phase_d_anti_aliasing); /* On genere simultanement le Z_Buffer, qui en fait ne sert a rien au niveau */ /* de l'elimination des lignes cachees de la montagne (vu le principe de */ /* construction), mais qui permet ensuite d'integrer une structure 3D autour */ /* de la montagne (par exemple en graphique). */ Test(IL_FAUT(Imontagnes_precises_____compatibilite_20100223)) Bblock INCR(intensite_courante,pas_intensite); /* Dans ce cas ('compatibilite_20100223=VRAI') lors de l'interpolation entre les niveaux */ /* 'N1' et 'N2', les niveaux marques seront bien dans [N1,N2] ce qui provoque des defauts */ /* d'aliasing sur les pentes a droite. */ Eblock ATes Bblock Eblock ETes INCR(Zf_courant_vecteur_vertical,pas_Zf); Eblock EDoI Eblock ETes Eblock ETes PULL_MASQUE; /* Restauration de l'etat de masquage apres le trace, et ce avant l'eventuel */ /* trace suivant... */ Test(IFET(IFGT(Xlast,Xmin) ,IFEQ(INTX(ASI2(vecteur_vertical,origine,x)),Xlast) ) ) Bblock DEFV(vectorI_2D,premiere_colonne); /* Lorsque l'on est en presence de la colonne 'Xlast', on trace simultanement */ /* sa voisinne de gauche ('Xmin' en general...) qui en fait n'est pas calculee ; */ /* ce vecteur la contient. */ INITIALISATION_VECTEUR_2D(premiere_colonne ,vPREX(ASI2(vecteur_vertical,origine,x)) ,vNEUT(ASI2(vecteur_vertical,origine,y)) ,vPREX(ASI2(vecteur_vertical,extremite,x)) ,vNEUT(ASI2(vecteur_vertical,extremite,y)) ); TRACE_VECTEUR_VERTICAL(imageAR ,premiere_colonne ,Yf_origine,Yf_extremite ,vPREX(X),Y,Zf ,CE_N_EST_PAS_LA_PHASE_D_ANTI_ALIASING ); /* Ainsi, on triche un peu, en dupliquant la colonne de gauche... */ Eblock ATes Bblock Eblock ETes RETU_ERROR; Eblock #undef NOMBRE_DE_PAS_D_INTERPOLATION_DE_LA_PROFONDEUR #undef NOMBRE_DE_PAS_D_INTERPOLATION_DE_L_INTENSITE #undef TRACE_POINT_3D_VUE_D_AVION #undef TRACE_POINT_3D #undef visualiser_la_falaise_avant_de_la_montagne #undef ARRONDI_NIVEAU EFonctionI /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D E L A S P E C U L A R I T E : */ /* */ /*************************************************************************************************************************************/ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____source_lumineuse_specularite,FU))); /* Definition de la specularite introduite le 20130101105228 en garantissant la */ /* compatibilite anterieure... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D U " D E P T H - C U E I N G " G E N E R A L I S E : */ /* */ /*************************************************************************************************************************************/ DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____depth_cueing_ponderation_niveau,FU))); DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____depth_cueing_ponderation_coordonnee_X,FZERO))); DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____depth_cueing_ponderation_coordonnee_Y,FZERO))); DEFV(Common,DEFV(Float,ZINT(Imontagnes_precises_____depth_cueing_translation,FZERO))); /* A compter du 19970908091406, le niveau calcule 'intensite_origine' (appele par la suite */ /* 'N' pour "niveau") subit avant d'etre utilise pour le trace la transformation lineaire */ /* suivante : */ /* */ /* (pN.N) + (pX.f(X)) + (pY.f(Y)) + t */ /* */ /* ou 'f(...)' represente une fonction qui fait passer d'abord les coordonnees dans [0,1] */ /* puis dans [NOIR,BLANC]. */ /* */ /* Ceci permet donc, par exemple, d'implementer de facon triviale un "depth-cueing" ou */ /* chacun des plans verticaux est represente par un code different des autres (aux */ /* restrictions pres du nombre de couleurs disponibles) tout en etant "anti-aliase" en */ /* faisant : */ /* */ /* pN = 0 */ /* pX = 0 */ /* pY = -1 */ /* t = BLANC */ /* */ /* ('v $xiirf/PAYS.R7$M'). */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N S D E S " B U G S " P R E S E N T S : */ /* */ /*************************************************************************************************************************************/ #ifdef BUG_SYSTEME_C_complexite_02 /* Common,DEFV(Fonction,) : bug... */ DEFV(Common,DEFV(Logical,_____BUG_SYSTEME_C_complexite_02)); #Aifdef BUG_SYSTEME_C_complexite_02 /* Common,DEFV(Fonction,) : bug... */ #Eifdef BUG_SYSTEME_C_complexite_02 /* Common,DEFV(Fonction,) : bug... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M I S E E N M O N T A G N E S " P R E C I S E " D ' U N E I M A G E : */ /* */ /*************************************************************************************************************************************/ /* ATTENTION, on introduit deux fonctions 'Imontagnes(...)' et 'Imontagnes_precises(...)' */ /* qui sont de toute evidence inutiles en 'TYPE_DE_imageA_surface_VERSION_01' mais dont la */ /* presence permet de simplifier considerablement la coexistence des deux versions... */ #define POSITION_DANS_LA_ZONE_DE_PENOMBRE(position) \ COND(IZGT(pente_rayon_lumineux),DIVI(position,pente_rayon_lumineux),FLOT(INFINI)) \ /* Calcul de la largeur de la zone de penombre en fonction de la pente du rayon lumineux */ \ /* courant ; on notera la prise en compte des rayons lumineux horizontaux... */ #ifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : pour la 'VERSION_01'. */ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Imontagnes_precises(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,nettoyer ,ARGUMENT_POINTERs(translation) ,ombres_portees,largeur_zone_penombre ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ,vue_d_avion ,anti_aliasing ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, qui est une vue texturee de la surface. */ DEFV(Argument,DEFV(Float,facteur_d_echelle)); /* Facteur d'echelle permettant de moduler le champ contenu dans 'imageA_surface', */ /* et par exemple de l'inverser. On notera bien que les parametres 'facteur_d_echelle' et */ /* 'Imontagnes_precises_____facteur_de_correction_perspective' interferent l'un avec */ /* l'autre comme cela est documente lors de la definition de ce dernier... */ /* Le 20020211111705, j'ai remarque que les deux parametres 'facteur_d_echelle' */ /* et 'Imontagnes_precises_____facteur_de_correction_perspective' devaient etre de meme */ /* signe... */ DEFV(Argument,DEFV(image,imageA_surface)); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface, */ DEFV(Argument,DEFV(image,imageA_texture)); /* Deuxieme image Argument, qui donne la texture de la surface. */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Logical,nettoyer)); /* Indicateur demandant ('VRAI') ou pas ('FAUX') la mise a noir */ /* de l'image 'imageR'. */ DEFV(Argument,DEFV(deltaF_2D,POINTERs(translation))); /* Translation horizontale ('dx') et verticale ('dy') de la montagne dans l'image */ /* Resultat exprimee en nombre de points de la matrice "imageR" ; on n'oubliera */ /* pas que cette translation est exprimee dans des unites telles que l'unite vaut */ /* respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,ombres_portees)); /* Les ombres portees doivent-elles etre presentes ('VRAI') ou non ('FAUX'). */ DEFV(Argument,DEFV(Float,largeur_zone_penombre)); /* Donne la largeur de la zone de penombre (valeur arbitraire, mais une valeur de */ /* l'ordre de la dizaine donne de bons resultats...). */ DEFV(Argument,DEFV(pointF_2D,POINTERs(source_lumineuse))); /* Donne dans le plan de l'image Resultat ('imageR'), les coordonnees de */ /* la source lumineuse ; ces coordonnees sont exprimees dans des unites */ /* telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,depth_cueing)); /* Doit-on faire ('VRAI') ou pas ('FAUX') du depth-cueing ? */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Float,min_depth_cueing)); /* Ce parametre est inclus dans le segment [0,1] ; plus il est */ /* proche de zero, plus, le "depth-cueing" est fort... */ DEFV(Argument,DEFV(Logical,vue_d_avion)); /* Definit le mode de representation : 'VRAI' donne une vue de dessus, */ /* alors que 'FAUX' donne une vue de cote. */ DEFV(Argument,DEFV(Logical,anti_aliasing)); /* Indique s'il faut faire ('VRAI') ou pas ('FAUX') de l'anti-aliasing */ /* sur l'image Resultat. */ /* */ /* Le 20011227173520 (c'est-a-dire un peu tard...) j'ai remarque que cet "anti-aliasing" */ /* qui est fait par interpolation entre les niveaux anterieurs des points extremes des */ /* segments verticaux, ne prenait pas en compte les niveaux anterieurs des points */ /* intermediaires de ces segments. Ceci peut donc avoir des consequences visibles, en */ /* particulier en ce qui concerne les vecteurs verticaux les plus longs sur un fond varie... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ #Aifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : pour la 'VERSION_01'. */ #Eifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : pour la 'VERSION_01'. */ #ifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : pour la 'VERSION_02'. */ BFonctionP DEFV(Common,DEFV(Float,SINT(Imontagnes_precises_____Ay_reduit,FU))); DEFV(Common,DEFV(Float,SINT(Imontagnes_precises_____By_reduit,FZERO))); /* Introduit le 20140627115130 afin de pouvoir, par exemple, inverser le "depth-cueing" */ /* ('v $xiirf/PAYU.I1$M' ou encore 'v $xiirf/PAYU.I2$M')... */ DEFV(Common,DEFV(FonctionP,POINTERp(Imontagnes_precises(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,nettoyer ,ARGUMENT_POINTERs(translation) ,ombres_portees,largeur_zone_penombre ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ,vue_d_avion ,anti_aliasing ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, qui est une vue texturee de la surface. */ DEFV(Argument,DEFV(Float,facteur_d_echelle)); /* Facteur d'echelle permettant de moduler le champ contenu dans 'imageA_surface', */ /* et par exemple de l'inverser. On notera bien que les parametres 'facteur_d_echelle' et */ /* 'Imontagnes_precises_____facteur_de_correction_perspective' interferent l'un avec */ /* l'autre comme cela est documente lors de la definition de ce dernier... */ /* Le 20020211111705, j'ai remarque que les deux parametres 'facteur_d_echelle' */ /* et 'Imontagnes_precises_____facteur_de_correction_perspective' devaient etre de meme */ /* signe... */ DEFV(Argument,DEFV(imageF,imageA_surface)); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface, */ DEFV(Argument,DEFV(image,imageA_texture)); /* Deuxieme image Argument, qui donne la texture de la surface. */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Logical,nettoyer)); /* Indicateur demandant ('VRAI') ou pas ('FAUX') la mise a noir */ /* de l'image 'imageR'. */ DEFV(Argument,DEFV(deltaF_2D,POINTERs(translation))); /* Translation horizontale ('dx') et verticale ('dy') de la montagne dans l'image */ /* Resultat exprimee en nombre de points de la matrice "imageR" ; on n'oubliera */ /* pas que cette translation est exprimee dans des unites telles que l'unite vaut */ /* respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,ombres_portees)); /* Les ombres portees doivent-elles etre presentes ('VRAI') ou non ('FAUX'). */ DEFV(Argument,DEFV(Float,largeur_zone_penombre)); /* Donne la largeur de la zone de penombre (valeur arbitraire, mais une valeur de */ /* l'ordre de la dizaine donne de bons resultats...). */ DEFV(Argument,DEFV(pointF_2D,POINTERs(source_lumineuse))); /* Donne dans le plan de l'image Resultat ('imageR'), les coordonnees de */ /* la source lumineuse ; ces coordonnees sont exprimees dans des unites */ /* telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,depth_cueing)); /* Doit-on faire ('VRAI') ou pas ('FAUX') du depth-cueing ? */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Float,min_depth_cueing)); /* Ce parametre est inclus dans le segment [0,1] ; plus il est */ /* proche de zero, plus, le "depth-cueing" est fort... */ DEFV(Argument,DEFV(Logical,vue_d_avion)); /* Definit le mode de representation : 'VRAI' donne une vue de dessus, */ /* alors que 'FAUX' donne une vue de cote. */ DEFV(Argument,DEFV(Logical,anti_aliasing)); /* Indique s'il faut faire ('VRAI') ou pas ('FAUX') de l'anti-aliasing */ /* sur l'image Resultat. */ /* */ /* Le 20011227173520 (c'est-a-dire un peu tard...) j'ai remarque que cet "anti-aliasing" */ /* qui est fait par interpolation entre les niveaux anterieurs des points extremes des */ /* segments verticaux, ne prenait pas en compte les niveaux anterieurs des points */ /* intermediaires de ces segments. Ceci peut donc avoir des consequences visibles, en */ /* particulier en ce qui concerne les vecteurs verticaux les plus longs sur un fond varie... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ #Aifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : pour la 'VERSION_02'. */ #Eifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : pour la 'VERSION_02'. */ Bblock DEFV(Float,INIT(facteur_d_ajustement_de_l_equation_de_la_surface ,DIVI(FLOT(COULEURS) ,FLOT(k___dimY) ) ) ); /* Ce facteur d'ajustement est lie au fait que l'echelle des niveaux de gris [NOIR,BLANC] */ /* d'une image ne change jamais, alors que le format d'une image, lui, le peut (via le */ /* format [dimX,dimY]). Ainsi pour eviter d'avoir des montagnes tres hautes dans une toute */ /* petite image (par exemple en mode 'Suq'), il faut reajuster les niveaux... */ DEFV(Float,INIT(pente_rayon_lumineux,FLOT__UNDEF)); /* Pente de la droite allant de la source lumineuse au point de cote */ /* maximale courant, en faisant les hypotheses suivantes : */ /* */ /* 1 - on trace la "montagne" de la droite vers la gauche, */ /* 2 - on suppose ce rayon lumineux contenu dans le plan vertical courant, */ /* */ /* enfin, cette pente vaut : (Ymax-Ysource)/(Xmax-Xsource) ; elle */ /* donne aussi ce que j'appelle le seuil de visibilite depuis la source */ /* lumineuse. */ DEFV(Logical,INIT(initialisation_pente_rayon_lumineux,LUNDEF)); /* Indicateur d'initialisation de "pente_rayon_lumineux" ; tant que la pente n'a */ /* pas ete calculee, et que l'initialisation est donc a faire, cet indicateur */ /* vaut 'VRAI', puis ensuite 'FAUX'. */ DEFV(vectorI_2D,vecteur_vertical); DEFV(Float,INIT(Yf_origine,FLOT__UNDEF)); DEFV(Float,INIT(Yf_extremite,FLOT__UNDEF)); /* Definition du vecteur vertical courant ; le point "origine" designe */ /* le point le plus bas, alors que le point "extremite" designe celui */ /* qui est le plus haut. La variable 'Yf_extremite' a ete introduite */ /* le 19970115125406 afin d'ameliorer le traitement anti-aliasing ; cette solution n'est */ /* certes pas tres elegante mais elle a l'avantage d'eviter de tout chambouler (il en est */ /* de meme pour la variable 'Yf_origine'). */ DEFV(Logical,INIT(premier_vecteur_vertical,LUNDEF)); /* Indicateur permettant de discriminer le premier vecteur vertical de chaque */ /* ligne ('VRAI') des autres ('FAUX') ; en fait, cet indicateur n'a de */ /* sens que lorsque l'anti-aliasing est demande... */ DEFV(Int,INIT(extremite_precedente,UNDEF)); /* Contient l'ordonnee 'y' de l'extremite du vecteur vertical precedent. */ DEFV(Int,INIT(sauvegarde_de_l_extremite,UNDEF)); /* Contient l'ordonnee 'y' de l'extremite du vecteur vertical courant. */ DEFV(Float,INIT(seuil_de_visibilite,FLOT__UNDEF)); /* Donne le seuil de visibilite depuis la source lumineuse. */ DEFV(Float,INIT(niveau_lumineux,MAX_NIVEAU_LUMINEUX)); /* Donne le niveau lumineux courant ; il est initialise sur le */ /* maximum, afin d'etre correct si l'ombrage n'est pas demande... */ DEFV(Float,INIT(y_reduit,FLOT__UNDEF)); /* Donne la coordonnee 'Y' reduite lors d'un depth-cueing dans [0,1[. */ DEFV(deltaF_3D,normale); /* Vecteur normal a la facette courante ; il est definit comme un accroissement, et non */ /* comme un vrai vecteur, car seule sa direction nous importe... */ DEFV(deltaF_3D,rayon_lumineux); /* Direction du rayon lumineux du point courant a la source lumineuse. */ DEFV(Float,INIT(intensite_extremite,FLOT__UNDEF)); /* Intensite lumineuse du point du haut d'un vecteur vertical. */ BDEFV(ligneF,liste_intensite_extremite); /* Liste des hautes intensites d'une ligne ; elle contient en fait une */ /* partie de celles de la ligne precedente, puis celle de la ligne courante. */ DEFV(Float,INIT(intensite_extremite_precedente,FLOT__UNDEF)); /* Contient l'intensite lumineuse du point du haut (c'est-a-dire l'extremite) */ /* du vecteur vertical precedent. */ DEFV(Float,INIT(sauvegarde_de_l_intensite_extremite,FLOT__UNDEF)); /* Contient l'intensite lumineuse du point du haut (c'est-a-dire l'extremite) */ /* du vecteur vertical courant. */ DEFV(Float,INIT(intensite_origine,FLOT__UNDEF)); /* Intensite lumineuse du point du bas d'un vecteur vertical. */ DEFV(Float,INIT(Zf_extremite,FLOT__UNDEF)); /* Coordonnee 'Z' du point du haut d'un vecteur vertical. */ /*..............................................................................................................................*/ BSaveModifyVariable(Logical ,Z_Buffer_____test_strict ,COND(IFET(IL_NE_FAUT_PAS(vue_d_avion) ,IL_NE_FAUT_PAS(Imontagnes_precises_____compatibilite_20100223) ) ,VRAI ,Z_Buffer_____test_strict ) ); Test(IL_FAUT(Imontagnes_precises_____verification_de_la_correction_perspective)) /* Test introduit le 20170413103352 lors de la regeneration de 'v $xiirf/PAYU.K3.21$M'. */ Bblock Test(IFOU(IFEXff(LAMBDA_DE_CORRECTION_PERSPECTIVE(Ymin),COORDONNEE_BARYCENTRIQUE_MINIMALE,COORDONNEE_BARYCENTRIQUE_MAXIMALE) ,IFEXff(LAMBDA_DE_CORRECTION_PERSPECTIVE(Ymax),COORDONNEE_BARYCENTRIQUE_MINIMALE,COORDONNEE_BARYCENTRIQUE_MAXIMALE) ) ) /* Test introduit le 20170413095025 lors de la regeneration de 'v $xiirf/PAYU.K3.21$M'. */ Bblock PRINT_ATTENTION("certains parametres ne sont pas compatibles pour une correction perspective correcte"); CAL1(Prer2("lambda(%d)=%f\n",Ymin,LAMBDA_DE_CORRECTION_PERSPECTIVE(Ymin))); CAL1(Prer2("lambda(%d)=%f\n",Ymax,LAMBDA_DE_CORRECTION_PERSPECTIVE(Ymax))); CAL1(Prer1("facteur d'echelle=%f\n",facteur_d_echelle)); CAL1(Prer1("facteur de correction perspective=%f\n",Imontagnes_precises_____facteur_de_correction_perspective)); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes TesF(IFET(IL_FAUT(vue_d_avion) ,IL_FAUT(anti_aliasing) ) ) Bblock PRINT_ATTENTION("la vue d'avion demandee sera faite sans 'anti-aliasing'"); /* ATTENTION, on n'edite plus ce message qui parait relativement inutile ; de plus, il me */ /* semble faux puisque les images "vues d'avion" sont correctement calculees... */ Eblock ATes Bblock Eblock ETes Test(I3ET(IL_FAUT(vue_d_avion) ,IZLE(facteur_d_echelle) ,IZLE(Imontagnes_precises_____translation_de_la_coordonnee_Z_lors_d_une_vue_d_avion) ) ) /* Test introduit le 20080214135820 lors de la regeneration de 'v $xiirf/PAYS.R5$M'... */ Bblock PRINT_ATTENTION("une vue d'avion avec facteur d'echelle negatif demande une translation strictement positive de 'Z'"); Eblock ATes Bblock Eblock ETes Test(I3ET(IL_FAUT(anti_aliasing) ,IL_FAUT(Imontagnes_precises_____interpoler_le_Z_Buffer_lors_de_l_anti_aliasing) ,IFNE(Z_Buffer_____valeur_initiale,VALEUR_INITIALE_DU_Z_BUFFER_POUR_LES_MONTAGNES) ) ) Bblock PRINT_ATTENTION("la valeur d'initialisation du 'Z-Buffer' n'est pas compatible avec un eventuel effet de brume"); Eblock ATes Bblock Eblock ETes /* A la date du 20090308184756 j'ai reussi, sans trop de difficultes, a autoriser le */ /* texturage en l'absence d'ombres portees. Le 20090309170209, il en fut de meme pour */ /* le "depth-cueing"... */ Test(IFLE(_cDENORMALISE_OX(ASI1(source_lumineuse,x)),Xmax)) Bblock PRINT_ERREUR("l'abscisse 'X' de la source lumineuse doit etre superieure a 'Xmax'"); Eblock ATes Bblock Eblock ETes Test(IL_FAUT(nettoyer)) Bblock CALS(Inoir(imageR)); /* Nettoyage de l'image resultat. */ Eblock ATes Bblock Eblock ETes EGAL(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_montagne,PLUS_GRANDE_ORDONNEE_SUR_LA_MONTAGNE); EGAL(Itrace_segment_vertical_____plus_grande_ordonnee_sur_la_last_ligne_de_la_montagne,PLUS_GRANDE_ORDONNEE_SUR_LA_MONTAGNE); /* Initialisation de l'aide au cadrage automatique des montagnes ; on va ainsi detecter */ /* les plus grandes ordonnees (globalement sur l'ensemble de la montagne -pour avoir le */ /* plus haut- et sur la 'last' ligne -pour avoir le plus bas-). */ begin_ligne Bblock EGAL(LIGNE(liste_intensite_extremite,X,Ymin),FLOT__NOIR); Eblock end_ligne EGAL(ASD1(normale,dz),FLOT(ADD2(PasZ,PasZ))); /* La troisieme composante d'une normale a une facette vaut toujours 2, car elle est en */ /* fait la somme de deux normales calculees dans les triangles {A,B,C} et {D,B,C}. */ begin_colonne_back Bblock Test(IFET(IFLE(Y,Yfirst) ,IFGE(Y,Ylast_trace) ) ) Bblock EGAL(initialisation_pente_rayon_lumineux,VRAI); /* Ainsi, pour cette nouvelle coupe de la "montagne", on sait */ /* que la pente du rayon lumineux n'a pas encore ete calculee, */ /* et que l'initialisation est donc a faire... */ EGAL(premier_vecteur_vertical,VRAI); /* Ainsi, on indique que l'on va tracer le premier vecteur vertical ; en fait, */ /* cet indicateur n'a de sens que lorsque l'anti-aliasing est demande... */ Test(IL_FAUT(depth_cueing)) Bblock EGAL(y_reduit,__DENORMALISE_NIVEAU(_____cNORMALISE_OY(RENY(Y)))); /* Ainsi, on convertit la coordonnee 'Y' en un niveau... */ EGAL(y_reduit,AXPB(Imontagnes_precises_____Ay_reduit,y_reduit,Imontagnes_precises_____By_reduit)); /* Introduit le 20140627115130 afin de pouvoir, par exemple, inverser le "depth-cueing" */ /* ('v $xiirf/PAYU.I1$M' ou encore 'v $xiirf/PAYU.I2$M')... */ EGAL(y_reduit,______NORMALISE_NIVEAU(NIVA(MAX2(y_reduit,MIN_INTENSITE)))); /* En effet, on ne peut tracer en noir... */ Eblock ATes Bblock Eblock ETes begin_ligne_back Bblock Test(IFGE(X,Xlast)) Bblock PUSH_MASQUE; /* Sauvegarde de l'etat de masquage avant l'acces aux differentes images, */ DEMASQUE_IMAGES; /* Et on le desactive pour acceder a leur integralite... */ EGAL(ASD2(vecteur_vertical,origine,x) ,ADD2(X,_lDENORMALISE_OX(ASI1(translation,dx))) ); EGAL(ASD2(vecteur_vertical,extremite,x) ,ASD2(vecteur_vertical,origine,x) ); EGAL(Yf_origine ,ADD2(SOUS(z_point_suivant(X,Y) ,FLOT(SOUS(Ymax,DECALAGE_VERTICAL(Y))) ) ,F__lDENORMALISE_OY(ASI1(translation,dy)) ) ); EGAL(ASD2(vecteur_vertical,origine,y) ,ENTE(Yf_origine) ); EGAL(Yf_extremite ,ADD2(SOUS(z_point_courant(X,Y) ,FLOT(SOUS(Ymax,DECALAGE_VERTICAL(ARRIERE(Y)))) ) ,F__lDENORMALISE_OY(ASI1(translation,dy)) ) ); EGAL(ASD2(vecteur_vertical,extremite,y) ,ENTE(Yf_extremite) ); Test(IL_FAUT(ombres_portees)) Bblock Test(IL_NE_FAUT_PAS(initialisation_pente_rayon_lumineux)) /* ATTENTION : il ne faut pas optimiser le "if" ci-dessous en le */ /* remplacant par un "ATes", car lorsqu'IL_NE_FAUT_PAS, et que le 'z' du */ /* point courant est au-dessus du seuil, on force une initialisation du */ /* rayon lumineux... */ Bblock EGAL(seuil_de_visibilite ,AXPB(pente_rayon_lumineux ,SOUS(FLOT(X),F__cDENORMALISE_OX(ASI1(source_lumineuse,x))) ,F__cDENORMALISE_OY(ASI1(source_lumineuse,y)) ) ); Test(IFGT(z_point_courant(X,Y),seuil_de_visibilite)) Bblock EGAL(initialisation_pente_rayon_lumineux,VRAI); /* Lorsqu'on est visible depuis la source lumineuse, il faut mettre a jour la */ /* pente courante du rayon lumineux de visibilite... */ Eblock ATes Bblock DEFV(Float,INIT(penombre,FLOT__UNDEF)); /* Permet de calculer le degrade de penombre lorsqu'il y a lieu... */ EGAL(penombre,SOUS(seuil_de_visibilite,z_point_courant(X,Y))); /* Lorsqu'on est invisible depuis la source lumineuse, on est donc */ /* a l'ombre ; on regarde malgre tout si l'on est pas dans la penombre... */ Test(IFLE(penombre,largeur_zone_penombre)) /* ATTENTION, avant le 19980206162821, il y avait ici : */ /* */ /* Test(IFLT(penombre,POSITION_DANS_LA_ZONE_DE_PENOMBRE(largeur_zone_penombre))) */ /* */ /* ce qui avait des consequences facheuses quand des points de la surface etaient situes */ /* plus haut que la source lumineuse... */ Bblock /* Cas ou on est dans la penombre (entre l'ombre et la lumiere) : */ EGAL(niveau_lumineux ,SCAL(NEGA(ATTENUATION_A_L_OMBRE(MAX_NIVEAU_LUMINEUX)) ,POSITION_DANS_LA_ZONE_DE_PENOMBRE(largeur_zone_penombre) ,POSITION_DANS_LA_ZONE_DE_PENOMBRE(penombre) ) ); /* ATTENTION, ici, 'niveau_lumineux' est un niveau Relatif (de type 'NIVR(...)'). */ Eblock ATes Bblock /* Cas ou on est dans l'ombre "absolue" : */ EGAL(niveau_lumineux,NEGA(ATTENUATION_A_L_OMBRE(MAX_NIVEAU_LUMINEUX))); /* ATTENTION, ici, 'niveau_lumineux' est un niveau Relatif (de type 'NIVR(...)'). */ Eblock ETes INCR(niveau_lumineux,NIVA(MAX_NIVEAU_LUMINEUX)); /* ATTENTION, ici, 'niveau_lumineux' est devenu ici un niveau Absolu (de type 'NIVA(...)'). */ Eblock ETes Eblock ATes Bblock Eblock ETes Test(IL_FAUT(initialisation_pente_rayon_lumineux)) /* ATTENTION : il ne faut pas optimiser le "if" ci-dessus en le */ /* remplacant par un "ATes", car lorsqu'IL_NE_FAUT_PAS, et que le 'z' du */ /* point courant est au-dessus du seuil, on force une initialisation du */ /* rayon lumineux... */ Bblock EGAL(initialisation_pente_rayon_lumineux,FAUX); /* Ainsi, on sait que l'initialisation de la pente du rayon lumineux */ /* de visibilite a ete faite... */ EGAL(pente_rayon_lumineux ,DIVI(SOUS(z_point_courant(X,Y) ,F__cDENORMALISE_OY(ASI1(source_lumineuse,y)) ) ,SOUS(FLOT(X),F__cDENORMALISE_OX(ASI1(source_lumineuse,x))) ) ); EGAL(niveau_lumineux,MAX_NIVEAU_LUMINEUX); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock EGAL(niveau_lumineux,MAX_NIVEAU_LUMINEUX); /* Ceci fut introduit le 20090309170209 afin de rendre le "depth-cueing" ainsi que le */ /* texturage independants de l'ombrage. C'est pourquoi le 'Test(...)' qui precedait avant */ /* cette date, est passe apres... */ Eblock ETes Test(IL_FAUT(depth_cueing)) /* Le 20090309170209 le "depth-cueing" ainsi que le texturage sont devenus independants de */ /* l'ombrage... */ Bblock #if ( (! defined(BUG_SYSTEME_C_complexite_02)) \ ) EGAL(niveau_lumineux ,MAX2(NIVA(MUL2(BARY(y_reduit ,______NORMALISE_NIVEAU(MAX_NIVEAU_LUMINEUX) ,min_depth_cueing ) ,NIVR(niveau_lumineux) ) ) ,MIN_INTENSITE ) ); #Aif ( (! defined(BUG_SYSTEME_C_complexite_02)) \ ) EGAL(niveau_lumineux ,fMAX2(NIVA(MUL2(BARY(y_reduit ,______NORMALISE_NIVEAU(MAX_NIVEAU_LUMINEUX) ,min_depth_cueing ) ,NIVR(niveau_lumineux) ) ) ,MIN_INTENSITE ) ); /* ATTENTION : on trouvait autrefois 'MAX2(...)' a la place de 'fMAX2(...)'. Malheureusement */ /* un probleme invraisemblable rencontre sur les SYSTEMEs 'SYSTEME_NWS3000_NEWSOS_CC' et */ /* 'SYSTEME_NWS3000_NEWSOS_2CC' a ainsi trouve sa solution. La situation etait la suivante : */ /* */ /* 1-la commande '$xci/montagne.01$K' fonctionnait parfaitement bien, */ /* 2-le programme '$xrc/mandel.02$K' par contre ne donnait pas le resultat attendu ; les */ /* tests ont montre que le resultat du 'MAX2(...)' etait une valeur tres faible (de l'ordre */ /* de 5.0e-310, alors qu'elle ne devrait pas etre inferieure a 'MIN_INTENSITE'). */ /* */ /* Encore une fois, il est difficile de comprendre comment cela pouvait marcher dans un cas */ /* et pas dans l'autre, le defaut, par exemple, ne dependant pas de l'ordre des includes : */ /* */ /* #include maths_compl_fonct_ITERATIONS_EXT */ /* #include image_image_MONTAGNES_EXT */ /* */ /* Le 20090309170209 le "depth-cueing" ainsi que le texturage sont devenus independants de */ /* l'ombrage... */ #Eif ( (! defined(BUG_SYSTEME_C_complexite_02)) \ ) Eblock ATes Bblock Eblock ETes EGAL(niveau_lumineux ,NIVA(SCAL(NIVR(niveau_lumineux) ,MAX_NIVEAU_LUMINEUX ,texture_courante(X,Y,z_point_courant(X,Y)) ) ) ); /* Et on applique la texture donnee par "imageA_texture". */ /* */ /* Le 20090309170209 le "depth-cueing" ainsi que le texturage sont devenus independants de */ /* l'ombrage... */ EGAL(intensite_extremite,LIGNE(liste_intensite_extremite,X,Y)); /* Note sur l'orientation actuelle des axes : */ /* */ /* */ /* Y ^ */ /* | */ /* | plan */ /* | de */ /* | l'image */ /* | */ /* O-------------> X */ /* / */ /* / */ /* / */ /* / */ /* Z . */ /* */ /* (Pour le graphique, les arguments et le 'Z-Buffer'). */ /* */ /* */ /* Z ^ */ /* | */ /* | */ /* | */ /* | Z = Yfirst_trace + (Ylast_trace - Y) */ /* | (profondeur / */ /* Ymin O-------------> X dans le / */ /* / 'Z-Buffer') / */ /* / / */ /* / plan du champ 2D coordonnee */ /* Ymax / a visualiser en 3D 'Y' du champ */ /* Y . */ /* */ /* (Pour la surface montagneuse ; le referentiel n'est pas "direct"). */ /* */ /* */ /* | | */ /* */ /* Y ---- D ------ C ----- */ /* . */ /* | . | */ /* | . | */ /* */ /* Y-1 ---- B ------ A ----- */ /* */ /* | | */ /* */ /* X-1 X */ /* */ EGAL(ASD1(normale,dx),NEUT(SOUS(z_point_suivant(vPREX(X),vNEUT(Y)),z_point_suivant(vNEUT(X),vNEUT(Y))))); EGAL(ASD1(normale,dy),NEUT(SOUS(z_point_courant(vNEUT(X),vNEUT(Y)),z_point_suivant(vNEUT(X),vNEUT(Y))))); /* Generation de la normale "basse" : on considere la facette triangulaire {A,B,C} */ /* suivante : */ /* */ /* [A(X,Y-I,Z(A)),B(X-I,Y-I,Z(B)),C(X,Y,Z(C))] */ /* */ /* elle definit un plan d'equation : */ /* */ /* | X-XA Y-YA Z-ZA | */ /* | XB-XA YB-YA ZB-ZA | = 0 */ /* | XC-XA YC-YA ZC-ZA | */ /* */ /* soit par definition : */ /* */ /* | X-XA Y-YA Z-ZA | */ /* | -1 0 ZB-ZA | = 0 */ /* | 0 -1 ZC-ZA | */ /* */ /* la normale a cette facette est donc le vecteur de coordonnees : */ /* */ /* [(ZB-ZA),(ZC-ZA),1]. */ /* */ INCR(ASD1(normale,dx),NEGA(SOUS(z_point_courant(vNEUT(X),vNEUT(Y)),z_point_courant(vPREX(X),vNEUT(Y))))); INCR(ASD1(normale,dy),NEGA(SOUS(z_point_suivant(vPREX(X),vNEUT(Y)),z_point_courant(vPREX(X),vNEUT(Y))))); /* Passage du reseau triangulaire au reseau carre de base : */ /* */ /* on considere la facette triangulaire {D,B,C} : */ /* */ /* [D(X-I,Y,Z(D)),B(X-I,Y-I,Z(B)),C(X,Y,Z(C))] */ /* */ /* elle definit le plan d'equation : */ /* */ /* | X-XD Y-YD Z-ZD | */ /* | XB-XD YB-YD ZB-ZD | = 0 */ /* | XC-XD YC-YD ZC-ZD | */ /* */ /* soit, par definition : */ /* */ /* | X-XD Y-YD Z-ZD | */ /* | 0 1 ZB-ZD | = 0 */ /* | 1 0 ZC-ZD | */ /* */ /* la normale a cette facette est donc le vecteur de coordonnees : */ /* */ /* [(ZC-ZD),(ZB-ZD),-1], */ /* */ /* ou en inversant l'orientation, car en effet, les deux */ /* facettes (A,B,C) ET (D,B,C) sont parcourus en sens */ /* inverses l'une de l'autre : */ /* */ /* [-(ZC-ZD),-(ZB-ZD),1]. */ /* */ /* enfin, on fait la moyenne entre cette normale */ /* [-(ZC-ZD),-(ZB-ZD),1], et la normale [(ZB-ZA),(ZC-ZA),1] */ /* calculee precedemment... */ #define source_lumineuse_Z \ Imontagnes_precises_____source_lumineuse_Z \ /* Pour raccourcir certaines lignes... */ INITIALISATION_ACCROISSEMENT_3D(rayon_lumineux ,NEGA(SOUS(FLOT(X) ,F__cDENORMALISE_OX(ASI1(source_lumineuse,x)) ) ) ,NEGA(MUL2(Imontagnes_precises_____inclinaison_de_la_source_lumineuse ,SOUS(FLOT(Y) ,FLOT(NEGA(_cDENORMALISE_OZ(source_lumineuse_Z))) ) ) ) /* La deuxieme composante du rayon lumineux est traitee differemment */ /* des deux autres ; de plus l'inversion ('NEGA') supplementaire */ /* qu'elle contient est liee au fait que l'axe 'OY' de la surface */ /* montagneuse et l'axe 'OZ' des arguments sont de sens oppose. */ ,NEGA(SOUS(FLOT(z_point_courant(X,Y)) ,F__cDENORMALISE_OY(ASI1(source_lumineuse,y)) ) ) ); /* Un point important est a noter : il y a une difference avec la */ /* programmation SOLAR, car je crois qu'en effet, elle est mauvaise... */ #undef source_lumineuse_Z EGAL(intensite_origine ,NIVA(MUL2(HOMO(PUIX(DIVI(prdF3D(normale,rayon_lumineux) ,RACX(MUL2(pytF3D(normale) ,pytF3D(rayon_lumineux) ) ) ) ,Imontagnes_precises_____source_lumineuse_specularite ) ,COSINUS_DE_PI ,COSINUS_DE_0 ,minimum_normalise_du_cosinus_d_une_normale ,maximum_normalise_du_cosinus_d_une_normale ) ,NIVR(niveau_lumineux) ) ) ); /* Normalisation (a priori dans [0,1]) du cosinus de la normale... */ /* */ /* La specularite a ete introduite le 20130101105228... */ EGAL(intensite_origine ,NIVA(LIN3(Imontagnes_precises_____depth_cueing_ponderation_niveau ,NIVR(intensite_origine) ,Imontagnes_precises_____depth_cueing_ponderation_coordonnee_X ,F___DENORMALISE_NIVEAU(_____cNORMALISE_OX(X)) ,Imontagnes_precises_____depth_cueing_ponderation_coordonnee_Y ,F___DENORMALISE_NIVEAU(_____cNORMALISE_OY(Y)) ,Imontagnes_precises_____depth_cueing_translation ) ) ); /* Normalisation (a priori dans [0,1]) du cosinus de la normale... */ EGAL(LIGNE(liste_intensite_extremite,X,Y),intensite_origine); /* Et cette "intensite_origine" deviendra la "intensite_extremite" pour la */ /* ligne suivante ; notons d'ailleurs que c'est a cause de l'initialisation */ /* de cette liste que l'on ne trace qu'a partir de 'Yfirst_trace'... */ EGAL(intensite_origine,MAX2(intensite_origine,MIN_INTENSITE)); EGAL(intensite_extremite,MAX2(intensite_extremite,MIN_INTENSITE)); /* Lorsque l'intensite lumineuse est trop faible, on la majore... */ PULL_MASQUE; /* Restauration de l'etat de masquage apres l'acces aux differentes images, */ /* et ce avant le trace... */ Test(IFET(IL_NE_FAUT_PAS(vue_d_avion) ,IL_FAUT(anti_aliasing) ) ) Bblock Test(EST_FAUX(premier_vecteur_vertical)) Bblock EGAL(sauvegarde_de_l_extremite,extremite_precedente); EGAL(sauvegarde_de_l_intensite_extremite,intensite_extremite_precedente); /* Pour tous les vecteurs verticaux (excepte le premier de chaque ligne), on memorise */ /* ses caracteristiques afin de faire son anti-aliasing lors du vecteur suivant... */ Eblock ATes Bblock Eblock ETes EGAL(extremite_precedente,ASD2(vecteur_vertical,extremite,y)); EGAL(intensite_extremite_precedente,intensite_extremite); Eblock ATes Bblock Eblock ETes Test(IFET(IL_FAUT(Imontagnes_precises_____visualiser_la_falaise_avant_de_la_montagne) ,IFEQ(Y,Ylast_trace) ) ) Bblock EGAL(ASD2(vecteur_vertical,origine,y),Ymin); /* Ceci a ete introduit le 20030326121557 et cela devait manquer depuis bien longtemps... */ Eblock ATes Bblock Eblock ETes Test(IFOU(IL_FAUT(vue_d_avion) ,IFOU(IFGE(ASD2(vecteur_vertical,extremite,y),ASD2(vecteur_vertical,origine,y)) ,EST_ACTIF(Masque_____etat) ) ) ) Bblock /* Le trace a lieu lorsque l'une (au moins) des trois conditions est presente : */ /* */ /* 1 - c'est une vue d'avion : en effet, rien n'est cache... */ /* 2 - c'est un vecteur "montant" (origine <= extremite) : */ /* */ /* * extremite */ /* /|\ */ /* | */ /* | */ /* | */ /* | */ /* * origine */ /* */ /* ce vecteur appartient a une face "avant", on le voit donc actuellement */ /* (c'est-a-dire qu'il pourra etre cache ulterieurement par une autre face). */ /* 3 - le Masque est actif : on trace systematiquement tous les vecteurs (et donc */ /* meme ceux des faces "arriere") car en effet on est incapable de savoir ce */ /* qui sera visible a travers les "trous" du Masque... */ /* */ Test(IFLE(Y,Yfirst_trace)) Bblock Test(TEST_MASQUE_ACTIF(X,Y,MASQUER_PARCOURS)) Bblock TRACE_VECTEUR_VERTICAL(imageR ,vecteur_vertical ,Yf_origine,Yf_extremite ,X,Y,z_point_courant(X,Y) ,CE_N_EST_PAS_LA_PHASE_D_ANTI_ALIASING ); Eblock ATes Bblock Eblock ETes Test(IFET(IL_NE_FAUT_PAS(vue_d_avion) ,IL_FAUT(anti_aliasing) ) ) Bblock Test(EST_FAUX(premier_vecteur_vertical)) Bblock Test(TEST_MASQUE_ACTIF(X,Y,MASQUER_PARCOURS)) Bblock Test(IFNE(ASD2(vecteur_vertical,extremite,y) ,sauvegarde_de_l_extremite ) ) Bblock /* Cas ou le vecteur vertical (abscisse 'X') que l'on vient de tracer n'a pas son extremit */ /* au meme niveau que son voisin de droite (abscisse 'X+1') : il y a donc une discontinuite */ /* (une marche...) que l'on va essayer de combler en montant ou en descendant... */ DEFV(vectorI_2D,complement_d_anti_aliasing); TRANSFERT_VECTEUR_2D(complement_d_anti_aliasing ,vecteur_vertical ); /* Vecteur introduit le 20100222122101... */ EGAL(ASD2(complement_d_anti_aliasing,origine,y),sauvegarde_de_l_extremite); Test(IFLT(ASD2(complement_d_anti_aliasing,origine,y) ,ASD2(complement_d_anti_aliasing,extremite,y) ) ) Bblock EGAL(ASD2(complement_d_anti_aliasing,origine,x) ,vSUCX(ASD2(complement_d_anti_aliasing,origine,x)) ); EGAL(ASD2(complement_d_anti_aliasing,extremite,x) ,vSUCX(ASD2(complement_d_anti_aliasing,extremite,x)) ); EGAL(intensite_origine,sauvegarde_de_l_intensite_extremite); /* Cas ou le voisin de droite (abscisse 'X+1') monte moins haut : c'est donc lui qu'il va */ /* falloir completer (vers le haut), d'ou les 'SUCX(...)' qui precedent : */ /* */ /* | + */ /* | + */ /* | + */ /* | | <-- sauvegarde_de_l_{intensite_extremite,extremite} */ /* | | */ /* | | */ /* | | */ /* */ /* X X+1 */ /* */ /* (les "+" indiquant le vecteur "complement" a tracer correspondant a l'anti-aliasing). */ Eblock ATes Bblock SWAP(ASD2(complement_d_anti_aliasing,origine,y) ,ASD2(complement_d_anti_aliasing,extremite,y) ); EGAL(intensite_origine,intensite_extremite); /* Cas ou le voisin de droite (abscisse 'X+1') monte plus haut : c'est donc le vecteur */ /* que l'on vient de tracer qu'il va falloir completer (vers le haut) : */ /* */ /* + | */ /* + | */ /* + | */ /* | | */ /* | | */ /* | | */ /* | | */ /* */ /* X X+1 */ /* */ /* (les "+" indiquant le vecteur "complement" a tracer correspondant a l'anti-aliasing). */ Eblock ETes Test(IFGT(Yf_origine,Yf_extremite)) Bblock fSWAP(Yf_origine ,Yf_extremite ); Eblock ATes Bblock Eblock ETes Test(TEST_DANS_L_IMAGE(ASD2(complement_d_anti_aliasing,extremite,x) ,ASD2(complement_d_anti_aliasing,extremite,y) ) ) Bblock DEFV(Float,INIT(intensite_extremite,FLOT__UNDEF)); /* Cette variable locale est destinee a ne pas perdre la valeur de 'intensite_extremite' */ /* pour pouvoir generer 'sauvegarde_de_l_intensite_extremite' pour le vecteur suivant... */ INITIALISATION_VECTEUR_2D(complement_d_anti_aliasing ,TRON(ASD2(complement_d_anti_aliasing,origine,x) ,Xmin ,Xmax ) ,TRON(ASD2(complement_d_anti_aliasing,origine,y) ,Ymin ,Ymax ) ,TRON(ASD2(complement_d_anti_aliasing,extremite,x) ,Xmin ,Xmax ) ,TRON(ASD2(complement_d_anti_aliasing,extremite,y) ,Ymin ,Ymax ) ); PUSH_MASQUE; /* Sauvegarde de l'etat de masquage avant l'acces a l'image. */ DEMASQUE_IMAGES; /* Et on le desactive a priori... */ EGAL(Zf_extremite ,loadF_point_valide(Z_Buffer ,ASD2(complement_d_anti_aliasing,extremite,x) ,ASD2(complement_d_anti_aliasing,extremite,y) ) ); EGAL(intensite_extremite ,FLOT(loadS_point_valide(imageR ,ASD2(complement_d_anti_aliasing,extremite,x) ,ASD2(complement_d_anti_aliasing,extremite,y) ) ) ); PULL_MASQUE; /* Restauration de l'etat de masquage apres l'acces a l'image. */ TRACE_VECTEUR_VERTICAL(imageR ,complement_d_anti_aliasing ,Yf_origine,Yf_extremite ,vSUCX(X),Y,z_point_courant(X,Y) ,C_EST_LA_PHASE_D_ANTI_ALIASING ); /* Je note le 20100220204800 que c'est ce 'TRACE_VECTEUR_VERTICAL(...)' avec */ /* 'C_EST_LA_PHASE_D_ANTI_ALIASING' qui est responsable d'un artefact ennuyeux */ /* dans les zones de penombre. Pour le voir, il suffit de faire : */ /* */ /* Pal */ /* */ /* $xci/gauss$X \ */ /* standard=FAUX \ */ /* $formatI | \ */ /* $xci/montagne.01$X \ */ /* standard=FAUX zero=FAUX \ */ /* T=$BLANC \ */ /* avion=FAUX \ */ /* Ty=0.9 \ */ /* penombre=0 \ */ /* attenuation=1 \ */ /* $formatI | \ */ /* $xci/display$X \ */ /* p=$xiP/cercle.35 \ */ /* $formatI */ /* */ /* */ /* pour voir apparaitre dans la zone de penombre au premier plan a gauche des petits */ /* segments verticaux incorrects qui partent de la penombre et descendent vers le bas */ /* de l'image. Ils font quelques pixels de haut et sont cyans sur fond jaune... */ /* */ /* Ce probleme fut "attaque" le 20100222122101 par l'introduction d'un vecteur specifique */ /* 'complement_d_anti_aliasing' different de 'vecteur_vertical'. C'etait la "confusion" */ /* anterieure des deux qui etait la cause du probleme : en effet 'vecteur_vertical' etait */ /* modifie pour la phase d'anti-aliasing et ce de facon irreversible. Alors il ne */ /* correspondait plus ensuite au vecteur vertical que l'on venait de tracer (avant */ /* "anti-aliasing"...). */ /* */ /* La vraie solution au probleme du 20100220204800 fut appliquee en permettant un test */ /* strict dans la gestion du 'Z-Buffer' ('v $xiii/Images$DEF Z_Buffer_____test_strict')... */ /* */ /* */ /* Aux environs du 20140704103958 je note un nouveau probleme que l'on peut mettre en */ /* evidence avec l'image 'v $xiirf/PAYU.K1$M' a condition de definir : */ /* */ /* set _____Deformation=$xiP/gris.54 */ /* */ /* Il y a alors une mesa a gauche qui en projection intersecte la "ligne d'horizon" H. */ /* A la gauche de celle-ci apparait une ligne verticale TC de la couleur du ciel alors */ /* qu'elle devrait etre du couleur de la terre. Cela vient du 'TRACE_VECTEUR_VERTICAL(...)' */ /* qui precede. En effet, il trace en segment vertical TC qui est "a cheval" sur la terre */ /* et le ciel : */ /* */ /* _________ */ /* Ciel | Mesa | */ /* | | */ /* extremite : ...... C| | */ /* ^| | */ /* H ^| | */ /* -----------------------------^-------------------- */ /* ^| | */ /* ^| | */ /* orgine : ......... T| | */ /* | | */ /* Terre | | */ /* */ /* Il est des lors evident que ce segment TC peut avoir la couleur du ciel en dessous de H. */ /* A cette date, je ne vois pas comment corriger cela. En particulier, des solutions */ /* possibles pourraient tester (et/ou interpoler) les niveaux anterieurs, mais il ne faut */ /* pas oublier que 'v $xiirf/PAYU.K1$M' est une image en vraies couleurs ce qui implique */ /* que ces tests (et/ou interpolations) hypothetiques seraient en general differents d'une */ /* composante chromatique a l'autre induisant alors d'autres anomalies (par exemple des */ /* incoherences chromatiques)... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock EGAL(premier_vecteur_vertical,FAUX); /* Ainsi, on sait que l'on vient de traiter le premier vecteur vertical de la ligne */ /* courante... */ Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock end_ligne_back Eblock ATes Bblock Eblock ETes Eblock end_colonne_back ESaveModifyVariable(Logical ,Z_Buffer_____test_strict ); EDEFV(ligneF,liste_intensite_extremite); /* Liste des hautes intensites d'une ligne ; elle contient en fait une */ /* partie de celles de la ligne precedente, puis celle de la ligne courante. */ RETI(imageR); Eblock EFonctionP #undef POSITION_DANS_LA_ZONE_DE_PENOMBRE #undef CE_N_EST_PAS_LA_PHASE_D_ANTI_ALIASING #undef C_EST_LA_PHASE_D_ANTI_ALIASING #undef TRACE_VECTEUR_VERTICAL #undef ATTENUATION_A_L_OMBRE #undef texture_courante #undef z_point_suivant_suivant #undef z_point_suivant #undef z_point_courant #undef z_point_precedent #ifdef TYPE_DE_imageA_surface_VERSION_01 # undef EQUATION_DE_LA_SURFACE #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 # undef EQUATION_DE_LA_SURFACE #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #undef LAMBDA_DE_CORRECTION_PERSPECTIVE #undef DECALAGE_VERTICAL #undef Ylast_trace #undef Ylast #undef Yfirst_trace #undef Yfirst #undef Xlast #undef AVANT #undef ARRIERE #undef PLUS_GRANDE_ORDONNEE_SUR_LA_MONTAGNE /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M I S E E N M O N T A G N E S " S T A N D A R D " D ' U N E I M A G E : */ /* */ /*************************************************************************************************************************************/ BFonctionP /* ATTENTION, on introduit deux fonctions 'Imontagnes(...)' et 'Imontagnes_precises(...)' */ /* qui sont de toute evidence inutiles en 'TYPE_DE_imageA_surface_VERSION_01' mais dont la */ /* presence permet de simplifier considerablement la coexistence des deux versions... */ #ifdef TYPE_DE_imageA_surface_VERSION_02 /* ATTENTION, les deux definitions qui suivent sont faites independamment pour les deux */ /* fonctions 'Imontagnes(...)' et 'Imontagnes_en_perspective(...)' afin qu'elles puissent */ /* prendre alors des valeurs differentes, ce qui n'est pas le cas actuellement... */ # define NIVEAU_PRECIS_MINIMAL \ ______________NOIR_NORMALISE # define NIVEAU_PRECIS_MAXIMAL \ ______________BLANC_NORMALISE /* Niveaux minimal et maximal dans 'imageA_surface_flottante'. */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 DEFV(Common,DEFV(FonctionP,POINTERp(Imontagnes(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,nettoyer ,ARGUMENT_POINTERs(translation) ,ombres_portees,largeur_zone_penombre ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ,vue_d_avion ,anti_aliasing ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, qui est une vue texturee de la surface. */ DEFV(Argument,DEFV(Float,facteur_d_echelle)); /* Facteur d'echelle permettant de moduler le champ contenu dans 'imageA_surface', */ /* et par exemple de l'inverser. On notera bien que les parametres 'facteur_d_echelle' et */ /* 'Imontagnes_precises_____facteur_de_correction_perspective' interferent l'un avec */ /* l'autre comme cela est documente lors de la definition de ce dernier... */ /* Le 20020211111705, j'ai remarque que les deux parametres 'facteur_d_echelle' */ /* et 'Imontagnes_precises_____facteur_de_correction_perspective' devaient etre de meme */ /* signe... */ DEFV(Argument,DEFV(image,imageA_surface)); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface, */ DEFV(Argument,DEFV(image,imageA_texture)); /* Deuxieme image Argument, qui donne la texture de la surface. */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Logical,nettoyer)); /* Indicateur demandant ('VRAI') ou pas ('FAUX') la mise a noir */ /* de l'image 'imageR'. */ DEFV(Argument,DEFV(deltaF_2D,POINTERs(translation))); /* Translation horizontale ('dx') et verticale ('dy') de la montagne dans l'image */ /* Resultat exprimee en nombre de points de la matrice "imageR" ; on n'oubliera */ /* pas que cette translation est exprimee dans des unites telles que l'unite vaut */ /* respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,ombres_portees)); /* Les ombres portees doivent-elles etre presentes ('VRAI') ou non ('FAUX'). */ DEFV(Argument,DEFV(Float,largeur_zone_penombre)); /* Donne la largeur de la zone de penombre (valeur arbitraire, mais une valeur de */ /* l'ordre de la dizaine donne de bons resultats...). */ DEFV(Argument,DEFV(pointF_2D,POINTERs(source_lumineuse))); /* Donne dans le plan de l'image Resultat ('imageR'), les coordonnees de */ /* la source lumineuse ; ces coordonnees sont exprimees dans des unites */ /* telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,depth_cueing)); /* Doit-on faire ('VRAI') ou pas ('FAUX') du depth-cueing ? */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Float,min_depth_cueing)); /* Ce parametre est inclus dans le segment [0,1] ; plus il est */ /* proche de zero, plus, le "depth-cueing" est fort... */ DEFV(Argument,DEFV(Logical,vue_d_avion)); /* Definit le mode de representation : 'VRAI' donne une vue de dessus, */ /* alors que 'FAUX' donne une vue de cote. */ DEFV(Argument,DEFV(Logical,anti_aliasing)); /* Indique s'il faut faire ('VRAI') ou pas ('FAUX') de l'anti-aliasing */ /* sur l'image Resultat. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock #ifdef TYPE_DE_imageA_surface_VERSION_02 BDEFV(imageF,imageA_surface_flottante); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface convertie en */ /* 'Float'... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 /*..............................................................................................................................*/ #ifdef TYPE_DE_imageA_surface_VERSION_01 CALS(Imontagnes_precises(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,nettoyer ,ARGUMENT_POINTERs(translation) ,ombres_portees,largeur_zone_penombre ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ,vue_d_avion ,anti_aliasing ) ); /* Generation de la surface montagneuse... */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 CALS(Istd_float(imageA_surface_flottante,NIVEAU_PRECIS_MINIMAL,NIVEAU_PRECIS_MAXIMAL,imageA_surface)); /* Conversion flottante preliminaire... */ CALS(Imontagnes_precises(imageR ,facteur_d_echelle,imageA_surface_flottante ,imageA_texture ,nettoyer ,ARGUMENT_POINTERs(translation) ,ombres_portees,largeur_zone_penombre ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ,vue_d_avion ,anti_aliasing ) ); /* Generation de la surface montagneuse... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #ifdef TYPE_DE_imageA_surface_VERSION_02 EDEFV(imageF,imageA_surface_flottante); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface convertie en */ /* 'Float'... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 RETI(imageR); Eblock #ifdef TYPE_DE_imageA_surface_VERSION_02 /* ATTENTION, les deux dedefinitions qui suivent sont faites independamment pour les deux */ /* fonctions 'Imontagnes(...)' et 'Imontagnes_en_perspective(...)' afin qu'elles puissent */ /* prendre alors des valeurs differentes, ce qui n'est pas le cas actuellement... */ # undef NIVEAU_PRECIS_MAXIMAL # undef NIVEAU_PRECIS_MINIMAL #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M I S E E N P E R S P E C T I V E M O N T A G N E U S E D ' U N E I M A G E : */ /* */ /* */ /* Definition : */ /* */ /* Cette fonction genere une repre- */ /* sentation 3D d'une image 2D, en */ /* utilisant la valeur de chaque point */ /* comme troisieme dimension ; le calcul */ /* est fait pour tout le champ {X,Y}. */ /* */ /* */ /* */ /* * */ /* ..@ .@ */ /* .* *.@ .@.@ */ /* ...@ . ..*@@@@ */ /* *@ .. .. .. .**@@@* */ /* @ .** . .*.@*@ **.. . . *@@@@@.@ .@ */ /* @****@.. @. **.*@ **.. .@.. .@.. .. ...@*@*@.*.@* */ /* .*.@@@*. .**.*@@.@. .*. . .@. @... .... . .@.** ..@@@* */ /* @.@@.@. *..**** @@@ .. * ** **.. . . .. . *.@ *..@@@@* .@ */ /* @*. @@.. @ @.@ ..@. .. .*@*@. ..@@@. ...*..****.. ...@*@@@**** */ /* . .**@..@@ @*. *@@..*. * @.**@.@@. ** ..*@@.@**. .@@@.*@ *@@ */ /* . . ** ..@@*@. *@****@. .***@..@@*.... @.*@ * .. .**.****@.. */ /* .... **.@@@@*. .*@**... .@.*.@ .*@ . .**@@.... **.@*@*@** */ /* *.... .@*@*...*.. @.@... .**@.@*@. **.. ***@.. * @*@.@ */ /* *.... .***.*@.* ..**.@..@. @*.*@@ *.* ..... .*@@... ..* @. ... */ /* @.. .*.@.**** ..@***@@@* *@. *.@@.*..*.**. @*@@ . * ** ... */ /* @@. . .@.* *.**. *.*@**@.*@@*@..@.@@@.*......@@.@.. ....... . */ /* @@ *. @.*@ **@.....@@*@.*@@*@*.@* *@ @@*.****.**. ..... .* */ /* @.@ @@*.@@ .@ .* @ .@@*@**@@*@@* * *.**. . ..... ... ....@. */ /* *@*..@*.** @* * *@@*@**@@@*.. .. .*.... ... .. . . . . .*. */ /* .@*@@**. .*.**@*@@@@*.@@@**. .. *@*....... . ..... . */ /* @@@..* **. . @.**@*@@@.@@@... *.**.... .@... . ... @... */ /* @**. ** . *.@@.@**@@ *.*@@* ** *.@.*.@@@. @*** .. @@* . */ /* @. . . . @@..***@ @* ..@* *. * .@*@*. .*@* . ... *@ .** */ /* @* .... .... .** *@@*@ .. @.** *.*. @@*.... @@@@ @*..* . @@* */ /* @ .**. *@*@@..*@..**. . * *..@ @ * @...*... @@@*****.... .*** */ /* */ /* */ /*************************************************************************************************************************************/ #define Y_to_Z(y) \ COZA(SOUS(COYR(y),COYR(SUCY(Ymax)))) \ /* Procedure de permutation des axes 'Y' et 'Z', et qui de plus place l'image */ \ /* 'champ_de_cotes' derriere le plan (OX,OY). ATTENTION, on ne peut supprimer le */ \ /* 'SUCY(...)' sous peine de creer des defauts dans l'image... */ #define Z_to_Y(z) \ COYA(ADD2(COZR(z),COZR(SUCZ(Zmax)))) \ /* Procedure de permutation des axes 'Z' et 'Y'. ATTENTION, on ne peut supprimer le */ \ /* 'SUCZ(...)' sous peine de creer des defauts dans l'image... */ #define IFEQ_a_peu_pres_sur_OX(x1,x2) \ IFEQ_a_peu_pres_absolu(x1,x2,MOIT(_____lNORMALISE_OX(pasX))) \ /* Procedure de test de l'egalite de deux abscisses a "epsilon" pres... */ #define IFEQ_a_peu_pres_sur_OY(y1,y2) \ IFEQ_a_peu_pres_absolu(y1,y2,MOIT(_____lNORMALISE_OY(pasY))) \ /* Procedure de test de l'egalite de deux ordonnees a "epsilon" pres ; on notera avec */ \ /* ATTENTION que 'IFEQ_a_peu_pres_sur_OY()' est utilise sur des coordonnees de type 'Z' */ \ /* mais qui representent des 'Y' dans 'champ_de_cotes'... */ #define CALCUL_DES_DEUX_INTERSECTIONS(Xintersection,Zintersection) \ Bblock \ Test(EST_FAUX(on_a_trouve_le_premier_point)) \ Bblock \ EGAL(ASD1(premier_point_d_intersection,x),Xintersection); \ EGAL(ASD1(premier_point_d_intersection,z),Zintersection); \ /* Mise en place du premier point d'intersection. */ \ EGAL(on_a_trouve_le_premier_point,VRAI); \ /* Ainsi, on sait qu'on connait le premier point d'intersection... */ \ Eblock \ ATes \ Bblock \ Test(EST_FAUX(on_a_trouve_le_deuxieme_point)) \ Bblock \ Test(IFET(IFEQ_a_peu_pres_sur_OX(Xintersection,ASD1(premier_point_d_intersection,x)) \ ,IFEQ_a_peu_pres_sur_OY(Zintersection,ASD1(premier_point_d_intersection,z)) \ ) \ ) \ Bblock \ EGAL(on_a_trouve_un_point_double,VRAI); \ /* Cas des "points-doubles" : il ne s'agit pas d'erreur ; ils se rencontrent lorsque la */ \ /* ligne de visee passe, en projection, par l'un des coins de 'champ_de_cotes'... */ \ Eblock \ ATes \ Bblock \ EGAL(ASD1(deuxieme_point_d_intersection,x),Xintersection); \ EGAL(ASD1(deuxieme_point_d_intersection,z),Zintersection); \ /* Mise en place du deuxieme point d'intersection. */ \ EGAL(on_a_trouve_le_deuxieme_point,VRAI); \ /* Ainsi, on sait qu'on connait le deuxieme point d'intersection... */ \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Test(IFOU(IFET(IFEQ_a_peu_pres_sur_OX(Xintersection,ASD1(premier_point_d_intersection,x)) \ ,IFEQ_a_peu_pres_sur_OY(Zintersection,ASD1(premier_point_d_intersection,z)) \ ) \ ,IFET(IFEQ_a_peu_pres_sur_OX(Xintersection,ASD1(deuxieme_point_d_intersection,x)) \ ,IFEQ_a_peu_pres_sur_OY(Zintersection,ASD1(deuxieme_point_d_intersection,z)) \ ) \ ) \ ) \ Bblock \ /* Cas des "points-doubles" : il ne s'agit pas d'erreur ; ils se rencontrent lorsque la */ \ /* ligne de visee passe, en projection, par l'un des coins de 'champ_de_cotes'... */ \ Eblock \ ATes \ Bblock \ PRINT_ERREUR("il y a plus de deux points distincts d'intersection"); \ CAL1(Prer2(" intersection1=(%g,%g)" \ ,ASD1(premier_point_d_intersection,x) \ ,ASD1(premier_point_d_intersection,z) \ ) \ ); \ CAL1(Prer2(" intersection2=(%g,%g)" \ ,ASD1(deuxieme_point_d_intersection,x) \ ,ASD1(deuxieme_point_d_intersection,z) \ ) \ ); \ CAL1(Prer2(" intersectionX=(%g,%g)" \ ,Xintersection \ ,Zintersection \ ) \ ); \ CAL1(Prer0("\n")); \ Eblock \ ETes \ Eblock \ ETes \ Eblock \ ETes \ Eblock \ /* Calcul des points d'intersection de la ligne de visee avec un prisme de hauteur infinie */ \ /* et de base 'champ_de_cotes'. */ #ifdef TYPE_DE_imageA_surface_VERSION_01 # define cote_courante(x,y) \ MUL2(facteur_d_echelle,______NORMALISE_NIVEAU(load_point(champ_de_cotes,x,y))) \ /* Definition du champ de cote au point {x,y} du champ 'champ_de_cotes'. */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 # define cote_courante(x,y) \ MUL2(facteur_d_echelle,NIVR(loadF_point_valide(champ_de_cotes,x,y))) \ /* Definition du champ de cote au point {x,y} du champ 'champ_de_cotes'. */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #define texture_courante(x,y) \ FLOT(NIVR(load_point_valide(champ_de_texture,x,y))) \ /* Definition de la texture a appliquer au point {x,y} de la montagne. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D E L A S P E C U L A R I T E : */ /* */ /*************************************************************************************************************************************/ DEFV(Common,DEFV(Float,ZINT(Imontagnes_en_perspective_precises_____source_lumineuse_specularite,FU))); /* Definition de la specularite introduite le 20130101105228 en garantissant la */ /* compatibilite anterieure... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M I S E E N P E R S P E C T I V E M O N T A G N E U S E " P R E C I S E " D ' U N E I M A G E : */ /* */ /*************************************************************************************************************************************/ /* ATTENTION, on introduit deux fonctions 'Imontagnes_en_perspective(...)' et */ /* 'Imontagnes_en_perspective_precises(...)' qui sont de toute evidence inutiles en */ /* 'TYPE_DE_imageA_surface_VERSION_01' mais dont la presence permet de simplifier */ /* considerablement la coexistence des deux versions... */ #ifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : pour la 'VERSION_01'. */ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Imontagnes_en_perspective_precises(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,ARGUMENT_POINTERs(translation) ,ARGUMENT_POINTERs(position_du_touriste_observateur) ,ombres_portees ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, qui est une vue texturee de la surface. */ DEFV(Argument,DEFV(Float,facteur_d_echelle)); /* Facteur d'echelle permettant de moduler le champ contenu dans 'imageA_surface', */ /* et par exemple de l'inverser... */ DEFV(Argument,DEFV(image,imageA_surface)); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface, */ DEFV(Argument,DEFV(image,imageA_texture)); /* Deuxieme image Argument, qui donne la texture de la surface. */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(deltaF_3D,POINTERs(translation))); /* Translation de l'ecran (c'est-a-dire du support de 'imageR') dans l'espace */ /* tridimensionnel ; on n'oubliera pas que cette translation est exprimee dans */ /* des unites telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]... */ DEFV(Argument,DEFV(pointF_3D,POINTERs(position_du_touriste_observateur))); /* Definition de la position de l'observateur. */ /* */ /* 'position_de_l_observateur' fut remplace par 'position_du_touriste_observateur' le */ /* 20061113115240 pour prepaper l'execution de 'v $xau/LACT16.82$Z' qui fait la modification */ /* 'v $xau/LACT16.61.modifier$sed position_de_l_observateur' et eviter ainsi une grosse */ /* ambiguite... */ DEFV(Argument,DEFV(Logical,ombres_portees)); /* Les ombres portees doivent-elles etre presentes ('VRAI') ou non ('FAUX'). */ DEFV(Argument,DEFV(pointF_3D,POINTERs(source_lumineuse))); /* Donne dans le plan de l'image Resultat ('imageR'), les coordonnees de */ /* la source lumineuse ; ces coordonnees sont exprimees dans des unites */ /* telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,depth_cueing)); /* Doit-on faire ('VRAI') ou pas ('FAUX') du depth-cueing ? */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Float,min_depth_cueing)); /* Ce parametre est inclus dans le segment [0,1] ; plus il est */ /* proche de zero, plus, le "depth-cueing" est fort... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ #Aifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : pour la 'VERSION_01'. */ #Eifdef TYPE_DE_imageA_surface_VERSION_01 /* Common,DEFV(Fonction,) : pour la 'VERSION_01'. */ #ifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : pour la 'VERSION_02'. */ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Imontagnes_en_perspective_precises(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,ARGUMENT_POINTERs(translation) ,ARGUMENT_POINTERs(position_du_touriste_observateur) ,ombres_portees ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, qui est une vue texturee de la surface. */ DEFV(Argument,DEFV(Float,facteur_d_echelle)); /* Facteur d'echelle permettant de moduler le champ contenu dans 'imageA_surface', */ /* et par exemple de l'inverser... */ DEFV(Argument,DEFV(imageF,imageA_surface)); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface, */ DEFV(Argument,DEFV(image,imageA_texture)); /* Deuxieme image Argument, qui donne la texture de la surface. */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(deltaF_3D,POINTERs(translation))); /* Translation de l'ecran (c'est-a-dire du support de 'imageR') dans l'espace */ /* tridimensionnel ; on n'oubliera pas que cette translation est exprimee dans */ /* des unites telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]... */ DEFV(Argument,DEFV(pointF_3D,POINTERs(position_du_touriste_observateur))); /* Definition de la position de l'observateur. */ /* */ /* 'position_de_l_observateur' fut remplace par 'position_du_touriste_observateur' le */ /* 20061113115240 pour prepaper l'execution de 'v $xau/LACT16.82$Z' qui fait la modification */ /* 'v $xau/LACT16.61.modifier$sed position_de_l_observateur' et eviter ainsi une grosse */ /* ambiguite... */ DEFV(Argument,DEFV(Logical,ombres_portees)); /* Les ombres portees doivent-elles etre presentes ('VRAI') ou non ('FAUX'). */ DEFV(Argument,DEFV(pointF_3D,POINTERs(source_lumineuse))); /* Donne dans le plan de l'image Resultat ('imageR'), les coordonnees de */ /* la source lumineuse ; ces coordonnees sont exprimees dans des unites */ /* telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,depth_cueing)); /* Doit-on faire ('VRAI') ou pas ('FAUX') du depth-cueing ? */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Float,min_depth_cueing)); /* Ce parametre est inclus dans le segment [0,1] ; plus il est */ /* proche de zero, plus, le "depth-cueing" est fort... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ #Aifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : pour la 'VERSION_02'. */ #Eifdef TYPE_DE_imageA_surface_VERSION_02 /* Common,DEFV(Fonction,) : pour la 'VERSION_02'. */ Bblock #ifdef TYPE_DE_imageA_surface_VERSION_01 BDEFV(image,champ_de_cotes); /* Cette image definie le champ de cote de la surface ; elle est obtenue par une */ /* symetrie d'axe 'OX' de l'image 'imageA_surface'. En effet, cette derniere est */ /* couchee dans le plan horizontal (OX,OZ), or l'axe 'OZ' vient vers l'observateur, */ /* ce qui fait que, par exemple, l'ancien 'Ymax' se trouve devant l'ancien 'Ymin', une */ /* fois sur le plan horizontal... */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 BDEFV(imageF,champ_de_cotes); /* Cette image definie le champ de cote de la surface ; elle est obtenue par une */ /* symetrie d'axe 'OX' de l'image 'imageA_surface'. En effet, cette derniere est */ /* couchee dans le plan horizontal (OX,OZ), or l'axe 'OZ' vient vers l'observateur, */ /* ce qui fait que, par exemple, l'ancien 'Ymax' se trouve devant l'ancien 'Ymin', une */ /* fois sur le plan horizontal... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 BDEFV(image,champ_de_texture); /* Et il en est de meme pour la texture... */ DEFV(pointF_3D,point_3D_courant_de_l_ecran); /* Definit le point courant sur l'ecran (c'est-a-dire dans 'imageR'), mais considere */ /* dans l'espace tridimensionnel, et que l'on va projeter, depuis l'observateur, sur */ /* la surface definie par le chmap 'champ_de_cotes'. */ DEFV(deltaF_3D,direction_de_visee_courante); /* Definit la ligne de visee courante (allant donc de l'observateur au point courant */ /* de l'ecran). */ DEFV(Float,INIT(distance_de_visee_courante,FLOT__UNDEF)); /* Definit la norme du vecteur 'direction_de_visee_courante'. */ DEFV(deltaF_3D,direction_image_observateur); /* Definit la ligne allant du centre de l'image a l'observateur, et qui est utilisee */ /* pour savoir si celui-ci ne "tourne pas le dos" a l'image 'champ_de_cotes'... */ DEFV(Float,INIT(X_pour_Zmin,FLOT__UNDEF)); /* Pour definir l'intersection de la ligne de visee avec la droite Z=Y_to_Z(Ymin) dans */ /* le plan (OX,OZ), */ DEFV(Float,INIT(X_pour_Zmax,FLOT__UNDEF)); /* Pour definir l'intersection de la ligne de visee avec la droite Z=Y_to_Z(Ymax) dans */ /* le plan (OX,OZ). */ DEFV(Float,INIT(Z_pour_Xmin,FLOT__UNDEF)); /* Pour definir l'intersection de la ligne de visee avec la droite X=Xmin dans */ /* le plan (OX,OZ), */ DEFV(Float,INIT(Z_pour_Xmax,FLOT__UNDEF)); /* Pour definir l'intersection de la ligne de visee avec la droite X=Xmax dans */ /* le plan (OX,OZ). */ DEFV(Logical,INIT(on_a_trouve_un_point_double,FAUX)); /* Pour savoir si l'on a trouve un point double. */ DEFV(Logical,INIT(on_a_trouve_le_premier_point,FAUX)); /* Pour savoir si l'on a trouve le premier point d'intersection. */ DEFV(pointF_3D,premier_point_d_intersection); /* Definition du premier point d'intersection de la ligne de visee avec un prisme infini */ /* de base 'champ_de_cotes'. */ DEFV(Logical,INIT(on_a_trouve_le_deuxieme_point,FAUX)); /* Pour savoir si l'on a trouve le deuxieme point d'intersection. */ DEFV(pointF_3D,deuxieme_point_d_intersection); /* Definition du deuxieme point d'intersection de la ligne de visee avec un prisme infini */ /* de base 'champ_de_cotes'. */ DEFV(deltaI_3D,amplitude_de_traversee); /* Amplitude de passage du premier au deuxieme point d'intersection. */ DEFV(Positive,INIT(nombre_de_points_entre_les_deux_points_d_intersection,UNDEF)); /* Nombre de points a tester dans 'champ_de_cotes' pour aller du premier au deuxieme */ /* point d'intersection dans le plan (OX,OZ). */ DEFV(pointF_3D,point_courant_ligne_de_visee); /* Point courant allant du premier au deuxieme point d'intersection sur la ligne de visee... */ DEFV(Logical,INIT(on_a_trouve_un_point_de_la_surface,FAUX)); /* Pour savoir si l'on a trouve un point d'intersection entre la surface et la ligne */ /* de visee. */ DEFV(deltaF_3D,normale); /* Vecteur normal a la facette courante ; il est definit comme un accroissement, et non */ /* comme un vrai vecteur, car seule sa direction nous importe... */ DEFV(deltaF_3D,rayon_lumineux); /* Direction du rayon lumineux du point courant a la source lumineuse. */ DEFV(Float,INIT(y_reduit,FLOT__UNDEF)); /* Donne la coordonnee 'Y' reduite lors d'un depth-cueing dans [0,1[. */ DEFV(Float,INIT(niveau_lumineux,MAX_NIVEAU_LUMINEUX)); /* Donne le niveau lumineux courant ; il est initialise sur le */ /* maximum, afin d'etre correct si l'ombrage n'est pas demande... */ /*..............................................................................................................................*/ Test(IFOU(IFNE(Zmin,Ymin) ,IFNE(Zmax,Ymax) ) ) Bblock PRINT_ATTENTION("les axes 'OY' et 'OZ' etant echanges en permanence, ils doivent etre definis de facon identique"); CAL1(Prer2("OY=(%d,%d)\n",Ymin,Ymax)); CAL1(Prer2("OZ=(%d,%d)\n",Zmin,Zmax)); Eblock ATes Bblock Eblock ETes #ifdef TYPE_DE_imageA_surface_VERSION_01 CALS(Ix_symetrie(champ_de_cotes,imageA_surface)); /* Afin de prendre en compte le fait que ces deux images 'imageA_surface' et */ /* 'imageA_texture' sont couchees sur le plan horizontal (OX,OZ), or l'axe 'OZ' vient */ /* vers l'observateurR... */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 CALS(IFx_symetrie(champ_de_cotes,imageA_surface)); /* Afin de prendre en compte le fait que ces deux images 'imageA_surface' et */ /* 'imageA_texture' sont couchees sur le plan horizontal (OX,OZ), or l'axe 'OZ' vient */ /* vers l'observateurR... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 CALS(Ix_symetrie(champ_de_texture,imageA_texture)); /* Afin de prendre en compte le fait que ces deux images 'imageA_surface' et */ /* 'imageA_texture' sont couchees sur le plan horizontal (OX,OZ), or l'axe 'OZ' vient */ /* vers l'observateurR... */ INITIALISATION_TRANSFORMATION; /* Au cas ou la transformation geometrique tri-dimensionnelle ne serait */ /* pas initialisee, on le fait sur la transformation unite. */ begin_image Bblock /* */ /* + */ /* +| */ /* + | */ /* Ymax ==> -Zmax ----------------------------+--|--------- */ /* / + | / */ /* / + | / */ /* / + | / */ /* / + | / */ /* / + * / */ /* / "image-surface" + / */ /* Y^ / (dans (OX,OZ)) + / */ /* | / + / */ /* | / + / */ /* Ymin ==> -Zm|n ----------------------------+------------ */ /* | + */ /* O---------> |\ + */ /* / X | \ + */ /* / | \ + */ /* Z/ | \ + */ /* | \+ */ /* | .\ */ /* | . \ */ /* | *P(Xp,Yp,Zp) */ /* \+ | */ /* +\ | */ /* ligne de + \ | ecran */ /* visee + \ | */ /* + \ | */ /* + \ | */ /* * \| */ /* O(Xo,Yo,Zo) */ /* */ INITIALISATION_POINT_3D(point_3D_courant_de_l_ecran ,TRANSFORMATION_GEOMETRIQUE_3D_Fx(_____cNORMALISE_OX(X) ,_____cNORMALISE_OY(Y) ,_____cNORMALISE_OZ(Zorigine) ,ASI1(translation,dx) ) ,TRANSFORMATION_GEOMETRIQUE_3D_Fy(_____cNORMALISE_OX(X) ,_____cNORMALISE_OY(Y) ,_____cNORMALISE_OZ(Zorigine) ,ASI1(translation,dy) ) ,TRANSFORMATION_GEOMETRIQUE_3D_Fz(_____cNORMALISE_OX(X) ,_____cNORMALISE_OY(Y) ,_____cNORMALISE_OZ(Zorigine) ,ASI1(translation,dz) ) ); /* Definition du point courant sur l'ecran (c'est-a-dire dans 'imageR'), mais considere */ /* dans l'espace tridimensionnel, et que l'on va projeter, depuis l'observateur, sur */ /* la surface definie par le champ 'champ_de_cotes'. */ INITIALISATION_ACCROISSEMENT_3D(direction_de_visee_courante ,SOUS(ASD1(point_3D_courant_de_l_ecran,x) ,ASI1(position_du_touriste_observateur,x) ) ,SOUS(ASD1(point_3D_courant_de_l_ecran,y) ,ASI1(position_du_touriste_observateur,y) ) ,SOUS(ASD1(point_3D_courant_de_l_ecran,z) ,ASI1(position_du_touriste_observateur,z) ) ); /* Definition de la direction de visee, comme allant de l'observateur a l'ecran */ EGAL(distance_de_visee_courante,longF3D(direction_de_visee_courante)); /* Puis de sa norme... */ Test(IZGT(distance_de_visee_courante)) Bblock INITIALISATION_ACCROISSEMENT_3D(direction_de_visee_courante ,DIVI(ASD1(direction_de_visee_courante,dx) ,distance_de_visee_courante ) ,DIVI(ASD1(direction_de_visee_courante,dy) ,distance_de_visee_courante ) ,DIVI(ASD1(direction_de_visee_courante,dz) ,distance_de_visee_courante ) ); /* Enfin, on normalise la direction de visee (lorsqu'elle est definie...). */ Test(IFOU(IFET(IZEQ(ASD1(direction_de_visee_courante,dx)) ,NINCff(ASI1(position_du_touriste_observateur,x) ,_____cNORMALISE_OX(Xmin) ,_____cNORMALISE_OX(Xmax) ) ) ,IFET(IZEQ(ASD1(direction_de_visee_courante,dz)) ,NINCff(ASI1(position_du_touriste_observateur,z) ,_____cNORMALISE_OZ(Y_to_Z(Ymin)) ,_____cNORMALISE_OZ(Y_to_Z(Ymax)) ) ) ) ) Bblock /* ATTENTION : la position en 'z' de l'observateur est comparee a des coordonnees de */ /* type 'y' ('Ymin' et 'Ymax'), ce qui est du au fait que l'image 'champ_de_cotes' est */ /* placee dans le plan (OX,OZ) ; enfin, on notera les 'Y_to_Z()' qui rappellent que l'axe */ /* 'OZ' vient vers nous, et que l'image 'champ_de_cotes' est placee derriere le plan */ /* (OX,OY)... */ PRINT_ERREUR("l'observateur ne regarde pas dans la direction de l'image a visualiser"); Eblock ATes Bblock INITIALISATION_ACCROISSEMENT_3D(direction_image_observateur ,SOUS(_____cNORMALISE_OX(Xcentre) ,ASI1(position_du_touriste_observateur,x) ) ,FZERO ,SOUS(_____cNORMALISE_OZ(Y_to_Z(Ycentre)) ,ASI1(position_du_touriste_observateur,z) ) ); /* Definition de la ligne allant de l'observateur au centre de l'image et qui est utilisee */ /* pour savoir si celui-ci ne "tourne pas le dos" a l'image 'champ_de_cotes' ; on notera */ /* que la composante en 'dy' est mise a 0, et ce afin de simuler dans le test qui va suivre */ /* un produit scalaire entre 'direction_image_observateur' et 'direction_de_visee_courante' */ /* dans le plan (Ox,OZ)... */ Test(IZGT(prdF3D(direction_image_observateur,direction_de_visee_courante))) Bblock /* Il faut que les deux pseudo-vecteurs 'direction_image_observateur' et */ /* 'direction_de_visee_courante' aillent a peu pres dans la meme direction pour avoir */ /* une chance de voir 'champ_de_cotes' depuis l'observateur... */ /* */ /* L'equation de la ligne de visee est : */ /* */ /* X - Xo Y - Yo Z - Zo */ /* ---------- = ---------- = ---------- */ /* visee(X) visee(Y) visee(Z) */ /* */ /* ou : */ /* */ /* {X,Y,Z} designe le point courant, */ /* (Xo,Yo,Zo) designe l'observateur, et */ /* (visee(X),visee(Y),visee(Z)) designe son vecteur directeur 'direction_de_visee_courante'. */ /* */ EGAL(Z_pour_Xmin ,COND(IZEQ(ASD1(direction_de_visee_courante,dx)) ,F_INFINI ,AXPB(DIVI(ASD1(direction_de_visee_courante,dz),ASD1(direction_de_visee_courante,dx)) ,SOUS(_____cNORMALISE_OX(Xmin),ASI1(position_du_touriste_observateur,x)) ,ASI1(position_du_touriste_observateur,z) ) ) ); /* Calcul de l'intersection de la ligne de visee avec la droite X=Xmin dans */ /* le plan (OX,OZ), qui est en general du type : */ /* */ /* visee(Z) */ /* Z = Zo + ----------.(Xmin-Xo). */ /* visee(X) */ /* */ EGAL(Z_pour_Xmax ,COND(IZEQ(ASD1(direction_de_visee_courante,dx)) ,F_INFINI ,AXPB(DIVI(ASD1(direction_de_visee_courante,dz),ASD1(direction_de_visee_courante,dx)) ,SOUS(_____cNORMALISE_OX(Xmax),ASI1(position_du_touriste_observateur,x)) ,ASI1(position_du_touriste_observateur,z) ) ) ); /* Calcul de l'intersection de la ligne de visee avec la droite X=Xmax dans */ /* le plan (OX,OZ), qui est en general du type : */ /* */ /* visee(Z) */ /* Z = Zo + ----------.(Xmax-Xo). */ /* visee(X) */ /* */ EGAL(X_pour_Zmin ,COND(IZEQ(ASD1(direction_de_visee_courante,dz)) ,F_INFINI ,AXPB(DIVI(ASD1(direction_de_visee_courante,dx),ASD1(direction_de_visee_courante,dz)) ,SOUS(_____cNORMALISE_OZ(Y_to_Z(Ymin)),ASI1(position_du_touriste_observateur,z)) ,ASI1(position_du_touriste_observateur,x) ) ) ); /* Calcul de l'intersection de la ligne de visee avec la droite Z=Y_to_Z(Ymin) dans */ /* le plan (OX,OZ), qui est en general du type : */ /* */ /* visee(X) */ /* X = Xo + ----------.(Y_to_Z(Ymin)-Xo). */ /* visee(Z) */ /* */ EGAL(X_pour_Zmax ,COND(IZEQ(ASD1(direction_de_visee_courante,dz)) ,F_INFINI ,AXPB(DIVI(ASD1(direction_de_visee_courante,dx),ASD1(direction_de_visee_courante,dz)) ,SOUS(_____cNORMALISE_OZ(Y_to_Z(Ymax)),ASI1(position_du_touriste_observateur,z)) ,ASI1(position_du_touriste_observateur,x) ) ) ); /* Calcul de l'intersection de la ligne de visee avec la droite Z=Y_to_Z(Ymax) dans */ /* le plan (OX,OZ), qui est en general du type : */ /* */ /* visee(X) */ /* X = Xo + ----------.(Y_to_Z(Ymax)-Xo). */ /* visee(Z) */ /* */ Test(IFET(IFET(NINCff(Z_pour_Xmin,_____cNORMALISE_OZ(Y_to_Z(Ymin)),_____cNORMALISE_OZ(Y_to_Z(Ymax))) ,NINCff(Z_pour_Xmax,_____cNORMALISE_OZ(Y_to_Z(Ymin)),_____cNORMALISE_OZ(Y_to_Z(Ymax))) ) ,IFET(NINCff(X_pour_Zmin,_____cNORMALISE_OX(Xmin),_____cNORMALISE_OX(Xmax)) ,NINCff(X_pour_Zmax,_____cNORMALISE_OX(Xmin),_____cNORMALISE_OX(Xmax)) ) ) ) Bblock /* L'observateur ne voit pas l'image a visualiser dans cette direction, mais cela ne */ /* constitue pas une erreur (ce sera en general le cas aux bords de l'ecran). */ Eblock ATes Bblock /* Calcul de l'intersection de la ligne de visee avec l'image dans le plan (OX,OZ) : */ /* */ /* | . . */ /* | \ . . */ /* | \ . . */ /* | \ . . */ /* | \ . . */ /* | \ . . */ /* | \ . . */ /* | \. . */ /* | + . */ /* | .\ . */ /* | . \ deuxieme point . */ /* Y_to_Z(Ymax) |............+....................................... */ /* | . |\ d'intersection . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ . */ /* | . | \ premier point */ /* Y_to_Z(Ymin) |............|------------+.......................... */ /* | . amplitude \ d'intersection */ /* | . de \ . */ /* | . traversee \_ . */ /* | . |\ visee. */ /* | . \ . */ /* | . \ . */ /* | . *Observateur */ /* | . \ . */ /* | . \ . */ /* | . \. */ /* | . + */ /* | . .\ */ /* | . . \ */ /* | . . \ */ /* | . . */ /* O-----------------------------------------------------> */ /* | Xmin Xmax X */ /* Z | */ /* */ EGAL(on_a_trouve_un_point_double,FAUX); /* A priori, on n'a pas trouve de point double. */ EGAL(on_a_trouve_le_premier_point,FAUX); EGAL(on_a_trouve_le_deuxieme_point,FAUX); /* A priori, on n'a encore trouve aucun point d'intersection... */ EGAL(ASD1(premier_point_d_intersection,y),FZERO); EGAL(ASD1(deuxieme_point_d_intersection,y),FZERO); /* A priori, on ne s'interesse pas a la troisieme coordonnee, qui est ici, il faut faire */ /* attention, la coordonnee 'Y'... */ Test(INCLff(Z_pour_Xmin,_____cNORMALISE_OZ(Y_to_Z(Ymin)),_____cNORMALISE_OZ(Y_to_Z(Ymax)))) Bblock CALCUL_DES_DEUX_INTERSECTIONS(_____cNORMALISE_OX(Xmin),Z_pour_Xmin); /* Calcul des deux points d'intersections... */ Eblock ATes Bblock Eblock ETes Test(INCLff(Z_pour_Xmax,_____cNORMALISE_OZ(Y_to_Z(Ymin)),_____cNORMALISE_OZ(Y_to_Z(Ymax)))) Bblock CALCUL_DES_DEUX_INTERSECTIONS(_____cNORMALISE_OX(Xmax),Z_pour_Xmax); /* Calcul des deux points d'intersections... */ Eblock ATes Bblock Eblock ETes Test(INCLff(X_pour_Zmin,_____cNORMALISE_OX(Xmin),_____cNORMALISE_OX(Xmax))) Bblock CALCUL_DES_DEUX_INTERSECTIONS(X_pour_Zmin,_____cNORMALISE_OZ(Y_to_Z(Ymin))); /* Calcul des deux points d'intersections... */ Eblock ATes Bblock Eblock ETes Test(INCLff(X_pour_Zmax,_____cNORMALISE_OX(Xmin),_____cNORMALISE_OX(Xmax))) Bblock CALCUL_DES_DEUX_INTERSECTIONS(X_pour_Zmax,_____cNORMALISE_OZ(Y_to_Z(Ymax))); /* Calcul des deux points d'intersections... */ Eblock ATes Bblock Eblock ETes Test(IFET(EST_VRAI(on_a_trouve_le_premier_point),EST_VRAI(on_a_trouve_le_deuxieme_point))) Bblock DEFV(Float,INIT(X_P,FLOT__UNDEF)); DEFV(Float,INIT(Y_P,FLOT__UNDEF)); /* Definition du point courant 'P'. */ DEFV(Int,INIT(X_G,UNDEF)); DEFV(Int,INIT(X_D,UNDEF)); DEFV(Int,INIT(Y_B,UNDEF)); DEFV(Int,INIT(Y_H,UNDEF)); /* Definition de la maille entiere entourant le point courant 'P' : */ /* */ /* G D */ /* */ /* | | | */ /* | */ /* [Y]+1 ---- * ------+-------- * ----- H */ /* | */ /* | | */ /* Y -----+------ P --------+------ */ /* | | */ /* | | | */ /* | | | */ /* | | | */ /* | | | */ /* | */ /* [Y] ---- * ------+-------- * ----- B */ /* | */ /* | | | */ /* */ /* [X] X [X]+1 */ /* */ /* ou '[x]' designe la partie entiere par defaut du nombre reel 'x', et ou {G,D,B,H} */ /* symbolisent {Gauche,Droite,Bas,Haut}. */ DEFV(Float,INIT(ponderation_BG,FLOT__UNDEF)); DEFV(Float,INIT(ponderation_BD,FLOT__UNDEF)); DEFV(Float,INIT(ponderation_HG,FLOT__UNDEF)); DEFV(Float,INIT(ponderation_HD,FLOT__UNDEF)); /* Coefficients d'interpolation lineaire a l'interieur de la maille definie ci-dessus. */ Test(IFLT(gpdisF3D(position_du_touriste_observateur,ASI1 ,deuxieme_point_d_intersection,ASD1 ) ,gpdisF3D(position_du_touriste_observateur,ASI1 ,premier_point_d_intersection,ASD1 ) ) ) Bblock fSWAP(ASD1(premier_point_d_intersection,x),ASD1(deuxieme_point_d_intersection,x)); fSWAP(ASD1(premier_point_d_intersection,y),ASD1(deuxieme_point_d_intersection,y)); fSWAP(ASD1(premier_point_d_intersection,z),ASD1(deuxieme_point_d_intersection,z)); /* Il faut que l'on trouve dans l'ordre sur 'direction_de_visee_courante' : l'observateur, */ /* le premier point d'intersection, et enfin le deuxieme point d'intersection... */ Eblock ATes Bblock Eblock ETes Test(IZEQ(ASD1(direction_de_visee_courante,dy))) Bblock EGAL(ASD1(premier_point_d_intersection,y) ,ASI1(position_du_touriste_observateur,y) ); EGAL(ASD1(deuxieme_point_d_intersection,y) ,ASI1(position_du_touriste_observateur,y) ); /* Si la ligne de visee est horizontale, la coordonnee 'Yi' des points d'intersection est */ /* aussi celle de l'observateur... */ Test(IFET(IZEQ(ASD1(direction_de_visee_courante,dx)) ,IZEQ(ASD1(direction_de_visee_courante,dz)) ) ) Bblock PRINT_ERREUR("les trois composantes de la visee sont nulles"); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Test(IZNE(ASD1(direction_de_visee_courante,dz))) Bblock EGAL(ASD1(premier_point_d_intersection,y) ,AXPB(DIVI(ASD1(direction_de_visee_courante,dy) ,ASD1(direction_de_visee_courante,dz) ) ,SOUS(ASD1(premier_point_d_intersection,z) ,ASI1(position_du_touriste_observateur,z) ) ,ASI1(position_du_touriste_observateur,y) ) ); EGAL(ASD1(deuxieme_point_d_intersection,y) ,AXPB(DIVI(ASD1(direction_de_visee_courante,dy) ,ASD1(direction_de_visee_courante,dz) ) ,SOUS(ASD1(deuxieme_point_d_intersection,z) ,ASI1(position_du_touriste_observateur,z) ) ,ASI1(position_du_touriste_observateur,y) ) ); /* Sinon, on calcule la coordonnee 'Yi' des points d'intersection a partir de la ligne de */ /* visee et d'une composante non nulle (ici 'dz') : */ /* */ /* visee(Y) */ /* Yi = Yo + ----------.(Zi-Zo). */ /* visee(Z) */ /* */ Eblock ATes Bblock Test(IZNE(ASD1(direction_de_visee_courante,dx))) Bblock EGAL(ASD1(premier_point_d_intersection,y) ,AXPB(DIVI(ASD1(direction_de_visee_courante,dy) ,ASD1(direction_de_visee_courante,dx) ) ,SOUS(ASD1(premier_point_d_intersection,x) ,ASI1(position_du_touriste_observateur,x) ) ,ASI1(position_du_touriste_observateur,y) ) ); EGAL(ASD1(deuxieme_point_d_intersection,y) ,AXPB(DIVI(ASD1(direction_de_visee_courante,dy) ,ASD1(direction_de_visee_courante,dx) ) ,SOUS(ASD1(deuxieme_point_d_intersection,x) ,ASI1(position_du_touriste_observateur,x) ) ,ASI1(position_du_touriste_observateur,y) ) ); /* Sinon, on calcule la coordonnee 'Yi' des points d'intersection a partir de la ligne de */ /* visee et d'une composante non nulle (ici 'dx') : */ /* */ /* visee(Y) */ /* Yi = Yo + ----------.(Xi-Xo). */ /* visee(X) */ /* */ Eblock ATes Bblock PRINT_ERREUR("la visee a lieu perpendiculairement au plan de l'image"); EGAL(ASD1(premier_point_d_intersection,y),F_INFINI); EGAL(ASD1(deuxieme_point_d_intersection,y),F_INFINI); Eblock ETes Eblock ETes Eblock ETes INITIALISATION_ACCROISSEMENT_3D(amplitude_de_traversee ,SOUS(_cDENORMALISE_OX(ASD1(deuxieme_point_d_intersection,x)) ,_cDENORMALISE_OX(ASD1(premier_point_d_intersection,x)) ) ,SOUS(_cDENORMALISE_OY(ASD1(deuxieme_point_d_intersection,y)) ,_cDENORMALISE_OY(ASD1(premier_point_d_intersection,y)) ) ,SOUS(_cDENORMALISE_OZ(ASD1(deuxieme_point_d_intersection,z)) ,_cDENORMALISE_OZ(ASD1(premier_point_d_intersection,z)) ) ); /* Calul de l'amplitude de passage du premier au deuxieme point d'intersection. */ EGAL(nombre_de_points_entre_les_deux_points_d_intersection ,TRPU(MAX2(DIVI(ABSO(ASD1(amplitude_de_traversee,dx)),pasX) ,DIVI(ABSO(ASD1(amplitude_de_traversee,dz)),pasY) ) ) ); /* Nombre de points a tester dans 'champ_de_cotes' pour aller du premier au deuxieme */ /* point d'intersection dans le plan (OX,OZ). */ TRANSFERT_POINT_3D(point_courant_ligne_de_visee,premier_point_d_intersection); /* Initialisation du point courant de balayage de la surface... */ EGAL(on_a_trouve_un_point_de_la_surface,FAUX); /* Pour savoir si l'on a trouve un point d'intersection entre la surface et la ligne */ /* de visee. */ Repe(nombre_de_points_entre_les_deux_points_d_intersection) Bblock Test(IFET(EST_FAUX(on_a_trouve_un_point_de_la_surface) ,I3ET(INCLff(ASD1(point_courant_ligne_de_visee,x) ,ASD1(premier_point_d_intersection,x) ,ASD1(deuxieme_point_d_intersection,x) ) ,INCLff(ASD1(point_courant_ligne_de_visee,y) ,ASD1(premier_point_d_intersection,y) ,ASD1(deuxieme_point_d_intersection,y) ) ,INCLff(ASD1(point_courant_ligne_de_visee,z) ,ASD1(premier_point_d_intersection,z) ,ASD1(deuxieme_point_d_intersection,z) ) ) ) ) /* On notera l'introduction du test d'inclusion (par 'INCLff(...)') des coordonnees du point */ /* courant par rapport a celles des deux points d'intersection. En effet, a cause d'erreurs */ /* d'arrondi, il est possible, lors du deplacement par incrementation du point courant, de */ /* sortir (de tres peu...) du segment forme par les deux points d'intersection. Enfin, on */ /* utilise 'INCLff(...)', et non pas 'IFINff(...)', car on ne connait pas a priori l'ordre */ /* des bornes... */ Bblock EGAL(X_P,F__cDENORMALISE_OX(ASD1(point_courant_ligne_de_visee,x))); EGAL(Y_P,Z_to_Y(F__cDENORMALISE_OZ(ASD1(point_courant_ligne_de_visee,z)))); /* Calcul du point courant 'P'. */ EGAL(X_G,NEUT(INTE(X_P))); EGAL(X_D,SUCX(INTE(X_P))); EGAL(Y_B,NEUT(INTE(Y_P))); EGAL(Y_H,SUCY(INTE(Y_P))); /* Calcul de la maille entiere entourant le point courant 'P'. */ EGAL(ponderation_BG,MUL2(SOUS(FLOT(X_D),NEUT(X_P)),SOUS(FLOT(Y_H),NEUT(Y_P)))); EGAL(ponderation_BD,MUL2(SOUS(NEUT(X_P),FLOT(X_G)),SOUS(FLOT(Y_H),NEUT(Y_P)))); EGAL(ponderation_HG,MUL2(SOUS(FLOT(X_D),NEUT(X_P)),SOUS(NEUT(Y_P),FLOT(Y_B)))); EGAL(ponderation_HD,MUL2(SOUS(NEUT(X_P),FLOT(X_G)),SOUS(NEUT(Y_P),FLOT(Y_B)))); /* Calcul des coefficients d'interpolation lineaire a l'interieur de la maille precedente. */ Test(IFOU(IFOU(IFEXff(ponderation_BG ,COORDONNEE_BARYCENTRIQUE_MINIMALE ,COORDONNEE_BARYCENTRIQUE_MAXIMALE ) ,IFEXff(ponderation_BD ,COORDONNEE_BARYCENTRIQUE_MINIMALE ,COORDONNEE_BARYCENTRIQUE_MAXIMALE ) ) ,IFOU(IFEXff(ponderation_HG ,COORDONNEE_BARYCENTRIQUE_MINIMALE ,COORDONNEE_BARYCENTRIQUE_MAXIMALE ) ,IFEXff(ponderation_HD ,COORDONNEE_BARYCENTRIQUE_MINIMALE ,COORDONNEE_BARYCENTRIQUE_MAXIMALE ) ) ) ) Bblock PRINT_ERREUR("des coordonnees barycentriques sont hors de [0,1]"); CAL1(Prer2("(X,Y)........................=(%d,%d)\n",X,Y)); CAL1(Prer3("premier point d'intersection.=(%+.17f,%+.17f,%+.17f)\n" ,ASD1(premier_point_d_intersection,x) ,ASD1(premier_point_d_intersection,y) ,ASD1(premier_point_d_intersection,z) ) ); CAL1(Prer3("deuxieme point d'intersection=(%+.17f,%+.17f,%+.17f)\n" ,ASD1(deuxieme_point_d_intersection,x) ,ASD1(deuxieme_point_d_intersection,y) ,ASD1(deuxieme_point_d_intersection,z) ) ); CAL1(Prer3("ligne de visee...............=(%+.17f,%+.17f,%+.17f)\n" ,ASD1(point_courant_ligne_de_visee,x) ,ASD1(point_courant_ligne_de_visee,y) ,ASD1(point_courant_ligne_de_visee,z) ) ); CAL1(Prer2("point courant................=(%+.17f,%+.17f)\n",X_P,Y_P)); CAL1(Prer1("Gauche.......................=%d\n",X_G)); CAL1(Prer1("Droite.......................=%d\n",X_D)); CAL1(Prer1("Bas..........................=%d\n",Y_B)); CAL1(Prer1("Haut.........................=%d\n",Y_H)); CAL1(Prer1("ponderation BG...............=%+g\n",ponderation_BG)); CAL1(Prer1("ponderation BD...............=%+g\n",ponderation_BD)); CAL1(Prer1("ponderation HG...............=%+g\n",ponderation_HG)); CAL1(Prer1("ponderation HD...............=%+g\n",ponderation_HD)); Eblock ATes Bblock Eblock ETes Test(IFGT(ASD1(point_courant_ligne_de_visee,y) ,LRZ4(ponderation_BG,cote_courante(X_G,Y_B) ,ponderation_BD,cote_courante(X_D,Y_B) ,ponderation_HD,cote_courante(X_D,Y_H) ,ponderation_HG,cote_courante(X_G,Y_H) ) ) ) Bblock /* Cas ou la ligne de visee passe au-dessus du point courant de la surface... */ Test(IFGE(nombre_de_points_entre_les_deux_points_d_intersection,DEUX)) Bblock INCR(ASD1(point_courant_ligne_de_visee,x) ,DIVI(_____lNORMALISE_OX(ASD1(amplitude_de_traversee,dx)) ,FLOT(TRMU(nombre_de_points_entre_les_deux_points_d_intersection)) ) ); INCR(ASD1(point_courant_ligne_de_visee,y) ,DIVI(_____lNORMALISE_OY(ASD1(amplitude_de_traversee,dy)) ,FLOT(TRMU(nombre_de_points_entre_les_deux_points_d_intersection)) ) ); INCR(ASD1(point_courant_ligne_de_visee,z) ,DIVI(_____lNORMALISE_OZ(ASD1(amplitude_de_traversee,dz)) ,FLOT(TRMU(nombre_de_points_entre_les_deux_points_d_intersection)) ) ); /* Progression du point courant... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock /* Cas ou la ligne de visee rentre en collision avec la surface... */ EGAL(on_a_trouve_un_point_de_la_surface,VRAI); /* Memorisons que l'on a trouve un point d'intersection avec la surface : on notera */ /* qu'a partir de maintenant, 'point_courant_ligne_de_visee' ne bouge plus... */ Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ERep Test(EST_VRAI(on_a_trouve_un_point_de_la_surface)) Bblock /* On notera que pour des raisons diverses : */ /* */ /* X # _cDENORMALISE_OX(ASD1(point_courant_ligne_de_visee,x)) */ /* Y # Z_to_Y(_cDENORMALISE_OZ(ASD1(point_courant_ligne_de_visee,z))) */ /* */ /* la difference portant sur tres peu d'unites... */ DEFV(Int,INIT(X_AD,PREX(X_G))); DEFV(Int,INIT(X_BC,SUCX(X_G))); DEFV(Int,INIT(Y_AB,PREY(Y_B))); DEFV(Int,INIT(Y_DC,SUCY(Y_B))); DEFV(Float,INIT(Z__A,UNDEF)); DEFV(Float,INIT(Z__B,UNDEF)); DEFV(Float,INIT(Z__C,UNDEF)); DEFV(Float,INIT(Z__D,UNDEF)); /* Definition d'un quadrilatere {A,B,C,D} entourant le point courant 'P' : */ /* */ /* | | | */ /* | */ /* [Y]+1 ---- D ------+-------- C ----- */ /* | */ /* | | | */ /* | | */ /* Y -----+------ P --------+------ */ /* | | */ /* | | | */ /* | | | */ /* | | | */ /* | */ /* [Y]-1 ---- A ------+-------- B ----- */ /* | */ /* | | | */ /* */ /* [X]-1 XX [X]+1 */ /* */ /* ou '[x]' designe la partie entiere par defaut du nombre reel 'x'. */ EGAL(Z__A,F__cDENORMALISE_OY(cote_courante(X_AD,Y_AB))); EGAL(Z__B,F__cDENORMALISE_OY(cote_courante(X_BC,Y_AB))); EGAL(Z__C,F__cDENORMALISE_OY(cote_courante(X_BC,Y_DC))); EGAL(Z__D,F__cDENORMALISE_OY(cote_courante(X_AD,Y_DC))); /* Ceci etant rendu necesaire parce que les niveaux (par exemple ceux qui sont transmis par */ /* 'Imontagnes_en_perspective(...)') sont dans {NIVEAU_PRECIS_MINIMAL,NIVEAU_PRECIS_MAXIMAL} */ /* ce qui correspond en fait a [0,1]... */ INITIALISATION_ACCROISSEMENT_3D(normale ,PvectX(SOUS(X_AD,X_BC) ,SOUS(Z__D,Z__B) ,SOUS(Y_to_Z(Y_DC),Y_to_Z(Y_AB)) ,SOUS(X_BC,X_AD) ,SOUS(Z__C,Z__A) ,SOUS(Y_to_Z(Y_DC),Y_to_Z(Y_AB)) ) ,PvectY(SOUS(X_AD,X_BC) ,SOUS(Z__D,Z__B) ,SOUS(Y_to_Z(Y_DC),Y_to_Z(Y_AB)) ,SOUS(X_BC,X_AD) ,SOUS(Z__C,Z__A) ,SOUS(Y_to_Z(Y_DC),Y_to_Z(Y_AB)) ) ,PvectZ(SOUS(X_AD,X_BC) ,SOUS(Z__D,Z__B) ,SOUS(Y_to_Z(Y_DC),Y_to_Z(Y_AB)) ,SOUS(X_BC,X_AD) ,SOUS(Z__C,Z__A) ,SOUS(Y_to_Z(Y_DC),Y_to_Z(Y_AB)) ) ); /* Approximation d'une normale possible au point 'P' par : */ /* */ /* --> ---> ---> */ /* N = BD /\ AC */ /* */ /* (n'oublions pas que l'axe 'OY' de l'image est oriente dans le sens inverse de l'axe */ /* 'OZ' de l'espace). */ INITIALISATION_ACCROISSEMENT_3D(rayon_lumineux ,SOUS(F__cDENORMALISE_OX(ASI1(source_lumineuse,x)) ,X_P ) ,SOUS(F__cDENORMALISE_OY(ASI1(source_lumineuse,y)) ,LRZ4(ponderation_BG,cote_courante(X_G,Y_B) ,ponderation_BD,cote_courante(X_D,Y_B) ,ponderation_HD,cote_courante(X_D,Y_H) ,ponderation_HG,cote_courante(X_G,Y_H) ) ) ,SOUS(F__cDENORMALISE_OZ(ASI1(source_lumineuse,z)) ,Y_to_Z(Y_P) ) ); /* Calcul du rayon lumineux courant... */ EGAL(niveau_lumineux,MAX_NIVEAU_LUMINEUX); /* A priori, on choisit le maximum... */ EGAL(niveau_lumineux ,MUL2(HOMO(PUIX(DIVI(prdF3D(normale,rayon_lumineux) ,RACX(MUL2(pytF3D(normale) ,pytF3D(rayon_lumineux) ) ) ) ,Imontagnes_en_perspective_precises_____source_lumineuse_specularite ) ,COSINUS_DE_PI ,COSINUS_DE_0 ,minimum_normalise_du_cosinus_d_une_normale ,maximum_normalise_du_cosinus_d_une_normale ) ,niveau_lumineux ) ); /* Prise en compte de l'eclairage par la source lumineuse. */ /* */ /* La specularite a ete introduite le 20130101105228... */ Test(IL_FAUT(depth_cueing)) Bblock EGAL(y_reduit,__DENORMALISE_NIVEAU(_____cNORMALISE_OY(COYA(Y_P)))); /* Ainsi, on convertit la coordonnee 'Y' en un niveau ; mais ATTENTION, la coordonnee 'Y' */ /* utilisee pour le "depth-cueing" n'est pas correcte, puisqu'en effet, la valeur ainsi */ /* obtenue est toujours la meme, quelle que soit la position de l'observateur par rapport */ /* a l'image... */ EGAL(y_reduit,______NORMALISE_NIVEAU(NIVA(MAX2(y_reduit,MIN_INTENSITE)))); /* En effet, on ne peut tracer en noir... */ EGAL(niveau_lumineux ,MAX2(NIVA(MUL2(BARY(y_reduit ,______NORMALISE_NIVEAU(MAX_NIVEAU_LUMINEUX) ,min_depth_cueing ) ,NIVR(niveau_lumineux) ) ) ,MIN_INTENSITE ) ); Eblock ATes Bblock Eblock ETes EGAL(niveau_lumineux ,SCAL(niveau_lumineux ,MAX_NIVEAU_LUMINEUX ,LRZ4(ponderation_BG,texture_courante(X_G,Y_B) ,ponderation_BD,texture_courante(X_D,Y_B) ,ponderation_HD,texture_courante(X_D,Y_H) ,ponderation_HG,texture_courante(X_G,Y_H) ) ) ); /* Et on applique la texture donnee par "champ_de_texture". */ Test(INCLff(niveau_lumineux,FLOT__NOIR,FLOT__BLANC)) /* ATTENTION : le test precedent : */ /* */ /* Test(INCLff(niveau,NOIR,BLANC)) */ /* */ /* implique l'evaluation des expressions 'MINI(NOIR,BLANC)' et 'MAXI(NOIR,BLANC)', et alors */ /* le compilateur de 'SYSTEME_ES9000_AIX_CC' sort le message de warning suivant : */ /* */ /* w "..."....: Unsigned compare with zero always true. */ /* */ /* ce qui est intolerable. Plutot que de passer de 'INCLff(...)' a 'IFINff(...)', et parce */ /* qu'il est des cas ou je n'ai pu faire disparaitre ce message, j'ai introduit dans */ /* 'v $xcc/cb$Z' le fichier '$xcc/cb$D/sup.Mwarning$sed' qui elimine ces messages... */ Bblock store_point_3D(GENP(NIVA(niveau_lumineux)) ,imageR ,X,Y,ASD1(point_courant_ligne_de_visee,z) ); /* ATTENTION : a la permutation des axes 'OY' et 'OZ'... */ Eblock ATes Bblock PRINT_ERREUR("le niveau du point courant est hors [NOIR,BLANC]"); Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Test(EST_FAUX(on_a_trouve_un_point_double)) Bblock PRINT_ERREUR("moins de deux points d'intersection ont ete trouve"); CAL1(Prer2("(X,Y)........................=(%d,%d)\n",X,Y)); CAL1(Prer1("X_pour_Zmin..................=%+.17f\n",X_pour_Zmin)); CAL1(Prer1("X_pour_Zmax..................=%+.17f\n",X_pour_Zmax)); CAL1(Prer1("Z_pour_Xmin..................=%+.17f\n",Z_pour_Xmin)); CAL1(Prer1("Z_pour_Xmax..................=%+.17f\n",Z_pour_Xmax)); CAL1(Prer1("Xmin.........................=%+.17f\n",_____cNORMALISE_OX(Xmin))); CAL1(Prer1("Xmax.........................=%+.17f\n",_____cNORMALISE_OX(Xmax))); CAL1(Prer1("Ymin.........................=%+.17f\n",_____cNORMALISE_OZ(Y_to_Z(Ymin)))); CAL1(Prer1("Ymax.........................=%+.17f\n",_____cNORMALISE_OZ(Y_to_Z(Ymax)))); Eblock ATes Bblock Eblock ETes Eblock ETes Eblock ETes Eblock ATes Bblock PRINT_ERREUR("l'observateur tourne surement le dos a l'image a visualiser"); Eblock ETes Eblock ETes Eblock ATes Bblock PRINT_ERREUR("l'observateur est mal place par rapport au plan de l'ecran"); Eblock ETes Eblock end_image EDEFV(image,champ_de_texture); /* Et il en est de meme pour la texture... */ #ifdef TYPE_DE_imageA_surface_VERSION_01 EDEFV(image,champ_de_cotes); /* Cette image definie le champ de cote de la surface ; elle est obtenue par une */ /* symetrie d'axe 'OX' de l'image 'imageA_surface'. En effet, cette derniere est */ /* couchee dans le plan horizontal (OX,OZ), or l'axe 'OZ' vient vers l'observateur, */ /* ce qui fait que, par exemple, l'ancien 'Ymax' se trouve devant l'ancien 'Ymin', une */ /* fois sur le plan horizontal... */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 EDEFV(imageF,champ_de_cotes); /* Cette image definie le champ de cote de la surface ; elle est obtenue par une */ /* symetrie d'axe 'OX' de l'image 'imageA_surface'. En effet, cette derniere est */ /* couchee dans le plan horizontal (OX,OZ), or l'axe 'OZ' vient vers l'observateur, */ /* ce qui fait que, par exemple, l'ancien 'Ymax' se trouve devant l'ancien 'Ymin', une */ /* fois sur le plan horizontal... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 RETI(imageR); Eblock EFonctionP #undef texture_courante #ifdef TYPE_DE_imageA_surface_VERSION_01 # undef cote_courante #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 # undef cote_courante #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #undef CALCUL_DES_DEUX_INTERSECTIONS #undef IFEQ_a_peu_pres_sur_OY #undef IFEQ_a_peu_pres_sur_OX #undef Y_to_Z #undef Z_to_Y #undef MAX_NIVEAU_LUMINEUX #undef MIN_INTENSITE #undef CLIPPING_INTENSITE /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M I S E E N P E R S P E C T I V E M O N T A G N E U S E D ' U N E I M A G E " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionP /* ATTENTION, on introduit deux fonctions 'Imontagnes_en_perspective(...)' et */ /* 'Imontagnes_en_perspective_precises(...)' qui sont de toute evidence inutiles en */ /* 'TYPE_DE_imageA_surface_VERSION_01' mais dont la presence permet de simplifier */ /* considerablement la coexistence des deux versions... */ #ifdef TYPE_DE_imageA_surface_VERSION_02 /* ATTENTION, les deux definitions qui suivent sont faites independamment pour les deux */ /* fonctions 'Imontagnes(...)' et 'Imontagnes_en_perspective(...)' afin qu'elles puissent */ /* prendre alors des valeurs differentes, ce qui n'est pas le cas actuellement... */ # define NIVEAU_PRECIS_MINIMAL \ ______________NOIR_NORMALISE # define NIVEAU_PRECIS_MAXIMAL \ ______________BLANC_NORMALISE /* Niveaux minimal et maximal dans 'imageA_surface_flottante'. */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 DEFV(Common,DEFV(FonctionP,POINTERp(Imontagnes_en_perspective(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,ARGUMENT_POINTERs(translation) ,ARGUMENT_POINTERs(position_du_touriste_observateur) ,ombres_portees ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, qui est une vue texturee de la surface. */ DEFV(Argument,DEFV(Float,facteur_d_echelle)); /* Facteur d'echelle permettant de moduler le champ contenu dans 'imageA_surface', */ /* et par exemple de l'inverser... */ DEFV(Argument,DEFV(image,imageA_surface)); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface, */ DEFV(Argument,DEFV(image,imageA_texture)); /* Deuxieme image Argument, qui donne la texture de la surface. */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(deltaF_3D,POINTERs(translation))); /* Translation de l'ecran (c'est-a-dire du support de 'imageR') dans l'espace */ /* tridimensionnel ; on n'oubliera pas que cette translation est exprimee dans */ /* des unites telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]... */ DEFV(Argument,DEFV(pointF_3D,POINTERs(position_du_touriste_observateur))); /* Definition de la position de l'observateur. */ /* */ /* 'position_de_l_observateur' fut remplace par 'position_du_touriste_observateur' le */ /* 20061113115240 pour prepaper l'execution de 'v $xau/LACT16.82$Z' qui fait la modification */ /* 'v $xau/LACT16.61.modifier$sed position_de_l_observateur' et eviter ainsi une grosse */ /* ambiguite... */ DEFV(Argument,DEFV(Logical,ombres_portees)); /* Les ombres portees doivent-elles etre presentes ('VRAI') ou non ('FAUX'). */ DEFV(Argument,DEFV(pointF_3D,POINTERs(source_lumineuse))); /* Donne dans le plan de l'image Resultat ('imageR'), les coordonnees de */ /* la source lumineuse ; ces coordonnees sont exprimees dans des unites */ /* telles que l'unite vaut respectivement [Xmin,Xmax] et [Ymin,Ymax]. */ DEFV(Argument,DEFV(Logical,depth_cueing)); /* Doit-on faire ('VRAI') ou pas ('FAUX') du depth-cueing ? */ /* mais ATTENTION, cette option n'est effective que si les */ /* ombres portees ont ete demandees !!! */ DEFV(Argument,DEFV(Float,min_depth_cueing)); /* Ce parametre est inclus dans le segment [0,1] ; plus il est */ /* proche de zero, plus, le "depth-cueing" est fort... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock #ifdef TYPE_DE_imageA_surface_VERSION_02 BDEFV(imageF,imageA_surface_flottante); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface convertie en */ /* 'Float'... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 /*..............................................................................................................................*/ #ifdef TYPE_DE_imageA_surface_VERSION_01 CALS(Imontagnes_en_perspective_precises(imageR ,facteur_d_echelle,imageA_surface ,imageA_texture ,ARGUMENT_POINTERs(translation) ,ARGUMENT_POINTERs(position_du_touriste_observateur) ,ombres_portees ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ) ); /* Generation de la surface montagneuse... */ #Aifdef TYPE_DE_imageA_surface_VERSION_01 #Eifdef TYPE_DE_imageA_surface_VERSION_01 #ifdef TYPE_DE_imageA_surface_VERSION_02 #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #ifdef TYPE_DE_imageA_surface_VERSION_02 CALS(Istd_float(imageA_surface_flottante,NIVEAU_PRECIS_MINIMAL,NIVEAU_PRECIS_MAXIMAL,imageA_surface)); /* Conversion flottante preliminaire... */ CALS(Imontagnes_en_perspective_precises(imageR ,facteur_d_echelle,imageA_surface_flottante ,imageA_texture ,ARGUMENT_POINTERs(translation) ,ARGUMENT_POINTERs(position_du_touriste_observateur) ,ombres_portees ,ARGUMENT_POINTERs(source_lumineuse) ,depth_cueing,min_depth_cueing ) ); /* Generation de la surface montagneuse... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 #ifdef TYPE_DE_imageA_surface_VERSION_02 EDEFV(imageF,imageA_surface_flottante); /* Premiere image Argument, qui donne la troisieme coordonnee de la surface convertie en */ /* 'Float'... */ #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 RETI(imageR); Eblock #ifdef TYPE_DE_imageA_surface_VERSION_02 /* ATTENTION, les deux dedefinitions qui suivent sont faites independamment pour les deux */ /* fonctions 'Imontagnes(...)' et 'Imontagnes_en_perspective(...)' afin qu'elles puissent */ /* prendre alors des valeurs differentes, ce qui n'est pas le cas actuellement... */ # undef NIVEAU_PRECIS_MAXIMAL # undef NIVEAU_PRECIS_MINIMAL #Aifdef TYPE_DE_imageA_surface_VERSION_02 #Eifdef TYPE_DE_imageA_surface_VERSION_02 EFonctionP _______________________________________________________________________________________________________________________________________