local f=CFrame.new local N=table.insert local o=(CFrame.new()).toWorldSpace local r=math.min local y=math.max local B=unpack function BoundingBoxModule.CalculateExtents(o,S,E)if#o==0 then return end local I=S and S.Min or o[1].Position local K=S and S.Max or o[1].Position local P,L,H=I.X,I.Y,I.Z local l,G,j=K.X,K.Y,K.Z for o,E in pairs(o)do if not((IsPhysicsStatic()or E.Anchored)and S)then local o=E.CFrame local S=E.Size/2 local I,K,A=S.X,S.Y,S.Z local X local c,q,e={},{},{}X=o*f(I,K,A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(-I,K,A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(I,-K,A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(I,K,-A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(-I,K,-A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(-I,-K,A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(I,-K,-A)N(c,X.x)N(q,X.y)N(e,X.z)X=o*f(-I,-K,-A)N(c,X.x)N(q,X.y)N(e,X.z)P=r(P,B(c))L=r(L,B(q))H=r(H,B(e))l=y(l,B(c))G=y(G,B(q))j=y(j,B(e))end end local A={Min=Vector3.new(P,L,H);Max=Vector3.new(l,G,j)}if E then return A end local X=Vector3.new(l-P,G-L,j-H)local c=CFrame.new(P+(l-P)/2,L+(G-L)/2,H+(j-H)/2)return X,c end return BoundingBoxModule

local CFrame_new = CFrame.new;
local table_insert = table.insert;
local CFrame_toWorldSpace = CFrame.new().toWorldSpace;
local math_min = math.min;
local math_max = math.max;
local unpack = unpack;

function BoundingBoxModule.CalculateExtents(Items, StaticExtents, ExtentsOnly)
	-- Returns the size and position of a box covering all items in `Items`

	-- Ensure there are items
	if #Items == 0 then
		return;
	end;

	-- Get initial extents data for comparison
	local ComparisonBaseMin = StaticExtents and StaticExtents.Min or Items[1].Position;
	local ComparisonBaseMax = StaticExtents and StaticExtents.Max or Items[1].Position;
	local MinX, MinY, MinZ = ComparisonBaseMin.X, ComparisonBaseMin.Y, ComparisonBaseMin.Z;
	local MaxX, MaxY, MaxZ = ComparisonBaseMax.X, ComparisonBaseMax.Y, ComparisonBaseMax.Z;

	-- Go through each part in `Items`
	for _, Part in pairs(Items) do

		-- Avoid re-calculating for static parts
		if not ((IsPhysicsStatic() or Part.Anchored) and StaticExtents) then

			-- Get shortcuts to part data
			local PartCFrame = Part.CFrame;
			local PartSize = Part.Size / 2;
			local SizeX, SizeY, SizeZ = PartSize.X, PartSize.Y, PartSize.Z;

			local Corner;
			local XPoints, YPoints, ZPoints = {}, {}, {};

			Corner = PartCFrame * CFrame_new(SizeX, SizeY, SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(-SizeX, SizeY, SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(SizeX, -SizeY, SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(SizeX, SizeY, -SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(-SizeX, SizeY, -SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(-SizeX, -SizeY, SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(SizeX, -SizeY, -SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			Corner = PartCFrame * CFrame_new(-SizeX, -SizeY, -SizeZ);
			table_insert(XPoints, Corner.x);
			table_insert(YPoints, Corner.y);
			table_insert(ZPoints, Corner.z);

			-- Reduce gathered points to min/max extents
			MinX = math_min(MinX, unpack(XPoints));
			MinY = math_min(MinY, unpack(YPoints));
			MinZ = math_min(MinZ, unpack(ZPoints));
			MaxX = math_max(MaxX, unpack(XPoints));
			MaxY = math_max(MaxY, unpack(YPoints));
			MaxZ = math_max(MaxZ, unpack(ZPoints));

		end;

	end;

	-- Calculate the extents
	local Extents = {
		Min = Vector3.new(MinX, MinY, MinZ),
		Max = Vector3.new(MaxX, MaxY, MaxZ);
	};

	-- Only return extents if requested
	if ExtentsOnly then
		return Extents;
	end;

	-- Calculate the bounding box size
	local Size = Vector3.new(
		MaxX - MinX,
		MaxY - MinY,
		MaxZ - MinZ
	);

	-- Calculate the bounding box center
	local Position = CFrame.new(
		MinX + (MaxX - MinX) / 2,
		MinY + (MaxY - MinY) / 2,
		MinZ + (MaxZ - MinZ) / 2
	);

	-- Return the size and position
	return Size, Position;

end;

return BoundingBoxModule;
