Adding Centre to Circle

Godot Version

4.6 Stable

Question

I’m trying to add origin to circle , so then I could create indices to render it triangles ( sliced pizza )

but something I don’t understand is how can I add this start_vector / point to PackedVector3Array() after loop , as debugger is complain no matter what I tried with push_back() append()

here is error

E 0:00:00:245   circle_mesh_array.gd:23 @ _ready(): Condition "array.size() != p_vertex_array_len" is true. Returning: ERR_INVALID_PARAMETER
  <C++ Source>  servers/rendering/rendering_server.cpp:612 @ _surface_set_data()
  <Stack Trace> circle_mesh_array.gd:23 @ _ready()

E 0:00:00:245   circle_mesh_array.gd:23 @ _ready(): Invalid array format for surface.
  <C++ Error>   Condition "err != OK" is true. Returning: ERR_INVALID_DATA
  <C++ Source>  servers/rendering/rendering_server.cpp:1310 @ mesh_create_surface_data_from_arrays()
  <Stack Trace> circle_mesh_array.gd:23 @ _ready()

E 0:00:00:245   circle_mesh_array.gd:23 @ _ready(): Condition "err != OK" is true.
  <C++ Source>  scene/resources/mesh.cpp:1825 @ add_surface_from_arrays()
  <Stack Trace> circle_mesh_array.gd:23 @ _ready()

Does this mean the .resize() need to be executed after loop again to resize or something else ?

current code

extends MeshInstance3D

func _ready() -> void:
	var surface_array = []
	surface_array.resize(Mesh.ARRAY_MAX)
	var my_vertices = PackedVector3Array()
	var my_uvs = PackedVector2Array()
	var my_normals = PackedVector3Array()
	
	var point := Vector3.RIGHT
	var steps := 32
	var angle_step := TAU / steps
	my_vertices.append(point)
	for i in steps:
		my_vertices.append(point)
		point = point.rotated(Vector3.UP, angle_step)
		my_uvs.push_back(Vector2(0,0))
		my_normals.push_back(Vector3.UP)
	
	surface_array[Mesh.ARRAY_VERTEX] = my_vertices
	surface_array[Mesh.ARRAY_TEX_UV] = my_uvs
	surface_array[Mesh.ARRAY_NORMAL] = my_normals
	  
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_POINTS, surface_array)

I tried before and after loop same error.

You need to append an uv and a normal as well. The number of all vertex attributes must match.

If you’re just drawing lines though, you can completely disregards uv and normal arrays, and only use the vertex array

Btw append() and push_back() do the same thing. So use either one or the other throughout the code for the sake of stylistic consistency.

Tried that
nothing on screen, and Debugger going crazy

E 0:00:00:249   draw_list_draw: Vertex amount (33) must be a multiple of the amount of vertices required by the render primitive (2).
  <C++ Error>   Condition "(to_draw % draw_list.validation.pipeline_primitive_divisor) != 0" is true.
  <C++ Source>  servers/rendering/rendering_device.cpp:5145 @ draw_list_draw()

extends MeshInstance3D

func _ready() -> void:
	var surface_array = []
	surface_array.resize(Mesh.ARRAY_MAX)
	var my_vertices = PackedVector3Array()

	var point := Vector3.RIGHT
	var steps := 32
	var angle_step := TAU / steps
	
	for i in steps:
		my_vertices.append(point)
		point = point.rotated(Vector3.UP, angle_step)
	my_vertices.append(point)
	surface_array[Mesh.ARRAY_VERTEX] = my_vertices
	  
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_LINES, surface_array)

ok 31 + 1 :slight_smile: but for POINTS its still showing nothing

For start, use the point primitve, not line. Line requires a pair of vertices for each line, so the total number of vertices must be even.

for points nothing is rendered now .

but also if I want to make for example indices for triangles pizza does it mean I need to add origin twice to keep count happy to be able make triangles/ lines ?

Show the code.

For triangle primitive, you’ll need 3 vertices per triangle. So the total number must be a multiple of 3. Otherwise the engine will complain.

