/*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N S D E L A V I S U A L I S A T I O N D ' U N E S P H E R E : */ /* */ /* */ /* Author of '$xrv/champs_5.1C$I' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 1993??????????). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O M P A T I B I L I T E : */ /* */ /*************************************************************************************************************************************/ #define RANDOMISER_LA_VISUALISATION_DES_PARTICULES \ LUNDEF DEFV(Local,DEFV(Logical,INIT(randomiser_la_visualisation_des_particules,RANDOMISER_LA_VISUALISATION_DES_PARTICULES))); #define RAYON_INTERIEUR_RELATIF_D_UNE_PARTICULE \ FLOT__UNDEF DEFV(Local,DEFV(Float,INIT(rayon_interieur_relatif_d_une_particule,RAYON_INTERIEUR_RELATIF_D_UNE_PARTICULE))); #define RAYON_EXTERIEUR_RELATIF_D_UNE_PARTICULE \ FLOT__UNDEF DEFV(Local,DEFV(Float,INIT(rayon_exterieur_relatif_d_une_particule,RAYON_EXTERIEUR_RELATIF_D_UNE_PARTICULE))); /* Donnees conservees pour des raisons de compatibilite, d'ou les valeurs implicites de */ /* type 'UNDEF', puisqu'elles ne servent plus a rien... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O M P T A G E D E S S P H E R E S " E N - E C R A N " : */ /* */ /*************************************************************************************************************************************/ DEFV(Local,DEFV(Int,INIT(compteur_des_spheres_dans_l_image,UNDEF))); /* Compteur des spheres visibles dans l'image courante. ATTENTION, on notera deux choses */ /* importantes : */ /* */ /* 1-l'intialisation de 'compteur_des_spheres_dans_l_image' est a la charge de quelqu'un */ /* d'autre (par exemple 'VISUALISATION_D_UNE_LISTE_DE_POINTS_AVEC_RENORMALISATION(...)' */ /* dans 'v $xrv/champs_5.12$I'). */ /* */ /* 2-une sphere dans l'image mais cachee entierement par une autre (via le 'Z-Buffer') */ /* sera malheureusement comptabilisee... */ /* */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* 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 D E L ' E C L A I R A G E : */ /* */ /*************************************************************************************************************************************/ #define INTENSITE_SPECULAIRE \ QUATRE DEFV(Local,DEFV(Float,INIT(intensite_speculaire,FLOT(INTENSITE_SPECULAIRE)))); /* Constante destinee a accentuer le caractere speculaire de l'eclairage... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D E L A T R A N S P A R E N C E : */ /* */ /*************************************************************************************************************************************/ #define COEFFICIENT_DE_TRANSPARENCE \ FZERO DEFV(Local,DEFV(Float,INIT(coefficient_de_transparence,COEFFICIENT_DE_TRANSPARENCE))); /* Coefficient de transparence : la valeur 0 indique une absence de transparence et la */ /* valeur 1, une transparence maximale... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D U B O R D A P P A R E N T D E S S P H E R E S : */ /* */ /*************************************************************************************************************************************/ #TestADef store_sphere__ANTI_ALIASING_____COMPATIBILITE_20060426 \ FAUX DEFV(Local,DEFV(Logical,INIT(store_sphere__anti_aliasing_____compatibilite_20060426 ,store_sphere__ANTI_ALIASING_____COMPATIBILITE_20060426 ) ) ); /* Afin d'assurer la compatibilite avec les resultats obtenus anterieurement a la date */ /* du 20060426140714 (voir '$xrv/champs_5.1C$I distance_courante_au_Z_Buffer'...). */ #define DEFINITION_DU_CONTOUR_APPARENT_DE_LA_SPHERE \ FU \ /* Constante destinee a definir ce qui est a l'interieur d'un contour apparent : l'interieur */ \ /* correspond aux valeurs de 'equation_representative_du_contour' inferieures a cette */ \ /* constante. */ #define MINIMUM_DE_L_EPAISSEUR_DE_L_INTERSECTION \ FRA8(epaisseur_de_la_couronne_d_anti_aliasing_effective) #define MAXIMUM_DE_L_EPAISSEUR_DE_L_INTERSECTION \ FRA2(epaisseur_de_la_couronne_d_anti_aliasing_effective) #define EPAISSEUR_DE_L_INTERSECTION \ BARY(MAXIMUM_DE_L_EPAISSEUR_DE_L_INTERSECTION \ ,MINIMUM_DE_L_EPAISSEUR_DE_L_INTERSECTION \ ,HOMO(DIVI(ASD1(vecteur_normal_approxime,dz),RACX(carre_de_la_norme_du_vecteur_normal_approxime)) \ ,FZERO,FU \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ) \ ) \ /* Definition de la distance-seuil en deca de laquelle on decrete que deux spheres forment */ \ /* a cet endroit leur intersection. On notera que l'on prend en compte ici l'inclinaison */ \ /* de la normale par rapport a l'axe 'OZ'. Ainsi plus une normale est inclinee par rapport */ \ /* a 'OZ', plus 'EPAISSEUR_DE_L_INTERSECTION' est important et proche de son maximum, et */ \ /* inversement, plus une normale est proche de 'OZ', plus 'EPAISSEUR_DE_L_INTERSECTION' */ \ /* est faible et proche de son minimum... */ \ /* */ \ /* Le 20060224114454, 'epaisseur_de_la_couronne_d_anti_aliasing_effective' a remplace */ \ /* 'epaisseur_de_la_couronne_d_anti_aliasing'... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* G E S T I O N D E S N I V E A U X ' RVB ' D E S P O I N T S : */ /* */ /*************************************************************************************************************************************/ #define FORCER_LE_NIVEAU_ANTERIEUR \ FAUX DEFV(Local,DEFV(Logical,INIT(forcer_le_niveau_anterieur,FORCER_LE_NIVEAU_ANTERIEUR))); #define NIVEAU_ANTERIEUR_A_FORCER \ NOIR DEFV(Local,DEFV(genere_p,INIT(niveau_anterieur_ROUGE_a_forcer,NIVEAU_ANTERIEUR_A_FORCER))); DEFV(Local,DEFV(genere_p,INIT(niveau_anterieur_VERTE_a_forcer,NIVEAU_ANTERIEUR_A_FORCER))); DEFV(Local,DEFV(genere_p,INIT(niveau_anterieur_BLEUE_a_forcer,NIVEAU_ANTERIEUR_A_FORCER))); /* Introduit le 20160806110540, au cas ou... */ #TestADef EDITER_LES_MESSAGES_DE_MAUVAIS_ENCADREMENT_DES_NIVEAUX_INTERPOLES \ FAUX DEFV(Local,DEFV(Logical,INIT(editer_les_messages_de_mauvais_encadrement_des_niveaux_interpoles ,EDITER_LES_MESSAGES_DE_MAUVAIS_ENCADREMENT_DES_NIVEAUX_INTERPOLES ) ) ); /* Introduit le 20130415134650 pour 'v $xiirv/.TREE.11.$U 20130415134953'... */ /* */ /* Le 20181227110537, le '#define' est devenu un '#TestADef' pour etre redefini dans */ /* 'v $xrv/particule.10$K EDITER_LES_MESSAGES_DE_MAUVAIS_ENCADREMENT_DES_NIVEAUX_INTERPOLES' */ /* lors de la mise au point de 'v $xrrv/CARR.35' avec "_____DistanceMini=0.050"... */ /* */ /* Le 20200325144451, la valeur par defaut est devenue 'FAUX' car, en effet, ce message ne */ /* sert a rien... */ #define niveau_RVB(niveau_RVB_du_point,nbRVB,ncRVB,iRVB,niveau_RVB_anterieur_eventuel_a_forcer) \ Bblock \ DEFV(genere_p,INIT(niveau_anterieur_du_point \ ,COND(IL_FAUT(forcer_le_niveau_anterieur) \ ,niveau_RVB_anterieur_eventuel_a_forcer \ ,load_point_valide(iRVB,INTE(ASD1(point_2Dt_courant,x)),INTE(ASD1(point_2Dt_courant,y))) \ ) \ ) \ ); \ /* Definition du niveau anterieur du point(X,Y), et ce afin d'aider le compilateur... */ \ DEFV(genere_p,INIT(niveau_posterieur_du_point \ ,GENP(TRON(NIVA(HOMO(modulation_d_eclairement \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ,MUL2(modulation_courante_de_la_luminance \ ,FLOT(NIVR(nbRVB)) \ ) \ ,MUL2(modulation_courante_de_la_luminance \ ,FLOT(NIVR(ncRVB)) \ ) \ ) \ ) \ ,FLOT(NOIR_PLANCHER_SUBSTITUTION) \ ,FLOT__BLANC \ ) \ ) \ ) \ ); \ /* Enfin, calcul du niveau du point courant. On notera la modulation de la luminance qui */ \ /* permet d'une part de simuler des fondus a l'ouverture et a la fermeture, et d'autre part */ \ /* de compenser la faible luminosite de certaines images... */ \ \ EGAL(niveau_posterieur_du_point \ ,NIVA(vBARY(NIVR(niveau_posterieur_du_point) \ ,NIVR(niveau_anterieur_du_point) \ ,coefficient_de_transparence \ ) \ ) \ ); \ /* Gestion de l'eventuelle transparence (cas ou le coefficient est non nul...). */ \ \ Test(IFNE(niveau_anterieur_du_point,niveau_posterieur_du_point)) \ Bblock \ EGAL(niveau_RVB_du_point \ ,NIVA(vBARY(NIVR(niveau_anterieur_du_point) \ ,NIVR(niveau_posterieur_du_point) \ ,correction_d_anti_aliasing_au_bord \ ) \ ) \ ); \ /* Enfin, prise en compte de la correction d'anti-aliasing ; le niveau a utiliser est donc */ \ /* interpole entre ce qui a ete calcule ('niveau_RVB_du_point') et ce qui se trouvait */ \ /* la avant ('load_point_valide(...)'), de facon a ce que tres pres du bord, le contenu */ \ /* anterieur soit preponderant : */ \ /* */ \ /* niveau = h.niveau + (1-h).anterieur */ \ /* */ \ /* ou 'h' designe 'correction_d_anti_aliasing_au_bord'. */ \ Eblock \ ATes \ Bblock \ EGAL(niveau_RVB_du_point \ ,niveau_posterieur_du_point \ ); \ /* Cas ou une correction n'est pas necessaire (ce test est surtout la pour eviter des */ \ /* problemes de "rebond" des splines...). */ \ Eblock \ ETes \ \ Test(NINCff(niveau_RVB_du_point,niveau_anterieur_du_point,niveau_posterieur_du_point)) \ Bblock \ Test(IL_FAUT(editer_les_messages_de_mauvais_encadrement_des_niveaux_interpoles)) \ /* Test introduit le 20130415134650... */ \ Bblock \ PRINT_ERREUR("un niveau interpole est mal encadre"); \ CAL1(Prer1(" niveau anterieur......................... = %d\n",niveau_anterieur_du_point)); \ CAL1(Prer1(" niveau posterieur calcule................ = %d\n",niveau_posterieur_du_point)); \ CAL1(Prer1(" niveau corrige (anti-aliasing)........... = %d\n",niveau_RVB_du_point)); \ CAL1(Prer1(" parametre d'interpolation (anti-aliasing) = %g\n",correction_d_anti_aliasing_au_bord)); \ /* Le 20081227102353, les messages precedents ont ete modifies afin d'ameliorer leur */ \ /* comprehension : */ \ /* */ \ /* "niveau calcule" --> "niveau posterieur calcule" */ \ /* "niveau corrige" --> "niveau corrige (anti-aliasing)" */ \ /* "parametre d'interpolation" --> "parametre d'interpolation (anti-aliasing)" */ \ /* */ \ /* lorsqu'ils sortent... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ EGAL(niveau_RVB_du_point \ ,NIVA(MOYE(NIVR(niveau_anterieur_du_point) \ ,NIVR(niveau_posterieur_du_point) \ ) \ ) \ ); \ /* Et on corrige la correction... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Calcul d'une des composantes du niveau du point courant. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D E S C O O R D O N N E E S C U R V I L I G N E S D E L A S P H E R E : */ /* */ /*************************************************************************************************************************************/ #define MINIMUM_DE_THETA \ FZERO #define MAXIMUM_DE_THETA \ CERCLE_TRIGONOMETRIQUE #define PAS_DE_THETA \ FRA4(FRA10(SOUS(MAXIMUM_DE_THETA,MINIMUM_DE_THETA))) DEFV(Local,DEFV(Float,INIT(pas_de_theta_de_la_sphere,PAS_DE_THETA))); /* Definition de la coordonnee curviligne 'theta'. Avant le 19991216115606 'PAS_DE_THETA' */ /* etait defini avec 'FRA2(FRA10(...))'. */ #define MINIMUM_DE_PHI \ FZERO #define MAXIMUM_DE_PHI \ PI #define PAS_DE_PHI \ FRA2(FRA10(SOUS(MAXIMUM_DE_PHI,MINIMUM_DE_PHI))) DEFV(Local,DEFV(Float,INIT(pas_de_phi_de_la_sphere,PAS_DE_PHI))); /* Definition de la coordonnee curviligne 'phi'. Avant le 19991216115606 'PAS_DE_PHI' */ /* etait defini avec 'FRA1(FRA10(...))'. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C H O I X E N T R E V I S U A L I S E R C O M P L E T E M E N T U N E S P H E R E */ /* O U N E V I S U A L I S E R Q U E S O N C E N T R E A P P A R E N T : */ /* */ /*************************************************************************************************************************************/ #define NE_VISUALISER_QUE_LE_CENTRE_DES_SPHERES \ FAUX DEFV(Local,DEFV(Logical,INIT(ne_visualiser_que_le_centre_des_spheres,NE_VISUALISER_QUE_LE_CENTRE_DES_SPHERES))); /* Indicateur precisant si l'on ne visualise que le centre des spheres ('VRAI') ou bien les */ /* spheres dans leur integralite ('FAUX'). Ceci a ete introduit le 19980907124444 pour */ /* faciliter le comptage des particules dans 'v $xrk/rdn_walk.41$K' lorsque les particules */ /* sont bidimensionnelles... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* E Q U A T I O N D E L A S P H E R E E T P R O J E C T I O N : */ /* */ /*************************************************************************************************************************************/ #define L_ESPACE_DE_L_IMAGE_EST_UN_TORE_SELON_OX \ FAUX #define L_ESPACE_DE_L_IMAGE_EST_UN_TORE_SELON_OY \ FAUX DEFV(Local,DEFV(Logical,INIT(l_espace_de_l_image_est_un_tore_selon_OX,L_ESPACE_DE_L_IMAGE_EST_UN_TORE_SELON_OX))); DEFV(Local,DEFV(Logical,INIT(l_espace_de_l_image_est_un_tore_selon_OY,L_ESPACE_DE_L_IMAGE_EST_UN_TORE_SELON_OY))); /* Ceci fut introduit le 20090816174959 de facon experimentale et approximative, en */ /* notant que cela n'a de sens que si 'IL_FAUT(ne_visualiser_que_le_centre_des_spheres)'... */ DEFV(Local,DEFV(pointF_3D,centre_3D_de_la_sphere)); DEFV(Local,DEFV(pointF_2D,centre_2D_de_la_sphere)); /* Definition du centre de la sphere dans l'espace tridimensionnel, et sa projection. */ DEFV(Local,DEFV(pointF_3D,point_3D_courant)); DEFV(Local,DEFV(pointF_2D,point_2D_courant)); DEFV(Local,DEFV(pointF_2D,point_2Dt_courant)); /* Definition du point courant de la sphere dans l'espace bidimensionnel, et sa projection. */ DEFV(Local,DEFV(deltaF_3D,vecteur_normal)); /* --> */ /* Vecteur normal N au point courant de la sphere. */ DEFV(Local,DEFV(Float,INIT(minimum_des_coordonnees_X_projetees,F_INFINI))); DEFV(Local,DEFV(Float,INIT(maximum_des_coordonnees_X_projetees,F_MOINS_L_INFINI))); DEFV(Local,DEFV(Float,INIT(minimum_des_coordonnees_Y_projetees,F_INFINI))); DEFV(Local,DEFV(Float,INIT(maximum_des_coordonnees_Y_projetees,F_MOINS_L_INFINI))); /* Introduit le 20180531100339 pour faciliter ulterieurement une aide au cadrage des images. */ /* On notera que ces extrema peuvent evidemment etre hors-ecran... */ #define DEFINITION_DU_POINT_3D_COURANT_SUR_LA_SPHERE(point_3D_courant,rayon,theta,phi) \ Bblock \ INITIALISATION_ACCROISSEMENT_3D(vecteur_normal \ ,Xcartesienne_3D(rayon,theta,phi) \ ,Ycartesienne_3D(rayon,theta,phi) \ ,Zcartesienne_3D(rayon,theta,phi) \ ); \ INITIALISATION_POINT_3D(point_3D_courant \ ,ADD2(ASD1(centre_3D_de_la_sphere,x),ASD1(vecteur_normal,dx)) \ ,ADD2(ASD1(centre_3D_de_la_sphere,y),ASD1(vecteur_normal,dy)) \ ,ADD2(ASD1(centre_3D_de_la_sphere,z),ASD1(vecteur_normal,dz)) \ ); \ Eblock \ /* Calcul des coordonnees du point courant tridimensionnel de la sphere. */ #define EDITER_LES_EXTREMA_DES_COORDONNEES_X_ET_Y_PROJETEES \ FAUX DEFV(Local,DEFV(Logical,INIT(editer_les_extrema_des_coordonnees_x_et_y_projetees ,EDITER_LES_EXTREMA_DES_COORDONNEES_X_ET_Y_PROJETEES ) ) ); /* Introduit le 20180531101315 pour aider au cadrage bi-dimensionnel et transfere ici */ /* le 20180601081321 depuis 'v $xrv/champs_5.12$I 20180601081333'... */ DEFV(Local,DEFV(Float,INIT(translation_X_des_coordonnees_projetees,FZERO))); DEFV(Local,DEFV(Float,INIT(translation_Y_des_coordonnees_projetees,FZERO))); /* Introduit le 20180531131658 pour faciliter le centrage des images (donc apres */ /* projection des points tridimensionnels... */ #define DEFINITION_DU_POINT_2D_COURANT_SUR_LA_SPHERE(point_2D,point_3D) \ Bblock \ INITIALISATION_POINT_2D(point_2D \ ,F__cDENORMALISE_OX(ADD2(Projection_OX(ASD1(point_3D,x) \ ,ASD1(point_3D,y) \ ,ASD1(point_3D,z) \ ) \ ,translation_X_des_coordonnees_projetees \ ) \ ) \ ,F__cDENORMALISE_OY(ADD2(Projection_OY(ASD1(point_3D,x) \ ,ASD1(point_3D,y) \ ,ASD1(point_3D,z) \ ) \ ,translation_Y_des_coordonnees_projetees \ ) \ ) \ ); \ /* ATTENTION, on notera que l'on ne fait pas : */ \ /* */ \ /* Test(EST_FAUX(LE_POINT_EST_INVISIBLE_OU_INDETERMINE(ASD1(point_3D,x) */ \ /* ,ASD1(point_3D,y) */ \ /* ,ASD1(point_3D,z) */ \ /* ) */ \ /* ) */ \ /* ) */ \ /* */ \ /* afin d'alleger le code qui suit. Tout repose donc sur l'hypothese que tous les points */ \ /* de la sphere sont visibles, en esperant que '$xrv/attractor.16$I' ait fait un tri */ \ /* correct dans 'MEMORISATION_DU_POINT_COURANT(...)'. */ \ /* */ \ /* Je note le 20090225105255 que c'est l'existence des "boites" {{minX,maxX}x{minY,maxY}}} */ \ /* et {{VminX,VmaxX}x{VminY,VmaxY}} qui interdit la possibilite de gerer, en option, l'image */ \ /* {iR,iV,iB} comme un tore via les fonctions {MOFX(...),MOFY(...)}. Si l'image {iR,iV,iB} */ \ /* etait un tore, alors les points d'image constituant la sphere courante pourrait former */ \ /* un ensemble non connexe, lorsque cette sphere est "a cheval" sur un ou plusieurs bords */ \ /* de l'image, ce qui est donc evidemment incompatible avec ces "boites". Cela fut verifie */ \ /* le 20090812171720 en introduisant ci-apres (et conditionnellement) : */ \ /* */ \ /* EGAL(ASD1(point_2D,x),MOFX(ASD1(point_2D,x))); */ \ /* EGAL(ASD1(point_2D,y),MOFY(ASD1(point_2D,y))); */ \ /* */ \ /* et effectivement le fonctionnement (teste avec 'v $xrs/cylindre.11$K' en tracant un */ \ /* cylindre incline ("ROTATION_OZ=1 ROTATION_OY=$pis2") etait incorrect pour les "fameux" */ \ /* points "a cheval". A cette date, je ne vois pas comment corriger cela. Finalement, le */ \ /* 20090814153037 j'essaye dans le cas 'IL_FAUT(ne_visualiser_que_le_centre_des_spheres)' */ \ /* et uniquement dans ce cas. Malheureusement cela ne marche pas mieux car, en effet */ \ /* le 'centre_2D_de_la_sphere' est calculee par la suite comme etant le centre de la */ \ /* boite {{VminX,VmaxX}x{VminY,VmaxY}} ; celle-ci etant mauvaise aux voisinages des bords, */ \ /* il en est de meme du centre de la sphere (trace alors tout seul en general a mi-distance */ \ /* des bords de l'image. Je renonce donc a cette solution "degradee" (valable donc */ \ /* uniquement dans le cas 'IL_FAUT(ne_visualiser_que_le_centre_des_spheres)'...). */ \ \ Test(IL_FAUT(editer_les_extrema_des_coordonnees_x_et_y_projetees)) \ /* Test d'optimisation de performances introduit le 20180601080652... */ \ Bblock \ EGAL(minimum_des_coordonnees_X_projetees,MIN2(minimum_des_coordonnees_X_projetees,ASD1(point_2D,x))); \ EGAL(maximum_des_coordonnees_X_projetees,MAX2(maximum_des_coordonnees_X_projetees,ASD1(point_2D,x))); \ EGAL(minimum_des_coordonnees_Y_projetees,MIN2(minimum_des_coordonnees_Y_projetees,ASD1(point_2D,y))); \ EGAL(maximum_des_coordonnees_Y_projetees,MAX2(maximum_des_coordonnees_Y_projetees,ASD1(point_2D,y))); \ /* Introduit le 20180531100339 pour faciliter ulterieurement un cadrage automatique... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Calcul des coordonnees du point courant bidimensionnel de la sphere. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C H O I X E N T R E L E M O D E R A P I D E E T L E M O D E L E N T : */ /* */ /*************************************************************************************************************************************/ /* Ce mode qui fonctionne mal en realite a ete supprime le 20090816110534... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* S I M U L A T I O N D E L A V I S U A L I S A T I O N D ' U N E S P H E R E E C L A I R E E : */ /* */ /*************************************************************************************************************************************/ #TestADef store_sphere__ANTI_ALIASING_____COMPATIBILITE_20050622 \ FAUX DEFV(Local,DEFV(Logical,INIT(store_sphere__anti_aliasing_____compatibilite_20050622 ,store_sphere__ANTI_ALIASING_____COMPATIBILITE_20050622 ) ) ); /* Afin d'assurer la compatibilite avec les resultats obtenus anterieurement a la date */ /* du 20050622154321 (voir '$xrv/champs_5.1C$I epaisseur_de_l_intersection_normalisee' */ /* ci-apres...). */ #TestADef store_sphere__ANTI_ALIASING_____COMPATIBILITE_20181227 \ FAUX DEFV(Local,DEFV(Logical,INIT(store_sphere__anti_aliasing_____compatibilite_20181227 ,store_sphere__ANTI_ALIASING_____COMPATIBILITE_20181227 ) ) ); /* Afin d'assurer la compatibilite avec les resultats obtenus anterieurement a la date */ /* du 20181227094921 (ceci a ete introduit pour 'v $xiirv/CARR.35' lors des tests de */ /* sa generation avec '_____DistanceMini=0.001', ce qui introduisait des points sombres */ /* aux intersections des spheres et dont la disposition etait relativement aleatoire...). */ #define store_sphere(nbR,nbV,nbB,ncR,ncV,ncB,iR,iV,iB,X_centre,Y_centre,Z_centre,Arayon,Vrayon) \ /* ATTENTION : {X,Y,Z} E [0,1]x[0,1]x[0,1]. */ \ /* */ \ /* Les deux arguments de type "rayon" signifient : */ \ /* */ \ /* 1-'Arayon' (appele ailleurs 'rayon_reel_absolu') : donne le rayon de la sphere dans */ \ /* l'espace [0,1]x[0,1]x[0,1]. Il s'agit donc du rayon "Absolu". */ \ /* */ \ /* 2-'Vrayon' (appele ailleurs 'rayon_reel_de_visualisation') : donne le rayon de la */ \ /* apres projection et donc avec un effet de perspective. Il s'agit donc du rayon de */ \ /* "Visualisation". */ \ /* */ \ Bblock \ DEFV(Logical,INIT(la_sphere_est_entierement_hors_de_l_image,VRAI)); \ /* A priori, la sphere que l'on va tracer est completement hors du cadre de l'image... */ \ \ INITIALISATION_POINT_3D(centre_3D_de_la_sphere \ ,X_centre \ ,Y_centre \ ,Z_centre \ ); \ /* Initialisation du centre effectif de la sphere... */ \ /* */ \ /* On notera que 'centre_2D_de_la_sphere' est soit calcule par projection de */ \ /* 'centre_3D_de_la_sphere', soit comme centre de gravite du contour apparent, */ \ /* suivant que l'on ne trace que le centre des spheres ou les spheres "completes"... */ \ \ Test(IL_FAUT(ne_visualiser_que_le_centre_des_spheres)) \ Bblock \ DEFV(Int,INIT(Xt,UNDEF)); \ DEFV(Int,INIT(Yt,UNDEF)); \ \ DEFINITION_DU_POINT_2D_COURANT_SUR_LA_SPHERE(centre_2D_de_la_sphere,centre_3D_de_la_sphere); \ /* Projection du centre effectif de la sphere... */ \ \ EGAL(Xt \ ,INTE(COND(EST_VRAI(l_espace_de_l_image_est_un_tore_selon_OX) \ ,MOFX(ASD1(centre_2D_de_la_sphere,x)) \ ,NEUT(ASD1(centre_2D_de_la_sphere,x)) \ ) \ ) \ ); \ EGAL(Yt \ ,INTE(COND(EST_VRAI(l_espace_de_l_image_est_un_tore_selon_OY) \ ,MOFY(ASD1(centre_2D_de_la_sphere,y)) \ ,NEUT(ASD1(centre_2D_de_la_sphere,y)) \ ) \ ) \ ); \ /* Possibilite de "tore selon 'OX' et/ou 'OY'" introduite le 20090816174959... */ \ \ Test(TEST_DANS_L_IMAGE(Xt,Yt)) \ Bblock \ store_point_ND_RVB(ncR,ncV,ncB \ ,iR,iV,iB \ ,Xt,Yt \ ,ASD1(centre_3D_de_la_sphere,z) \ ,TRI_DIMENSIONNEL \ ); \ /* Generation du centre d'une sphere lorsque l'on ne visualise que lui... */ \ /* */ \ /* Je note le 20090225105255 que c'est l'existence des "boites" {{minX,maxX},{minY,maxY}}} */ \ /* et {{VminX,VmaxX},{VminY,VmaxY}} qui interdit la possibilite de gerer, en option, l'image */ \ /* {iR,iV,iB} comme un tore via les fonctions {MOFX(...),MOFY(...)}. */ \ \ EGAL(la_sphere_est_entierement_hors_de_l_image,FAUX); \ /* La sphere (reduite donc a un point) est entierement dans le cadre de l'image... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ DEFV(Float,INIT(theta_de_la_sphere,FLOT__UNDEF)); \ DEFV(Float,INIT(phi_de_la_sphere,FLOT__UNDEF)); \ /* Definition des coordonnees curvilignes de la sphere... */ \ DEFV(Float,INIT(affinage_des_pas,FLOT__UNDEF)); \ /* Afin de corriger les pas de 'theta' et de 'phi' afin de bien echantillonner la sphere... */ \ DEFV(pointF_3D,point_3D_le_plus_proche); \ DEFV(pointF_2D,point_2D_le_plus_proche); \ /* Definition du point le plus proche de l'observateur. */ \ DEFV(Float,INIT(theta_du_point_le_plus_proche,FLOT__UNDEF)); \ DEFV(Float,INIT(phi_du_point_le_plus_proche,FLOT__UNDEF)); \ /* Coordonnees curvilignes du point le plus proche de l'observateur. */ \ DEFV(Float,INIT(distance_du_point_le_plus_proche,F_INFINI)); \ /* Distance du point le plus proche de l'observateur. */ \ DEFV(Float,INIT(rayon_du_contour_apparent,FLOT__UNDEF)); \ /* Definition du contour apparent de la sphere... */ \ DEFV(Int,INIT(minX,INFINI)); \ DEFV(Int,INIT(maxX,MOINS_L_INFINI)); \ DEFV(Int,INIT(minY,INFINI)); \ DEFV(Int,INIT(maxY,MOINS_L_INFINI)); \ /* Definition du "sous-buffer" de collision grace a [minX,maxX]x[minY,maxY]. Cette */ \ /* definition est faite en variables locales afin d'automatiser sa reinitialisation */ \ /* pour chaque nouvelle sphere... */ \ /* */ \ /* Le 19991216115606 l'initialisation qui etait anterieurement : */ \ /* */ \ /* DEFV(Int,INIT(minX,Xmax)); */ \ /* DEFV(Int,INIT(maxX,Xmin)); */ \ /* DEFV(Int,INIT(minY,Ymax)); */ \ /* DEFV(Int,INIT(maxY,Ymin)); */ \ /* */ \ /* a ete modifiee afin d'eviter un defaut sur les spheres partiellement hors-image... */ \ DEFV(Float,INIT(VminX,F_INFINI)); \ DEFV(Float,INIT(VmaxX,F_MOINS_L_INFINI)); \ DEFV(Float,INIT(VminY,F_INFINI)); \ DEFV(Float,INIT(VmaxY,F_MOINS_L_INFINI)); \ /* Definition identique a [minX,maxX]x[minY,maxY] si ce n'est qu'ici meme les points hors */ \ /* de l'image sont pris en compte, et ce afin de calculer le rayon du contour apparent... */ \ /* */ \ /* Le 19991216115606 l'initialisation qui etait anterieurement : */ \ /* */ \ /* DEFV(Float,INIT(VminX,FLOT(Xmax))); */ \ /* DEFV(Float,INIT(VmaxX,FLOT(Xmin))); */ \ /* DEFV(Float,INIT(VminY,FLOT(Ymax))); */ \ /* DEFV(Float,INIT(VmaxY,FLOT(Ymin))); */ \ /* */ \ /* a ete modifiee afin d'eviter un defaut sur les spheres partiellement hors-image... */ \ DEFV(Float,INIT(equation_representative_du_contour,FLOT__UNDEF)); \ /* Valeur courante au point {X,Y} de la fonction representative du contour de la forme */ \ /* materialisant la particule. */ \ DEFV(Float,INIT(distance_normalisee_au_centre,FLOT__UNDEF)); \ /* Distance normalisee dans [0,1] du point courant {X,Y} au centre du disque. */ \ DEFV(deltaF_3D,vecteur_normal_approxime); \ /* --> */ \ /* Approximation du vecteur normal N au point courant de la sphere destinee a lutter */ \ /* contre le fait que les points tridimensionnels ne se projettent pas exactement sur des */ \ /* points bidimensionnels de coordonnees entieres... */ \ DEFV(deltaF_3D,rayon_lumineux_inverse); \ /* --> */ \ /* Rayon lumineux inverse S (allant du point courant de l'ellipsoide a la source */ \ /* lumineuse). */ \ DEFV(Float,INIT(produit_des_modules_de_N_et_S,FLOT__UNDEF)); \ /* --> */ \ /* Produit du module du vecteur normal N et du module du vecteur rayon lumineux */ \ /* --> */ \ /* inverse S . */ \ DEFV(Float,INIT(modulation_d_eclairement,FLOT__UNDEF)); \ /* Modulation de l'eclairement du point courant calcule a partir de l'angle entre la */ \ /* --> --> */ \ /* vecteur normal N et le rayon lumineux inverse S . */ \ \ DoIn(theta_de_la_sphere,MINIMUM_DE_THETA,MAXIMUM_DE_THETA,pas_de_theta_de_la_sphere) \ Bblock \ DoIn(phi_de_la_sphere,MINIMUM_DE_PHI,MAXIMUM_DE_PHI,pas_de_phi_de_la_sphere) \ Bblock \ DEFV(Float,INIT(distance_du_point_courant,FLOT__UNDEF)); \ /* Definition de la distance de l'observateur au point courant... */ \ DEFINITION_DU_POINT_3D_COURANT_SUR_LA_SPHERE(point_3D_le_plus_proche \ ,Vrayon \ ,theta_de_la_sphere \ ,phi_de_la_sphere \ ); \ DEFINITION_DU_POINT_2D_COURANT_SUR_LA_SPHERE(point_2D_le_plus_proche,point_3D_le_plus_proche); \ /* Calcul des coordonnees du point courant de la sphere, et projection... */ \ /* */ \ /* On notera que de plus cette operation initialise la premiere fois les valeurs de */ \ /* 'Projection_OX_OY_____position_de_l_observateur' et de */ \ /* 'Projection_OX_OY_____plan_de_projection' definies dans le fichier */ \ /* 'v $xiii/vecteurs$FON'. */ \ /* */ \ /* ATTENTION, on notera que l'on ne fait pas : */ \ /* */ \ /* Test(EST_FAUX(LE_POINT_EST_INVISIBLE_OU_INDETERMINE(ASD1(point_3D_le_plus_proche,x) */ \ /* ,ASD1(point_3D_le_plus_proche,y) */ \ /* ,ASD1(point_3D_le_plus_proche,z) */ \ /* ) */ \ /* ) */ \ /* ) */ \ /* */ \ /* afin d'alleger le code qui suit. Tout repose donc sur l'hypothese que tous les points */ \ /* de la sphere sont visibles, en esperant que '$xrv/attractor.16$I' ait fait un tri */ \ /* correct dans 'MEMORISATION_DU_POINT_COURANT(...)'. */ \ \ EGAL(VminX,MIN2(VminX,ASD1(point_2D_le_plus_proche,x))); \ EGAL(VmaxX,MAX2(VmaxX,ASD1(point_2D_le_plus_proche,x))); \ EGAL(VminY,MIN2(VminY,ASD1(point_2D_le_plus_proche,y))); \ EGAL(VmaxY,MAX2(VmaxY,ASD1(point_2D_le_plus_proche,y))); \ \ EGAL(minX,MIN2(minX,INTE(ASD1(point_2D_le_plus_proche,x)))); \ EGAL(maxX,MAX2(maxX,INTE(ASD1(point_2D_le_plus_proche,x)))); \ EGAL(minY,MIN2(minY,INTE(ASD1(point_2D_le_plus_proche,y)))); \ EGAL(maxY,MAX2(maxY,INTE(ASD1(point_2D_le_plus_proche,y)))); \ /* Puis on met a jour la definition du plus petit rectangle contenant le contour apparent */ \ /* de cette sphere projetee mais en tenant compte que des points dans l'image... */ \ /* */ \ /* Avant le 19991216115606, ce mise a jour avait lieu de facon conditionnelle grace a : */ \ /* */ \ /* Test(TEST_DANS_L_IMAGE(INTE(ASD1(point_2D_le_plus_proche,x)) */ \ /* ,INTE(ASD1(point_2D_le_plus_proche,y)) */ \ /* ) */ \ /* ) */ \ /* */ \ /* mais cela n'a plus d'utilite dorenavant... */ \ Eblock \ EDoI \ Eblock \ EDoI \ \ EGAL(rayon_du_contour_apparent \ ,MOIT(MIN2(SOUS(VmaxX,VminX) \ ,SOUS(VmaxY,VminY) \ ) \ ) \ ); \ /* Calcul du rayon du contour apparent ; il vaut mieux le calculer ici que lors des boucles */ \ /* precedentes, car ici le pas relatif a (theta,phi) etant eventuellement plus fin, ce */ \ /* calcul sera plus precis. */ \ \ Test(IZLE(rayon_du_contour_apparent)) \ Bblock \ PRINT_ATTENTION("le Rayon du contour apparent est nul"); \ EGAL(rayon_du_contour_apparent,UN); \ /* Et ce afin d'eviter des problemes ulterieurs lors du calcul de l'equation du contour... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ INITIALISATION_POINT_2D(centre_2D_de_la_sphere \ ,MOYE(VminX,VmaxX) \ ,MOYE(VminY,VmaxY) \ ); \ /* Et determination du veritable centre du contour apparent... */ \ \ CALCUL_DE_LA_DISTANCE_CRITIQUE_NORMALISEE_AU_BORD(rayon_du_contour_apparent,Arayon); \ /* Preparation du traitement anti-aliasing de cette sphere... */ \ /* */ \ /* L'argument 'Arayon' a ete introduit le 20060224151605... */ \ \ begin_colonneQ(DoIn,minY,maxY,pasY) \ Bblock \ begin_ligneQ(DoIn,minX,maxX,pasX) \ Bblock \ INITIALISATION_POINT_2D(point_2Dt_courant \ ,FLOT(COND(EST_VRAI(l_espace_de_l_image_est_un_tore_selon_OX) \ ,MODX(X) \ ,NEUT(X) \ ) \ ) \ ,FLOT(COND(EST_VRAI(l_espace_de_l_image_est_un_tore_selon_OY) \ ,MODY(Y) \ ,NEUT(Y) \ ) \ ) \ ); \ /* Prise en compte eventuelle de la structure "Torique" de l'image (ceci a ete introduit */ \ /* le 20090818092838). */ \ \ Test(TEST_DANS_L_IMAGE(INTE(ASD1(point_2Dt_courant,x)),INTE(ASD1(point_2Dt_courant,y)))) \ Bblock \ DEFV(genere_p,INIT(niveau_ROUGE_du_point,ncR)); \ DEFV(genere_p,INIT(niveau_VERTE_du_point,ncV)); \ DEFV(genere_p,INIT(niveau_BLEUE_du_point,ncB)); \ /* Niveau du point courant initialise sur le maximum, et ce au cas ou le grand axe et le */ \ /* petit axe de l'ellipsoide seraient nuls... */ \ DEFV(Float,INIT(correction_d_anti_aliasing_au_bord,FLOT__UNDEF)); \ /* Afin de corriger l'aliasing sur le contour apparent des spheres... */ \ \ DEFV(Float,INIT(Z_approxime_au_carre,FLOT__UNDEF)); \ /* Valeurs intermediaires destinees a l'approximation de la coordonnee 'Z'... */ \ \ INITIALISATION_POINT_2D(point_2D_courant \ ,FLOT(X) \ ,FLOT(Y) \ ); \ /* Le point projete courant est pris comme etant le point "raster" courant... */ \ \ EGAL(Z_approxime_au_carre \ ,SOUS(EXP2(rayon_du_contour_apparent) \ ,disF2D(ASD1(centre_2D_de_la_sphere,x),ASD1(centre_2D_de_la_sphere,y) \ ,ASD1(point_2D_courant,x),ASD1(point_2D_courant,y) \ ) \ ) \ ); \ /* Calcul du carre de la distance du point bidimensionnel au contour apparent. En effet, */ \ /* on calcule ici quelque chose qui ressemble fortement a : */ \ /* */ \ /* 2 2 2 2 */ \ /* Z = R - (X + Y ) */ \ /* */ \ /* c'est-a-dire le carre de la coordonnee 'Z' que l'on ne connait pas a priori... */ \ \ Test(IZLT(Z_approxime_au_carre)) \ Bblock \ EGAL(Z_approxime_au_carre,FZERO); \ /* Les valeurs negatives sont ramenees a 0... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ INITIALISATION_POINT_3D(point_3D_courant \ ,_____cNORMALISE_OX(ASD1(point_2D_courant,x)) \ ,_____cNORMALISE_OY(ASD1(point_2D_courant,y)) \ ,ADD2(ASD1(centre_3D_de_la_sphere,z) \ ,SCAL(RACX(Z_approxime_au_carre),rayon_du_contour_apparent,Arayon) \ ) \ ); \ /* Le point dans l'espace tridimensionnel est approxime grossierement en calculant une */ \ /* fausse troisieme dimension a partir des deux coordonnees bidimensionnelles... */ \ /* */ \ /* Avant le 19991216123813, on trouvait ici : */ \ /* */ \ /* _____cNORMALISE_OZ(RACX(Z_approxime_au_carre)) */ \ /* */ \ /* mais cela semble faux car la taille du contour apparent change en fonction de la */ \ /* coordonnee 'Z' alors que le rayon ne change pas en realite... */ \ \ EGAL(equation_representative_du_contour \ ,DIVI(disF2D(ASD1(centre_2D_de_la_sphere,x),ASD1(centre_2D_de_la_sphere,y) \ ,ASD1(point_2D_courant,x),ASD1(point_2D_courant,y) \ ) \ ,EXP2(rayon_du_contour_apparent) \ ) \ ); \ /* Valeur courante au point {X,Y} de la fonction representative du contour de la forme */ \ /* materialisant la particule. */ \ \ EGAL(distance_normalisee_au_centre \ ,RACX(equation_representative_du_contour) \ ); \ /* Calcul de la distance euclidienne normalisee du point courant {X,Y} au centre du disque. */ \ \ Test(IFLE(distance_normalisee_au_centre,DEFINITION_DU_CONTOUR_APPARENT_DE_LA_SPHERE)) \ Bblock \ DEFV(Float,INIT(carre_de_la_norme_du_vecteur_normal_approxime,FLOT__UNDEF)); \ /* Norme du vecteur normal approxime... */ \ DEFV(Float,INIT(distance_courante_au_Z_Buffer,FLOT__UNDEF)); \ /* Distance du point courant au contenu courant du 'Z_Buffer' au point {X,Y}. */ \ DEFV(Float,INIT(epaisseur_de_l_intersection_normalisee,FLOT__UNDEF)); \ /* Afin de resoudre le probleme du 20050622153457 documente ci-apres... */ \ \ INITIALISATION_ACCROISSEMENT_3D(vecteur_normal_approxime \ ,SOUS(ASD1(point_2D_courant,x) \ ,ASD1(centre_2D_de_la_sphere,x) \ ) \ ,SOUS(ASD1(point_2D_courant,y) \ ,ASD1(centre_2D_de_la_sphere,y) \ ) \ ,FLOT__UNDEF \ ); \ /* --> */ \ /* Debut de l'approximation du vecteur normal N au point courant. */ \ \ EGAL(ASD1(vecteur_normal_approxime,dz) \ ,SOUS(EXP2(rayon_du_contour_apparent) \ ,pytF2D(vecteur_normal_approxime) \ ) \ ); \ /* Le calcul de la troisieme composante du vecteur normal approxime se fait en deux temps */ \ /* car en effet la valeur calculee ci-dessus peut etre negative (a cause des 'INTE(...)' */ \ /* ci-dessus ; on ne peut donc prendre directement 'RACX(...)'... */ \ \ Test(IZLT(ASD1(vecteur_normal_approxime,dz))) \ Bblock \ EGAL(ASD1(vecteur_normal_approxime,dz),FZERO); \ /* Dans le cas ou une valeur negative est rencontree, on la ramene a 0... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ INITIALISATION_ACCROISSEMENT_3D(vecteur_normal_approxime \ ,NEUT(ASD1(vecteur_normal_approxime,dx)) \ ,NEUT(ASD1(vecteur_normal_approxime,dy)) \ ,RACX(ASD1(vecteur_normal_approxime,dz)) \ ); \ /* --> */ \ /* Suite et fin de l'approximation du vecteur normal N en prenant en compte le fait que */ \ /* les coordonnees sont entieres ; on approxime donc la normale avec les points de */ \ /* coordonnees entieres bien qu'elle soit connue exactement (mais en des points non */ \ /* entiers...). */ \ \ EGAL(carre_de_la_norme_du_vecteur_normal_approxime,pytF3D(vecteur_normal_approxime)); \ /* Norme du vecteur normal approxime... */ \ \ EGAL(correction_d_anti_aliasing_au_bord \ ,CORRECTION_D_ANTI_ALIASING(distance_normalisee_au_centre) \ ); \ /* En fait, 'modulation_d_eclairement' pourra etre corrige par ce facteur, car en effet, */ \ /* dans certaines circonstances, le point le plus lumineux de l'ellipsoide peut se trouver */ \ /* tres pres de son contour apparent, et donc creer un probleme d'aliasing. On calcule donc */ \ /* ici la correction en fonction du point courant par rapport au contour apparent de */ \ /* l'ellipsoide. Il convient de remarquer que la distance utilisee ici est une distance */ \ /* bidimensionnelle dans le plan, et non pas une distance dans l'espace tridimensionnel. */ \ /* Elle definie bien (ou du moins son complement a 'COORDONNEE_BARYCENTRIQUE_MAXIMALE') une */ \ /* distance du point courant bidimensionnel {X,Y} au contour apparent... */ \ \ INITIALISATION_ACCROISSEMENT_3D(rayon_lumineux_inverse \ ,SOUS(X_PHYSIQUE_DANS_01(ASD1(LsourceT,x)) \ ,ASD1(point_3D_courant,x) \ ) \ ,SOUS(Y_PHYSIQUE_DANS_01(ASD1(LsourceT,y)) \ ,ASD1(point_3D_courant,y) \ ) \ ,SOUS(Z_PHYSIQUE_DANS_01(ASD1(LsourceT,z)) \ ,ASD1(point_3D_courant,z) \ ) \ ); \ /* Generation du rayon lumineux inverse. */ \ EGAL(produit_des_modules_de_N_et_S \ ,RACX(MUL2(carre_de_la_norme_du_vecteur_normal_approxime \ ,pytF3D(rayon_lumineux_inverse) \ ) \ ) \ ); \ /* Calcul de : */ \ /* */ \ /* --> --> */ \ /* |N|.|S| */ \ /* */ \ \ Test(IZGT(produit_des_modules_de_N_et_S)) \ Bblock \ EGAL(modulation_d_eclairement \ ,PUIX(COS1(DIVI(prdF3D(vecteur_normal_approxime,rayon_lumineux_inverse) \ ,produit_des_modules_de_N_et_S \ ) \ ) \ ,intensite_speculaire \ ) \ ); \ /* --> --> */ \ /* Designant par N la normale et par S le rayon lumineux inverse, la modulation de */ \ /* --> --> */ \ /* l'eclairement s'obtient en calculant le cosinus de l'angle entre N et S : */ \ /* */ \ /* --> --> */ \ /* --> --> N . S */ \ /* cos( N , S ) = --------- */ \ /* --> --> */ \ /* |N|.|S| */ \ /* */ \ /* puis en le ramenant dans [0,1] et en accentuant le phenomene (reflets speculaires)... */ \ Eblock \ ATes \ Bblock \ EGAL(modulation_d_eclairement \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ); \ /* Nous sommes ici dans le cas ou la particule est "tangente" a la source lumineuse... */ \ Eblock \ ETes \ \ Test(IFEXff(modulation_d_eclairement \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ) \ ) \ Bblock \ PRINT_ERREUR("la modulation d'eclairement est hors de [0,1]"); \ CAL1(Prer1(" elle vaut : %g\n",modulation_d_eclairement)); \ CAL1(Prer1(" equation = %g\n",equation_representative_du_contour)); \ CAL1(Prer1(" distance = %g\n",distance_normalisee_au_centre)); \ CAL1(Prer1(" aliasing = %g\n",correction_d_anti_aliasing_au_bord)); \ CAL1(Prer3(" normale N = (%g,%g,%g)\n" \ ,ASD1(vecteur_normal_approxime,dx) \ ,ASD1(vecteur_normal_approxime,dy) \ ,ASD1(vecteur_normal_approxime,dz) \ ) \ ); \ CAL1(Prer3(" lumiere S = (%g,%g,%g)\n" \ ,ASD1(rayon_lumineux_inverse,dx) \ ,ASD1(rayon_lumineux_inverse,dy) \ ,ASD1(rayon_lumineux_inverse,dz) \ ) \ ); \ CAL1(Prer1(" N.S = %g\n" \ ,prdF3D(vecteur_normal_approxime,rayon_lumineux_inverse) \ ) \ ); \ CAL1(Prer1(" |N|.|S| = %g\n",produit_des_modules_de_N_et_S)); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ EGAL(distance_courante_au_Z_Buffer \ ,MUL2(COND(IL_FAUT(store_sphere__anti_aliasing_____compatibilite_20060426) \ ,FU \ ,rapport_courant_du_zoom \ ) \ ,SOUA(ASD1(point_3D_courant,z) \ ,loadF_point(Z_Buffer \ ,INTE(ASD1(point_2Dt_courant,x)) \ ,INTE(ASD1(point_2Dt_courant,y)) \ ) \ ) \ ) \ ); \ /* Distance du point courant au contenu courant du 'Z_Buffer' au point {X,Y}. */ \ /* */ \ /* L'introduction du rapport courant de zoom a eu lieu le 20060426140714. Cela manquait */ \ /* car en effet, la gestion de l'anti-aliasing a lieu en coordonnees ecran (en pixels ; */ \ /* rappelons que 'EPAISSEUR_DE_L_INTERSECTION' est exprime en pixels...). Cela s'est vu */ \ /* lors du calcul de l'image 'v $xiirs/SPHE.61' qui, au debut, presentait d'affreux */ \ /* zig-zags dans la jonction du premier plan ; il est vite apparu que cela etait lie */ \ /* au fort zoom qu'elle subissait (ZOOM=0.22). Malheureusement, il est evident qu'apres */ \ /* le 20060426140714 la plupart des images anterieures ne seront pas recalculables */ \ /* exactement identiques a elles-memes : il y aura de petites differences, sauf usage */ \ /* de l'option : */ \ /* */ \ /* compatibilite_20060426=VRAI */ \ /* */ \ /* evidemment... */ \ \ Test(IL_FAUT(store_sphere__anti_aliasing_____compatibilite_20050622)) \ Bblock \ EGAL(epaisseur_de_l_intersection_normalisee \ ,_____lNORMALISE_OZ(EPAISSEUR_DE_L_INTERSECTION) \ ); \ /* Le 20050622154321, en testant le programme 'v $xrs/project3D.11$K', j'ai note que */ \ /* lorsque 'dimZ' est trop petit (il valait 8 dans ce test...), cela conduit a des */ \ /* corrections d'anti-aliasing aberrantes, d'ou le remplacement de l'appel a la procedure */ \ /* '_____lNORMALISE_OZ(...)' par quelque chose de plus complique... */ \ Eblock \ ATes \ Bblock \ EGAL(epaisseur_de_l_intersection_normalisee \ ,_____lNORMALISE_AXES(MAX2(dimZ,k___dimZ),EPAISSEUR_DE_L_INTERSECTION) \ ); \ /* Ainsi, lorsque 'dimZ' est trop petit, il est majore... */ \ Eblock \ ETes \ \ Test(IFLE(distance_courante_au_Z_Buffer \ ,epaisseur_de_l_intersection_normalisee \ ) \ ) \ Bblock \ DEFV(Float,INIT(correction_d_anti_aliasing_aux_intersections \ ,INTERPOLATION_MIXTE \ (store_sphere__anti_aliasing_____compatibilite_20181227 \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,FZERO \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ,FZERO \ ,DIVI(distance_courante_au_Z_Buffer \ ,epaisseur_de_l_intersection_normalisee \ ) \ ) \ ) \ ); \ /* Lorsque le point a marquer est pratiquement a la meme profondeur que le point precedent, */ \ /* c'est qu'il y a intersection de deux spheres : on va donc faire la moyenne du niveau a */ \ /* a marquer et du niveau anterieur... */ \ \ Test(IFGE(correction_d_anti_aliasing_au_bord,COORDONNEE_BARYCENTRIQUE_MAXIMALE)) \ /* Le 20060426123057, le 'IFEQ(...)' est devenu un 'IFGE(...)' car, en effet, la procedure */ \ /* 'INTERPOLATION_CUBIQUE(...)' a des "rebonds" et donc il n'est pas evident que ci-dessus */ \ /* 'correction_d_anti_aliasing_aux_intersections' soit effectivement dans le segment espere */ \ /* [COORDONNEE_BARYCENTRIQUE_MINIMALE,COORDONNEE_BARYCENTRIQUE_MAXIMALE]... */ \ Bblock \ EGAL(correction_d_anti_aliasing_au_bord \ ,correction_d_anti_aliasing_aux_intersections \ ); \ /* Cas ou l'on est juste en presence d'une intersection... */ \ Eblock \ ATes \ Bblock \ EGAL(correction_d_anti_aliasing_au_bord \ ,MIN2(correction_d_anti_aliasing_au_bord \ ,correction_d_anti_aliasing_aux_intersections \ ) \ ); \ /* Cas ou l'on est en presence simultanement d'un bord et d'une intersection. On notera que */ \ /* l'on utilise la fonction 'MIN2(...)', car en effet l'utilisation de 'MOYE(...)' faisait */ \ /* apparaitre des defauts visuels (points sur-lumineux) la ou il y avait une forte disparite */ \ /* entre les deux corrections ("de bord" et "d'intersection") ; l'utilisation de 'MAX2(...)' */ \ /* ne faisait qu'amplifier ces defauts... */ \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ Test(NINCff(correction_d_anti_aliasing_au_bord \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ) \ ) \ Bblock \ Test(NINCff(correction_d_anti_aliasing_au_bord \ ,SOUS(COORDONNEE_BARYCENTRIQUE_MINIMALE,GRAND_EPSILON) \ ,ADD2(COORDONNEE_BARYCENTRIQUE_MAXIMALE,GRAND_EPSILON) \ ) \ ) \ /* Ce test destine a ne pas sortir de messages d'erreur a ete introduit le 20050516115705 */ \ /* car, en effet, le 'INTERPOLATION_CUBIQUE(...)' qui precede introduit des "rebonds" et */ \ /* il n'est donc pas anormal que l'on soit hors de [0,1] a epsilon pres... */ \ Bblock \ PRINT_ERREUR("le parametre d'interpolation n'est pas dans [0,1]"); \ CAL1(Prer1(" parametre d'interpolation = %g\n" \ ,correction_d_anti_aliasing_au_bord \ ) \ ); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ EGAL(correction_d_anti_aliasing_au_bord \ ,TRON(correction_d_anti_aliasing_au_bord \ ,COORDONNEE_BARYCENTRIQUE_MINIMALE \ ,COORDONNEE_BARYCENTRIQUE_MAXIMALE \ ) \ ); \ /* Et on corrige cette anomalie par troncation... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ niveau_RVB(niveau_ROUGE_du_point,nbR,ncR,iR,niveau_anterieur_ROUGE_a_forcer); \ niveau_RVB(niveau_VERTE_du_point,nbV,ncV,iV,niveau_anterieur_VERTE_a_forcer); \ niveau_RVB(niveau_BLEUE_du_point,nbB,ncB,iB,niveau_anterieur_BLEUE_a_forcer); \ /* Enfin, calcul du niveau du point courant. */ \ \ store_point_ND_RVB(niveau_ROUGE_du_point,niveau_VERTE_du_point,niveau_BLEUE_du_point \ ,iR,iV,iB \ ,INTE(ASD1(point_2Dt_courant,x)),INTE(ASD1(point_2Dt_courant,y)) \ ,ASD1(point_3D_courant,z) \ ,TRI_DIMENSIONNEL \ ); \ /* Generation du point courant dans le cas d'une visualisation complete d'une sphere. */ \ /* */ \ /* La prise en compte eventuelle de la structure "torique" de l'image a ete introduite */ \ /* le 20090818092838). */ \ \ EGAL(la_sphere_est_entierement_hors_de_l_image,FAUX); \ /* On memorise qu'au moins un point de la sphere courante est dans l'image ; rappelons que */ \ /* cela ne signifie pas obligatoirement qu'il est visible, puisqu'il peut etre cache par */ \ /* une autre sphere plus proche de l'observateur... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ end_ligneQ(EDoI) \ Eblock \ end_colonneQ(EDoI) \ Eblock \ ETes \ \ Test(EST_FAUX(la_sphere_est_entierement_hors_de_l_image)) \ Bblock \ INCR(compteur_des_spheres_dans_l_image,I); \ /* Lorsqu'au moins un point de la sphere a ete marque, cette sphere est comptee parmi les */ \ /* spheres visibles. Rappelons que cela ne signifie pas obligatoirement qu'elle est visible, */ \ /* puisqu'elle peut etre cachee par une autre sphere plus proche de l'observateur... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ Eblock \ /* ATTENTION : {X,Y,Z} E [0,1]x[0,1]x[0,1]. */