LINE_CORNER_NONE = 0
LINE_CORNER_MITER = 1
LINE_CORNER_ROUND = 2
do
local plotting = false
local plots, quads = {}, {}
local plot_count, quad_count = 0, 0
local thickness = 0
local min_angle = 0
local corner_type = 0
function draw.StartLine(_thickness, _min_angle, _corner_type)
assert(not plotting, "how come your mom lets you have 2 lines")
plotting = true
plot_count, quad_count = 0, 0
thickness = (tonumber(_thickness) or 10) / 2
min_angle = math.pi - math.rad(tonumber(_min_angle) or 20)
corner_type = tonumber(_corner_type) or 0
end
function draw.AddLinePoint(x, y)
assert(plotting, "better start a line boy")
if not y then
y = x.y
x = x.x
end
plot_count = plot_count + 1
plots[plot_count] = Vector(x, y)
end
function draw.EndLine()
assert(plotting, "cut me point 2 g fam")
plotting = false
assert(plot_count > 1, "A minimum of 2 points are required to draw a line.")
for i = 1, plot_count - 1 do
local a, b = plots[i], plots[i + 1]
local ab = b - a
ab:Normalize()
local ab_right = Vector(-ab.y, ab.x)
quad_count = quad_count + 1
quads[quad_count] = {
a + ab_right * thickness,
a - ab_right * thickness,
b - ab_right * thickness,
b + ab_right * thickness,
}
end
if plot_count >= 3 then
for i = 2, plot_count - 1 do
local a, b, c = unpack(plots, i - 1, i + 1)
local left_quad = quads[i - 1]
local right_quad = quads[i]
local ab, bc do
ab = b - a
bc = c - b
ab:Normalize()
bc:Normalize()
end
local angle = math.acos(ab:Dot(bc))
local bc_right = Vector(-bc.y, bc.x)
local is_left = false
if ab:Dot(bc_right) > 0 then
is_left = true
end
if corner_type == LINE_CORNER_MITER then
local height = thickness / math.cos(angle / 2)
local joint_direction = bc - ab
joint_direction:Normalize()
if is_left then
joint_direction = -joint_direction
end
if angle <= min_angle then
left_quad[3] = b - joint_direction * height
left_quad[4] = b + joint_direction * height
right_quad[1] = left_quad[4]
right_quad[2] = left_quad[3]
end
elseif corner_type == LINE_CORNER_ROUND then
local bd = (is_left and left_quad[4] or right_quad[2]) - b
bd:Normalize()
local step = 1 / thickness
local theta = (0.5 * math.pi - math.atan2(bd.y, bd.x)) % math.tau
mesh.Begin(MATERIAL_POLYGON, 1)
for a = theta, theta + angle + step, step do
local sin, cos = math.sin(a), math.cos(a)
local pos = b + Vector(sin, cos) * thickness
mesh.Position(pos)
mesh.AdvanceVertex()
end
mesh.Position(b)
mesh.AdvanceVertex()
mesh.End()
end
end
end
mesh.Begin(MATERIAL_QUADS, quad_count)
for i, quad in ipairs(quads) do
mesh.Quad(unpack(quad))
end
mesh.End()
end
end
--[[
EXAMPLE
]]--
local plots = {}
for i = 1, 20 do
if #plots == 0 then
table.insert(plots, Vector(ScrW() / 2, ScrH() / 2))
else
local rand_direction = Vector(math.Rand(-1, 1), math.Rand(-1, 1))
rand_direction:Normalize()
local last_plot = plots[#plots]
table.insert(plots, last_plot + rand_direction * math.random(100, 400))
end
end
hook.Add("PostRender", "", function()
cam.Start2D()
surface.SetDrawColor(255, 255 ,255)
render.SetMaterial(Material("vgui/white"))
draw.StartLine(50, 15, math.floor(CurTime() % 3))
for i, plot in ipairs(plots) do
draw.AddLinePoint(plot)
end
draw.EndLine()
cam.End2D()
end)
Comments