1 Like

for points code

extends MeshInstance3D

func _ready() -> void:
	var surface_array = []
	surface_array.resize(Mesh.ARRAY_MAX)
	var my_vertices = PackedVector3Array()

	var point := Vector3.RIGHT
	var steps := 32
	var angle_step := TAU / steps
	
	for i in steps:
		my_vertices.append(point)
		point = point.rotated(Vector3.UP, angle_step)
	my_vertices.append(point)
	surface_array[Mesh.ARRAY_VERTEX] = my_vertices
	  
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_POINTS, surface_array)

nothing on screen

Go back to last working version.

right so uv and normals to be added right ?

extends MeshInstance3D

func _ready() -> void:
	var surface_array = []
	surface_array.resize(Mesh.ARRAY_MAX)
	var my_vertices = PackedVector3Array()
	var my_uvs = PackedVector2Array()
	var my_normals = PackedVector3Array()
	
	var point := Vector3.RIGHT
	var steps := 32
	var angle_step := TAU / steps
	my_vertices.append(point) 
	my_uvs.append(Vector2(0,0))
	my_normals.append(Vector3.UP)
	for i in steps:
		my_vertices.append(point)
		point = point.rotated(Vector3.UP, angle_step)
		my_uvs.append(Vector2(0,0))
		my_normals.append(Vector3.UP)
	
	surface_array[Mesh.ARRAY_VERTEX] = my_vertices
	surface_array[Mesh.ARRAY_TEX_UV] = my_uvs
	surface_array[Mesh.ARRAY_NORMAL] = my_normals
	  
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_POINTS, surface_array)

but just find out the point is not actually origin , I will need to take some opposite 2 vertices and find middle

The center is (0,0)

1 Like

could I get it by some formula from my_vertices take array index 0 and steps/2 and minus those two Vector3 values - , instead of hardcode Vector3(0,0,0) ?

print(my_vertices.get(0), my_vertices.get(steps/2))
(1.0, 0.0, 0.0)(-0.999999, 0.0, 0.0)

Why? The way you calculate your circle points imply that the center is at 0,0. The center is a given, the points are relative to the center, not the other way around.

Always start with defining the center. If you want center at some position other than zero, you’ll need to add the center position to the point positions.

Although having a center other than zero is typically not needed.

Starting point can be anything you like. Whatever you use it will do full TAU rotation around the origin.

1 Like

in case I change variable

var point := Vector3.RIGHT

to something else

current code

extends MeshInstance3D

func _ready() -> void:
	var surface_array = []
	surface_array.resize(Mesh.ARRAY_MAX)
	var my_vertices = PackedVector3Array()
	var my_uvs = PackedVector2Array()
	var my_normals = PackedVector3Array()
	
	var point := Vector3.RIGHT
	var steps := 32
	var angle_step := TAU / steps
	for i in steps:
		my_vertices.append(point)
		point = point.rotated(Vector3.UP, angle_step)
		my_uvs.append(Vector2(0,0))
		my_normals.append(Vector3.UP)
	my_vertices.append(my_vertices.get(0) + my_vertices.get(steps/2)) 
	my_uvs.append(Vector2(0,0))
	my_normals.append(Vector3.UP)
	
	surface_array[Mesh.ARRAY_VERTEX] = my_vertices
	surface_array[Mesh.ARRAY_TEX_UV] = my_uvs
	surface_array[Mesh.ARRAY_NORMAL] = my_normals
	  
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_POINTS, surface_array)

I’m just not sure why removing the uvs and normals causes problems. It should work with vertex positions only.

not sure, but it didn’t worked for me .

Have you tried it yourself ?

It’s probably shading making it black. Try setting unshaded flag for the material and then remove uvs and normals.

No, the origin is Vector3(0, 0, 0). You can use Vector3.ZERO

1 Like


it doesn’t have any material option only override , shall I create override and set it there ?

Yes, assign a new material to material_override and set it there.