Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Creating a Region3 around a model?

How would I go about creating a Region3 around a model? Right now, I have this, but it doesn't go around the entire model:


local function getC(obj, t)
	if obj:IsA("Model") or obj:IsA("Folder") then return getC(obj:GetChildren()[1], t) end
	if obj:IsA("BasePart") then
		if t=="X" then
			if obj.Position.X >= 0 then
				return obj.Position.X + (obj.Size.X/2)
			else
				return obj.Position.X - (obj.Size.X/2)
			end
		elseif t=="Y" then
			if obj.Position.Y >= 0 then
				return obj.Position.Y + (obj.Size.Y/2)
			else
				return obj.Position.Y - (obj.Size.Y/2)
			end
		elseif t=="Z" then
			if obj.Position.Z >= 0 then
				return obj.Position.Z + (obj.Size.Z/2)
			else
				return obj.Position.Z - (obj.Size.Z/2)
			end
		end
	end
	return false
end

for _,v in pairs(model:GetChildren()) do
	local gX = 0
	local gY = 0
	local gZ = 0
	
	local gXl = 1000000000
	local gYl = 1000000000
	local gZl = 1000000000
	
	for _,q in pairs(v:GetChildren()) do
		x = getC(q, "X")
		y = getC(q, "Y")
		z = getC(q, "Z")
		if x then
			if x > gX then gX = x end
			if x < gXl then gXl = x end
		end
		if y then
			if y > gY then gY = y end
			if y < gYl then gYl = y end
		end
		if z then
			if z > gZ then gZ = z end
			if z < gZl then gZl = z end
		end
	end
	
	local uc = Vector3.new(gX+1000, gY+250, gZl+1000) --uppercorner
	local lc = Vector3.new(gXl-1000, gYl-250, gZl-1000) --lowercorner
	
	local tbl = {
		["model"] = v,
		["region3"] = Region3.new(uc,lc),
		["upper"] = uc,
		["lower"] = lc
	}
	table.insert(_G.rs, tbl)
end

Any help is appreciated.

1 answer

✓ Accepted answer
function GetModelAABB(model)
    local modelMin = nil
    local modelMax = nil
    for _, v in pairs(model:GetChildren()) do
        if v:IsA("BasePart") then
            local cf = v.CFrame
            local size = v.Size
            local baseCf = cf * CFrame.new(-size/2)
            for x = 0, 1 do
                for y = 0, 1 do
                    for z = 0, 1 do
                        local testCorner = (baseCf * CFrame.new( size * Vector3.new(x, y, z))).p

                        if not modelMin then
                            modelMin = testCorner
                        end

                        if not modelMax then
                            modelMax = testCorner
                        end

                        modelMin = Vector3.new(
                            math.min(modelMin.x, testCorner.x),
                            math.min(modelMin.y, testCorner.y),
                            math.min(modelMin.z, testCorner.z)
                        )
                        modelMax = Vector3.new(
                            math.max(modelMax.x, testCorner.x),
                            math.max(modelMax.y, testCorner.y),
                            math.max(modelMax.z, testCorner.z)
                        )   
                    end
                end
            end
        end
    end

    return Region3.new(modelMin, modelMax)
end

This returns a Region3 that hugs the model.

Get each corner of each part in the model, and get the minimum/maximum in each dimension. Return a Region3 made out of these. I have not run this, but in theory this should work. Make sure model is actually a model, otherwise this will error.

EDIT: Also, parts are not examined recursively. You may want to modify this so that it does.

EDITEDIT: Tested and found a missing parenthesis. It works.

6 comments

1

Thank you! If I had the reputation to upvote, I would. This was exactly what I was looking for.

0

I appreciate that you at least tried, though.

0

This is already a core function, model:GetExtentsSize(). It's not perfect, but yours is even less so.

1

@cabbler GetExtentsSize only gives me the size of the box around the model, it doesn't return the actual region.

0

"It's not perfect, but yours is even less so." I highly doubt that. Do you have any proof? My implementation covers the definition of an axis-aligned bounding box (it's as good as we're going to get in Roblox, anyway, without getting the vertices of a mesh). Moreover, GetExtentsSize() is dependent on the rotation of a model's PrimaryPart (which is arbitrary), and rotations are no good for Region3s

0

Excellent, thanks! I've been struggling for ages trying to line up models and non of the built in functions seem to be up to the task! Even just trying to put a 'car ON the road' is a nightmare!

This discussion is preserved as it was. New answers, comments, and votes are closed.