I’m trying to make an object placement system that allows for objects to be placed on any surface (floor, wall, ceiling) This is done by finding the surface normal and adding an offset based on object size.
The problem is that I’m always adding the offset to the Y position.
The object’s placement is correct when it’s on the floor because its adding the Y size. If it were on the ceiling, it’d have to subtract the Y size. If it were on a wall it’d have to either add/subtract the X or Y size. checking for the normals (if normal == X then) seems like a lazy and long workaround, so I’d like to know what would be a more mathematical solution?
Here’s how I’m getting the position.
function Placement:CalculatePlace(position, target, normal)
if position then
local yOffset = (self.Object:GetModelSize() / 2).Y
-- yOffset is only added and only to position.Y
local offsetPos = Vector3.new(position.X, position.Y + yOffset, position.Z)
return CFrame.new(offsetPos, offsetPos + normal) * CFrame.Angles(math.rad(-90), 0, 0)
end
end
local UP = Vector3.new(0,1,0)
function Placement:CalculatePlace(position, target, normal)
if position then
local theta = math.acos(UP:Dot(normal)) -- get the angle for rotation
local axis = UP:Cross(normal).unit
return CFrame.new(position + normal + self.Object:GetModelSize().Y / 2) * CFrame.fromAxisAngle(axis, theta)
end
end
Perhaps something like this would work. You could just get the angle needed to rotate, and the axis to rotate it around for the rotation. And use the normal plus and position and half the size of the object on the y for the position of it.
function Placement:CalculatePlace(position, target, normal)
if position then
local yOffset = (self.Object:GetModelSize() / 2).Y
-- yOffset is only added and only to position.Y
local cfr = CFrame.new(position.X,position.Y,position.Z)
local offsetPos = cfr + cfr.LookVector*yOffset
return CFrame.new(offsetPos, offsetPos + normal) * CFrame.Angles(math.rad(-90), 0, 0)
end
end