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