bool Torus::All_Intersections(const Ray& ray, IStack& Depth_Stack, SceneThreadData *Thread) { int i, max_i, Found; DBL Depth[4]; VECTOR IPoint; Found = false; if ((max_i = Intersect(ray, Depth, Thread)) > 0) { for (i = 0; i < max_i; i++) { if ((Depth[i] > DEPTH_TOLERANCE) && (Depth[i] < MAX_DISTANCE)) { VEvaluateRay(IPoint, ray.Origin, Depth[i], ray.Direction); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth[i], IPoint, this)); Found = true; } } } } return(Found); }
static int All_Cone_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { int Intersection_Found, cnt, i; VECTOR IPoint; CONE_INT I[4]; Intersection_Found = false; if ((cnt = intersect_cone(Ray, (CONE *)Object, I)) != 0) { for (i = 0; i < cnt; i++) { VEvaluateRay(IPoint, Ray->Initial, I[i].d, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(I[i].d,IPoint,Object,I[i].t,Depth_Stack); Intersection_Found = true; } } } return (Intersection_Found); }
inline DBL Float_IsoSurface_Function(ISOSURFACE* ISOSRF, DBL* t) { VECTOR VTmp; VEvaluateRay(VTmp, ISOSRF->P, *t, ISOSRF->D); return ((DBL)(ISOSRF->Inv3) * (Evaluate_Function(*(ISOSRF->Function), VTmp) - ISOSRF->threshold)); }
static int All_Box_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { int Intersection_Found; int Side1, Side2; DBL Depth1, Depth2; VECTOR IPoint; Increase_Counter(stats[Ray_Box_Tests]); Intersection_Found = false; if (Intersect_Box(Ray, ((BOX *)Object)->Trans, ((BOX *)Object)->bounds[0], ((BOX *)Object)->bounds[1], &Depth1, &Depth2, &Side1, &Side2)) { if (Depth1 > DEPTH_TOLERANCE) { VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth1,IPoint,Object,Side1,Depth_Stack); Intersection_Found = true; } } VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth2,IPoint,Object,Side2,Depth_Stack); Intersection_Found = true; } } if (Intersection_Found) { Increase_Counter(stats[Ray_Box_Tests_Succeeded]); } return (Intersection_Found); }
static int All_Quadric_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { DBL Depth1, Depth2; VECTOR IPoint; register int Intersection_Found; Intersection_Found = false; if (Intersect_Quadric(Ray, (QUADRIC *)Object, &Depth1, &Depth2)) { if ((Depth1 > Small_Tolerance) && (Depth1 < Max_Distance)) { VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry(Depth1, IPoint, Object, Depth_Stack); Intersection_Found = true; } } if ((Depth2 > Small_Tolerance) && (Depth2 < Max_Distance)) { VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry(Depth2, IPoint, Object, Depth_Stack); Intersection_Found = true; } } } return(Intersection_Found); }
bool Plane::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { DBL Depth; VECTOR IPoint; if (Intersect(ray, &Depth, Thread)) { VEvaluateRay(IPoint, ray.Origin, Depth, ray.Direction); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth,IPoint,this)); return(true); } } return(false); }
static int All_Plane_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { DBL Depth; VECTOR IPoint; if (Intersect_Plane(Ray, (PLANE *)Object, &Depth)) { VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry(Depth,IPoint,Object,Depth_Stack); return(true); } } return(false); }
static int All_Disc_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { int Intersection_Found; DBL Depth; VECTOR IPoint; Intersection_Found = false; if (Intersect_Disc (Ray, (DISC *)Object, &Depth)) { VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction); if (Point_In_Clip (IPoint, Object->Clip)) { push_entry(Depth,IPoint,Object,Depth_Stack); Intersection_Found = true; } } return (Intersection_Found); }
static DBL constant_fog(RAY *Ray, DBL Depth, DBL Width, FOG *Fog, COLOUR Colour) { DBL k; VECTOR P; if (Fog->Turb != NULL) { Depth += Width / 2.0; VEvaluateRay(P, Ray->Initial, Depth, Ray->Direction); VEvaluateEq(P, Fog->Turb->Turbulence); /* The further away the less influence turbulence has. */ k = exp(-Width / Fog->Distance); Width *= 1.0 - k * min(1.0, Turbulence(P, Fog->Turb, NULL)*Fog->Turb_Depth); } Assign_Colour(Colour, Fog->Colour); return (exp(-Width / Fog->Distance)); }
int IsoSurface_Function_Find_Root(ISOSURFACE* ISOSRF, VECTOR P, VECTOR D, DBL* Depth1, DBL* Depth2, bool in_shadow_test) { DBL dt, t21, l_b, l_e, oldmg; ISO_Pair EP1, EP2; VECTOR VTmp; Increase_Counter(stats[Ray_IsoSurface_Find_Root]); VLength(ISOSRF->Vlength, D); if(ISOSRF->cache) { Increase_Counter(stats[Ray_IsoSurface_Cache]); VEvaluateRay(VTmp, P, *Depth1, D); VSubEq(VTmp, ISOSRF->P); VLength(l_b, VTmp); VEvaluateRay(VTmp, P, *Depth2, D); VSubEq(VTmp, ISOSRF->D); VLength(l_e, VTmp); if((ISOSRF->fmax - ISOSRF->max_gradient * max(l_b, l_e)) > 0.0) { Increase_Counter(stats[Ray_IsoSurface_Cache_Succeeded]); return false; } } Assign_Vector(ISOSRF->P, P); Assign_Vector(ISOSRF->D, D); ISOSRF->cache = false; EP1.t = *Depth1; EP1.f = Float_IsoSurface_Function(ISOSRF, Depth1); ISOSRF->fmax = EP1.f; if((ISOSRF->closed == false) && (EP1.f < 0.0)) { ISOSRF->Inv3 *= -1; EP1.f *= -1; } EP2.t = *Depth2; EP2.f = Float_IsoSurface_Function(ISOSRF, Depth2); ISOSRF->fmax = min(EP2.f, ISOSRF->fmax); oldmg = ISOSRF->max_gradient; t21 = (*Depth2 - *Depth1); if((ISOSRF->eval == true) && (ISOSRF->max_gradient > ISOSRF->eval_param[0])) ISOSRF->max_gradient *= ISOSRF->eval_param[2]; dt = ISOSRF->max_gradient * ISOSRF->Vlength * t21; if(IsoSurface_Function_Find_Root_R(ISOSRF, &EP1, &EP2, dt, t21, 1.0 / (ISOSRF->Vlength * t21), in_shadow_test)) { if(ISOSRF->eval == true) { DBL curvar = fabs(ISOSRF->max_gradient - oldmg); if(curvar > ISOSRF->mginfo->eval_var) ISOSRF->mginfo->eval_var = curvar; ISOSRF->mginfo->eval_cnt++; ISOSRF->mginfo->eval_gradient_sum += ISOSRF->max_gradient; if(ISOSRF->max_gradient > ISOSRF->mginfo->eval_max) ISOSRF->mginfo->eval_max = ISOSRF->max_gradient; } *Depth1 = ISOSRF->tl; return true; } else if(!in_shadow_test) { ISOSRF->cache = true; VEvaluateRay(ISOSRF->P, P, EP1.t, D); VEvaluateRay(ISOSRF->D, P, EP2.t, D); return false; } return false; }
static int All_IsoSurface_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) { ISOSURFACE * Isosrf = (ISOSURFACE *)Object; int Side1 = 0, Side2 = 0, itrace = 0, i_flg = 0; DBL Depth1 = 0.0, Depth2 = 0.0, len = 0.0; RAY New_Ray; VECTOR IPoint; VECTOR P, D; DBL tmax = 0.0, tmin = 0.0, tmp = 0.0; int i = 0 ; /* count of intervals in stack - 1 */ int IFound = false; int begin = 0, end = 0; bool in_shadow_test = false; VECTOR VTmp; Increase_Counter(stats[Ray_IsoSurface_Bound_Tests]); in_shadow_test = ((Ray->Optimisiation_Flags & OPTIMISE_SHADOW_TEST) == OPTIMISE_SHADOW_TEST); if(Isosrf->container_shape) { if(Isosrf->Trans != NULL) { MInvTransPoint(New_Ray.Initial, Ray->Initial, Isosrf->Trans); MInvTransDirection(New_Ray.Direction, Ray->Direction, Isosrf->Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Intersect_Sphere(&New_Ray, Isosrf->container.sphere.center, (Isosrf->container.sphere.radius) * (Isosrf->container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Intersect_Sphere(Ray, Isosrf->container.sphere.center, (Isosrf->container.sphere.radius) * (Isosrf->container.sphere.radius), &Depth1, &Depth2); } Decrease_Counter(stats[Ray_Sphere_Tests]); if(i_flg) Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]); } else { i_flg = Intersect_Box(Ray, Isosrf->Trans, Isosrf->container.box.corner1, Isosrf->container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(Depth1 < 0.0) Depth1 = 0.0; if(i_flg) /* IsoSurface_Bound_Tests */ { Increase_Counter(stats[Ray_IsoSurface_Bound_Tests_Succeeded]); if(Isosrf->Trans != NULL) { MInvTransPoint(P, Ray->Initial, Isosrf->Trans); MInvTransDirection(D, Ray->Direction, Isosrf->Trans); } else { Assign_Vector(P, Ray->Initial); Assign_Vector(D, Ray->Direction); } Isosrf->Inv3 = 1; if(Isosrf->closed != false) { VEvaluateRay(VTmp, P, Depth1, D); tmp = Vector_IsoSurface_Function(Isosrf, VTmp); if(Depth1 > Isosrf->accuracy) { if(tmp < 0.0) /* The ray hits the bounding shape */ { VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction); if(Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth1, IPoint, Object, Side1, Depth_Stack); IFound = true; itrace++; Isosrf->Inv3 *= -1; } } } else { if(tmp < (Isosrf->max_gradient * Isosrf->accuracy * 4.0)) { Depth1 = Isosrf->accuracy * 5.0; VEvaluateRay(VTmp, P, Depth1, D); if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0) Isosrf->Inv3 = -1; /* Change the sign of the function (IPoint is in the bounding shpae.)*/ } VEvaluateRay(VTmp, P, Depth2, D); if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0.0) { VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction); if(Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth2, IPoint, Object, Side2, Depth_Stack); IFound = true; } } } } /* METHOD 2 by R. Suzuki */ tmax = Depth2 = min(Depth2, BOUND_HUGE); tmin = Depth1 = min(Depth2, Depth1); if((tmax - tmin) < Isosrf->accuracy) return (false); Increase_Counter(stats[Ray_IsoSurface_Tests]); if((Depth1 < Isosrf->accuracy) && (Isosrf->Inv3 == 1)) { /* IPoint is on the isosurface */ VEvaluateRay(VTmp, P, tmin, D); if(fabs(Vector_IsoSurface_Function(Isosrf, VTmp)) < (Isosrf->max_gradient * Isosrf->accuracy * 4.0)) { tmin = Isosrf->accuracy * 5.0; VEvaluateRay(VTmp, P, tmin, D); if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0) Isosrf->Inv3 = -1; /* change the sign and go into the isosurface */ } } for (; itrace < Isosrf->max_trace; itrace++) { if(IsoSurface_Function_Find_Root(Isosrf, P, D, &tmin, &tmax, in_shadow_test) == false) break; else { VEvaluateRay(IPoint, Ray->Initial, tmin, Ray->Direction); if(Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(tmin, IPoint, Object, 0 /*Side1*/, Depth_Stack); IFound = true; } } tmin += Isosrf->accuracy * 5.0; if((tmax - tmin) < Isosrf->accuracy) break; Isosrf->Inv3 *= -1; } if(IFound) Increase_Counter(stats[Ray_IsoSurface_Tests_Succeeded]); } return (IFound); }
static DBL ground_fog(RAY *Ray, DBL Depth, DBL Width, FOG *Fog, COLOUR Colour) { DBL fog_density, delta; DBL start, end; DBL y1, y2, k; VECTOR P, P1, P2; /* Get start point. */ VEvaluateRay(P1, Ray->Initial, Depth, Ray->Direction); /* Get end point. */ VLinComb2(P2, 1.0, P1, Width, Ray->Direction); /* * Could preform transfomation here to translate Start and End * points into ground fog space. */ VDot(y1, P1, Fog->Up); VDot(y2, P2, Fog->Up); start = (y1 - Fog->Offset) / Fog->Alt; end = (y2 - Fog->Offset) / Fog->Alt; /* Get integral along y-axis from start to end. */ if (start <= 0.0) { if (end <= 0.0) { fog_density = 1.0; } else { fog_density = (atan(end) - start) / (end - start); } } else { if (end <= 0.0) { fog_density = (atan(start) - end) / (start - end); } else { delta = start - end; if (fabs(delta) > EPSILON) { fog_density = (atan(start) - atan(end)) / delta; } else { fog_density = 1.0 / (Sqr(start) + 1.0); } } } /* Apply turbulence. */ if (Fog->Turb != NULL) { VHalf(P, P1, P2); VEvaluateEq(P, Fog->Turb->Turbulence); /* The further away the less influence turbulence has. */ k = exp(-Width / Fog->Distance); Width *= 1.0 - k * min(1.0, Turbulence(P, Fog->Turb, NULL)*Fog->Turb_Depth); } Assign_Colour(Colour, Fog->Colour); return (exp(-Width * fog_density / Fog->Distance)); }