BOOL hit_geo_sphere (GEO *Generic, RAY *Ray, HIT *Hit, PAIR *Bound, void *Info) { GEO_SPHERE *Geo; VECTOR Point; REAL a, b, Distance, Delta; Geo = (GEO_SPHERE *) Generic; VEC_SUB (Point, Ray->Point, Geo->Point); a = - VEC_DOT (Point, Ray->Vector); b = VEC_DOT (Point, Point); Delta = a * a - b + Geo->Radius * Geo->Radius; if (Delta < 0.0) return (FALSE); Delta = sqrt (Delta); Distance = a - Delta; /* - Epsilon;*/ if (Distance < Bound->u || Distance > Bound->v) return (FALSE); if (Hit) { Ray->Distance = Distance; VEC_LIN (Point, Ray->Point, Distance, Ray->Vector); VEC_SUB (Hit->Normal, Point, Geo->Point); if (VEC_DOT (Ray->Vector, Hit->Normal) > 0.0) VEC_NEG (Hit->Normal); VEC_UNIT (Hit->Normal, Distance); VEC_LIN (Hit->Point, Point, Epsilon, Hit->Normal); xyz2uv_geo_sphere (Geo, Hit); } return (TRUE); }
/******************************************************** * Search for an intersection between a nappe and a ray * *******************************************************/ BOOL hit_geo_nappe (GEO *Generic, RAY *Ray, HIT *Hit, PAIR *Bound, void *Info) { GEO_NAPPE *Geo; FCT *Fct; PNT *Pnt, *PntA, *PntB; VECTOR Normal; VECTOR Point; REAL a, b, c, u, v, uA, vA, uB, vB, Distance, Real; Geo = (GEO_NAPPE *) Generic; Fct = (FCT *) Info; Distance = VEC_DOT (Ray->Vector, Fct->Normal); if (ABS(Distance) < EPSILON) return (FALSE); Pnt = Geo->TabPnt + Fct->i; VEC_SUB (Point, Pnt->Point, Ray->Point); Distance = VEC_DOT (Point, Fct->Normal) / Distance ; /*-Epsilon est vire*/ if (Distance < Bound->u || Distance > Bound->v) return (FALSE); VEC_LIN (Point, Ray->Point, Distance, Ray->Vector); if ((ABS(Fct->Normal.z) > ABS(Fct->Normal.x)) && (ABS(Fct->Normal.z) > ABS(Fct->Normal.y))) { u = Point.x - Pnt->Point.x; v = Point.y - Pnt->Point.y; PntA = Geo->TabPnt + Fct->j; PntB = Geo->TabPnt + Fct->k; uA = PntA->Point.x - Pnt->Point.x; vA = PntA->Point.y - Pnt->Point.y; uB = PntB->Point.x - Pnt->Point.x; vB = PntB->Point.y - Pnt->Point.y; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA-u*vA) / a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } if (Fct->l == Fct->i) return (FALSE); PntA = Geo->TabPnt + Fct->l; uA = PntA->Point.x - Pnt->Point.x; vA = PntA->Point.y - Pnt->Point.y; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } return (FALSE); } else if (ABS(Fct->Normal.y) > ABS(Fct->Normal.x)) { u = Point.z - Pnt->Point.z; v = Point.x - Pnt->Point.x; PntA = Geo->TabPnt + Fct->j; PntB = Geo->TabPnt + Fct->k; uA = PntA->Point.z - Pnt->Point.z; vA = PntA->Point.x - Pnt->Point.x; uB = PntB->Point.z - Pnt->Point.z; vB = PntB->Point.x - Pnt->Point.x; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } if (Fct->l == Fct->i) return (FALSE); PntA = Geo->TabPnt + Fct->l; uA = PntA->Point.z - Pnt->Point.z; vA = PntA->Point.x - Pnt->Point.x; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } return (FALSE); } else if (ABS(Fct->Normal.x) > EPSILON) { u = Point.y - Pnt->Point.y; v = Point.z - Pnt->Point.z; PntA = Geo->TabPnt + Fct->j; PntB = Geo->TabPnt + Fct->k; uA = PntA->Point.y - Pnt->Point.y; vA = PntA->Point.z - Pnt->Point.z; uB = PntB->Point.y - Pnt->Point.y; vB = PntB->Point.z - Pnt->Point.z; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } if (Fct->l == Fct->i) return (FALSE); PntA = Geo->TabPnt + Fct->l; uA = PntA->Point.y - Pnt->Point.y; vA = PntA->Point.z - Pnt->Point.z; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } return (FALSE); } return (FALSE); }