bool BicubicPatch::intersect_subpatch(const BasicRay &ray, const TripleVector3d& V1, const DBL uu[3], const DBL vv[3], DBL *Depth, Vector3d& P, Vector3d& N, DBL *u, DBL *v) const { DBL squared_b0, squared_b1; DBL d, n, a, b, r; Vector3d Q; Vector3d T1; Matrix3x3 B, IB; Vector3d NN[3]; B[0] = V1[1] - V1[0]; B[1] = V1[2] - V1[0]; B[2] = cross(B[0], B[1]); d = B[2].lengthSqr(); squared_b0 = B[0].lengthSqr(); squared_b1 = B[1].lengthSqr(); if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0)) { return false; } d = 1.0 / sqrt(d); B[2] *= d; /* Degenerate triangle. */ if (!MInvers3(B, IB)) { return false; } d = dot(ray.Direction, IB[2]); if (fabs(d) < BEZIER_EPSILON) { return false; } Q = V1[0] - ray.Origin; n = dot(Q, IB[2]); *Depth = n / d; if (*Depth < BEZIER_TOLERANCE) { return false; } T1 = ray.Direction * (*Depth); P = ray.Origin + T1; Q = P - V1[0]; a = dot(Q, IB[0]); b = dot(Q, IB[1]); if ((a < 0.0) || (b < 0.0) || (a + b > 1.0)) { return false; } r = 1.0 - a - b; bezier_value(&Control_Points, uu[0], vv[0], T1, NN[0]); bezier_value(&Control_Points, uu[1], vv[1], T1, NN[1]); bezier_value(&Control_Points, uu[2], vv[2], T1, NN[2]); N = NN[0] * r + NN[1] * a + NN[2] * b; *u = r * uu[0] + a * uu[1] + b * uu[2]; *v = r * vv[0] + a * vv[1] + b * vv[2]; d = N.lengthSqr(); if (d > BEZIER_EPSILON) { d = 1.0 / sqrt(d); N *= d; } else { N = Vector3d(1.0, 0.0, 0.0); } return true; }
static int intersect_subpatch(BICUBIC_PATCH *Shape, RAY *ray, VECTOR V1[3], DBL uu[3], DBL vv[3], DBL *Depth, VECTOR P, VECTOR N, DBL *u, DBL *v) { DBL squared_b0, squared_b1; DBL d, n, a, b, r; VECTOR Q, T1; VECTOR B[3], IB[3], NN[3]; VSub(B[0], V1[1], V1[0]); VSub(B[1], V1[2], V1[0]); VCross(B[2], B[0], B[1]); VDot(d, B[2], B[2]); squared_b0 = VSumSqr(B[0]); squared_b1 = VSumSqr(B[1]); if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0)) { return (0); } d = 1.0 / sqrt(d); VScaleEq(B[2], d); /* Degenerate triangle. */ if (!MInvers3(B, IB)) { return (0); } VDot(d, ray->Direction, IB[2]); if (fabs(d) < BEZIER_EPSILON) { return (0); } VSub(Q, V1[0], ray->Initial); VDot(n, Q, IB[2]); *Depth = n / d; if (*Depth < BEZIER_TOLERANCE) { return (0); } VScale(T1, ray->Direction, *Depth); VAdd(P, ray->Initial, T1); VSub(Q, P, V1[0]); VDot(a, Q, IB[0]); VDot(b, Q, IB[1]); if ((a < 0.0) || (b < 0.0) || (a + b > 1.0)) { return (0); } r = 1.0 - a - b; Make_Vector(N, 0.0, 0.0, 0.0); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[0], vv[0], T1, NN[0]); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[1], vv[1], T1, NN[1]); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[2], vv[2], T1, NN[2]); VScale(T1, NN[0], r); VAddEq(N, T1); VScale(T1, NN[1], a); VAddEq(N, T1); VScale(T1, NN[2], b); VAddEq(N, T1); *u = r * uu[0] + a * uu[1] + b * uu[2]; *v = r * vv[0] + a * vv[1] + b * vv[2]; VDot(d, N, N); if (d > BEZIER_EPSILON) { d = 1.0 / sqrt(d); VScaleEq(N, d); } else { Make_Vector(N, 1, 0, 0); } return (1); }