giants-godot/addons/LineRenderer/LineRenderer.gd

156 lines
4.1 KiB
GDScript

extends ImmediateGeometry
export var points = [Vector3(0,0,0),Vector3(0,5,0)]
export var startThickness = 0.1
export var endThickness = 0.1
export var cornerSmooth = 5
export var capSmooth = 5
export var drawCaps = true
export var drawCorners = true
export var globalCoords = true
export var scaleTexture = true
var camera
var cameraOrigin
func _ready():
pass
func _process(delta):
if points.size() < 2:
return
camera = get_viewport().get_camera()
if camera == null:
return
cameraOrigin = to_local(camera.get_global_transform().origin)
var progressStep = 1.0 / points.size();
var progress = 0;
var thickness = lerp(startThickness, endThickness, progress);
var nextThickness = lerp(startThickness, endThickness, progress + progressStep);
clear()
begin(Mesh.PRIMITIVE_TRIANGLES)
for i in range(points.size() - 1):
var A = points[i]
var B = points[i+1]
if globalCoords:
A = to_local(A)
B = to_local(B)
var AB = B - A;
var orthogonalABStart = (cameraOrigin - ((A + B) / 2)).cross(AB).normalized() * thickness;
var orthogonalABEnd = (cameraOrigin - ((A + B) / 2)).cross(AB).normalized() * nextThickness;
var AtoABStart = A + orthogonalABStart
var AfromABStart = A - orthogonalABStart
var BtoABEnd = B + orthogonalABEnd
var BfromABEnd = B - orthogonalABEnd
if i == 0:
if drawCaps:
cap(A, B, thickness, capSmooth)
if scaleTexture:
var ABLen = AB.length()
var ABFloor = floor(ABLen)
var ABFrac = ABLen - ABFloor
set_uv(Vector2(ABFloor, 0))
add_vertex(AtoABStart)
set_uv(Vector2(-ABFrac, 0))
add_vertex(BtoABEnd)
set_uv(Vector2(ABFloor, 1))
add_vertex(AfromABStart)
set_uv(Vector2(-ABFrac, 0))
add_vertex(BtoABEnd)
set_uv(Vector2(-ABFrac, 1))
add_vertex(BfromABEnd)
set_uv(Vector2(ABFloor, 1))
add_vertex(AfromABStart)
else:
set_uv(Vector2(1, 0))
add_vertex(AtoABStart)
set_uv(Vector2(0, 0))
add_vertex(BtoABEnd)
set_uv(Vector2(1, 1))
add_vertex(AfromABStart)
set_uv(Vector2(0, 0))
add_vertex(BtoABEnd)
set_uv(Vector2(0, 1))
add_vertex(BfromABEnd)
set_uv(Vector2(1, 1))
add_vertex(AfromABStart)
if i == points.size() - 2:
if drawCaps:
cap(B, A, nextThickness, capSmooth)
else:
if drawCorners:
var C = points[i+2]
if globalCoords:
C = to_local(C)
var BC = C - B;
var orthogonalBCStart = (cameraOrigin - ((B + C) / 2)).cross(BC).normalized() * nextThickness;
var angleDot = AB.dot(orthogonalBCStart)
if angleDot > 0:
corner(B, BtoABEnd, B + orthogonalBCStart, cornerSmooth)
else:
corner(B, B - orthogonalBCStart, BfromABEnd, cornerSmooth)
progress += progressStep;
thickness = lerp(startThickness, endThickness, progress);
nextThickness = lerp(startThickness, endThickness, progress + progressStep);
end()
func cap(center, pivot, thickness, smoothing):
var orthogonal = (cameraOrigin - center).cross(center - pivot).normalized() * thickness;
var axis = (center - cameraOrigin).normalized();
var array = []
for i in range(smoothing + 1):
array.append(Vector3(0,0,0))
array[0] = center + orthogonal;
array[smoothing] = center - orthogonal;
for i in range(1, smoothing):
array[i] = center + (orthogonal.rotated(axis, lerp(0, PI, float(i) / smoothing)));
for i in range(1, smoothing + 1):
set_uv(Vector2(0, (i - 1) / smoothing))
add_vertex(array[i - 1]);
set_uv(Vector2(0, (i - 1) / smoothing))
add_vertex(array[i]);
set_uv(Vector2(0.5, 0.5))
add_vertex(center);
func corner(center, start, end, smoothing):
var array = []
for i in range(smoothing + 1):
array.append(Vector3(0,0,0))
array[0] = start;
array[smoothing] = end;
var axis = start.cross(end).normalized()
var offset = start - center
var angle = offset.angle_to(end - center)
for i in range(1, smoothing):
array[i] = center + offset.rotated(axis, lerp(0, angle, float(i) / smoothing));
for i in range(1, smoothing + 1):
set_uv(Vector2(0, (i - 1) / smoothing))
add_vertex(array[i - 1]);
set_uv(Vector2(0, (i - 1) / smoothing))
add_vertex(array[i]);
set_uv(Vector2(0.5, 0.5))
add_vertex(center);