Scale model to be within the screen's bounds?

I’m trying to make it so that a model is always within a screen’s view.
For example, I have this scenario here:

On smaller screens, like the iPad, the 3D text gets cut off because of the screen’s inferior size!

Is there a way I can detect if the text is being cut off, and then scale it down from there? I know how to programmatically scale models, just need to know how to tell if the 3D text is being cut off in the first place.

Ideally, you would have multiple menu screen configurations for different aspect ratios.

For instance, once the screen gets narrow enough, you could move the title to be on top of the buttons, instead.

But it you really wanted to try and do it automatically I suppose you could.

You could use this function to compute the on-screen bounding box and see if its entirely within the screen:

-- returns true if a part's 2D bounding box on screen is fully within the screen rect's
local function OnScreen(camera, cframe, size)
    -- 1. get all eight points in 3D space for the part

    local pos, front, right, up = cframe.Position, cframe.LookVector, cframe.RightVector, cframe.UpVector
    local hx, hy, hz = size.X / 2, size.Y / 2, size.Z / 2

    local points = {
        pos - front * hz - right * hx - up * hy,
        pos - front * hz - right * hx + up * hy,
        pos - front * hz + right * hx - up * hy,
        pos - front * hz + right * hx + up * hy,
        pos + front * hz - right * hx - up * hy,
        pos + front * hz - right * hx + up * hy,
        pos + front * hz + right * hx - up * hy,
        pos + front * hz + right * hx + up * hy,
    }
    
    -- 2. compute AABB of the part's bounds on screen
    
    local minX, maxX, minY, maxY = math.huge, -math.huge, math.huge, -math.huge
    
    for i = 1, 8 do
        local screenPoint = camera:WorldToViewportPoint(points[i])
        local x, y = screenPoint.X, screenPoint.Y
        
        if screenPoint.Z > 0 then
            if x < minX then minX = x end
            if x > maxX then maxX = x end
            if y < minY then minY = y end
            if y > maxY then maxY = y end
        end
    end
    
    -- 3. AABB is within screen?
    
    local w, h = camera.ViewportSize.X, camera.ViewportSize.Y
    
    return minX >= 0 and maxX <= w and minY >= 0 and maxY <= h
end

Usage like:

if OnScreen(workspace.CurrentCamera, model:GetBoundingBox()) then
  print("on screen completely")
else
  print("off screen a bit")
end
1 Like