Hey guys! I’m currently making a plugin and i need a bit of help for the math behind scaling a pivot point with a model!

Scaling the model itself:

local function scaleModel(model, scale)
local origin = model.PrimaryPart.Position
for _, part in ipairs(model:GetDescendants()) do
if part:IsA("BasePart") or part:IsA("MeshPart") then
local pos = part.Position
local rotCf = part.CFrame - pos
local fromOriginDir = pos - origin
part.Size *= Vector3.new(scale, scale, scale)
part.CFrame = rotCf + origin + fromOriginDir*scale
end
end
end

After yoinking someone’s code which i will later clean up, i’ve got the actually scaling the model sorted. However, the issue is, the pivot point does not follow with the scale of the model, as it does like when you normally scale with studio’s scale tool. This causes clipping:

As you can see from the video, the scale is the issue since when unscaled it works perfectly. This is due to the pivot position remaining in the same position and not scaling with the model, which i need to figure out how to do!

As you can see, studio’s tool does it perfectly. If anyone has the source code / can link it for me to check out then I’d be very grateful! Thank you for all help in advance!

Can probably move the CFrame with your fromOriginDir approach instead of my scaleToPivot fn. May just need to change position to the model:GetPivot().Position value (which uses model pivot by default or PrimaryPart pivot if there is one). If there is a PrimaryPart, then the part’s PivotOffset will need to be scaled too (otherwise the pivot ends up in wrong place after adjusting placement).

-- this finds new position value for part being scaled toward pivot
local function scaleToPivot(pivotPos, partPos, scaleFactor)
return Vector3.new(
(pivotPos.X + scaleFactor * (partPos.X - pivotPos.X)),
(pivotPos.Y + scaleFactor * (partPos.Y - pivotPos.Y)),
(pivotPos.Z + scaleFactor * (partPos.Z - pivotPos.Z))
)
end
local function scaleModel(model, scale)
local pivotPos = model:GetPivot().Position
for _, part in ipairs(model:GetDescendants()) do
if part:IsA("BasePart") or part:IsA("MeshPart") then
part.Size *= Vector3.new(scale, scale, scale)
part.Position = scaleToPivot(pivotPos, part.Position, scale)
end
end
-- if using PrimaryPart, scale the PivotOffset
if model.PrimaryPart then
model.PrimaryPart.PivotOffset = CFrame.new(model.PrimaryPart.PivotOffset.Position * scale)
end
end

Thank you! This worked perfectly, and replaced my less elegant solution of making a fake pivot point, making that the primary part and using that instead!

Also thank you once again for the effort you put into this post, aswell as also accounting for the use of with or without primary parts! A very well deserved solution

Something to note: This doesn’t adjust PivotOffset for any parts except for the PrimaryPart. You may consider modifying the code so it scales PivotOffset for any other parts inside a model that may have custom pivot placement, for completeness (prob a generalized version of the final if statement moved inside the for loop).

The plugin is looking good in the video! GL with that moving forward!