I made a post about this issue earlier, and everyone seems to have missed the point. I think maybe I just didn’t explain it well. I have a part, I know where I want the part’s corners to be, how do I CFrame the part to get it to match with the desired corners? Like this:
You could group all the points and then use :GetBoundingBox(). This will give you a CFrame of the center of the model. This will not allow for any extra parts inside the model you are trying to get the center from.
Example Code
local CenterPart = script.Parent
local CenterCFrame = script.Parent.Points:GetBoundingBox()
CenterPart.CFrame = CenterCFrame
I found a way. You can get the center by grabbing average position. I think this should also work for the orientation.
CenterPoint.Position = (script.Parent.Point1.Position + script.Parent.Point2.Position + script.Parent.Point3.Position + script.Parent.Point4.Position) / 4
--Change every position to your vector3 values.
See the line segment labeled CA in the diagram? The center of that will be the Position of the part.
… AB in the diagram? That’s going to be the RightVector of the CFrame.
… BC in the diagram? That’s going to be the UpVector of the CFrame.
Code:
local a, b, c = --< ... three points (Vector3s) in a clockwise direction, assuming that you're looking directly at the front of the part >
local position = (c + a)/2 -- the midpoint of segment CA, which will be the position of the part.
local right = (b - a).Unit -- ... the RightVector of the CFrame you want.
local up = (c - b).Unit --- ... the UpVector of the CFrame you want.
local cf = CFrame.fromMatrix(position, right, up) -- Tada! This should be the CFrame of the part.
(note: I may have swapped right and up. So if the LookVector of the CFrame isn’t facing in the direction you want, just swap the two. Also play around with different corners if the up and right aren’t facing the correct direction. This should give you a rough idea on how to approach this problem.)
Ah I see .fromMatrix that right there is what I really needed. I was already doing a method similar to that, but it had some inaccuracies, so that operation definitely helps.
I know, but in this example, (b-c).Unit represents the lookvector of the final cframe, since if it were the upvector, the part would result 90 degrees off
Well, it really depends. You didn’t explain which dimension of the part is flat. I was assuming that the Size.Z of the part was 0, in which case I would be right.
If instead it was Y that would be flat (so that BC would be the LookVector instead of the UpVector) then you can use Vector3:Cross to calculate the UpVector that you want (look up what a vector cross product is if you want, it’s generally useful if you want a vector that is perpendicular to two vectors)
local right = (b - a).Unit -- ... the RightVector of the CFrame you want.
local look = (c - b).Unit --- ... the LookVector of the CFrame you want.
local uo = right:Cross(look) -- the UpVector of the CFrame you want. I may have swapped these two, so again if it doesn't face the right direction, just switch the two.
local cf = CFrame.fromMatrix(position, right, up) -- Tada! This should be the CFrame of the part.
local function toPlane(verts)
local centre = Vector3.new() * 0
for _, vert in ipairs(verts) do
centre = centre + vert
end
centre = centre / #verts
local function toAngle(p, c)
return math.atan2(p.z - c.z, p.x - c.x)
end
local function byPolarAngle(va, vb, centre)
return toAngle(va, centre) > toAngle(vb, centre)
end
table.sort(verts, function (a, b)
return byPolarAngle(a, b, centre)
end)
local front = (verts[1] - verts[4]).unit
local right = (verts[3] - verts[4]).unit
local up = right:Cross(front)
return {
cf = CFrame.new(
centre.x, centre.y, centre.z,
right.x, up.x, -front.x,
right.y, up.y, -front.y,
right.z, up.z, -front.z
);
sz = Vector3.new(
(verts[1] - verts[4]).magnitude,
0,
(verts[3] - verts[4]).magnitude
);
}
end
-- e.g.
local vertices = { }
for i, v in ipairs(script.Parent:GetChildren()) do
if v:IsA 'BasePart' then
vertices[#vertices + 1] = v.Position
end
end
local info = toPlane(vertices)
local plane = Instance.new 'Part'
plane.Anchored = true
plane.Transparency = 0.5
plane.Size = info.sz
plane.CFrame = info.cf
plane.Parent = script