public ContainmentType Contains(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); if (XMVector3.Greater(d2, XMVector.Multiply(sphereRadius, sphereRadius))) { return(ContainmentType.Disjoint); } XMVector insideAll = XMVector.LessOrEqual(boxMin + sphereRadius, sphereCenter); insideAll = XMVector.AndInt(insideAll, XMVector.LessOrEqual(sphereCenter, boxMax - sphereRadius)); insideAll = XMVector.AndInt(insideAll, XMVector.Greater(boxMax - boxMin, sphereRadius)); return(XMVector3.EqualInt(insideAll, XMVector.TrueInt) ? ContainmentType.Contains : ContainmentType.Intersects); }
public static BoundingSphere CreateFromPoints(XMFloat3[] points) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Length == 0) { throw new ArgumentOutOfRangeException("points"); } // Find the points with minimum and maximum x, y, and z XMVector minX, maxX, minY, maxY, minZ, maxZ; minX = maxX = minY = maxY = minZ = maxZ = points[0]; for (int i = 1; i < points.Length; i++) { XMVector point = points[i]; float px = point.X; float py = point.Y; float pz = point.Z; if (px < minX.X) { minX = point; } if (px > maxX.X) { maxX = point; } if (py < minY.Y) { minY = point; } if (py > maxY.Y) { maxY = point; } if (pz < minZ.Z) { minZ = point; } if (pz > maxZ.Z) { maxZ = point; } } // Use the min/max pair that are farthest apart to form the initial sphere. XMVector deltaX = maxX - minX; XMVector distX = XMVector3.Length(deltaX); XMVector deltaY = maxY - minY; XMVector distY = XMVector3.Length(deltaY); XMVector deltaZ = maxZ - minZ; XMVector distZ = XMVector3.Length(deltaZ); XMVector v_center; XMVector v_radius; if (XMVector3.Greater(distX, distY)) { if (XMVector3.Greater(distX, distZ)) { // Use min/max x. v_center = XMVector.Lerp(maxX, minX, 0.5f); v_radius = distX * 0.5f; } else { // Use min/max z. v_center = XMVector.Lerp(maxZ, minZ, 0.5f); v_radius = distZ * 0.5f; } } else { //// Y >= X if (XMVector3.Greater(distY, distZ)) { // Use min/max y. v_center = XMVector.Lerp(maxY, minY, 0.5f); v_radius = distY * 0.5f; } else { // Use min/max z. v_center = XMVector.Lerp(maxZ, minZ, 0.5f); v_radius = distZ * 0.5f; } } // Add any points not inside the sphere. for (int i = 0; i < points.Length; i++) { XMVector point = points[i]; XMVector delta = point - v_center; XMVector dist = XMVector3.Length(delta); if (XMVector3.Greater(dist, v_radius)) { // Adjust sphere to include the new point. v_radius = (v_radius + dist) * 0.5f; v_center += (XMVector.Replicate(1.0f) - XMVector.Divide(v_radius, dist)) * delta; } } return(new BoundingSphere(v_center, v_radius.X)); }