int BicubicPatch::bezier_subpatch_intersect(const BasicRay &ray, const ControlPoints *Patch, DBL u0, DBL u1, DBL v0, DBL v1, IStack& Depth_Stack, TraceThreadData *Thread) { int cnt = 0; TripleVector3d V1; DBL u, v, Depth; DBL uu[3], vv[3]; Vector3d P, N; Vector2d UV; Vector2d uv_point, tpoint; V1[0] = (*Patch)[0][0]; V1[1] = (*Patch)[0][3]; V1[2] = (*Patch)[3][3]; uu[0] = u0; uu[1] = u0; uu[2] = u1; vv[0] = v0; vv[1] = v1; vv[2] = v1; if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v)) { if (Clip.empty() || Point_In_Clip(P, Clip, Thread)) { /* transform current point from uv space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; Depth_Stack->push(Intersection(Depth, P, N, UV, this)); cnt++; } } V1[1] = V1[2]; V1[2] = (*Patch)[3][0]; uu[1] = uu[2]; uu[2] = u1; vv[1] = vv[2]; vv[2] = v0; if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v)) { if (Clip.empty() || Point_In_Clip(P, Clip, Thread)) { /* transform current point from uv space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; Depth_Stack->push(Intersection(Depth, P, N, UV, this)); cnt++; } } return (cnt); }
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); }
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_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; Vector3d IPoint; if (Intersect(ray, &Depth, Thread)) { IPoint = ray.Evaluate(Depth); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth,IPoint,this)); return(true); } } return(false); }
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); }
bool Superellipsoid::insert_hit(const BasicRay &ray, DBL Depth, IStack& Depth_Stack, TraceThreadData *Thread) { Vector3d IPoint; if ((Depth > DEPTH_TOLERANCE) && (Depth < MAX_DISTANCE)) { IPoint = ray.Evaluate(Depth); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth, IPoint, this)); return(true); } } return(false); }
bool Lathe::test_hit(const BasicRay &ray, IStack& Depth_Stack, DBL d, DBL w, int n, TraceThreadData *Thread) { Vector3d IPoint; if ((d > DEPTH_TOLERANCE) && (d < MAX_DISTANCE)) { IPoint = ray.Evaluate(d); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(d, IPoint, this, n, w)); 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); }
bool Sor::test_hit(const BasicRay &ray, IStack& Depth_Stack, DBL d, DBL k, int t, int n, TraceThreadData *Thread) { Vector3d IPoint; if ((d > DEPTH_TOLERANCE) && (d < MAX_DISTANCE)) { IPoint = ray.Evaluate(d); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { /* is the extra copy of d redundant? */ Depth_Stack->push(Intersection(d, IPoint, this, t, n, k)); return(true); } } return(false); }
bool Lemon::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { bool Intersection_Found; int cnt, i; Vector3d Real_Normal; Vector3d Real_Pt,INormal; LEMON_INT I[4]; Vector3d P,D; DBL len; Thread->Stats()[Ray_Lemon_Tests]++; MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); len = D.length(); D /= len; Intersection_Found = false; if ((cnt = Intersect(P, D, I, Thread)) != 0) { for (i = 0; i < cnt; i++) { Real_Pt = ray.Origin + I[i].d/len * ray.Direction; if (Clip.empty() || Point_In_Clip(Real_Pt, Clip, Thread)) { INormal = I[i].n; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(I[i].d/len,Real_Pt,Real_Normal,this)); Intersection_Found = true; } } } if(Intersection_Found) { Thread->Stats()[Ray_Lemon_Tests_Succeeded]++; } return (Intersection_Found); }
bool Triangle::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { DBL Depth; Vector3d IPoint; Thread->Stats()[Ray_Triangle_Tests]++; if (Intersect(ray, &Depth)) { Thread->Stats()[Ray_Triangle_Tests_Succeeded]++; IPoint = ray.Evaluate(Depth); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth,IPoint,this)); 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); }
bool SpindleTorus::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { int i, max_i, Found; DBL Depth[4]; Vector3d 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)) { IPoint = ray.Evaluate(Depth[i]); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { // To test whether the point is on the spindle, // we test whether it is inside a sphere around the origin going through the spindle's tips. Vector3d P; MInvTransPoint(P, IPoint, Trans); bool onSpindle = (P.lengthSqr() < mSpindleTipYSqr); bool validIntersection = (onSpindle ? (mSpindleMode & SpindleVisible) : (mSpindleMode & NonSpindleVisible)); if (validIntersection) { Depth_Stack->push(Intersection(Depth[i], IPoint, this, P, onSpindle)); Found = true; } } } } } return(Found); }
bool Disc::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { int Intersection_Found; DBL Depth; Vector3d IPoint; Intersection_Found = false; Thread->Stats()[Ray_Disc_Tests]++; if (Intersect(ray, &Depth)) { Thread->Stats()[Ray_Disc_Tests_Succeeded]++; IPoint = ray.Evaluate(Depth); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth,IPoint,this)); Intersection_Found = true; } } return (Intersection_Found); }
bool Cone::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { int Intersection_Found, cnt, i; Vector3d IPoint; CONE_INT I[4]; Intersection_Found = false; if ((cnt = Intersect(ray, I, Thread)) != 0) { for (i = 0; i < cnt; i++) { IPoint = ray.Evaluate(I[i].d); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(I[i].d,IPoint,this,I[i].t)); Intersection_Found = true; } } } return (Intersection_Found); }
bool Fractal::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { bool Intersection_Found; bool LastIsInside = false; bool CurrentIsInside, NextIsInside; DBL Depth, Depth_Max; DBL Dist, Dist_Next, LenSqr, LenInv; Vector3d IPoint, Mid_Point, Next_Point, Real_Pt; Vector3d Real_Normal, F_Normal; Vector3d Direction; BasicRay New_Ray; Thread->Stats()[Ray_Fractal_Tests]++; Intersection_Found = false; /* Get into Fractal's world. */ if (Trans != NULL) { MInvTransDirection(Direction, ray.Direction, Trans); LenSqr = Direction.lengthSqr(); if (LenSqr == 0.0) { return (false); } if (LenSqr != 1.0) { LenInv = 1.0 / sqrt(LenSqr); Direction *= LenInv; } else LenInv = 1.0; New_Ray.Direction = Direction; MInvTransPoint(New_Ray.Origin, ray.Origin, Trans); } else { Direction = ray.Direction; New_Ray = ray; LenInv = 1.0; } /* Bound fractal. */ if (!F_Bound(New_Ray, this, &Depth, &Depth_Max)) { return (false); } if (Depth_Max < Fractal_Tolerance) { return (false); } if (Depth < Fractal_Tolerance) { Depth = Fractal_Tolerance; } /* Jump to starting point */ Next_Point = New_Ray.Origin + Direction * Depth; CurrentIsInside = D_Iteration(Next_Point, this, Direction, &Dist, Thread->Fractal_IStack); /* Light ray starting inside ? */ if (CurrentIsInside) { Next_Point += (2.0 * Fractal_Tolerance) * Direction; Depth += 2.0 * Fractal_Tolerance; if (Depth > Depth_Max) { return (false); } CurrentIsInside = D_Iteration(Next_Point, this, Direction, &Dist, Thread->Fractal_IStack); } /* Ok. Trace it */ while (Depth < Depth_Max) { /* * Get close to the root: Advance with Next_Point, keeping track of last * position in IPoint... */ while (1) { if (Dist < Precision) Dist = Precision; Depth += Dist; if (Depth > Depth_Max) { if (Intersection_Found) Thread->Stats()[Ray_Fractal_Tests_Succeeded]++; return (Intersection_Found); } IPoint = Next_Point; Next_Point += Dist * Direction; NextIsInside = D_Iteration(Next_Point, this, Direction, &Dist_Next, Thread->Fractal_IStack); if (NextIsInside != CurrentIsInside) { /* Set surface was crossed... */ Depth -= Dist; break; } else { Dist = Dist_Next; /* not reached */ } } /* then, polish the root via bisection method... */ while (Dist > Fractal_Tolerance) { Dist *= 0.5; Mid_Point = IPoint + Dist * Direction; LastIsInside = Iteration(Mid_Point, this, Thread->Fractal_IStack); if (LastIsInside == CurrentIsInside) { IPoint = Mid_Point; Depth += Dist; if (Depth > Depth_Max) { if (Intersection_Found) Thread->Stats()[Ray_Fractal_Tests_Succeeded]++; return (Intersection_Found); } } } if (!CurrentIsInside) /* Mid_Point isn't inside the set */ { IPoint += Dist * Direction; Depth += Dist; Iteration(IPoint, this, Thread->Fractal_IStack); } else { if (LastIsInside != CurrentIsInside) { Iteration(IPoint, this, Thread->Fractal_IStack); } } if (Trans != NULL) { MTransPoint(Real_Pt, IPoint, Trans); Normal_Calc(this, F_Normal, Thread->Fractal_IStack); MTransNormal(Real_Normal, F_Normal, Trans); } else { Real_Pt = IPoint; Normal_Calc(this, Real_Normal, Thread->Fractal_IStack); } if (Clip.empty() || Point_In_Clip(Real_Pt, Clip, Thread)) { Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth * LenInv, Real_Pt, Real_Normal, this)); Intersection_Found = true; /* If fractal isn't used with CSG we can exit now. */ if (!(Type & IS_CHILD_OBJECT)) { break; } } /* Start over where work was left */ IPoint = Next_Point; Dist = Dist_Next; CurrentIsInside = NextIsInside; } if (Intersection_Found) Thread->Stats()[Ray_Fractal_Tests_Succeeded]++; return (Intersection_Found); }
bool Parametric::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect, uv; Ray New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; DBL Intervals_Low[2][32]; DBL Intervals_Hi[2][32]; int SectorNum[32]; Thread->Stats()[Ray_Par_Bound_Tests]++; if(container_shape) { if(Trans != NULL) { MInvTransPoint(New_Ray.Origin, ray.Origin, Trans); MInvTransDirection(New_Ray.Direction, ray.Direction, Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Sphere::Intersect(New_Ray, container.sphere.center, (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Sphere::Intersect(ray, container.sphere.center, (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2); } Thread->Stats()[Ray_Sphere_Tests]--; if(i_flg) Thread->Stats()[Ray_Sphere_Tests_Succeeded]--; } else { i_flg = Box::Intersect(ray, Trans, container.box.corner1, container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Thread->Stats()[Ray_Par_Bound_Tests_Succeeded]++; Thread->Stats()[Ray_Parametric_Tests]++; if (Trans != NULL) { MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); } else { P[X] = ray.Origin[X]; P[Y] = ray.Origin[Y]; P[Z] = ray.Origin[Z]; D[X] = ray.Direction[X]; D[Y] = ray.Direction[Y]; D[Z] = ray.Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = umin; Intervals_Hi[INDEX_U][0] = umax; Intervals_Low[INDEX_V][0] = vmin; Intervals_Hi[INDEX_V][0] = vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[0]), accuracy, low_vect, hi_vect, max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[1]), accuracy, low_vect, hi_vect, max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[2]), accuracy, low_vect, hi_vect, max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Assign_UV_Vect(uv, low_vect); } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Thread->Stats()[Ray_Parametric_Tests_Succeeded]++; VScale(IPoint, ray.Direction, TResult); VAddEq(IPoint, ray.Origin); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (ObjectPtr ) Object, Depth_Stack); */ Depth_Stack->push(Intersection(TResult, IPoint, uv, this)); return true; } } return false; }
bool IsoSurface::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { int Side1 = 0, Side2 = 0, itrace = 0; DBL Depth1 = 0.0, Depth2 = 0.0; BasicRay New_Ray; Vector3d IPoint; Vector3d Plocal, Dlocal; DBL tmax = 0.0, tmin = 0.0, tmp = 0.0; DBL maxg = max_gradient; int i = 0 ; /* count of intervals in stack - 1 */ int IFound = false; int begin = 0, end = 0; bool in_shadow_test = false; Vector3d VTmp; Thread->Stats()[Ray_IsoSurface_Bound_Tests]++; if(container->Intersect(ray, Trans, Depth1, Depth2, Side1, Side2)) /* IsoSurface_Bound_Tests */ { Thread->Stats()[Ray_IsoSurface_Bound_Tests_Succeeded]++; in_shadow_test = ray.IsShadowTestRay(); if(Depth1 < 0.0) Depth1 = 0.0; if(Trans != NULL) { MInvTransPoint(Plocal, ray.Origin, Trans); MInvTransDirection(Dlocal, ray.Direction, Trans); } else { Plocal = ray.Origin; Dlocal = ray.Direction; } Thread->isosurfaceData->Inv3 = 1; if(closed != false) { VTmp = Plocal + Depth1 * Dlocal; tmp = Vector_Function(Thread->functionContext, VTmp); if(Depth1 > accuracy) { if(tmp < 0.0) /* The ray hits the bounding shape */ { IPoint = ray.Evaluate(Depth1); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth1, IPoint, this, 1, Side1)); IFound = true; itrace++; Thread->isosurfaceData->Inv3 *= -1; } } } else { if(tmp < (maxg * accuracy * 4.0)) { Depth1 = accuracy * 5.0; VTmp = Plocal + Depth1 * Dlocal; if(Vector_Function(Thread->functionContext, VTmp) < 0) Thread->isosurfaceData->Inv3 = -1; /* Change the sign of the function (IPoint is in the bounding shpae.)*/ } VTmp = Plocal + Depth2 * Dlocal; if(Vector_Function(Thread->functionContext, VTmp) < 0.0) { IPoint = ray.Evaluate(Depth2); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth2, IPoint, this, 1, Side2)); IFound = true; } } } } /* METHOD 2 by R. Suzuki */ tmax = Depth2 = min(Depth2, BOUND_HUGE); tmin = Depth1 = min(Depth2, Depth1); if((tmax - tmin) < accuracy) { if (IFound) Depth_Stack->pop(); // we added an intersection already, so we need to undo that return (false); } Thread->Stats()[Ray_IsoSurface_Tests]++; if((Depth1 < accuracy) && (Thread->isosurfaceData->Inv3 == 1)) { /* IPoint is on the isosurface */ VTmp = Plocal + tmin * Dlocal; if(fabs(Vector_Function(Thread->functionContext, VTmp)) < (maxg * accuracy * 4.0)) { tmin = accuracy * 5.0; VTmp = Plocal + tmin * Dlocal; if(Vector_Function(Thread->functionContext, VTmp) < 0) Thread->isosurfaceData->Inv3 = -1; /* change the sign and go into the isosurface */ } } Thread->isosurfaceData->ctx = Thread->functionContext; for (; itrace < max_trace; itrace++) { if(Function_Find_Root(*(Thread->isosurfaceData), Plocal, Dlocal, &tmin, &tmax, maxg, in_shadow_test, Thread) == false) break; else { IPoint = ray.Evaluate(tmin); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(tmin, IPoint, this, 0, 0 /*Side1*/)); IFound = true; } } tmin += accuracy * 5.0; if((tmax - tmin) < accuracy) break; Thread->isosurfaceData->Inv3 *= -1; } if(IFound) Thread->Stats()[Ray_IsoSurface_Tests_Succeeded]++; } if(eval == true) { DBL temp_max_gradient = max_gradient; // TODO FIXME - works around nasty gcc (found using 4.0.1) bug failing to honor casting away of volatile on pass by value on template argument lookup [trf] max_gradient = max((DBL)temp_max_gradient, maxg); // TODO FIXME - This is not thread-safe but should be!!! [trf] } return (IFound); }
int All_Parametric_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) { PARAMETRIC * Par = (PARAMETRIC *)Object; PRECOMP_PAR_DATA * PData = ((PARAMETRIC *)Object)->PData; VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect; RAY New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, UResult, VResult, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; Increase_Counter(stats[Ray_Par_Bound_Tests]); if(Par->container_shape) { if(Par->Trans != NULL) { MInvTransPoint(New_Ray.Initial, Ray->Initial, Par->Trans); MInvTransDirection(New_Ray.Direction, Ray->Direction, Par->Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Intersect_Sphere(&New_Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Intersect_Sphere(Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->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, Par->Trans, Par->container.box.corner1, Par->container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Increase_Counter(stats[Ray_Par_Bound_Tests_Succeeded]); Increase_Counter(stats[Ray_Parametric_Tests]); if (Par->Trans != NULL) { MInvTransPoint(P, Ray->Initial, Par->Trans); MInvTransDirection(D, Ray->Direction, Par->Trans); } else { P[X] = Ray->Initial[X]; P[Y] = Ray->Initial[Y]; P[Z] = Ray->Initial[Z]; D[X] = Ray->Direction[X]; D[Y] = Ray->Direction[Y]; D[Z] = Ray->Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * Par->accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = Par->umin; Intervals_Hi[INDEX_U][0] = Par->umax; Intervals_Low[INDEX_V][0] = Par->vmin; Intervals_Hi[INDEX_V][0] = Par->vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[0]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[1]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[2]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < Par->accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Par->last_u = UResult = low_vect[U]; Par->last_v = VResult = low_vect[V]; } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Increase_Counter(stats[Ray_Parametric_Tests_Succeeded]); VScale(IPoint, Ray->Direction, TResult); VAddEq(IPoint, Ray->Initial); if (Point_In_Clip(IPoint, Par->Clip)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (OBJECT *) Object, Depth_Stack); */ // UV_VECT uv; // Make_UV_Vector(uv, UResult, VResult); // push_uv_entry(TResult, IPoint, uv, (OBJECT *)Object, Depth_Stack); push_entry(TResult, IPoint, (OBJECT *)Object, Depth_Stack); return true; } } return false; }
int BicubicPatch::bezier_tree_walker(const BasicRay &ray, const BEZIER_NODE *Node, IStack& Depth_Stack, TraceThreadData *Thread) { int i, cnt = 0; DBL Depth, u, v; DBL uu[3], vv[3]; Vector3d N, P; TripleVector3d V1; Vector2d UV; Vector2d uv_point, tpoint; const BEZIER_CHILDREN *Children; const BEZIER_VERTICES *Vertices; /* * Make sure the ray passes through a sphere bounding * the control points of the patch. */ if (!spherical_bounds_check(ray, Node->Center, Node->Radius_Squared)) { return (0); } /* * If this is an interior node then continue the descent, * else do a check against the vertices. */ if (Node->Node_Type == BEZIER_INTERIOR_NODE) { Children = reinterpret_cast<const BEZIER_CHILDREN *>(Node->Data_Ptr); for (i = 0; i < Node->Count; i++) { cnt += bezier_tree_walker(ray, Children->Children[i], Depth_Stack, Thread); } } else if (Node->Node_Type == BEZIER_LEAF_NODE) { Vertices = reinterpret_cast<const BEZIER_VERTICES *>(Node->Data_Ptr); V1[0] = Vertices->Vertices[0]; V1[1] = Vertices->Vertices[1]; V1[2] = Vertices->Vertices[2]; uu[0] = Vertices->uvbnds[0]; uu[1] = Vertices->uvbnds[0]; uu[2] = Vertices->uvbnds[1]; vv[0] = Vertices->uvbnds[2]; vv[1] = Vertices->uvbnds[3]; vv[2] = Vertices->uvbnds[3]; /* * Triangulate this subpatch, then check for * intersections in the triangles. */ if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v)) { if (Clip.empty() || Point_In_Clip(P, Clip, Thread)) { /* transform current point from uv space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; Depth_Stack->push(Intersection(Depth, P, N, UV, this)); cnt++; } } V1[1] = V1[2]; V1[2] = Vertices->Vertices[3]; uu[1] = uu[2]; uu[2] = Vertices->uvbnds[1]; vv[1] = vv[2]; vv[2] = Vertices->uvbnds[2]; if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v)) { if (Clip.empty() || Point_In_Clip(P, Clip, Thread)) { /* transform current point from object space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; Depth_Stack->push(Intersection(Depth, P, N, UV, this)); cnt++; } } } else { throw POV_EXCEPTION_STRING("Bad Node type in bezier_tree_walker()."); } return (cnt); }
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); }
bool Sphere::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { Thread->Stats()[Ray_Sphere_Tests]++; if(Do_Ellipsoid) { register int Intersection_Found; DBL Depth1, Depth2, len; Vector3d IPoint; BasicRay New_Ray; // Transform the ray into the ellipsoid's space MInvTransRay(New_Ray, ray, Trans); len = New_Ray.Direction.length(); New_Ray.Direction /= len; Intersection_Found = false; if(Intersect(New_Ray, Center, Sqr(Radius), &Depth1, &Depth2)) { Thread->Stats()[Ray_Sphere_Tests_Succeeded]++; if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE)) { IPoint = New_Ray.Evaluate(Depth1); MTransPoint(IPoint, IPoint, Trans); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth1 / len, IPoint, this)); Intersection_Found = true; } } if((Depth2 > DEPTH_TOLERANCE) && (Depth2 < MAX_DISTANCE)) { IPoint = New_Ray.Evaluate(Depth2); MTransPoint(IPoint, IPoint, Trans); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth2 / len, IPoint, this)); Intersection_Found = true; } } } return(Intersection_Found); } else { register int Intersection_Found; DBL Depth1, Depth2; Vector3d IPoint; Intersection_Found = false; if(Intersect(ray, Center, Sqr(Radius), &Depth1, &Depth2)) { Thread->Stats()[Ray_Sphere_Tests_Succeeded]++; if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE)) { IPoint = ray.Evaluate(Depth1); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth1, IPoint, this)); Intersection_Found = true; } } if((Depth2 > DEPTH_TOLERANCE) && (Depth2 < MAX_DISTANCE)) { IPoint = ray.Evaluate(Depth2); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth2, IPoint, this)); Intersection_Found = true; } } } return(Intersection_Found); } }
bool Ovus::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { bool Found = false; Vector3d Real_Normal, Real_Pt, INormal, IPoint; DBL Depth1, Depth2, Depth3, Depth4, Depth5, Depth6; DBL len, horizontal; Vector3d P,D; Thread->Stats()[Ray_Ovus_Tests]++; MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); len = D.length(); D /= len; Intersect_Ovus_Spheres(P, D, &Depth1, &Depth2, &Depth3, &Depth4, &Depth5, &Depth6, Thread); if (Depth1 > EPSILON) { IPoint = P + Depth1 * D; if (IPoint[Y] < BottomVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint / BottomRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth1/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth2 > EPSILON) { IPoint = P + Depth2 * D; if (IPoint[Y] < BottomVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint / BottomRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth2/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth3 > EPSILON) { IPoint = P + Depth3 * D; if (IPoint[Y] > TopVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= BottomRadius; INormal /= TopRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth3/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth4 > EPSILON) { IPoint = P + Depth4 * D; if (IPoint[Y] > TopVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= BottomRadius; INormal /= TopRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth4/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth5 > EPSILON) { IPoint = P + Depth5 * D; MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= VerticalPosition; horizontal = sqrt(Sqr(INormal[X]) + Sqr(INormal[Z])); INormal[X] += (INormal[X] * HorizontalPosition / horizontal); INormal[Z] += (INormal[Z] * HorizontalPosition / horizontal); INormal.normalize(); MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth5/len, Real_Pt, Real_Normal, this)); Found = true; } } if (Depth6 > EPSILON) { IPoint = P + Depth6 * D; MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= VerticalPosition; horizontal = sqrt(Sqr(INormal[X]) + Sqr(INormal[Z])); INormal[X] += (INormal[X] * HorizontalPosition / horizontal); INormal[Z] += (INormal[Z] * HorizontalPosition / horizontal); INormal.normalize(); MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth6/len, Real_Pt, Real_Normal, this)); Found = true; } } if (Found) { Thread->Stats()[Ray_Ovus_Tests_Succeeded]++; } return (Found); }