/*************************************************************************************************************************************/ /* */ /* G E N E R A T I O N D E S S E R P E N T S R E L A T I V E M E N T R E C T I L I G N E S */ /* A V E C T E N T A T I V E D ' E V I T E M E N T D ' I N T E R - C O L L I S I O N S : */ /* */ /* */ /* : oo oooo : */ /* : oo + ... */ /* o oo o +++ oo ++ :: ... */ /* o oo ........... + ++ + .. */ /* o : oo :: ........ + oo ........ o +++.. */ /* o: o ..... ++ ::: + ...o. o...++++ */ /* o .o. --......:: ++++oo o o .... ... */ /* : o ... o ..: ..++ o +oo ...... o */ /* : o ... ::::.o ++ o +oo ... o */ /* : o.::: .. oo o ooo ...oo. */ /* : ::..:o ...+ o o o++ o .o. + ... */ /* ::::: .. o .. o+ o+o oo.. + ... */ /* : .. +o.. + o o+ o ooo ... ... */ /* :.. + o + o o+ o o ... + .. */ /* ... + +oo + ooo o ... + ... */ /* ... + + o + oo oo ... + .. */ /* ..- +o oo + o.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 oo */ /* .. - +... oo : */ /* .. - .. .... oo : */ /* .. -.. .... o : */ /* .. .-..... + : -- */ /* ..... ...... + - */ /* ...... o- + */ /* ooo */ /* */ /* */ /* Author of '$xrk/serpents.03$K' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 1989??????????). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* I N T E R F A C E ' listG ' : */ /* */ /* */ /* :Debut_listG: */ /* :Fin_listG: */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F I C H I E R S D ' I N C L U D E S : */ /* */ /*************************************************************************************************************************************/ #include INCLUDES_BASE #include maths_fonct_COURBES_1_EXT /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* P A R A M E T R E S : */ /* */ /*************************************************************************************************************************************/ #define GRAINE 1789 \ /* Graine initiale du generateur aleatoire (Vive le gland Plesident Mityrand... Mais */ \ /* pourquoi dis-je cela : est-ce a cause de la revolution, ou a cause de l'aleatoire ?). */ #define PAS_DE_LA_GRAINE \ ZERO \ /* Afin de faire evoluer eventuellement (s'il est different de 0) la GRAINE... */ #define XB_min SOUS(Xmin,FRA4(dimX)) \ /* Pour definir l'espace tri-dimensionnel dans lequel doivent rester les points aleatoires. */ #define XB_max ADD2(Xmax,FRA4(dimX)) \ /* Pour definir l'espace tri-dimensionnel dans lequel doivent rester les points aleatoires. */ #define YB_min SOUS(Ymin,FRA4(dimY)) \ /* Pour definir l'espace tri-dimensionnel dans lequel doivent rester les points aleatoires. */ #define YB_max ADD2(Ymax,FRA4(dimY)) \ /* Pour definir l'espace tri-dimensionnel dans lequel doivent rester les points aleatoires. */ #define FACTEUR_D_HOMOTHETIE_Z \ DIVI(MdimXY,COULEURS) \ /* Pour passer de l'axe des 'Z' aux couleurs du depth-cueing... */ #define ZB_min COZA(MUL2(FACTEUR_D_HOMOTHETIE_Z,NIVR(NIVEAU_ORIGINE))) \ /* Pour definir l'espace tri-dimensionnel dans lequel doivent rester les points aleatoires. */ #define ZB_max COZA(MUL2(FACTEUR_D_HOMOTHETIE_Z,NIVR(NIVEAU_EXTREMITE))) \ /* Pour definir l'espace tri-dimensionnel dans lequel doivent rester les points aleatoires. */ #define NOMBRE_DE_TENTATIVES_SUR_UN_POINT \ DOUB(SEIZE) \ /* Nombre maximal de tentatives de generation d'un point aleatoire lorsqu'on */ \ /* detecte des "recouvrements"... */ #define NOMBRE_DE_TENTATIVES_SUR_UN_ARC \ SEIZE \ /* Nombre maximal de tentatives de generation d'un arc lorsqu'on detecte des */ \ /* pseudo-collisions... */ #define NIVEAU_DE_MASQUAGE_DE_L_ARC_PRECEDENT \ BLANC \ /* Niveau destine a exclure par masquage l'arc genere precedemment... */ #define TAUX_DE_REGRESSION \ PARE(0.95) \ /* Donne la "vitesse" de retour de 'P3' vers 'P1' en cas de collisions... */ #define PAS_DE_PARCOURS_DE_LA_SPIRALE \ SUCC(SEIZE) \ /* On parcours la spirale en sautant des points... */ #define SPHERE_X FRA2(dimX) \ /* Pour definir la distance maximale (P1,P2). */ #define SPHERE_Y FRA2(dimY) \ /* Pour definir la distance maximale (P1,P2). */ #define SPHERE_Z FRA2(MUL2(FACTEUR_D_HOMOTHETIE_Z,COULEURS)) \ /* Pour definir la distance maximale (P1,P2). */ #define M_DELTA_X FRA2(SPHERE_X) \ /* "Ouverture" arriere du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ \ /* cette valeur est proche de 0 (apres '_____lNORMALISE_OX'), moins le retour en arriere */ \ /* est possible... */ #define M_DELTA_Y FRA2(SPHERE_Y) \ /* "Ouverture" arriere du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ \ /* cette valeur est proche de 0 (apres '_____lNORMALISE_OY'), moins le retour en arriere */ \ /* est possible... */ #define M_DELTA_Z FRA2(SPHERE_Z) \ /* "Ouverture" arriere du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ \ /* cette valeur est proche de 0 (apres '_____lNORMALISE_OZ'), moins le retour en arriere */ \ /* est possible... */ #define P_DELTA_X FZERO \ /* "Ouverture" avant du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ \ /* cette valeur est proche de 1 (apres '_____lNORMALISE_OX'), plus l'eloignement en avant */ \ /* est rapide... */ #define P_DELTA_Y FZERO \ /* "Ouverture" avant du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ \ /* cette valeur est proche de 1 (apres '_____lNORMALISE_OY'), plus l'eloignement en avant */ \ /* est rapide... */ #define P_DELTA_Z FZERO \ /* "Ouverture" avant du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ \ /* cette valeur est proche de 1 (apres '_____lNORMALISE_OZ'), plus l'eloignement en avant */ \ /* est rapide... */ #define NIVEAU_ORIGINE \ NOIR_PLANCHER_1 \ /* Niveau origine du trace (correspond grossierement au 'Z' ; je dit "grossierement" car */ \ /* en effet pour les niveaux, l'interpolation est lineaire et non pas cubique puisqu'on */ \ /* ne connait pas les derivees). */ #define NIVEAU_EXTREMITE \ BLANC \ /* Niveau origine du trace (correspond grossierement au 'Z' ; je dit "grossierement" car */ \ /* en effet pour les niveaux, l'interpolation est lineaire et non pas cubique puisqu'on */ \ /* ne connait pas les derivees). */ #define AFFAIBLISSEMENT_AU_BORD \ QUAR(FDU) \ /* Afin de faire un degrade du centre vers le bord... */ #define NOMBRE_D_ARCS_F1 \ DOUB(QUATRE) \ /* Nombre d'arcs pour la famille 'F1'. */ #define NOMBRE_DE_POINTS_F1 \ SEIZE \ /* Nombre de points definissant le multi-arc de cubique (il y a un arc de moins que */ \ /* de points) de la famille 'F1'. */ #define RAYON_DU_POINT_F1 \ DOUZE \ /* Rayon du point representatif de la famille 'F1'. */ #define COULEURS_F1 \ L_SUBSTITUTION_11 \ /* Liste de substitution de trace de la famille 'F1'. */ #define NOMBRE_D_ARCS_F2 \ NEUT(NOMBRE_D_ARCS_F1) \ /* Nombre d'arcs pour la famille 'F2'. */ #define NOMBRE_DE_POINTS_F2 \ NOMBRE_DE_POINTS_F1 \ /* Nombre de points definissant le multi-arc de cubique (il y a un arc de moins que */ \ /* de points) de la famille 'F2'. */ #define RAYON_DU_POINT_F2 \ TIER(RAYON_DU_POINT_F1) \ /* Rayon du point representatif de la famille 'F2'. */ #define COULEURS_F2 \ L_SUBSTITUTION_12 \ /* Liste de substitution de trace de la famille 'F2'. */ #define NOMBRE_D_ARCS_F3 \ DOUB(NOMBRE_D_ARCS_F1) \ /* Nombre d'arcs pour la famille 'F3'. */ #define NOMBRE_DE_POINTS_F3 \ NOMBRE_DE_POINTS_F1 \ /* Nombre de points definissant le multi-arc de cubique (il y a un arc de moins que */ \ /* de points) de la famille 'F3'. */ #define RAYON_DU_POINT_F3 \ TIER(RAYON_DU_POINT_F1) \ /* Rayon du point representatif de la famille 'F3'. */ #define COULEURS_F3 \ L_SUBSTITUTION_13 \ /* Liste de substitution de trace de la famille 'F3'. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M A C R O S U T I L E S : */ /* */ /*************************************************************************************************************************************/ #define EVITEMENT(rayon) \ GRO1(rayon) \ /* Pour faire que les serpents s'evitent, on fait une premiere passe avec un rayon */ \ /* augmente dans les proportions indiquees ici (en fait 'GRO3' est plus physique...). */ #define SEUIL_AVANT(rayon) \ EVITEMENT(CHOI(_____lNORMALISE_OX(rayon) \ ,_____lNORMALISE_OY(rayon) \ ) \ ) \ /* Afin de simuler l'evitement des serpents... */ #define SEUIL_ARRIERE(rayon) \ EVITEMENT(CHOI(_____lNORMALISE_OX(rayon) \ ,_____lNORMALISE_OY(rayon) \ ) \ ) \ /* Afin de simuler l'evitement des serpents... */ #define GENERE_COORDONNEE_ALEATOIRE(coordonnee,borne_inferieure,borne_superieure,_____cNORMALISE_OXYZ,V_min,V_max) \ Bblock \ DEFV(Float,INIT(inferieur,borne_inferieure)); \ DEFV(Float,INIT(superieur,borne_superieure)); \ DEFV(Float,INIT(amplitude,FLOT__UNDEF)); \ /* Ces variables intermediaires sont uniquement creees afin d'accelerer la compilation... */ \ EGAL(amplitude,TRMU(LENG(inferieur,superieur))); \ /* Le 'LENG' n'est pas fait dans 'INIT' afin d'accelerer la compilation ; d'autre part, */ \ /* le 'TRMU' est la afin que 'amplitude' soit nul, si 'inferieur' et 'superieur' sont egaux. */ \ EGAL(inferieur,TRON(inferieur,V_min,V_max)); \ EGAL(superieur,TRON(superieur,V_min,V_max)); \ /* Le 'TRON' n'est pas fait dans 'INIT' afin d'accelerer la compilation... */ \ Test(IFLT(V_min,V_max)) \ Bblock \ Test(IFET(IFEQ(inferieur,V_min),IFEQ(superieur,V_min))) \ Bblock \ EGAL(inferieur,V_min); \ EGAL(superieur,ADD2(V_min,amplitude)); \ /* Reinitialisation arbitraire lorsque les deux bornes sont egales... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Test(IFET(IFEQ(inferieur,V_max),IFEQ(superieur,V_max))) \ Bblock \ EGAL(inferieur,SOUS(V_max,amplitude)); \ EGAL(superieur,V_max); \ /* Reinitialisation arbitraire lorsque les deux bornes sont egales... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Test(IL_NE_FAUT_PAS(couper_l_arc_courant)) \ Bblock \ CALS(rdnI2D(ADRESSE(pointI_spirale) \ ,UNDEF \ ,RDN_INIT \ ,inferieur \ ,superieur \ ) \ ); \ /* Initialisation du generateur aleatoire. */ \ EGAL(coordonnee \ ,_____cNORMALISE_OXYZ(INTE(rdnI2D(ADRESSE(pointI_spirale) \ ,graine_courante \ ,RDN_GENERE \ ,FLOT__ARGUMENT_ABSENT,FLOT__ARGUMENT_ABSENT \ ) \ ) \ ) \ ); \ Repe(PAS_DE_PARCOURS_DE_LA_SPIRALE) \ Bblock \ SPIRALE_INITIALISATION; \ /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'. */ \ SPIRALE_DEPLACEMENT(ASD1(pointI_spirale,x),ASD1(pointI_spirale,y)); \ /* Deplacement du point courant de la spirale... */ \ SPIRALE_PARCOURS; \ /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant... */ \ INCR(graine_courante,pas_de_la_graine); \ /* Et enfin, modification eventuelle de la graine du generateur aleatoire... */ \ Eblock \ ERep \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Generation d'une coordonnee aleatoire avec restriction a la boite [V_min,V_max]. */ #define GENERE_POINT_ALEATOIRE(point,X_min,X_max,Y_min,Y_max,Z_min,Z_max,VX_min,VX_max,VY_min,VY_max,VZ_min,VZ_max) \ Bblock \ DEFV(Logical,INIT(generer_un_point,VRAI)); \ /* Indique s'il faut ou pas generer un point (on en genere au moins un, le premier). */ \ DEFV(Positive,INIT(nombre_de_tentatives_sur_un_point,NOMBRE_DE_TENTATIVES_SUR_UN_POINT)); \ /* Donne le nombre de tentatives restant a faire pour generer un point aleatoire */ \ /* lorsqu'il y a "recouvrement"... */ \ Tant(IFET(IL_FAUT(generer_un_point),IZGT(nombre_de_tentatives_sur_un_point))) \ Bblock \ GENERE_COORDONNEE_ALEATOIRE(ASD1(point,x),X_min,X_max,_____cNORMALISE_OX,VX_min,VX_max); \ GENERE_COORDONNEE_ALEATOIRE(ASD1(point,y),Y_min,Y_max,_____cNORMALISE_OY,VY_min,VY_max); \ GENERE_COORDONNEE_ALEATOIRE(ASD1(point,z),Z_min,Z_max,_____cNORMALISE_OZ,VZ_min,VZ_max); \ Test(IFEQ(load_point_valide(ImageR \ ,INTE(COXA(PROJECTION_OX(COXR(_cDENORMALISE_OX(ASD1(point,x))) \ ,COYR(_cDENORMALISE_OY(ASD1(point,y))) \ ,COZR(_cDENORMALISE_OZ(ASD1(point,z))) \ ) \ ) \ ) \ ,INTE(COYA(PROJECTION_OY(COXR(_cDENORMALISE_OX(ASD1(point,x))) \ ,COYR(_cDENORMALISE_OY(ASD1(point,y))) \ ,COZR(_cDENORMALISE_OZ(ASD1(point,z))) \ ) \ ) \ ) \ ) \ ,NOIR \ ) \ ) \ Bblock \ EGAL(generer_un_point,FAUX); \ /* Si le point aleatoire genere tombe dans le "vide", on le prend ; sinon, on le refuse */ \ /* et on en genere un autre, et ce afin d'eviter des problemes de detection de collisions : */ \ /* en effet, si le point (dit "de controle") d'un arc tombe sur un point deja occupe apres */ \ /* projection, etant donne qu'on masque les extremites des arcs afin de ne pas trouver */ \ /* de fausses collisions, les points de l'arc anterieur seront eux-aussi masques, et il */ \ /* n'y aura pas de collisions detectees... */ \ Eblock \ ATes \ Bblock \ DECR(nombre_de_tentatives_sur_un_point,I); \ /* Malgre tout, on empeche les bouclages a l'infini... */ \ Test(IZEQ(nombre_de_tentatives_sur_un_point)) \ Bblock \ EGAL(couper_l_arc_courant,VRAI); \ /* On a fait trop de tentatives : on arrete la... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ETes \ Eblock \ ETan \ Eblock \ /* Generation d'un point aleatoire avec restriction a la boite [VXYZ_min,VXYZ_max]. */ #define GENERE_VECTEUR_ALEATOIRE(origine,extremite) \ Bblock \ Test(IL_NE_FAUT_PAS(couper_l_arc_courant)) \ Bblock \ DEFV(deltaI_3D,vecteur_aleatoire_courant); \ /* Donne en permanence le vecteur aleatoire de type (P1,P2) ou (P2,P3). */ \ INITIALISATION_ACCROISSEMENT_3D(vecteur_aleatoire_courant \ ,SOUS(_cDENORMALISE_OX(ASD1(extremite,x)),_cDENORMALISE_OX(ASD1(origine,x))) \ ,SOUS(_cDENORMALISE_OY(ASD1(extremite,y)),_cDENORMALISE_OY(ASD1(origine,y))) \ ,SOUS(_cDENORMALISE_OZ(ASD1(extremite,z)),_cDENORMALISE_OZ(ASD1(origine,z))) \ ); \ EGAL(rayon_courant,RACX(FLOT(pytI3D(vecteur_aleatoire_courant)))); \ Test(IZEQ(rayon_courant)) \ Bblock \ PRINT_ERREUR("le rayon courant est nul, il va y avoir des divisions par 0"); \ EGAL(rayon_courant,FU); \ /* Pour les eviter malgre tout... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ EGAL(rayon_courant,FU); \ /* Pour eviter d'ulterieures divisions par 0... */ \ Eblock \ ETes \ Eblock \ /* Calcul du vecteur aleatoire (P1,P2) ou (P2,P3), et son module. */ #define SET_P1(X0,Y0,Z0) \ Bblock \ INITIALISATION_POINT_3D(pointF_P1,_____cNORMALISE_OX(X0),_____cNORMALISE_OY(Y0),_____cNORMALISE_OZ(Z0)); \ Eblock \ /* Definition du point P1. */ #define SET_P2(X0,Y0,Z0) \ Bblock \ INITIALISATION_POINT_3D(pointF_P2,_____cNORMALISE_OX(X0),_____cNORMALISE_OY(Y0),_____cNORMALISE_OZ(Z0)); \ Eblock \ /* Definition du point P2. */ #define SET_P3(X0,Y0,Z0) \ Bblock \ INITIALISATION_POINT_3D(pointF_P3,_____cNORMALISE_OX(X0),_____cNORMALISE_OY(Y0),_____cNORMALISE_OZ(Z0)) \ Eblock \ /* Definition du point P3. */ #define SET_P4(X0,Y0,Z0) \ Bblock \ INITIALISATION_POINT_3D(pointF_P4,_____cNORMALISE_OX(X0),_____cNORMALISE_OY(Y0),_____cNORMALISE_OZ(Z0)); \ Eblock \ /* Definition du point P4. */ #define MOVE_POINTS \ Bblock \ SET_P1(_cDENORMALISE_OX(ASD1(pointF_P2,x)) \ ,_cDENORMALISE_OY(ASD1(pointF_P2,y)) \ ,_cDENORMALISE_OZ(ASD1(pointF_P2,z)) \ ); \ SET_P2(_cDENORMALISE_OX(ASD1(pointF_P3,x)) \ ,_cDENORMALISE_OY(ASD1(pointF_P3,y)) \ ,_cDENORMALISE_OZ(ASD1(pointF_P3,z)) \ ); \ SET_P3(_cDENORMALISE_OX(ASD1(pointF_P4,x)) \ ,_cDENORMALISE_OY(ASD1(pointF_P4,y)) \ ,_cDENORMALISE_OZ(ASD1(pointF_P4,z)) \ ); \ Eblock \ /* Decalage des points (P1,P2,P3,P4) --> (P2,P3,P4,P4). */ #define DRAW_CUBIQUE_4(image,rayon_du_point,niveau_a_l_origine,niveau_a_l_extremite) \ Bblock \ Test(IL_NE_FAUT_PAS(couper_l_arc_courant)) \ Bblock \ Test(IFID(image,Masque)) \ Bblock \ CALS(Ivisualisation_arc_de_cubique_4P(Masque \ ,ADRESSE(pointF_P3) \ ,ADRESSE(pointF_P3) \ ,niveau_a_l_extremite \ ,ADRESSE(pointF_P3) \ ,niveau_a_l_extremite \ ,ADRESSE(pointF_P3) \ ,CHOI(_____lNORMALISE_OX(rayon_du_point) \ ,_____lNORMALISE_OY(rayon_du_point) \ ) \ ,FU \ ,BI_DIMENSIONNEL \ ) \ ); \ /* Trace du point extremite uniquement dans le cas du 'Masque'... */ \ Eblock \ ATes \ Bblock \ CALS(Ivisualisation_arc_de_cubique_4P(image \ ,ADRESSE(pointF_P1) \ ,ADRESSE(pointF_P2) \ ,niveau_a_l_origine \ ,ADRESSE(pointF_P3) \ ,niveau_a_l_extremite \ ,ADRESSE(pointF_P4) \ ,CHOI(_____lNORMALISE_OX(rayon_du_point) \ ,_____lNORMALISE_OY(rayon_du_point) \ ) \ ,affaiblissement_au_bord \ ,TRI_DIMENSIONNEL \ ) \ ); \ /* Trace de l'arc de cubique pour une image quelconque ; attention, pour le 'Masque', */ \ /* il ne faut surtout pas modifier le 'Z-Buffer' car en effet, la generation de */ \ /* l'image 'ImageR' s'en trouverait perturbee... */ \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Trace de l'arc de cubique... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D O N N E E S C O M M U N E S : */ /* */ /*************************************************************************************************************************************/ DEFV(Local,DEFV(Int,INIT(graine_courante,GRAINE))); /* Graine variable de generation des nombres aleatoires, */ DEFV(Local,DEFV(Int,INIT(pas_de_la_graine,PAS_DE_LA_GRAINE))); /* Et son pas de variation eventuel... */ DEFV(Local,DEFV(Float,INIT(sphere_X,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(sphere_Y,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(sphere_Z,FLOT__UNDEF))); /* Definition de la sphere de proximite (P1,P2), (P2,P3) et (P3,P4). */ DEFV(Local,DEFV(Float,INIT(M_delta_X,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(M_delta_Y,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(M_delta_Z,FLOT__UNDEF))); /* "Ouverture" arriere du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ /* cette valeur est proche de 0, moins le retour en arriere est possible... */ DEFV(Local,DEFV(Float,INIT(P_delta_X,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(P_delta_Y,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(P_delta_Z,FLOT__UNDEF))); /* "Ouverture" avant du cone de generation des points aleatoires 'P3' et 'P4' ; plus */ /* cette valeur est proche de 1, plus l'eloignement en avant est rapide... */ DEFV(Local,DEFV(Float,INIT(affaiblissement_au_bord,AFFAIBLISSEMENT_AU_BORD))); /* Afin de faire le degrade du centre vers le bord pour les disques. */ DEFV(Local,DEFV(Float,INIT(taux_de_regression,TAUX_DE_REGRESSION))); /* Donne la "vitesse" de retour de 'P3' vers 'P1' en cas de collisions... */ DEFV(Local,DEFV(pointI_2D,pointI_spirale)); /* Point d'un espace en spirale destinee a generer des nombres aleatoires. */ SPIRALE_DEFINITION_GENERALE(SE12(PasX,PasY),ZERO) /* Donnees de generation d'une spirale de parcours d'une image. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* G E N E R A T I O N D ' U N E F A M I L L E D E S E R P E N T S : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Local,DEFV(FonctionI,genere_une_famille_de_serpents(nombre_d_arcs ,nombre_de_points ,liste_de_substitution ,rayon_du_point ) ) ) DEFV(Argument,DEFV(Positive,nombre_d_arcs)); /* Nombre d'arcs a generer pour cette famille. */ DEFV(Argument,DEFV(Positive,nombre_de_points)); /* Nombre de points definissant chaque arc (en fait, on en genere 2 de plus...). */ DEFV(Argument,DEFV(Int,liste_de_substitution)); /* Definition de la liste de substitution a utiliser pour cette generation. */ DEFV(Argument,DEFV(Positive,rayon_du_point)); /* Rayon du disque materialisant un point. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(pointF_3D,pointF_P1); DEFV(pointF_3D,pointF_P2); DEFV(pointF_3D,pointF_P3); DEFV(pointF_3D,pointF_P4); /* Definition des quatre points definissant l'arc de cubique. */ DEFV(Float,INIT(rayon_courant,FLOT__UNDEF)); /* Module du vecteur aleatoire (P1,P2) ou (P2,P3). */ DEFV(Logical,INIT(couper_l_arc_courant,LUNDEF)); /* Indique s'il faut ou pas arreter la generation de l'arc courant (cas des sorties...). */ DEFV(Positive,INIT(nombre_de_tentatives_sur_un_arc,UNDEF)); /* Donne le nombre de tentatives restant a faire pour generer un arc lorsqu'il */ /* y a des pseudo-collisions... */ DEFV(Positive,INIT(nombre_de_pseudo_collisions,INFINI)); /* Donne le nombre de pseudo-collisions ; il est initialise de facon a ce que le */ /* comptage soit fait au moins une fois... */ INIT_ERROR; /*..............................................................................................................................*/ SUBSTITUTION(liste_de_substitution); /* Mise en place des bonnes couleurs... */ Komp(numero_de_l_arc,nombre_d_arcs) Bblock EGAL(couper_l_arc_courant,FAUX); /* A priori, on ne va pas couper, puisqu'on commence... */ PUSH_FILTRAGE; SET_FILTRAGE(INACTIF); /* On inhibe temporairement le filtrage afin de generer correctement le masque... */ CALS(Iinitialisation(Masque,NIVEAU_DE_MASQUAGE_DE_L_ARC_PRECEDENT)); /* A priori, on ne masque rien... */ PULL_FILTRAGE; Komp(numero_du_point,SUCC(SUCC(nombre_de_points))) Bblock Choi(numero_du_point) Bblock Ca1e(UN) Bblock GENERE_POINT_ALEATOIRE(pointF_P1 ,XB_min,XB_max ,YB_min,YB_max ,ZB_min,ZB_min ,XB_min,XB_max ,YB_min,YB_max ,ZB_min,ZB_min ); /* Initialisation du point 'P1' (tout a fait aleatoire mais dans le carre */ /* [XB_min,XB_max]x[YB_min,YB_max] et sur le plan du "fond" 'ZB_min'). */ Eblock ECa1 Ca1e(DEUX) Bblock GENERE_POINT_ALEATOIRE(pointF_P2 ,SOUS(_cDENORMALISE_OX(ASD1(pointF_P1,x)),_lDENORMALISE_OX(sphere_X)) ,ADD2(_cDENORMALISE_OX(ASD1(pointF_P1,x)),_lDENORMALISE_OX(sphere_X)) ,SOUS(_cDENORMALISE_OY(ASD1(pointF_P1,y)),_lDENORMALISE_OY(sphere_Y)) ,ADD2(_cDENORMALISE_OY(ASD1(pointF_P1,y)),_lDENORMALISE_OY(sphere_Y)) ,SOUS(_cDENORMALISE_OZ(ASD1(pointF_P1,z)),_lDENORMALISE_OZ(sphere_Z)) ,ADD2(_cDENORMALISE_OZ(ASD1(pointF_P1,z)),_lDENORMALISE_OZ(sphere_Z)) ,XB_min,XB_max ,YB_min,YB_max ,ZB_min,ZB_max ); /* Initialisation du point 'P2' (a l'interieur d'une sphere centree sur P1). */ Eblock ECa1 Ca1e(TROIS) Bblock GENERE_VECTEUR_ALEATOIRE(pointF_P1,pointF_P2); GENERE_POINT_ALEATOIRE(pointF_P3 ,COXA(SOUS(BARY(COXR(_cDENORMALISE_OX(ASD1(pointF_P2,x))) ,COXR(_cDENORMALISE_OX(ASD1(pointF_P1,x))) ,NEGA(DIVI(_lDENORMALISE_OX(sphere_X),rayon_courant)) ) ,_lDENORMALISE_OX(M_delta_X) ) ) ,NEUT(ADD2(BARY(COXR(_cDENORMALISE_OX(ASD1(pointF_P2,x))) ,COXR(_cDENORMALISE_OX(ASD1(pointF_P1,x))) ,NEGA(DIVI(_lDENORMALISE_OX(sphere_X),rayon_courant)) ) ,_lDENORMALISE_OX(P_delta_X) ) ) ,COYA(SOUS(BARY(COYR(_cDENORMALISE_OY(ASD1(pointF_P2,y))) ,COYR(_cDENORMALISE_OY(ASD1(pointF_P1,y))) ,NEGA(DIVI(_lDENORMALISE_OY(sphere_Y),rayon_courant)) ) ,_lDENORMALISE_OY(M_delta_Y) ) ) ,NEUT(ADD2(BARY(COYR(_cDENORMALISE_OY(ASD1(pointF_P2,y))) ,COYR(_cDENORMALISE_OY(ASD1(pointF_P1,y))) ,NEGA(DIVI(_lDENORMALISE_OY(sphere_Y),rayon_courant)) ) ,_lDENORMALISE_OY(P_delta_Y) ) ) ,COZA(SOUS(BARY(COZR(_cDENORMALISE_OZ(ASD1(pointF_P2,z))) ,COZR(_cDENORMALISE_OZ(ASD1(pointF_P1,z))) ,NEGA(DIVI(_lDENORMALISE_OZ(sphere_Z),rayon_courant)) ) ,_lDENORMALISE_OZ(M_delta_Z) ) ) ,NEUT(ADD2(BARY(COZR(_cDENORMALISE_OZ(ASD1(pointF_P2,z))) ,COZR(_cDENORMALISE_OZ(ASD1(pointF_P1,z))) ,NEGA(DIVI(_lDENORMALISE_OZ(sphere_Z),rayon_courant)) ) ,_lDENORMALISE_OZ(P_delta_Z) ) ) ,XB_min,XB_max ,YB_min,YB_max ,ZB_min,ZB_max ); /* Initialisation du point 'P3' (dans la direction P1 --> P2, on definit un point PP3 */ /* a distance 'sphere_XYZ' de 'P2' ; autour de 'PP3', on construit une sphere a l'interieur */ /* de laquelle on choisit aleatoirement le point 'P3'). Donnons precisemment la facon */ /* de calculer le minimum et le maximum communique au generateur aleatoire : */ /* */ /* P2 - P1 */ /* minimum = P2 + ---------.S - M */ /* R */ /* */ /* P2 - P1 */ /* maximum = P2 + ---------.S + P */ /* R */ /* */ /* ou : */ /* */ /* 'R' : designe 'rayon_courant', c'est-a-dire la norme du vecteur (P1,P2), */ /* 'S' : designe 'S_delta_X', 'S_delta_Y' ou encore 'S_delta_Z', */ /* 'M' : designe 'M_delta_X', 'M_delta_Y' ou encore 'M_delta_Z', */ /* 'P' : designe 'P_delta_X', 'P_delta_Y' ou encore 'P_delta_Z', */ /* */ /* ce qui donne sur un diagramme mono-dimensionnel : */ /* */ /* P1 P2 */ /* ..........*..................*.......X------------------X........... */ /* | | */ /* | | */ /* minimum maximum */ /* */ /* le point aleatoire desire ne pouvant qu'etre dans [minimum,maximum]. */ /* */ Eblock ECa1 Defo Bblock /* On notera que le point 'P4' peut etre recalcule plusieurs fois, en cas de collisions. */ EGAL(nombre_de_tentatives_sur_un_arc,NOMBRE_DE_TENTATIVES_SUR_UN_ARC); /* Donne le nombre de tentatives restant a faire pour generer un point de l'arc */ /* courant lorsqu'il y a pseudo-collisions... */ EGAL(nombre_de_pseudo_collisions,INFINI); /* L'initialisation est faite de telle facon que les points de type 'P4' soit toujours */ /* calcule au moins une fois en mode de detection des pseudo-collsions... */ Tant(IFET(IZNE(nombre_de_pseudo_collisions),IZGT(nombre_de_tentatives_sur_un_arc))) Bblock GENERE_VECTEUR_ALEATOIRE(pointF_P2,pointF_P3); GENERE_POINT_ALEATOIRE(pointF_P4 ,COXA(SOUS(BARY(COXR(_cDENORMALISE_OX(ASD1(pointF_P3,x))) ,COXR(_cDENORMALISE_OX(ASD1(pointF_P2,x))) ,NEGA(DIVI(_lDENORMALISE_OX(sphere_X),rayon_courant)) ) ,_lDENORMALISE_OX(M_delta_X) ) ) ,NEUT(ADD2(BARY(COXR(_cDENORMALISE_OX(ASD1(pointF_P3,x))) ,COXR(_cDENORMALISE_OX(ASD1(pointF_P2,x))) ,NEGA(DIVI(_lDENORMALISE_OX(sphere_X),rayon_courant)) ) ,_lDENORMALISE_OX(P_delta_X) ) ) ,COYA(SOUS(BARY(COYR(_cDENORMALISE_OY(ASD1(pointF_P3,y))) ,COYR(_cDENORMALISE_OY(ASD1(pointF_P2,y))) ,NEGA(DIVI(_lDENORMALISE_OY(sphere_Y),rayon_courant)) ) ,_lDENORMALISE_OY(M_delta_Y) ) ) ,NEUT(ADD2(BARY(COYR(_cDENORMALISE_OY(ASD1(pointF_P3,y))) ,COYR(_cDENORMALISE_OY(ASD1(pointF_P2,y))) ,NEGA(DIVI(_lDENORMALISE_OY(sphere_Y),rayon_courant)) ) ,_lDENORMALISE_OY(P_delta_Y) ) ) ,COZA(SOUS(BARY(COZR(_cDENORMALISE_OZ(ASD1(pointF_P3,z))) ,COZR(_cDENORMALISE_OZ(ASD1(pointF_P2,z))) ,NEGA(DIVI(_lDENORMALISE_OZ(sphere_Z),rayon_courant)) ) ,_lDENORMALISE_OZ(M_delta_Z) ) ) ,NEUT(ADD2(BARY(COZR(_cDENORMALISE_OZ(ASD1(pointF_P3,z))) ,COZR(_cDENORMALISE_OZ(ASD1(pointF_P2,z))) ,NEGA(DIVI(_lDENORMALISE_OZ(sphere_Z),rayon_courant)) ) ,_lDENORMALISE_OZ(P_delta_Z) ) ) ,XB_min,XB_max ,YB_min,YB_max ,ZB_min,ZB_max ); /* Initialisation du point 'P4' (dans la direction P2 --> P3, on definit un point PP4 */ /* a distance 'sphere_XYZ' de 'P3' ; autour de 'PP4', on construit une sphere a l'interieur */ /* de laquelle on choisit aleatoirement le point 'P4'). Voir le commentaire ci-dessus. */ DEMARRAGE_DU_COMPTAGE_DES_PSEUDO_COLLISIONS(SEUIL_AVANT(rayon_du_point) ,SEUIL_ARRIERE(rayon_du_point) ); MASQUE_IMAGES(NIVEAU_DE_MASQUAGE_DE_L_ARC_PRECEDENT); /* Ce masquage a pour effet de ne faire le comptage que la ou il n'y a pas masquage ; or */ /* celui-ci correspond a toute l'image sauf l'extremite de l'arc precedent, et ce afin de */ /* resoudre le probleme du recouvrement des points extremite de l'arc precedent et */ /* origine ('P2') de l'arc courant... */ DRAW_CUBIQUE_4(ImageR ,rayon_du_point ,NIVA(DIVI(COZR(_cDENORMALISE_OZ(ASD1(pointF_P2,z))) ,FACTEUR_D_HOMOTHETIE_Z ) ) ,NIVA(DIVI(COZR(_cDENORMALISE_OZ(ASD1(pointF_P3,z))) ,FACTEUR_D_HOMOTHETIE_Z ) ) ); /* Trace virtuel de l'arc de cubique (P2,P3) a l'aide des points (P1,P2,P3,P4). */ DEMASQUE_IMAGES; ARRET_DU_COMPTAGE_DES_PSEUDO_COLLISIONS(nombre_de_pseudo_collisions); /* En fait, on va changer le point 'P4' tant qu'il a des collisions... */ DECR(nombre_de_tentatives_sur_un_arc,I); /* Malgre tout, on empeche les bouclages a l'infini... */ Test(IZNE(nombre_de_pseudo_collisions)) Bblock Test(IZEQ(nombre_de_tentatives_sur_un_arc)) Bblock EGAL(couper_l_arc_courant,VRAI); /* On a fait trop de tentative : on arrete la... */ Eblock ATes Bblock /* Lorsqu'on a encore le droit de retenter, on deplace le point 'P3'... */ INITIALISATION_POINT_3D(pointF_P3 ,BARY(ASD1(pointF_P1,x),ASD1(pointF_P3,x),taux_de_regression) ,BARY(ASD1(pointF_P1,y),ASD1(pointF_P3,y),taux_de_regression) ,BARY(ASD1(pointF_P1,z),ASD1(pointF_P3,z),taux_de_regression) ); /* En cas de collisions, on deplace le point 'P3' ; afin de ne pas perturber le */ /* raccordement des arcs au niveau des tangentes, le point 'P3' doit etre rapproche */ /* de 'P1' en se deplacant sur la droite (P1,P3) ; rappelons qu'en effet la tangente */ /* en 'P2' est donnee par la direction (P1,P3)... */ Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ETan DRAW_CUBIQUE_4(ImageR ,rayon_du_point ,NIVA(DIVI(COZR(_cDENORMALISE_OZ(ASD1(pointF_P2,z))) ,FACTEUR_D_HOMOTHETIE_Z ) ) ,NIVA(DIVI(COZR(_cDENORMALISE_OZ(ASD1(pointF_P3,z))) ,FACTEUR_D_HOMOTHETIE_Z ) ) ); /* Trace reel de l'arc de cubique (P2,P3) a l'aide des points (P1,P2,P3,P4). */ PUSH_FILTRAGE; SET_FILTRAGE(INACTIF); /* On inhibe temporairement le filtrage afin de generer correctement le masque... */ CALS(Iinitialisation(Masque,NIVEAU_DE_MASQUAGE_DE_L_ARC_PRECEDENT)); DRAW_CUBIQUE_4(Masque ,SUCC(rayon_du_point) ,VCOMP(NIVEAU_DE_MASQUAGE_DE_L_ARC_PRECEDENT) ,VCOMP(NIVEAU_DE_MASQUAGE_DE_L_ARC_PRECEDENT) ); /* Et generation d'un masque correspondant au complement de l'extremite */ /* de l'arc que l'on vient de generer ; le 'SUCC' est la pour corriger d'eventuelles */ /* erreurs d'arrondis qui rendrait le masque trop etroit... */ PULL_FILTRAGE; MOVE_POINTS; /* Et "rotation" des points : (P1,P2,P3,P4) --> (P2,P3,P4,P4). */ Eblock EDef Eblock ECho Eblock EKom Eblock EKom RETU_ERROR; Eblock EFonctionI /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* G E N E R A T I O N D E S S E R P E N T S R E L A T I V E M E N T R E C T I L I G N E S : */ /* */ /*************************************************************************************************************************************/ BCommande(nombre_d_arguments,arguments) /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(CHAR,INIC(POINTERc(nom_imageR),NOM_PIPE)); DEFV(Positive,INIT(nombre_d_arcs_F1,NOMBRE_D_ARCS_F1)); DEFV(Positive,INIT(nombre_de_points_F1,NOMBRE_DE_POINTS_F1)); DEFV(genere_p,INIT(couleurs_F1,COULEURS_F1)); DEFV(Positive,INIT(rayon_du_point_F1,RAYON_DU_POINT_F1)); /* Parametres de definition de la famille 'F1'. */ DEFV(Positive,INIT(nombre_d_arcs_F2,NOMBRE_D_ARCS_F2)); DEFV(Positive,INIT(nombre_de_points_F2,NOMBRE_DE_POINTS_F2)); DEFV(genere_p,INIT(couleurs_F2,COULEURS_F2)); DEFV(Positive,INIT(rayon_du_point_F2,RAYON_DU_POINT_F2)); /* Parametres de definition de la famille 'F2'. */ DEFV(Positive,INIT(nombre_d_arcs_F3,NOMBRE_D_ARCS_F3)); DEFV(Positive,INIT(nombre_de_points_F3,NOMBRE_DE_POINTS_F3)); DEFV(genere_p,INIT(couleurs_F3,COULEURS_F3)); DEFV(Positive,INIT(rayon_du_point_F3,RAYON_DU_POINT_F3)); /* Parametres de definition de la famille 'F3'. */ /*..............................................................................................................................*/ GET_ARGUMENTSv(nombre_d_arguments ,BLOC(GET_ARGUMENT_C("imageR=""R=",nom_imageR); GET_ARGUMENT_I("methode=",gen_ft_____methode_standard); GET_ARGUMENT_I("graine=""g=",graine_courante); GET_ARGUMENT_L("affiner_rdn=",rdnIFnD_____affiner_la_generation); GET_ARGUMENT_L("iterer_rdn=",rdnIFnD_____iterer_la_generation); GET_ARGUMENT_I("pg=""pas=",pas_de_la_graine); GET_ARGUMENT_F("regression=",taux_de_regression); GIT_ARGUMENT_F("sx=""sX=",sphere_X,_____lNORMALISE_OX(I_lHOMOTHETIE_Std_OX(SPHERE_X))); GIT_ARGUMENT_F("sy=""sY=",sphere_Y,_____lNORMALISE_OY(I_lHOMOTHETIE_Std_OY(SPHERE_Y))); GIT_ARGUMENT_F("sz=""sZ=",sphere_Z,_____lNORMALISE_OZ(I_lHOMOTHETIE_Std_OZ(SPHERE_Z))); GIT_ARGUMENT_F("Mx=""MX=",M_delta_X,_____lNORMALISE_OX(I_lHOMOTHETIE_Std_OX(M_DELTA_X))); GIT_ARGUMENT_F("My=""MY=",M_delta_Y,_____lNORMALISE_OY(I_lHOMOTHETIE_Std_OY(M_DELTA_Y))); GIT_ARGUMENT_F("Mz=""MZ=",M_delta_Z,_____lNORMALISE_OZ(I_lHOMOTHETIE_Std_OZ(M_DELTA_Z))); GIT_ARGUMENT_F("Px=""PX=",P_delta_X,_____lNORMALISE_OX(I_lHOMOTHETIE_Std_OX(P_DELTA_X))); GIT_ARGUMENT_F("Py=""PY=",P_delta_Y,_____lNORMALISE_OY(I_lHOMOTHETIE_Std_OY(P_DELTA_Y))); GIT_ARGUMENT_F("Pz=""PZ=",P_delta_Z,_____lNORMALISE_OZ(I_lHOMOTHETIE_Std_OZ(P_DELTA_Z))); /* Le 20120210211727, les 'I_lHOMOTHETIE_Std_O?(...)'s furent introduits... */ GET_ARGUMENT_F("affaiblissement=",affaiblissement_au_bord); GET_ARGUMENT_I("a1=",nombre_d_arcs_F1); GET_ARGUMENT_I("p1=",nombre_de_points_F1); GET_ARGUMENT_P("c1=",couleurs_F1); GET_ARGUMENT_I("r1=",rayon_du_point_F1); GET_ARGUMENT_I("a2=",nombre_d_arcs_F2); GET_ARGUMENT_I("p2=",nombre_de_points_F2); GET_ARGUMENT_P("c2=",couleurs_F2); GET_ARGUMENT_I("r2=",rayon_du_point_F2); GET_ARGUMENT_I("a3=",nombre_d_arcs_F3); GET_ARGUMENT_I("p3=",nombre_de_points_F3); GET_ARGUMENT_P("c3=",couleurs_F3); GET_ARGUMENT_I("r3=",rayon_du_point_F3); ) ); Test(IFNE(NIVEAU_HORS_ECRAN,NOIR)) Bblock PRINT_ERREUR("le niveau hors-ecran doit etre NOIR"); Eblock ATes Bblock Eblock ETes CALi(Inoir(ImageR)); /* R : futur resultat (avant la mise en place des pas). */ EGAL(projecteur_OX,FZERO); EGAL(projecteur_OY,FZERO); /* On inhibe completement la projection (pour tout voir...). */ SPIRALE_VALIDATION; /* Validation des pas de parcours (pasX,pasY) des images. */ SET_FILTRAGE(ACTIF); INITIALISATION_POINT_2D(pointI_spirale,Xcentre,Ycentre); SPIRALE_REINITIALISATION_BRAS_ET_DELTAS; /* Initialisation de la spirale. */ CALS(Iinit_Z_Buffer()); CALS(genere_une_famille_de_serpents(nombre_d_arcs_F1 ,nombre_de_points_F1 ,couleurs_F1 ,rayon_du_point_F1 ) ); /* Generation de la premiere famille de serpents, */ CALS(genere_une_famille_de_serpents(nombre_d_arcs_F2 ,nombre_de_points_F2 ,couleurs_F2 ,rayon_du_point_F2 ) ); /* Generation de la seconde famille de serpents, */ CALS(genere_une_famille_de_serpents(nombre_d_arcs_F3 ,nombre_de_points_F3 ,couleurs_F3 ,rayon_du_point_F3 ) ); /* Generation de la troisieme famille de serpents. */ CALi(Iupdate_image(nom_imageR,ImageR)); RETU_Commande; Eblock ECommande