Create 3D lines

Godot Version

4.3

Question

I want to create a 3D line with adjustable thickness. This is the code I generated using AI, and it works, but it is always perpendicular to the y-axis. I don’t know how to modify it because I am not particularly familiar with 3D operations

extends Node3D
#extends Spatial
@onready var mesh_instance_3d: MeshInstance3D = $MeshInstance3D
@onready var camera_3d: Camera3D = $Camera3D

#var i_mesh:ImmediateMesh
var mesh:Mesh

func _ready() -> void:
	#draw_debug_mesh = ImmediateMesh.new()
	#i_mesh = mesh_instance_3d.mesh

	
	var from = Vector3(0, 0, 0)
	var to = Vector3(10, 12, 10)
	var radius = 0.05
	var segments = 8
	
	var meshs = create_thick_line0(from, to, radius, segments)

	mesh_instance_3d.mesh = meshs[0]
	#mesh_instance_3d.transform = meshs[1]
	




func create_thick_line0(from: Vector3, to: Vector3, radius: float, segments: int):
	var direction = to - from
	var length = direction.length()
	direction = direction.normalized()

	## Create a basis (rotation) to align the cylinder along the direction
	#var B = Basis()
	var B1 = Basis.looking_at(direction, Vector3.UP)

	var T = Transform3D()
	T.basis = B1
	T.origin = from + direction * length * 0.5  # Move to midpoint

	# Build cylinder mesh using SurfaceTool
	var st = SurfaceTool.new()
	st.begin(Mesh.PRIMITIVE_TRIANGLES)
	st.set_smooth_group(1)

	for i in range(segments):
		var angle1 = TAU * i / segments
		var angle2 = TAU * (i + 1) / segments

		var p1 = Vector3(radius * cos(angle1), -length / 2, radius * sin(angle1))
		var p2 = Vector3(radius * cos(angle2), -length / 2, radius * sin(angle2))
		var p3 = Vector3(radius * cos(angle1), length / 2, radius * sin(angle1))
		var p4 = Vector3(radius * cos(angle2), length / 2, radius * sin(angle2))

		# Side triangles (two per segment)
		st.set_normal((p1 - p2).cross(p3 - p1).normalized())
		st.add_vertex(p1)
		st.add_vertex(p2)
		st.add_vertex(p3)

		st.set_normal((p2 - p4).cross(p3 - p2).normalized())
		st.add_vertex(p2)
		st.add_vertex(p4)
		st.add_vertex(p3)

	st.index()
	mesh = st.commit()
	
	#mesh = mesh.duplicate()
	###mesh.surface_set_material(0, SpatialMaterial.new())
##
	### Apply transform to orient the cylinder
	#var xform = Transform3D()
	#xform.basis = basis
	#xform.origin = from + direction * length * 0.5
	#mesh.transform=xform
	return [mesh,T]

This seems remarkably over-complicated. A line is defined by two points. So you need two points, each defined by a Vector3. Then a thickness for the line.

But all that SurfaceTool stuff is overkill and not really performative. It also clearly doesn’t work. This is the problem with LLMs. They lie. They are not good at math. They are just reconstructing things that other people wrote. They do not actually know anything.

You have two options:

  1. Continue vibe coding. Just feed it back into the LLM, tell it your problem and see what it comes up with. Vibe coding is about learning how to communicate with an LLM what you need until you learn how to get it. It is not unlike being a project manager talking to human developers.
  2. Learn how to do it yourself. It may be a learning curve, but understanding how it works is going to help you out when you have a problem going forward. If you want to take this approach, read on.

This is one of those times where computer programming requires some math. I recommend you read this part of the docs.

Then, all you need to do is get the distance between your two points, add a MeshInstance3D to your scene, and a CylinderMesh and make it as long as your two points, as thick as you want, move it to your first point, and rotate it towards your second.

thank you for you help

2 Likes

Upon further consideration, you will need to move the origin to one of the cylinder’s faces to make the above work.