I am working on a GUI that will place a line over the horizon depending on the orientation of a part to which your camera’s cframe is set to.
I’ve looked at a few topics about this already but I haven’t really found any useful information.
I am working on a GUI that will place a line over the horizon depending on the orientation of a part to which your camera’s cframe is set to.
I’ve looked at a few topics about this already but I haven’t really found any useful information.
Please be more specific with your problem
Also there’s many different kinds of artifical horizons and you also need to clarify on that too
Simplest way would be to use the Highlight instance to draw an outline around the part, but you can’t really do much customization.
An alternative way would be make your own Highlighting method. Map the 3D corner position of the part into the 2D viewport screen and then connect them with UI Frames. You would have to use a convex hull algorithm to find the outermost points and then draw a polygon around it, which will draw an outline around the original part. Downside is you can really only use this for cubes, rectangular prisms, and wedges since cylinders, spheres, and custom meshes don’t have definitive “corners”.
Attached is an example. It’s very buggy because of how WorldToViewportPoint works on positions outside of the screen.
outlineParts.rbxl (55.6 KB)
--!strict
local p = workspace:WaitForChild('Part')
local sui = script.Parent
local sizeToCorner: {Vector3} = {
Vector3.new(1, 1, 1),
Vector3.new(1, 1, -1),
Vector3.new(-1, 1, 1),
Vector3.new(-1, 1, -1),
Vector3.new(1, -1, 1),
Vector3.new(1, -1, -1),
Vector3.new(-1, -1, 1),
Vector3.new(-1, -1, -1),
}
--this convexHull algorithm was pulled from here: https://love2d.org/forums/viewtopic.php?t=93842
--it was written for vanilla Lua, so Luau optimizations may not apply here!!!
--ccw() was modified to work with roblox Vector2 objects
local ccw = function(a: Vector2, b: Vector2, c: Vector2): boolean
return (b.X - a.X) * (c.Y - a.Y) > (b.Y - a.Y) * (c.X - a.X)
end
local function convexHull(pl: {Vector2}): {Vector2}
if #pl == 0 then return {} end
table.sort(pl, function(left,right)
return left.X < right.X
end)
local h = {}
-- lower hull
for i,pt in pairs(pl) do
while #h >= 2 and not ccw(h[#h-1], h[#h], pt) do
table.remove(h,#h)
end
table.insert(h,pt)
end
-- upper hull
local t = #h + 1
for i=#pl, 1, -1 do
local pt = pl[i]
while #h >= t and not ccw(h[#h-1], h[#h], pt) do
table.remove(h,#h)
end
table.insert(h,pt)
end
table.remove(h,#h)
return h
end
local function drawHorizon(part: Part, outline: {Frame}): {Frame}
local cam = workspace.CurrentCamera
local pos3D: CFrame = part.CFrame
local size3DHalf: Vector3 = part.Size*.5
local corners2D: {Vector2} = table.create(8)
for _, v in sizeToCorner do
local pos2D: Vector3 = cam:WorldToViewportPoint((pos3D*CFrame.new(v*size3DHalf)).Position)
table.insert(corners2D, Vector2.new(pos2D.X, pos2D.Y))
end
for _, f in outline do
f.Visible = false
end
local hull: {Vector2} = convexHull(corners2D)
for i, v in hull do
local to: Vector2 = hull[i+1] or hull[1]
local exists: Frame? = outline[i]
local f: Frame
if exists then
f = exists
else
f = Instance.new('Frame')
f.AnchorPoint = Vector2.one*.5
f.Parent = sui
outline[i] = f
end
local disp: Vector2 = to - v
local midpoint: Vector2 = to:Lerp(v, .5)
f.Rotation = math.deg(math.atan2(disp.Y, disp.X))
f.Position = UDim2.fromOffset(midpoint.X, midpoint.Y)
f.Size = UDim2.fromOffset(disp.Magnitude, 4)
f.Visible = true
end
return outline
end
local hull: {Frame} = {}
game:GetService('RunService').RenderStepped:Connect(function()
hull = drawHorizon(p, hull)
end)
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.