CSGPolygon3D appears to not add points

Godot Version

4.4

Question

I have a script which is supposed to generate a path roughly based on a bezier curve using CSGPolygon3D. I did have it working at one point, but now it won’t which is quite confusing. The two relevant scripts are below, along with the debugger error messages. All help appreciated :slight_smile:

track_generator.gd

extends Node3D
@onready var curve = $CSGPolygon3D/Path3D.curve
var nextPoint : Vector3
signal send_Vector2(pos:Vector2)
var iterations = 9

func _ready():
	create_curve(Vector2(0,0), Vector2(50,50), Vector2(0,40))
	create_curve(Vector2(50,50), Vector2(100,0), Vector2(100,40))

func create_curve(start:Vector2, end:Vector2, control:Vector2):
	send_Vector2.emit(start)
	curve.add_point(nextPoint)
	var vec2s = PackedVector2Array()
	for i in 9:
		var t = i+1
		vec2s.append(calc_points(start, end, control, t*0.1))
	for j in 9:
		send_Vector2.emit(vec2s[j])
		curve.add_point(nextPoint)
	send_Vector2.emit(end)
	curve.add_point(nextPoint)

func receive_vector_3(pos: Vector3) -> void:
	nextPoint = pos
	
func calc_points(start : Vector2, end : Vector2, control : Vector2, t : float):
	var a = start.lerp(control, t)
	var b = control.lerp(end, t)
	var c = a.lerp(b, t)
	return c.round()

terrain.gd

extends Node3D

@onready var mesh_instance = $StaticBody3D/MeshInstance3D

@export var width = 256
@export var depth = 256
@export var height = 30
var arr = PackedVector3Array()
var point : Vector3
signal return_Vector3(pos:Vector3)

func _ready():
	var fast_noise_lite = FastNoiseLite.new();
	fast_noise_lite.seed = randi()
	# Set noise parameters
	fast_noise_lite.noise_type = FastNoiseLite.TYPE_PERLIN
	fast_noise_lite.frequency = 0.0025
	
	# Create a PlaneMesh and generate terrain
	var plane_mesh = PlaneMesh.new()
	plane_mesh.size = Vector2(width, depth)
	plane_mesh.subdivide_depth = width - 1
	plane_mesh.subdivide_width = depth - 1

	var array_mesh = ArrayMesh.new()
	array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, plane_mesh.surface_get_arrays(0))

	# Create SurfaceTool
	var surface_tool = SurfaceTool.new()
	surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)

	# Generate vertices based on noise
	for z in range(depth):
		for x in range(width):
			var vertex_position = Vector3(x - width/2, 0, z - depth/2)
			vertex_position.y = fast_noise_lite.get_noise_2d(x, z) * height
			surface_tool.add_vertex(vertex_position)

	# Connect the vertices to form triangles
	for z in range(depth - 1):
		for x in range(width - 1):
			var idx = z * width + x
			surface_tool.add_index(idx)
			surface_tool.add_index(idx + 1)
			surface_tool.add_index(idx + width)
			
			surface_tool.add_index(idx + 1)
			surface_tool.add_index(idx + width + 1)
			surface_tool.add_index(idx + width)
	
	# Commit the mesh to the MeshInstance3D
	surface_tool.generate_normals()
	var generated_mesh = surface_tool.commit()
	mesh_instance.mesh = generated_mesh

	# Color
	var material = StandardMaterial3D.new()
	material.albedo_color = Color(0.4, 0.8, 0.2)  # A greenish color for grass, for example
	mesh_instance.material_override = material
	mesh_instance.create_trimesh_collision()
	
	#testing
	var mdt = MeshDataTool.new()
	mdt.create_from_surface(mesh_instance.mesh, 0)
	for i in mdt.get_vertex_count():
		arr.append(mdt.get_vertex(i))

func get_vector_2(pos: Vector2) -> void:
	for coord in arr:
		if coord.x == pos.x and coord.z == pos.y:
			point = coord
			point.y = point.y + 0.1
	return_Vector3.emit(point)

ERRORS:
E 0:00:01:415 looking_at: The target vector can’t be zero.
<C++ Error> Condition “p_target.is_zero_approx()” is true. Returning: Basis()
<C++ Source> core/math/basis.cpp:1049 @ looking_at()
E 0:00:01:415 _find_interval: Zero length interval.
<C++ Error> Method/function failed. Returning: interval
<C++ Source> scene/resources/curve.cpp:1874 @ _find_interval()
E 0:00:01:415 _find_interval: Zero length interval.
<C++ Error> Method/function failed. Returning: interval
<C++ Source> scene/resources/curve.cpp:1874 @ _find_interval()
E 0:00:01:415 looking_at: The transform’s origin and target can’t be equal.
<C++ Error> Condition “origin.is_equal_approx(p_target)” is true. Returning: Transform3D()
<C++ Source> core/math/transform_3d.cpp:81 @ looking_at()
E 0:00:01:416 _find_interval: Zero length interval.
<C++ Error> Method/function failed. Returning: interval
<C++ Source> scene/resources/curve.cpp:1874 @ _find_interval()
E 0:00:01:416 _find_interval: Zero length interval.
<C++ Error> Method/function failed. Returning: interval
<C++ Source> scene/resources/curve.cpp:1874 @ _find_interval()
E 0:00:01:416 looking_at: The target vector can’t be zero.
<C++ Error> Condition “p_target.is_zero_approx()” is true. Returning: Basis()
<C++ Source> core/math/basis.cpp:1049 @ looking_at()
E 0:00:01:416 looking_at: The target vector can’t be zero.
<C++ Error> Condition “p_target.is_zero_approx()” is true. Returning: Basis()
<C++ Source> core/math/basis.cpp:1049 @ looking_at()
E 0:00:01:416 _find_interval: Zero length interval.
<C++ Error> Method/function failed. Returning: interval
<C++ Source> scene/resources/curve.cpp:1874 @ _find_interval()
E 0:00:01:416 looking_at: The transform’s origin and target can’t be equal.
<C++ Error> Condition “origin.is_equal_approx(p_target)” is true. Returning: Transform3D()
<C++ Source> core/math/transform_3d.cpp:81 @ looking_at()

