I want to know how to make something like the video as follow:
I do know that they use SurfaceGui and Rotations in 3D Space, however, how do I ensure that all screen types and devices are able to see the full GUI?
I want to know how to make something like the video as follow:
I do know that they use SurfaceGui and Rotations in 3D Space, however, how do I ensure that all screen types and devices are able to see the full GUI?
You need to compute the width / height of the frustum plane for either (a) a given desired size or (b) a desired distance, e.g.
-- i.e. get the size of the frustum plane given the radius of an object
-- that you're trying to encapsulate
--
-- can be used to approximate dist required to fit some arbitrary AABB
-- inside of a frustum where radius = math.max(AABB.Size.X, AABB.Size.Y)
--
local function getFrustumRectForRadius(transform, screenSize, fieldOfView, radius)
local aspectRatio = screenSize.X / screenSize.Y
local hfov = math.rad(fieldOfView * 0.5)
local distance = radius / math.sin(hfov)
local htanfov = math.tan(hfov)
local height = 2 * htanfov * distance
local width = height * aspectRatio
local origin = transform * CFrame.new(0, 0, -distance)
local normal = transform.ZVector
return {
width = width,
height = height,
normal = normal,
distance = -origin.Position:Dot(normal),
origin = CFrame.fromMatrix(origin.Position, -origin.XVector, origin.YVector, -normal),
}
end
-- i.e. get the size of the frustum plane at a given distance
local function getFrustumRectAtDistance(transform, screenSize, fieldOfView, distance)
local aspectRatio = screenSize.X / screenSize.Y
local hfov = math.rad(fieldOfView * 0.5)
local htanfov = math.tan(hfov)
local height = 2 * htanfov * distance
local width = height * aspectRatio
local origin = transform * CFrame.new(0, 0, -distance)
local normal = transform.ZVector
return {
width = width,
height = height,
normal = normal,
distance = -origin.Position:Dot(normal),
origin = CFrame.fromMatrix(origin.Position, -origin.XVector, origin.YVector, -normal),
}
end
Learn more about the viewing/camera frustum here, but an example usage would be:
local camera = game.Workspace.CurrentCamera
local part = Instance.new('Part')
part.Anchored = true
part.Transparency = 1
part.Parent = workspace
local surfaceGui = Instance.new('SurfaceGui')
surfaceGui.Face = Enum.NormalId.Front
surfaceGui.Adornee = part
surfaceGui.AlwaysOnTop = true
surfaceGui.Parent = part
local label = Instance.new('TextLabel')
label.Size = UDim2.fromScale(1, 1)
label.Text = 'Hello, world!'
label.TextScaled = true
label.BackgroundTransparency = 1
label.Parent = surfaceGui
local connection
connection = RunService.RenderStepped:Connect(function (dt)
local now = os.clock()
local spin = CFrame.Angles(math.cos(now)*0.25, math.sin(now)*0.5, 0) -- just to demo it moving around
-- get our camera properties
local transform = camera.CFrame
local fieldOfView = camera.FieldOfView
local viewportSize = camera.ViewportSize
-- compute the frustum plane rect or you could of course use the distance
-- i.e. ...
-- local rect = getFrustumRectAtDistance(transform, viewportSize, fieldOfView, 10)
--
-- where 10 = some arbitrary distance
--
local rect = getFrustumRectForRadius(transform, viewportSize, fieldOfView, 1) -- where 1 = some arbitrary size you're trying to fit
-- put the surface gui part into position
part.CFrame = rect.origin * spin
part.Size = Vector3.new(rect.width, rect.height, 0.01)
end)
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.