Skip to content

Instantly share code, notes, and snippets.

@stravant
Created May 26, 2020 16:47
Show Gist options
  • Save stravant/0fcc931af34fce8c19ebe50c7f101d64 to your computer and use it in GitHub Desktop.
Save stravant/0fcc931af34fce8c19ebe50c7f101d64 to your computer and use it in GitHub Desktop.
Compute Two Bounding Boxes
--[[
Micro-optimized code for computing a local space and the global space
bounding box for a set of parts and attachments as fast as possible.
]]
local function computeTwoBoundingBoxes(basisCFrame1, allParts, allAttachments)
local basisX, basisY, basisZ = basisCFrame1.X, basisCFrame1.Y, basisCFrame1.Z
local inverseBasis1 = basisCFrame1:Inverse()
local xmin1, xmax1 = math.huge, -math.huge
local ymin1, ymax1 = math.huge, -math.huge
local zmin1, zmax1 = math.huge, -math.huge
local xmin2, xmax2 = math.huge, -math.huge
local ymin2, ymax2 = math.huge, -math.huge
local zmin2, zmax2 = math.huge, -math.huge
for _, part in ipairs(allParts) do
if not part:IsA("Terrain") then
local cframe = part.CFrame
local size = part.Size
local sx, sy, sz = size.X, size.Y, size.Z
-- Calculation for bounding box in the space of basisCFrame1
local localCFrame1 = inverseBasis1 * cframe -- put cframe in our local basis
local _, _, _,
t00, t01, t02,
t10, t11, t12,
t20, t21, t22 = localCFrame1:components()
local hw1 = 0.5 * (math.abs(sx * t00) + math.abs(sy * t10) + math.abs(sz * t20))
local hh1 = 0.5 * (math.abs(sx * t01) + math.abs(sy * t11) + math.abs(sz * t21))
local hd1 = 0.5 * (math.abs(sx * t02) + math.abs(sy * t12) + math.abs(sz * t22))
local at1x, at1y, at1z = localCFrame1.X, localCFrame1.Y, localCFrame1.Z
xmin1 = math.min(xmin1, at1x - hw1)
xmax1 = math.max(xmax1, at1x + hw1)
ymin1 = math.min(ymin1, at1y - hh1)
ymax1 = math.max(ymax1, at1y + hh1)
zmin1 = math.min(zmin1, at1z - hd1)
zmax1 = math.max(zmax1, at1z + hd1)
-- Calculation for the bounding box in the global coordinate space
_, _, _,
t00, t01, t02,
t10, t11, t12,
t20, t21, t22 = cframe:components()
local hw2 = 0.5 * (math.abs(sx * t00) + math.abs(sy * t01) + math.abs(sz * t02))
local hh2 = 0.5 * (math.abs(sx * t10) + math.abs(sy * t11) + math.abs(sz * t12))
local hd2 = 0.5 * (math.abs(sx * t20) + math.abs(sy * t21) + math.abs(sz * t22))
local at2x, at2y, at2z = cframe.X, cframe.Y, cframe.Z
xmin2 = math.min(xmin2, at2x - hw2)
xmax2 = math.max(xmax2, at2x + hw2)
ymin2 = math.min(ymin2, at2y - hh2)
ymax2 = math.max(ymax2, at2y + hh2)
zmin2 = math.min(zmin2, at2z - hd2)
zmax2 = math.max(zmax2, at2z + hd2)
end
end
for _, attachment in ipairs(allAttachments) do
local worldPosition = attachment.WorldPosition
local localPosition = inverseBasis1 * worldPosition
local localx, localy, localz = localPosition.X, localPosition.Y, localPosition.Z
xmin1 = math.min(xmin1, localx)
xmax1 = math.max(xmax1, localx)
ymin1 = math.min(ymin1, localy)
ymax1 = math.max(ymax1, localy)
zmin1 = math.min(zmin1, localz)
zmax1 = math.max(zmax1, localz)
local globalx, globaly, globalz = worldPosition.X, worldPosition.Y, worldPosition.Z
xmin2 = math.min(xmin2, globalx)
xmax2 = math.max(xmax2, globalx)
ymin2 = math.min(ymin2, globaly)
ymax2 = math.max(ymax2, globaly)
zmin2 = math.min(zmin2, globalz)
zmax2 = math.max(zmax2, globalz)
end
local localBoundingBoxOffset = Vector3.new(
0.5 * (xmin1 + xmax1),
0.5 * (ymin1 + ymax1),
0.5 * (zmin1 + zmax1)
)
local localBoundingBoxSize = Vector3.new(
xmax1 - xmin1,
ymax1 - ymin1,
zmax1 - zmin1
)
local globalBoundingBoxOffset = Vector3.new(
0.5 * (xmin2 + xmax2) - basisX,
0.5 * (ymin2 + ymax2) - basisY,
0.5 * (zmin2 + zmax2) - basisZ
)
local globalBoundingBoxSize = Vector3.new(
xmax2 - xmin2,
ymax2 - ymin2,
zmax2 - zmin2
)
return localBoundingBoxOffset, localBoundingBoxSize,
globalBoundingBoxOffset, globalBoundingBoxSize
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment