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