in Inc/DirectXCollision.inl [1069:1169]
inline void BoundingSphere::CreateFromPoints(BoundingSphere& Out, size_t Count, const XMFLOAT3* pPoints, size_t Stride) noexcept
{
assert(Count > 0);
assert(pPoints);
// Find the points with minimum and maximum x, y, and z
XMVECTOR MinX, MaxX, MinY, MaxY, MinZ, MaxZ;
MinX = MaxX = MinY = MaxY = MinZ = MaxZ = XMLoadFloat3(pPoints);
for (size_t i = 1; i < Count; ++i)
{
XMVECTOR Point = XMLoadFloat3(reinterpret_cast<const XMFLOAT3*>(reinterpret_cast<const uint8_t*>(pPoints) + i * Stride));
float px = XMVectorGetX(Point);
float py = XMVectorGetY(Point);
float pz = XMVectorGetZ(Point);
if (px < XMVectorGetX(MinX))
MinX = Point;
if (px > XMVectorGetX(MaxX))
MaxX = Point;
if (py < XMVectorGetY(MinY))
MinY = Point;
if (py > XMVectorGetY(MaxY))
MaxY = Point;
if (pz < XMVectorGetZ(MinZ))
MinZ = Point;
if (pz > XMVectorGetZ(MaxZ))
MaxZ = Point;
}
// Use the min/max pair that are farthest apart to form the initial sphere.
XMVECTOR DeltaX = XMVectorSubtract(MaxX, MinX);
XMVECTOR DistX = XMVector3Length(DeltaX);
XMVECTOR DeltaY = XMVectorSubtract(MaxY, MinY);
XMVECTOR DistY = XMVector3Length(DeltaY);
XMVECTOR DeltaZ = XMVectorSubtract(MaxZ, MinZ);
XMVECTOR DistZ = XMVector3Length(DeltaZ);
XMVECTOR vCenter;
XMVECTOR vRadius;
if (XMVector3Greater(DistX, DistY))
{
if (XMVector3Greater(DistX, DistZ))
{
// Use min/max x.
vCenter = XMVectorLerp(MaxX, MinX, 0.5f);
vRadius = XMVectorScale(DistX, 0.5f);
}
else
{
// Use min/max z.
vCenter = XMVectorLerp(MaxZ, MinZ, 0.5f);
vRadius = XMVectorScale(DistZ, 0.5f);
}
}
else // Y >= X
{
if (XMVector3Greater(DistY, DistZ))
{
// Use min/max y.
vCenter = XMVectorLerp(MaxY, MinY, 0.5f);
vRadius = XMVectorScale(DistY, 0.5f);
}
else
{
// Use min/max z.
vCenter = XMVectorLerp(MaxZ, MinZ, 0.5f);
vRadius = XMVectorScale(DistZ, 0.5f);
}
}
// Add any points not inside the sphere.
for (size_t i = 0; i < Count; ++i)
{
XMVECTOR Point = XMLoadFloat3(reinterpret_cast<const XMFLOAT3*>(reinterpret_cast<const uint8_t*>(pPoints) + i * Stride));
XMVECTOR Delta = XMVectorSubtract(Point, vCenter);
XMVECTOR Dist = XMVector3Length(Delta);
if (XMVector3Greater(Dist, vRadius))
{
// Adjust sphere to include the new point.
vRadius = XMVectorScale(XMVectorAdd(vRadius, Dist), 0.5f);
vCenter = XMVectorAdd(vCenter, XMVectorMultiply(XMVectorSubtract(XMVectorReplicate(1.0f), XMVectorDivide(vRadius, Dist)), Delta));
}
}
XMStoreFloat3(&Out.Center, vCenter);
XMStoreFloat(&Out.Radius, vRadius);
}