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 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)); }