/* Definitions et fonctions d'utilite generale */ /* pour la gestion de spheres */ /* */ /* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2009 */ #include #include "RayTracing-Sphere.h" #include "RayTracing-LumierePonctuelle.h" #include "RayTracing-LumiereDirectionnelle.h" /* Fonction de determination de l'intersection */ /* entre un rayon lumineux et une sphere. */ /* Un int booleen en retour pour indiquer */ /* l'existence ou non d'une intersection. */ /* Un double en passage par adresse pour */ /* retourner la distance entre l'origine */ /* du rayon en l'intersection la plus proche */ /* de l'origine du rayon sur sa trajectoire. */ int intersection(rayonLumineux *rl,sphere *sp,double *d) { double sx = rl->origine.x - sp->centre.x ; double sy = rl->origine.y - sp->centre.y; double sz = rl->origine.z - sp->centre.z; double a = rl->direction.x*rl->direction.x + rl->direction.y*rl->direction.y + rl->direction.z*rl->direction.z; double b = 2.0F*(rl->direction.x*sx + rl->direction.y*sy + rl->direction.z*sz); double c = sx*sx + sy*sy + sz*sz - sp->rayon*sp->rayon; double delta = b*b-4*a*c; if ( delta < 0.0 ) return(0); if ( delta == 0 ) { double t = -b/(2.0*a); if ( t >= 0.000001) { *d = t; return(1); } else return(0); } { double t = (-b-sqrt(delta))/(2.0*a); if ( t >= 0.000001 ) { *d = t; return(1); } } { double t = (-b+sqrt(delta))/(2.0*a); if ( t >= 0.000001 ) { *d = t; return(1); } } return(0); } /* Fonction de determination de l'existence */ /* d'une intersection entre un rayon lumineux */ /* et une sphere. */ int intersection(rayonLumineux *rl,sphere *sp) { double sx = rl->origine.x - sp->centre.x ; double sy = rl->origine.y - sp->centre.y; double sz = rl->origine.z - sp->centre.z; double a = rl->direction.x*rl->direction.x + rl->direction.y*rl->direction.y + rl->direction.z*rl->direction.z; double b = 2.0F*(rl->direction.x*sx + rl->direction.y*sy + rl->direction.z*sz); double c = sx*sx + sy*sy + sz*sz - sp->rayon*sp->rayon; double delta = b*b-4*a*c; if ( delta < 0.0F ) return(0); if ( delta == 0 ) { double t = -b/(2.0*a); if ( t >= 0.000001) { return(1); } else return(0); } { double t = (-b-sqrt(delta))/(2.0*a); if ( t >= 0.000001 ) { return(1); } } { double t = (-b+sqrt(delta))/(2.0*a); if ( t >= 0.000001 ) { return(1); } } return(0); } /* Fonction de calcul de la normale exterieure */ /* en un point d'une sphere */ void calculNormale(direction *d,position *p,sphere *sp) { d->x = (p->x - sp->centre.x)/sp->rayon; d->y = (p->y - sp->centre.y)/sp->rayon; d->z = (p->z - sp->centre.z)/sp->rayon; d->t = 0.0; } /* Fonction de calcul de la quantite d'energie */ /* diffusee en un point d'une sphere */ /* sous l'ensemble des eclairages crees */ /* par les sources lumineuses presentes */ /* dans une scene */ /* La normale a la sphere au point est donnee */ /* en entete */ void calculDiffusion(energie *e, scene *scn, sphere *sp,position *p,direction *n) { e->r = e->v = e->b = 0.0; int i; for ( i = 0 ; i < scn->nbLumieresPonctuelles ; i++ ) { lumierePonctuelle *lp = &scn->lumieresPonctuelles[i]; double d = distance(p,&lp->position); if ( estEclaire(p,scn,lp,d) ) { energie ed; calculDiffusion(&ed,p,n,&sp->materiel.kd,lp); e->r += ed.r; e->v += ed.v; e->b += ed.b; } } for ( i = 0 ; i < scn->nbLumieresDirectionnelles ; i++ ) { lumiereDirectionnelle *ld = &scn->lumieresDirectionnelles[i]; if ( estEclaire(p,scn,ld) ) { energie ed; calculDiffusion(&ed,n,&sp->materiel.kd,ld); e->r += ed.r; e->v += ed.v; e->b += ed.b; } } } /* Fonction de calcul du rayon lumineux */ /* reflechi cree par un rayon lumineux incident */ void rayonReflechi(rayonLumineux *rr, rayonLumineux *ri, sphere *sp,position *p,direction *n) { direction i = ri->direction; i.x *= -1; i.y *= -1; i.z *= -1; rr->origine = *p; reflexion(&rr->direction,&i,n); } /* Fonction de calcul du rayon lumineux */ /* transmis genere eventuellement */ /* par un rayon lumineux incident */ int rayonTransmis(rayonLumineux *rt, rayonLumineux *ri, sphere *sp,position *p,direction *n, double niSurnt,int exterieur) { direction norm = *n; if ( !exterieur ) { norm.x *= -1; norm.y *= -1; norm.z *= -1; } direction i = ri->direction; i.x *= -1; i.y *= -1; i.z *= -1; if ( transmission(&rt->direction,&i,&norm,niSurnt) ) { rt->origine = *p; return(1); } else return(0); }