void Compute_Cylinder_Data(OBJECT *Object) { DBL tmpf; VECTOR axis; CONE *Cone = (CONE *)Object; VSub(axis, Cone->apex, Cone->base); VLength(tmpf, axis); if (tmpf < EPSILON) { Error("Degenerate cylinder, base point = apex point."); } else { VInverseScaleEq(axis, tmpf); Compute_Coordinate_Transform(Cone->Trans, Cone->base, axis, Cone->apex_radius, tmpf); } Cone->dist = 0.0; /* Recalculate the bounds */ Compute_Cone_BBox(Cone); }
static int intersect_poylgon(RAY *Ray, POLYGON *Polyg, DBL *Depth) { DBL x, y, len; VECTOR p, d; /* Don't test degenerate polygons. */ if (Test_Flag(Polyg, DEGENERATE_FLAG)) { return(false); } Increase_Counter(stats[Ray_Polygon_Tests]); /* Transform the ray into the polygon space. */ MInvTransPoint(p, Ray->Initial, Polyg->Trans); MInvTransDirection(d, Ray->Direction, Polyg->Trans); VLength(len, d); VInverseScaleEq(d, len); /* Intersect ray with the plane in which the polygon lies. */ if (fabs(d[Z]) < ZERO_TOLERANCE) { return(false); } *Depth = -p[Z] / d[Z]; if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance)) { return(false); } /* Does the intersection point lie inside the polygon? */ x = p[X] + *Depth * d[X]; y = p[Y] + *Depth * d[Y]; if (in_polygon(Polyg->Data->Number, Polyg->Data->Points, x, y)) { Increase_Counter(stats[Ray_Polygon_Tests_Succeeded]); *Depth /= len; return (true); } else { return (false); } }
static int compute_smooth_triangle(SMOOTH_TRIANGLE *Triangle) { VECTOR P3MinusP2, VTemp1, VTemp2; DBL x, y, z, uDenominator, Proj; VSub(P3MinusP2, Triangle->P3, Triangle->P2); x = fabs(P3MinusP2[X]); y = fabs(P3MinusP2[Y]); z = fabs(P3MinusP2[Z]); Triangle->vAxis = max3_coordinate(x, y, z); VSub(VTemp1, Triangle->P2, Triangle->P3); VNormalize(VTemp1, VTemp1); VSub(VTemp2, Triangle->P1, Triangle->P3); VDot(Proj, VTemp2, VTemp1); VScaleEq(VTemp1, Proj); VSub(Triangle->Perp, VTemp1, VTemp2); VNormalize(Triangle->Perp, Triangle->Perp); VDot(uDenominator, VTemp2, Triangle->Perp); VInverseScaleEq(Triangle->Perp, -uDenominator); /* Degenerate if smooth normals are more than 90 from actual normal or its inverse. */ VDot(x,Triangle->Normal_Vector,Triangle->N1); VDot(y,Triangle->Normal_Vector,Triangle->N2); VDot(z,Triangle->Normal_Vector,Triangle->N3); if ( ((x<0.0) && (y<0.0) && (z<0.0)) || ((x>0.0) && (y>0.0) && (z>0.0)) ) { return(true); } Set_Flag(Triangle, DEGENERATE_FLAG); return(false); }
static int Intersect_Disc (RAY *Ray, DISC *disc, DBL *Depth) { DBL t, u, v, r2, len; VECTOR P, D; Increase_Counter(stats[Ray_Disc_Tests]); /* Transform the point into the discs space */ MInvTransPoint(P, Ray->Initial, disc->Trans); MInvTransDirection(D, Ray->Direction, disc->Trans); VLength(len, D); VInverseScaleEq(D, len); if (fabs(D[Z]) > EPSILON) { t = -P[Z] / D[Z]; if (t >= 0.0) { u = P[X] + t * D[X]; v = P[Y] + t * D[Y]; r2 = Sqr(u) + Sqr(v); if ((r2 >= disc->iradius2) && (r2 <= disc->oradius2)) { *Depth = t / len; if ((*Depth > Small_Tolerance) && (*Depth < Max_Distance)) { Increase_Counter(stats[Ray_Disc_Tests_Succeeded]); return (true); } } } } return (false); }
void Plane::Scale(const VECTOR Vector, const TRANSFORM *tr) { DBL Length; if(Trans == NULL) { VDivEq(Normal_Vector, Vector); VLength(Length, Normal_Vector); VInverseScaleEq(Normal_Vector, Length); Distance /= Length; Compute_BBox(); } else { Transform(tr); } }
static void Scale_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans) { DBL Length; PLANE *Plane = (PLANE *) Object; if (Plane->Trans == NULL) { VDivEq(Plane->Normal_Vector, Vector); VLength(Length, ((PLANE *)Object)->Normal_Vector); VInverseScaleEq (((PLANE *)Object)->Normal_Vector, Length); ((PLANE *)Object)->Distance /= Length; Compute_Plane_BBox(Plane); } else { Transform_Plane (Object, Trans); } }
static void Quadric_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter) { QUADRIC *Quadric = (QUADRIC *) Object; DBL Len; /* This is faster and shorter. [DB 7/94] */ Result[X] = 2.0 * QA * Inter->IPoint[X] + QB * Inter->IPoint[Y] + QC * Inter->IPoint[Z] + QD; Result[Y] = QB * Inter->IPoint[X] + 2.0 * QE * Inter->IPoint[Y] + QF * Inter->IPoint[Z] + QG; Result[Z] = QC * Inter->IPoint[X] + QF * Inter->IPoint[Y] + 2.0 * QH * Inter->IPoint[Z] + QI; VLength(Len, Result); if (Len == 0.0) { /* The normal is not defined at this point of the surface. */ /* Set it to any arbitrary direction. */ Make_Vector(Result, 1.0, 0.0, 0.0); } else { VInverseScaleEq(Result, Len); } }
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; }
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 Torus::Intersect(const Ray& ray, DBL *Depth, SceneThreadData *Thread) const { int i, n; DBL len, R2, Py2, Dy2, PDy2, k1, k2; DBL y1, y2, r1, r2; DBL c[5]; DBL r[4]; VECTOR P, D; DBL DistanceP; // Distance from P to torus center (origo). DBL BoundingSphereRadius; // Sphere fully (amply) enclosing torus. DBL Closer; // P is moved Closer*D closer to torus. Thread->Stats()[Ray_Torus_Tests]++; /* Transform the ray into the torus space. */ MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); VLength(len, D); VInverseScaleEq(D, len); i = 0; y1 = -MinorRadius; y2 = MinorRadius; r1 = Sqr(MajorRadius - MinorRadius); if ( MajorRadius < MinorRadius ) r1 = 0; r2 = Sqr(MajorRadius + MinorRadius); #ifdef TORUS_EXTRA_STATS Thread->Stats()[Torus_Bound_Tests]++; #endif if (Test_Thick_Cylinder(P, D, y1, y2, r1, r2)) { #ifdef TORUS_EXTRA_STATS Thread->Stats()[Torus_Bound_Tests_Succeeded]++; #endif // Move P close to bounding sphere to have more precise root calculation. // Bounding sphere radius is R + r, we add r once more to ensure // that P is safely outside sphere. BoundingSphereRadius = MajorRadius + MinorRadius + MinorRadius; DistanceP = VSumSqr(P); // Distance is currently squared. Closer = 0.0; if (DistanceP > Sqr(BoundingSphereRadius)) { DistanceP = sqrt(DistanceP); // Now real distance. Closer = DistanceP - BoundingSphereRadius; VAddScaledEq(P, Closer, D); } R2 = Sqr(MajorRadius); r2 = Sqr(MinorRadius); Py2 = P[Y] * P[Y]; Dy2 = D[Y] * D[Y]; PDy2 = P[Y] * D[Y]; k1 = P[X] * P[X] + P[Z] * P[Z] + Py2 - R2 - r2; k2 = P[X] * D[X] + P[Z] * D[Z] + PDy2; c[0] = 1.0; c[1] = 4.0 * k2; c[2] = 2.0 * (k1 + 2.0 * (k2 * k2 + R2 * Dy2)); c[3] = 4.0 * (k2 * k1 + 2.0 * R2 * PDy2); c[4] = k1 * k1 + 4.0 * R2 * (Py2 - r2); n = Solve_Polynomial(4, c, r, Test_Flag(this, STURM_FLAG), ROOT_TOLERANCE, Thread); while(n--) Depth[i++] = (r[n] + Closer) / len; } if (i) Thread->Stats()[Ray_Torus_Tests_Succeeded]++; return(i); }
int Compute_Triangle(TRIANGLE *Triangle,int Smooth) { int swap,degn; VECTOR V1, V2, Temp; DBL Length; VSub(V1, Triangle->P1, Triangle->P2); VSub(V2, Triangle->P3, Triangle->P2); VCross(Triangle->Normal_Vector, V1, V2); VLength(Length, Triangle->Normal_Vector); /* Set up a flag so we can ignore degenerate triangles */ if (Length == 0.0) { Set_Flag(Triangle, DEGENERATE_FLAG); return(false); } /* Normalize the normal vector. */ VInverseScaleEq(Triangle->Normal_Vector, Length); VDot(Triangle->Distance, Triangle->Normal_Vector, Triangle->P1); Triangle->Distance *= -1.0; find_triangle_dominant_axis(Triangle); swap = false; switch (Triangle->Dominant_Axis) { case X: if ((Triangle->P2[Y] - Triangle->P3[Y])*(Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - Triangle->P3[Z])*(Triangle->P2[Y] - Triangle->P1[Y])) { swap = true; } break; case Y: if ((Triangle->P2[X] - Triangle->P3[X])*(Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - Triangle->P3[Z])*(Triangle->P2[X] - Triangle->P1[X])) { swap = true; } break; case Z: if ((Triangle->P2[X] - Triangle->P3[X])*(Triangle->P2[Y] - Triangle->P1[Y]) < (Triangle->P2[Y] - Triangle->P3[Y])*(Triangle->P2[X] - Triangle->P1[X])) { swap = true; } break; } if (swap) { Assign_Vector(Temp, Triangle->P2); Assign_Vector(Triangle->P2, Triangle->P1); Assign_Vector(Triangle->P1, Temp); if (Smooth) { Assign_Vector(Temp, ((SMOOTH_TRIANGLE *)Triangle)->N2); Assign_Vector(((SMOOTH_TRIANGLE *)Triangle)->N2, ((SMOOTH_TRIANGLE *)Triangle)->N1); Assign_Vector(((SMOOTH_TRIANGLE *)Triangle)->N1, Temp); } } degn=true; if (Smooth) { degn=compute_smooth_triangle((SMOOTH_TRIANGLE *)Triangle); } /* Build the bounding information from the vertices. */ Compute_Triangle_BBox(Triangle); return(degn); }
static void IsoSurface_Normal(VECTOR Result, OBJECT* Object, INTERSECTION* Inter) { VECTOR New_Point, TPoint; ISOSURFACE *Isosrf = (ISOSURFACE *)Object; FUNCTION Function = *(((ISOSURFACE *)Object)->Function); DBL funct; switch (Inter->i1) { case SIDE_X_0: Make_Vector(Result, -1.0, 0.0, 0.0); break; case SIDE_X_1: Make_Vector(Result, 1.0, 0.0, 0.0); break; case SIDE_Y_0: Make_Vector(Result, 0.0, -1.0, 0.0); break; case SIDE_Y_1: Make_Vector(Result, 0.0, 1.0, 0.0); break; case SIDE_Z_0: Make_Vector(Result, 0.0, 0.0, -1.0); break; case SIDE_Z_1: Make_Vector(Result, 0.0, 0.0, 1.0); break; default: /* Transform the point into the isosurface space */ if(((ISOSURFACE *)Object)->Trans != NULL) MInvTransPoint(New_Point, Inter->IPoint, Isosrf->Trans); else Assign_Vector(New_Point, Inter->IPoint); if(Isosrf->container_shape) { VSub(Result, New_Point, Isosrf->container.sphere.center); VLength(funct, Result); if(fabs(funct - Isosrf->container.sphere.radius) < EPSILON) { VInverseScaleEq(Result, Isosrf->container.sphere.radius); break; } } Assign_Vector(TPoint, New_Point); funct = Evaluate_Function(Function, TPoint); Assign_Vector(TPoint, New_Point); TPoint[X] += Isosrf->accuracy; Result[X] = Evaluate_Function(Function, TPoint) - funct; Assign_Vector(TPoint, New_Point); TPoint[Y] += Isosrf->accuracy; Result[Y] = Evaluate_Function(Function, TPoint) - funct; Assign_Vector(TPoint, New_Point); TPoint[Z] += Isosrf->accuracy; Result[Z] = Evaluate_Function(Function, TPoint) - funct; if((Result[X] == 0) && (Result[Y] == 0) && (Result[Z] == 0)) Result[X] = 1.0; VNormalize(Result, Result); } /* Transform the point into the boxes space. */ if(((ISOSURFACE *)Object)->Trans != NULL) { MTransNormal(Result, Result, ((ISOSURFACE *)Object)->Trans); VNormalize(Result, Result); } }
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); }
void Compute_Cone_Data(OBJECT *Object) { DBL tlen, len, tmpf; VECTOR tmpv, axis, origin; CONE *Cone = (CONE *)Object; /* Process the primitive specific information */ if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON) { /* What we are dealing with here is really a cylinder */ Set_Flag(Cone, CYLINDER_FLAG); Compute_Cylinder_Data(Object); return; } if (Cone->apex_radius < Cone->base_radius) { /* Want the bigger end at the top */ Assign_Vector(tmpv,Cone->base); Assign_Vector(Cone->base,Cone->apex); Assign_Vector(Cone->apex,tmpv); tmpf = Cone->base_radius; Cone->base_radius = Cone->apex_radius; Cone->apex_radius = tmpf; } /* Find the axis and axis length */ VSub(axis, Cone->apex, Cone->base); VLength(len, axis); if (len < EPSILON) { Error("Degenerate cone/cylinder."); } else { VInverseScaleEq(axis, len); } /* Determine alignment */ tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius); VScale(origin, axis, tmpf); VSub(origin, Cone->base, origin); tlen = tmpf + len; Cone->dist = tmpf / tlen; Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen); /* Recalculate the bounds */ Compute_Cone_BBox(Cone); }
static int intersect_cone(RAY *Ray, CONE *Cone, CONE_INT *Intersection) { int i = 0; DBL a, b, c, z, t1, t2, len; DBL d; VECTOR P, D; Increase_Counter(stats[Ray_Cone_Tests]); /* Transform the ray into the cones space */ MInvTransPoint(P, Ray->Initial, Cone->Trans); MInvTransDirection(D, Ray->Direction, Cone->Trans); VLength(len, D); VInverseScaleEq(D, len); if (Test_Flag(Cone, CYLINDER_FLAG)) { /* Solve intersections with a cylinder */ a = D[X] * D[X] + D[Y] * D[Y]; if (a > EPSILON) { b = P[X] * D[X] + P[Y] * D[Y]; c = P[X] * P[X] + P[Y] * P[Y] - 1.0; d = b * b - a * c; if (d >= 0.0) { d = sqrt(d); t1 = (-b + d) / a; t2 = (-b - d) / a; z = P[Z] + t1 * D[Z]; if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0)) { Intersection[i].d = t1 / len; Intersection[i++].t = SIDE_HIT; } z = P[Z] + t2 * D[Z]; if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0)) { Intersection[i].d = t2 / len; Intersection[i++].t = SIDE_HIT; } } } } else { /* Solve intersections with a cone */ a = D[X] * D[X] + D[Y] * D[Y] - D[Z] * D[Z]; b = D[X] * P[X] + D[Y] * P[Y] - D[Z] * P[Z]; c = P[X] * P[X] + P[Y] * P[Y] - P[Z] * P[Z]; if (fabs(a) < EPSILON) { if (fabs(b) > EPSILON) { /* One intersection */ t1 = -0.5 * c / b; z = P[Z] + t1 * D[Z]; if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0)) { Intersection[i].d = t1 / len; Intersection[i++].t = SIDE_HIT; } } } else { /* Check hits against the side of the cone */ d = b * b - a * c; if (d >= 0.0) { d = sqrt(d); t1 = (-b - d) / a; t2 = (-b + d) / a; z = P[Z] + t1 * D[Z]; if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0)) { Intersection[i].d = t1 / len; Intersection[i++].t = SIDE_HIT; } z = P[Z] + t2 * D[Z]; if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0)) { Intersection[i].d = t2 / len; Intersection[i++].t = SIDE_HIT; } } } } if (Test_Flag(Cone, CLOSED_FLAG) && (fabs(D[Z]) > EPSILON)) { d = (1.0 - P[Z]) / D[Z]; a = (P[X] + d * D[X]); b = (P[Y] + d * D[Y]); if (((Sqr(a) + Sqr(b)) <= 1.0) && (d > Cone_Tolerance) && (d < Max_Distance)) { Intersection[i].d = d / len; Intersection[i++].t = CAP_HIT; } d = (Cone->dist - P[Z]) / D[Z]; a = (P[X] + d * D[X]); b = (P[Y] + d * D[Y]); if ((Sqr(a) + Sqr(b)) <= (Test_Flag(Cone, CYLINDER_FLAG) ? 1.0 : Sqr(Cone->dist)) && (d > Cone_Tolerance) && (d < Max_Distance)) { Intersection[i].d = d / len; Intersection[i++].t = BASE_HIT; } } if (i) { Increase_Counter(stats[Ray_Cone_Tests_Succeeded]); } return (i); }