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; }
void Parametric::UVCoord(UV_VECT Result, const Intersection *inter, TraceThreadData *Thread) const { Assign_UV_Vect(Result, inter->Iuv); }
static void Bicubic_Patch_UVCoord(UV_VECT Result, OBJECT *, INTERSECTION *Inter) { /* Use preocmputed uv coordinates. */ Assign_UV_Vect(Result, Inter->Iuv); }