I’ve been recently delving into things such as WFC and whatnot for procedural room generation (think DOORS-esque stuff). Most of it is fairly straightforward – except for placing procedurally generated furniture.
My problem is that I cannot seem to place specific furnitures on the surface of a specific part:
In this example, the furniture cluster on the left is positioned correctly, but the furniture cluster on the right is not. My goal is to have the furniture placed on the top of the green bounding brick through using its bounding box.
To do this, I’m grabbing the bounding block of each model using the GetBoundingBox() function.
Then, I place the furniture randomly on the bounding block using the following formula: green.CFrame * CFrame.new((RND:NextNumber() - 0.5) * green.Size.X, green.Size.Y/2 + ModelBound.Y/2, (RND:NextNumber() - 0.5) * green.Size.Z)
This formula works appropriately for most furniture models, but not in the example above. The Y-size of the bounding box is roughly half of most other furniture models, and that’s where my suspicions lie – it’s seemingly something to do with the division here that is causing that specific chair model to end up in the floor.
Any advice?
There are a few ways to “place” models, i.e. set their CFrame. Are you using SetPrimaryPartCFrame, PivotTo or some other way? This matters because SetPrimaryPartCFrame does… just that and PivotTo moves the model such that it’s pivot CFrame becomes the given CFrame. For example if the furniture on the left has a pivot point that’s centered in all axes, while the stuff on the right has a pivot in their center horizontally but at the top, then PivotTo would give the behavior you see.
SetPrimaryPartCFrame might also give weird results, because the PrimaryPart is unlikely to be at the center of the model’s bounding box unless you specifically construct the models that way.
My recommendation is to manually set the pivot point of each model that “sits on the floor” to a point that’s centered horizontally but at floor level vertically. The pivot point editor makes this very easy. That way you don’t need to compute the center point of each model, just the point on the surface of the floor.
E.g. if you have a function to generate a point on the part surface, just do
function placeModelOnPart(model, part)
model:PivotTo(CFrame.new() + randomPointOnPart(part, Enum.NormalId.Top))
end
If you’re using SetPrimaryPartCFrame and you really want to use the approach you described with the bounding boxes, try temporarily setting the PrimaryPart to a model that has the same CFrame as the bounding box. That might fix it.