EDIT: This reply is an old response. Checkout this post for a module that does a better calculation
ViewportFrame Model Fitter
Okay, so I think I have a decent enough solution going here.
So things you have to take into account:
-
You want to be rotating around the center of the model, not necessarily the primary part. As such you should use the
:GetBoundingBox()
method. -
As you have noted, your best bet to fit something to the camera is to use the field of view and find the distance based on that.
I did this by finding the max extent value and then treating that as the vertical limit. Then I offset the camera by the half diagonal length created by the other two extent components.
local modelCF, modelSize = model:GetBoundingBox()
local rotInv = (modelCF - modelCF.p):inverse()
modelCF = modelCF * rotInv
modelSize = rotInv * modelSize
modelSize = Vector3.new(math.abs(modelSize.x), math.abs(modelSize.y), math.abs(modelSize.z))
local diagonal = 0
local maxExtent = math.max(modelSize.x, modelSize.y, modelSize.z)
local tan = math.tan(math.rad(camera.FieldOfView/2))
if (maxExtent == modelSize.x) then
diagonal = math.sqrt(modelSize.y*modelSize.y + modelSize.z*modelSize.z)/2
elseif (maxExtent == modelSize.y) then
diagonal = math.sqrt(modelSize.x*modelSize.x + modelSize.z*modelSize.z)/2
else
diagonal = math.sqrt(modelSize.x*modelSize.x + modelSize.y*modelSize.y)/2
end
local minDist = (maxExtent/2)/tan + diagonal
ViewFrameFit.rbxl (497.3 KB)
Note: One caveat is that because of how we do the distance FOV calculation we are only accounting for the vertical. This means if you have a frame with an aspect ration that favours the vertical then the whole model may not be shown.
Hope that helps!