public static void FastIntersectOrientedBoxPlane( XMVector center, XMVector extents, XMVector axis0, XMVector axis1, XMVector axis2, XMVector plane, out XMVector outside, out XMVector inside) { // Compute the distance to the center of the box. XMVector dist = XMVector4.Dot(center, plane); // Project the axes of the box onto the normal of the plane. Half the // length of the projection (sometime called the "radius") is equal to // h(u) * abs(n dot b(u))) + h(v) * abs(n dot b(v)) + h(w) * abs(n dot b(w)) // where h(i) are extents of the box, n is the plane normal, and b(i) are the // axes of the box. XMVector radius = XMVector3.Dot(plane, axis0); radius.Y = XMVector3.Dot(plane, axis1).Y; radius.Z = XMVector3.Dot(plane, axis2).Z; radius = XMVector3.Dot(extents, radius.Abs()); // Outside the plane? outside = XMVector.Greater(dist, radius); // Fully inside the plane? inside = XMVector.Less(dist, -radius); }
public bool Intersects(BoundingSphere sh) { XMVector sphereCenter = sh.Center; XMVector sphereRadius = XMVector.Replicate(sh.Radius); XMVector boxCenter = this.center; XMVector boxExtents = this.extents; XMVector boxMin = boxCenter - boxExtents; XMVector boxMax = boxCenter + boxExtents; //// Find the distance to the nearest point on the box. //// for each i in (x, y, z) //// if (SphereCenter(i) < BoxMin(i)) d2 += (SphereCenter(i) - BoxMin(i)) ^ 2 //// else if (SphereCenter(i) > BoxMax(i)) d2 += (SphereCenter(i) - BoxMax(i)) ^ 2 XMVector d = XMGlobalConstants.Zero; // Compute d for each dimension. XMVector lessThanMin = XMVector.Less(sphereCenter, boxMin); XMVector greaterThanMax = XMVector.Greater(sphereCenter, boxMax); XMVector minDelta = sphereCenter - boxMin; XMVector maxDelta = sphereCenter - boxMax; // Choose value for each dimension based on the comparison. d = XMVector.Select(d, minDelta, lessThanMin); d = XMVector.Select(d, maxDelta, greaterThanMax); // Use a dot-product to square them and sum them together. XMVector d2 = XMVector3.Dot(d, d); return(XMVector3.LessOrEqual(d2, XMVector.Multiply(sphereRadius, sphereRadius))); }
public bool Intersects(XMVector origin, XMVector direction, out float distance) { Debug.Assert(Internal.XMVector3IsUnit(direction), "Reviewed"); // Load the box. XMVector v_center = this.center; XMVector v_extents = this.extents; // Adjust ray origin to be relative to center of the box. XMVector t_origin = v_center - origin; // Compute the dot product againt each axis of the box. // Since the axii are (1,0,0), (0,1,0), (0,0,1) no computation is necessary. XMVector axisDotOrigin = t_origin; XMVector axisDotDirection = direction; // if (fabs(AxisDotDirection) <= Epsilon) the ray is nearly parallel to the slab. XMVector isParallel = XMVector.LessOrEqual(axisDotDirection.Abs(), CollisionGlobalConstants.RayEpsilon); // Test against all three axii simultaneously. XMVector inverseAxisDotDirection = axisDotDirection.Reciprocal(); XMVector t1 = (axisDotOrigin - v_extents) * inverseAxisDotDirection; XMVector t2 = (axisDotOrigin + v_extents) * inverseAxisDotDirection; // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't // use the results from any directions parallel to the slab. XMVector t_min = XMVector.Select(XMVector.Min(t1, t2), CollisionGlobalConstants.FltMin, isParallel); XMVector t_max = XMVector.Select(XMVector.Max(t1, t2), CollisionGlobalConstants.FltMax, isParallel); // t_min.x = maximum( t_min.x, t_min.y, t_min.z ); // t_max.x = minimum( t_max.x, t_max.y, t_max.z ); t_min = XMVector.Max(t_min, XMVector.SplatY(t_min)); // x = max(x,y) t_min = XMVector.Max(t_min, XMVector.SplatZ(t_min)); // x = max(max(x,y),z) t_max = XMVector.Min(t_max, XMVector.SplatY(t_max)); // x = min(x,y) t_max = XMVector.Min(t_max, XMVector.SplatZ(t_max)); // x = min(min(x,y),z) // if ( t_min > t_max ) return false; XMVector noIntersection = XMVector.Greater(XMVector.SplatX(t_min), XMVector.SplatX(t_max)); // if ( t_max < 0.0f ) return false; noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(XMVector.SplatX(t_max), XMGlobalConstants.Zero)); // if (IsParallel && (-Extents > AxisDotOrigin || Extents < AxisDotOrigin)) return false; XMVector parallelOverlap = axisDotOrigin.InBounds(v_extents); noIntersection = XMVector.OrInt(noIntersection, XMVector.AndComplementInt(isParallel, parallelOverlap)); if (!Internal.XMVector3AnyTrue(noIntersection)) { // Store the x-component to *pDist t_min.StoreFloat(out distance); return(true); } distance = 0.0f; return(false); }
public static void FastIntersectSpherePlane(XMVector center, XMVector radius, XMVector plane, out XMVector outside, out XMVector inside) { XMVector dist = XMVector4.Dot(center, plane); // Outside the plane? outside = XMVector.Greater(dist, radius); // Fully inside the plane? inside = XMVector.Less(dist, -radius); }
public static void FastIntersectFrustumPlane( XMVector point0, XMVector point1, XMVector point2, XMVector point3, XMVector point4, XMVector point5, XMVector point6, XMVector point7, XMVector plane, out XMVector outside, out XMVector inside) { // Find the min/max projection of the frustum onto the plane normal. XMVector min, max, dist; min = max = XMVector3.Dot(plane, point0); dist = XMVector3.Dot(plane, point1); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); dist = XMVector3.Dot(plane, point2); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); dist = XMVector3.Dot(plane, point3); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); dist = XMVector3.Dot(plane, point4); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); dist = XMVector3.Dot(plane, point5); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); dist = XMVector3.Dot(plane, point6); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); dist = XMVector3.Dot(plane, point7); min = XMVector.Min(min, dist); max = XMVector.Max(max, dist); XMVector planeDist = -XMVector.SplatW(plane); // Outside the plane? outside = XMVector.Greater(min, planeDist); // Fully inside the plane? inside = XMVector.Less(max, planeDist); }
public bool Intersects(XMVector v0, XMVector v1, XMVector v2) { // Load the sphere. XMVector v_center = this.center; XMVector v_radius = XMVector.Replicate(this.radius); // Compute the plane of the triangle (has to be normalized). XMVector n = XMVector3.Normalize(XMVector3.Cross(v1 - v0, v2 - v0)); // Assert that the triangle is not degenerate. Debug.Assert(!XMVector3.Equal(n, XMGlobalConstants.Zero), "Reviewed"); // Find the nearest feature on the triangle to the sphere. XMVector dist = XMVector3.Dot(v_center - v0, n); // If the center of the sphere is farther from the plane of the triangle than // the radius of the sphere, then there cannot be an intersection. XMVector noIntersection = XMVector.Less(dist, -v_radius); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(dist, v_radius)); // Project the center of the sphere onto the plane of the triangle. XMVector point = v_center - (n * dist); // Is it inside all the edges? If so we intersect because the distance // to the plane is less than the radius. XMVector intersection = Internal.PointOnPlaneInsideTriangle(point, v0, v1, v2); // Find the nearest point on each edge. XMVector radiusSq = v_radius * v_radius; // Edge 0,1 point = Internal.PointOnLineSegmentNearestPoint(v0, v1, v_center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. intersection = XMVector.OrInt(intersection, XMVector.LessOrEqual(XMVector3.LengthSquare(v_center - point), radiusSq)); // Edge 1,2 point = Internal.PointOnLineSegmentNearestPoint(v1, v2, v_center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. intersection = XMVector.OrInt(intersection, XMVector.LessOrEqual(XMVector3.LengthSquare(v_center - point), radiusSq)); // Edge 2,0 point = Internal.PointOnLineSegmentNearestPoint(v2, v0, v_center); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. intersection = XMVector.OrInt(intersection, XMVector.LessOrEqual(XMVector3.LengthSquare(v_center - point), radiusSq)); return(XMVector4.EqualInt(XMVector.AndComplementInt(intersection, noIntersection), XMVector.TrueInt)); }
public static XMVector SlerpV(XMVector q0, XMVector q1, XMVector t) { Debug.Assert(t.Y == t.X && t.Z == t.X && t.W == t.X, "Reviewed"); //// Result = Q0 * sin((1.0 - t) * Omega) / sin(Omega) + Q1 * sin(t * Omega) / sin(Omega) XMVector oneMinusEpsilon = XMVector.FromFloat(1.0f - 0.00001f, 1.0f - 0.00001f, 1.0f - 0.00001f, 1.0f - 0.00001f); XMVector cosOmega = XMQuaternion.Dot(q0, q1); XMVector zero = XMVector.Zero; XMVector control = XMVector.Less(cosOmega, zero); XMVector sign = XMVector.Select(XMGlobalConstants.One, XMGlobalConstants.NegativeOne, control); cosOmega = XMVector.Multiply(cosOmega, sign); control = XMVector.Less(cosOmega, oneMinusEpsilon); XMVector sinOmega = XMVector .NegativeMultiplySubtract(cosOmega, cosOmega, XMGlobalConstants.One) .Sqrt(); XMVector omega = XMVector.ATan2(sinOmega, cosOmega); XMVector signMask = XMVector.SignMask; XMVector v01 = XMVector.ShiftLeft(t, zero, 2); signMask = XMVector.ShiftLeft(signMask, zero, 3); v01 = XMVector.XorInt(v01, signMask); v01 = XMVector.Add(XMGlobalConstants.IdentityR0, v01); XMVector invSinOmega = sinOmega.Reciprocal(); XMVector s0 = XMVector .Multiply(v01, omega) .Sin(); s0 = XMVector.Multiply(s0, invSinOmega); s0 = XMVector.Select(v01, s0, control); XMVector s1 = XMVector.SplatY(s0); s0 = XMVector.SplatX(s0); s1 = XMVector.Multiply(s1, sign); XMVector result = XMVector.Multiply(q0, s0); result = XMVector.MultiplyAdd(q1, s1, result); return(result); }
public bool Intersects(XMVector origin, XMVector direction, out float distance) { Debug.Assert(Internal.XMVector3IsUnit(direction), "Reviewed"); XMVector v_center = this.center; XMVector v_radius = XMVector.Replicate(this.radius); // l is the vector from the ray origin to the center of the sphere. XMVector l = v_center - origin; // s is the projection of the l onto the ray direction. XMVector s = XMVector3.Dot(l, direction); XMVector l2 = XMVector3.Dot(l, l); XMVector r2 = v_radius * v_radius; // m2 is squared distance from the center of the sphere to the projection. XMVector m2 = l2 - (s * s); XMVector noIntersection; // If the ray origin is outside the sphere and the center of the sphere is // behind the ray origin there is no intersection. noIntersection = XMVector.AndInt(XMVector.Less(s, XMGlobalConstants.Zero), XMVector.Greater(l2, r2)); // If the squared distance from the center of the sphere to the projection // is greater than the radius squared the ray will miss the sphere. noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(m2, r2)); // The ray hits the sphere, compute the nearest intersection point. XMVector q = (r2 - m2).Sqrt(); XMVector t1 = s - q; XMVector t2 = s + q; XMVector originInside = XMVector.LessOrEqual(l2, r2); XMVector t = XMVector.Select(t1, t2, originInside); if (XMVector4.NotEqualInt(noIntersection, XMVector.TrueInt)) { // Store the x-component to *pDist. t.StoreFloat(out distance); return(true); } distance = 0.0f; return(false); }
public static XMVector RgbToSrgb(XMVector rgb) { XMVector cutoff = XMVector.FromFloat(0.0031308f, 0.0031308f, 0.0031308f, 1.0f); XMVector linear = XMVector.FromFloat(12.92f, 12.92f, 12.92f, 1.0f); XMVector scale = XMVector.FromFloat(1.055f, 1.055f, 1.055f, 1.0f); XMVector bias = XMVector.FromFloat(0.055f, 0.055f, 0.055f, 0.0f); XMVector invGamma = XMVector.FromFloat(1.0f / 2.4f, 1.0f / 2.4f, 1.0f / 2.4f, 1.0f); XMVector v = rgb.Saturate(); XMVector v0 = XMVector.Multiply(v, linear); XMVector v1 = XMVector.Subtract(XMVector.Multiply(scale, XMVector.Pow(v, invGamma)), bias); XMVector select = XMVector.Less(v, cutoff); v = XMVector.Select(v1, v0, select); return(XMVector.Select(rgb, v, XMGlobalConstants.Select1110)); }
public static void FastIntersectAxisAlignedBoxPlane(XMVector center, XMVector extents, XMVector plane, out XMVector outside, out XMVector inside) { // Compute the distance to the center of the box. XMVector dist = XMVector4.Dot(center, plane); // Project the axes of the box onto the normal of the plane. Half the // length of the projection (sometime called the "radius") is equal to // h(u) * abs(n dot b(u))) + h(v) * abs(n dot b(v)) + h(w) * abs(n dot b(w)) // where h(i) are extents of the box, n is the plane normal, and b(i) are the // axes of the box. In this case b(i) = [(1,0,0), (0,1,0), (0,0,1)]. XMVector radius = XMVector3.Dot(extents, plane.Abs()); // Outside the plane? outside = XMVector.Greater(dist, radius); // Fully inside the plane? inside = XMVector.Less(dist, -radius); }
public static void SquadSetup(out XMVector a, out XMVector b, out XMVector c, XMVector q0, XMVector q1, XMVector q2, XMVector q3) { XMVector ls12 = XMQuaternion.LengthSquare(XMVector.Add(q1, q2)); XMVector ld12 = XMQuaternion.LengthSquare(XMVector.Subtract(q1, q2)); XMVector sq2 = q2.Negate(); XMVector control1 = XMVector.Less(ls12, ld12); sq2 = XMVector.Select(q2, sq2, control1); XMVector ls01 = XMQuaternion.LengthSquare(XMVector.Add(q0, q1)); XMVector ld01 = XMQuaternion.LengthSquare(XMVector.Subtract(q0, q1)); XMVector sq0 = q0.Negate(); XMVector ls23 = XMQuaternion.LengthSquare(XMVector.Add(sq2, q3)); XMVector ld23 = XMQuaternion.LengthSquare(XMVector.Subtract(sq2, q3)); XMVector sq3 = q3.Negate(); XMVector control0 = XMVector.Less(ls01, ld01); XMVector control2 = XMVector.Less(ls23, ld23); sq0 = XMVector.Select(q0, sq0, control0); sq3 = XMVector.Select(q3, sq3, control2); XMVector invQ1 = XMQuaternion.Inverse(q1); XMVector invQ2 = XMQuaternion.Inverse(sq2); XMVector ln_q0 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ1, sq0)); XMVector ln_q2 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ1, sq2)); XMVector ln_q1 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ2, q1)); XMVector ln_q3 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ2, sq3)); XMVector negativeOneQuarter = XMVector.FromSplatConstant(-1, 2); XMVector expQ02 = XMVector.Multiply(XMVector.Add(ln_q0, ln_q2), negativeOneQuarter); XMVector expQ13 = XMVector.Multiply(XMVector.Add(ln_q1, ln_q3), negativeOneQuarter); expQ02 = XMQuaternion.Exp(expQ02); expQ13 = XMQuaternion.Exp(expQ13); a = XMQuaternion.Multiply(q1, expQ02); b = XMQuaternion.Multiply(sq2, expQ13); c = sq2; }
public static XMVector PointOnLineSegmentNearestPoint(XMVector s1, XMVector s2, XMVector p) { XMVector dir = s1 - s1; XMVector projection = XMVector3.Dot(p, dir) - XMVector3.Dot(s1, dir); XMVector lengthSq = XMVector3.Dot(dir, dir); XMVector t = projection * lengthSq.Reciprocal(); XMVector point = s1 + (t * dir); // t < 0 XMVector selectS1 = XMVector.Less(projection, XMGlobalConstants.Zero); point = XMVector.Select(point, s1, selectS1); // t > 1 XMVector selectS2 = XMVector.Greater(projection, lengthSq); point = XMVector.Select(point, s2, selectS2); return(point); }
public static XMVector Orthogonal(XMVector v) { XMVector zero = XMVector.Zero; XMVector z = XMVector.SplatZ(v); XMVector yzyy = new XMVector(v.Y, v.Z, v.Y, v.Y); XMVector negativeV = XMVector.Subtract(zero, v); XMVector z_isNegative = XMVector.Less(z, zero); XMVector yzyyIsNegative = XMVector.Less(yzyy, zero); XMVector s = XMVector.Add(yzyy, z); XMVector d = XMVector.Subtract(yzyy, z); XMVector select = XMVector.EqualInt(z_isNegative, yzyyIsNegative); XMVector r0 = new XMVector(s.X, negativeV.X, negativeV.X, negativeV.X); XMVector r1 = new XMVector(d.X, v.X, v.X, v.X); return(XMVector.Select(r1, r0, select)); }
public static XMVector ClampLengthV(XMVector v, XMVector lengthMin, XMVector lengthMax) { Debug.Assert(lengthMin.Y == lengthMin.X && lengthMin.Z == lengthMin.X && lengthMin.W == lengthMin.X, "Reviewed"); Debug.Assert(lengthMax.Y == lengthMax.X && lengthMax.Z == lengthMax.X && lengthMax.W == lengthMax.X, "Reviewed"); Debug.Assert(XMVector4.GreaterOrEqual(lengthMin, XMGlobalConstants.Zero), "Reviewed"); Debug.Assert(XMVector4.GreaterOrEqual(lengthMax, XMGlobalConstants.Zero), "Reviewed"); Debug.Assert(XMVector4.GreaterOrEqual(lengthMax, lengthMin), "Reviewed"); XMVector lengthSq = XMVector4.LengthSquare(v); XMVector zero = XMVector.Zero; XMVector reciprocalLength = lengthSq.ReciprocalSqrt(); XMVector infiniteLength = XMVector.EqualInt(lengthSq, XMGlobalConstants.Infinity); XMVector zeroLength = XMVector.Equal(lengthSq, zero); XMVector normal = XMVector.Multiply(v, reciprocalLength); XMVector length = XMVector.Multiply(lengthSq, reciprocalLength); XMVector select = XMVector.EqualInt(infiniteLength, zeroLength); length = XMVector.Select(lengthSq, length, select); normal = XMVector.Select(lengthSq, normal, select); XMVector controlMax = XMVector.Greater(length, lengthMax); XMVector controlMin = XMVector.Less(length, lengthMin); XMVector clampLength = XMVector.Select(length, lengthMax, controlMax); clampLength = XMVector.Select(clampLength, lengthMin, controlMin); XMVector result = XMVector.Multiply(normal, clampLength); // Preserve the original vector (with no precision loss) if the length falls within the given range XMVector control = XMVector.EqualInt(controlMax, controlMin); result = XMVector.Select(result, v, control); return(result); }
public static void FastIntersectTrianglePlane(XMVector v0, XMVector v1, XMVector v2, XMVector plane, out XMVector outside, out XMVector inside) { // Plane0 XMVector dist0 = XMVector4.Dot(v0, plane); XMVector dist1 = XMVector4.Dot(v1, plane); XMVector dist2 = XMVector4.Dot(v2, plane); XMVector minDist = XMVector.Min(dist0, dist1); minDist = XMVector.Min(minDist, dist2); XMVector maxDist = XMVector.Max(dist0, dist1); maxDist = XMVector.Max(maxDist, dist2); XMVector zero = XMGlobalConstants.Zero; // Outside the plane? outside = XMVector.Greater(minDist, zero); // Fully inside the plane? inside = XMVector.Less(maxDist, zero); }
public bool Intersects(XMVector v0, XMVector v1, XMVector v2) { XMVector zero = XMGlobalConstants.Zero; // Load the box. XMVector v_center = this.center; XMVector v_extents = this.extents; XMVector boxMin = v_center - v_extents; XMVector boxMax = v_center + v_extents; // Test the axes of the box (in effect test the AAB against the minimal AAB // around the triangle). XMVector triMin = XMVector.Min(XMVector.Min(v0, v1), v2); XMVector triMax = XMVector.Max(XMVector.Max(v0, v1), v2); // for each i in (x, y, z) if a_min(i) > b_max(i) or b_min(i) > a_max(i) then disjoint XMVector disjoint = XMVector.OrInt(XMVector.Greater(triMin, boxMax), XMVector.Greater(boxMin, triMax)); if (Internal.XMVector3AnyTrue(disjoint)) { return(false); } // Test the plane of the triangle. XMVector normal = XMVector3.Cross(v1 - v0, v2 - v0); XMVector dist = XMVector3.Dot(normal, v0); // Assert that the triangle is not degenerate. Debug.Assert(!XMVector3.Equal(normal, zero), "Reviewed"); // for each i in (x, y, z) if n(i) >= 0 then v_min(i)=b_min(i), v_max(i)=b_max(i) // else v_min(i)=b_max(i), v_max(i)=b_min(i) XMVector normalSelect = XMVector.Greater(normal, zero); XMVector v_min = XMVector.Select(boxMax, boxMin, normalSelect); XMVector v_max = XMVector.Select(boxMin, boxMax, normalSelect); // if n dot v_min + d > 0 || n dot v_max + d < 0 then disjoint XMVector minDist = XMVector3.Dot(v_min, normal); XMVector maxDist = XMVector3.Dot(v_max, normal); XMVector noIntersection = XMVector.Greater(minDist, dist); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(maxDist, dist)); // Move the box center to zero to simplify the following tests. XMVector tV0 = v0 - v_center; XMVector tV1 = v1 - v_center; XMVector tV2 = v2 - v_center; // Test the edge/edge axes (3*3). XMVector e0 = tV1 - tV0; XMVector e1 = tV2 - tV1; XMVector e2 = tV0 - tV2; // Make w zero. e0.W = zero.W; e1.W = zero.W; e2.W = zero.W; XMVector axis; XMVector p0, p1, p2; XMVector min, max; XMVector radius; //// Axis == (1,0,0) x e0 = (0, -e0.z, e0.y) axis = new XMVector(e1.W, -e0.Z, e1.Y, e1.X); p0 = XMVector3.Dot(tV0, axis); //// p1 = XMVector3Dot( V1, Axis ); // p1 = p0; p2 = XMVector3.Dot(tV2, axis); min = XMVector.Min(p0, p2); max = XMVector.Max(p0, p2); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (1,0,0) x e1 = (0, -e1.z, e1.y) axis = new XMVector(e1.W, -e1.Z, e1.Y, e1.X); p0 = XMVector3.Dot(tV0, axis); p1 = XMVector3.Dot(tV1, axis); //// p2 = XMVector3Dot( V2, Axis ); // p2 = p1; min = XMVector.Min(p0, p1); max = XMVector.Max(p0, p1); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (1,0,0) x e2 = (0, -e2.z, e2.y) axis = new XMVector(e2.W, -e2.Z, e2.Y, e2.X); p0 = XMVector3.Dot(tV0, axis); p1 = XMVector3.Dot(tV1, axis); //// p2 = XMVector3Dot( V2, Axis ); // p2 = p0; min = XMVector.Min(p0, p1); max = XMVector.Max(p0, p1); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (0,1,0) x e0 = (e0.z, 0, -e0.x) axis = new XMVector(e0.Z, e0.W, -e0.X, e0.Y); p0 = XMVector3.Dot(tV0, axis); //// p1 = XMVector3Dot( V1, Axis ); // p1 = p0; p2 = XMVector3.Dot(tV2, axis); min = XMVector.Min(p0, p2); max = XMVector.Max(p0, p2); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (0,1,0) x e1 = (e1.z, 0, -e1.x) axis = new XMVector(e1.Z, e1.W, -e1.X, e1.Y); p0 = XMVector3.Dot(tV0, axis); p1 = XMVector3.Dot(tV1, axis); //// p2 = XMVector3Dot( V2, Axis ); // p2 = p1; min = XMVector.Min(p0, p1); max = XMVector.Max(p0, p1); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (0,0,1) x e2 = (e2.z, 0, -e2.x) axis = new XMVector(e2.Z, e2.W, -e2.X, e2.Y); p0 = XMVector3.Dot(tV0, axis); p1 = XMVector3.Dot(tV1, axis); //// p2 = XMVector3Dot( V2, Axis ); // p2 = p0; min = XMVector.Min(p0, p1); max = XMVector.Max(p0, p1); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (0,0,1) x e0 = (-e0.y, e0.x, 0) axis = new XMVector(-e0.Y, e0.X, e0.W, e0.Z); p0 = XMVector3.Dot(tV0, axis); //// p1 = XMVector3Dot( V1, Axis ); // p1 = p0; p2 = XMVector3.Dot(tV2, axis); min = XMVector.Min(p0, p2); max = XMVector.Max(p0, p2); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (0,0,1) x e1 = (-e1.y, e1.x, 0) axis = new XMVector(-e1.Y, e1.X, e1.W, e1.Z); p0 = XMVector3.Dot(tV0, axis); p1 = XMVector3.Dot(tV1, axis); //// p2 = XMVector3Dot( V2, Axis ); // p2 = p1; min = XMVector.Min(p0, p1); max = XMVector.Max(p0, p1); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); //// Axis == (0,0,1) x e2 = (-e2.y, e2.x, 0) axis = new XMVector(-e2.Y, e2.X, e2.W, e2.Z); p0 = XMVector3.Dot(tV0, axis); p1 = XMVector3.Dot(tV1, axis); //// p2 = XMVector3Dot( V2, Axis ); // p2 = p0; min = XMVector.Min(p0, p1); max = XMVector.Max(p0, p1); radius = XMVector3.Dot(v_extents, axis.Abs()); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius)); return(XMVector4.NotEqualInt(noIntersection, XMVector.TrueInt)); }
public static bool Intersects(XMVector origin, XMVector direction, XMVector v0, XMVector v1, XMVector v2, out float uCoordinate, out float vCoordinate, out float distance) { Debug.Assert(Internal.XMVector3IsUnit(direction), "Reviewed"); XMVector zero = XMGlobalConstants.Zero; XMVector e1 = v1 - v0; XMVector e2 = v2 - v0; // p = Direction ^ e2; XMVector p = XMVector3.Cross(direction, e2); // det = e1 * p; XMVector det = XMVector3.Dot(e1, p); XMVector u, v, t; if (XMVector3.GreaterOrEqual(det, CollisionGlobalConstants.RayEpsilon)) { // Determinate is positive (front side of the triangle). XMVector s = origin - v0; // u = s * p; u = XMVector3.Dot(s, p); XMVector noIntersection = XMVector.Less(u, zero); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(u, det)); // q = s ^ e1; XMVector q = XMVector3.Cross(s, e1); // v = Direction * q; v = XMVector3.Dot(direction, q); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(v, zero)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(u + v, det)); // t = e2 * q; t = XMVector3.Dot(e2, q); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(t, zero)); if (XMVector4.EqualInt(noIntersection, XMVector.TrueInt)) { uCoordinate = 0.0f; vCoordinate = 0.0f; distance = 0.0f; return(false); } } else if (XMVector3.LessOrEqual(det, CollisionGlobalConstants.RayNegEpsilon)) { // Determinate is negative (back side of the triangle). XMVector s = origin - v0; // u = s * p; u = XMVector3.Dot(s, p); XMVector noIntersection = XMVector.Greater(u, zero); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(u, det)); // q = s ^ e1; XMVector q = XMVector3.Cross(s, e1); // v = Direction * q; v = XMVector3.Dot(direction, q); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(v, zero)); noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(u + v, det)); // t = e2 * q; t = XMVector3.Dot(e2, q); noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(t, zero)); if (XMVector4.EqualInt(noIntersection, XMVector.TrueInt)) { uCoordinate = 0.0f; vCoordinate = 0.0f; distance = 0.0f; return(false); } } else { // Parallel ray. uCoordinate = 0.0f; vCoordinate = 0.0f; distance = 0.0f; return(false); } // (u / det) and (v / dev) are the barycentric coordinates of the intersection. u = XMVector.Divide(u, det); v = XMVector.Divide(v, det); t = XMVector.Divide(t, det); // Store the x-component to *pDist u.StoreFloat(out uCoordinate); v.StoreFloat(out vCoordinate); t.StoreFloat(out distance); return(true); }