Can you provide a bit more: structure, who’s calling who?

Also you have a couple of places where ints and floats mix, which can be a disaster in disguise sometimes.

1 Like

@Brawlawnzo OK, the structure is as follows:
main.tscn
-Terrain
-Track Generator
-Other Environment Nodes, Camera Nodes, and Meshes Unrelated

Track Generator.tscn
-CSGPolygon3D
–Path3D

terrain.tscn
-StaticBody3D
–CollisionShape3D
–MeshInstance3D

Just to clarify, there is a single node3d as the parent in all of the tscn files, named identically to the file name.

All of the code from above is being called on ready, so the only manual calling is the signals. As for floats and ints, I do know what I am doing in that regard, and made sure it’s not an issue :wink:

Hm, that didn’t help much, still can’t seem to recreate your error.

I noticed, however, that in the create_curve(...) function you send the signal, but don’t stop execution to wait for the answering one (assuming you do need the returning value) - this could lead to unexpected behaviour. You might want to revision the setup here, because one shouldn’t need coroutines for such a simple and frequent exchange of values.

1 Like

Unfortunately, using signals is the only way I know how to transfer variables between scripts. I tried global variables but I kept getting errors that way. I will try to learn that, as well as how to wait between calls, and get back to you. Thanks for the advice.

There was a question here recently about linkage - maybe it will give you a couple of pointers:

1 Like

Thank you so much for your help @Brawlawnzo ! What I was able to do is export the terrain variable to the track generator script and get the terrain array directly in the track generator, avoiding the signals altogether. Now, instead of nothing, I get this nice curve.


For anybody with issues like this in the future, here are the updated scripts:
track_generator.gd

extends Node3D
@onready var curve = $CSGPolygon3D/Path3D.curve
@export var terrain : Node3D
var nextPoint : Vector3
var iterations = 9

func _ready():
	create_curve(Vector2(0,0), Vector2(50,50), Vector2(0,40))
	create_curve(Vector2(50,50), Vector2(100,0), Vector2(100,40))

func create_curve(start:Vector2, end:Vector2, control:Vector2):
	curve.add_point(get_vector3(start))
	var vec2s = PackedVector2Array()
	for i in 9:
		var t = i+1
		vec2s.append(calc_points(start, end, control, t*0.1))
	for j in 9:
		curve.add_point(get_vector3(vec2s[j]))
	curve.add_point(get_vector3(end))
		

func get_vector3(pos:Vector2):
	for coord in terrain.arr:
		if coord.x == pos.x and coord.z == pos.y:
			var point = coord
			point.y = point.y + 0.1
			return point
	
func calc_points(start : Vector2, end : Vector2, control : Vector2, t : float):
	var a = start.lerp(control, t)
	var b = control.lerp(end, t)
	var c = a.lerp(b, t)
	return c.round()

terrain.gd

extends Node3D

@onready var mesh_instance = $StaticBody3D/MeshInstance3D

@export var width = 256
@export var depth = 256
@export var height = 30
var arr = PackedVector3Array()
var point : Vector3

func _ready():
	var fast_noise_lite = FastNoiseLite.new();
	fast_noise_lite.seed = randi()
	# Set noise parameters
	fast_noise_lite.noise_type = FastNoiseLite.TYPE_PERLIN
	fast_noise_lite.frequency = 0.0025
	
	# Create a PlaneMesh and generate terrain
	var plane_mesh = PlaneMesh.new()
	plane_mesh.size = Vector2(width, depth)
	plane_mesh.subdivide_depth = width - 1
	plane_mesh.subdivide_width = depth - 1

	var array_mesh = ArrayMesh.new()
	array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, plane_mesh.surface_get_arrays(0))

	# Create SurfaceTool
	var surface_tool = SurfaceTool.new()
	surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)

	# Generate vertices based on noise
	for z in range(depth):
		for x in range(width):
			var vertex_position = Vector3(x - width/2, 0, z - depth/2)
			vertex_position.y = fast_noise_lite.get_noise_2d(x, z) * height
			surface_tool.add_vertex(vertex_position)

	# Connect the vertices to form triangles
	for z in range(depth - 1):
		for x in range(width - 1):
			var idx = z * width + x
			surface_tool.add_index(idx)
			surface_tool.add_index(idx + 1)
			surface_tool.add_index(idx + width)
			
			surface_tool.add_index(idx + 1)
			surface_tool.add_index(idx + width + 1)
			surface_tool.add_index(idx + width)
	
	# Commit the mesh to the MeshInstance3D
	surface_tool.generate_normals()
	var generated_mesh = surface_tool.commit()
	mesh_instance.mesh = generated_mesh

	# Color
	var material = StandardMaterial3D.new()
	material.albedo_color = Color(0.4, 0.8, 0.2)  # A greenish color for grass, for example
	mesh_instance.material_override = material
	mesh_instance.create_trimesh_collision()
	
	#testing
	var mdt = MeshDataTool.new()
	mdt.create_from_surface(mesh_instance.mesh, 0)
	for i in mdt.get_vertex_count():
		arr.append(mdt.get_vertex(i))

Thanks again for staying patient with me and guiding me in the right direction.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.