Ejemplo n.º 1
0
        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));
        }