_______________________________________________________________________________________________________________________________________
/*************************************************************************************************************************************/
/* */
/* 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
_______________________________________________________________________________________________________________________________________