From 5733a3b043587d5873db5868ff50d9b594690b94 Mon Sep 17 00:00:00 2001 From: Guillaume Vern Date: Fri, 28 Nov 2025 01:51:14 +0100 Subject: [PATCH] smooth mesh --- NoclipCamera.gd | 9 ++-- activation.gd | 11 +++-- sample_point.gd | 16 +------ sample_point.tscn | 2 + smooth_world.gd | 104 ++++++++++++++++++++++++++++++++++------------ smooth_world.tscn | 4 +- surface_point.gd | 9 +--- world.tscn | 1 + 8 files changed, 99 insertions(+), 57 deletions(-) diff --git a/NoclipCamera.gd b/NoclipCamera.gd index 4589971..86ba0c5 100644 --- a/NoclipCamera.gd +++ b/NoclipCamera.gd @@ -2,10 +2,11 @@ extends RigidBody3D var rot_x = 0 var rot_y = 0 -@onready var world = $"../World/" +@onready var world = preload("res://world.tscn") @export var PLAYER_SPEED = 1 @export var PLAYER_REACH = 1000 +@export var NOCLIP = false @export_range(0.00001, 0.01) var LOOK_SENSITIVITY = 0.002 var move_x = 0 var move_y = 0 @@ -48,8 +49,10 @@ func _input(event): camera.rotate_object_local(Vector3(-1, 0, 0), rot_y) # then rotate in X # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta): - process_noclip() - #process_physics_movements() + if NOCLIP: + process_noclip() + else: + process_physics_movements() #for hit_pos in ray_hit_positions: #DebugDraw3D.draw_sphere(hit_pos) diff --git a/activation.gd b/activation.gd index 67f0466..6a8b4af 100644 --- a/activation.gd +++ b/activation.gd @@ -7,6 +7,9 @@ enum EnumWorld {CUBIC_WORLD, SMOOTH_WORLD} var enabled_world: EnumWorld = EnumWorld.CUBIC_WORLD +var smooth_world = preload("res://smooth_world.tscn") +var cubic_world = preload("res://cubic_world.tscn") + signal change_world func _process(_delta: float) -> void: @@ -17,11 +20,7 @@ func _process(_delta: float) -> void: func _on_change_world(): match wanted_world: EnumWorld.CUBIC_WORLD: - if $SmoothWorld: - $SmoothWorld.queue_free() - add_child(load("res://cubic_world.tscn").instantiate()) + add_child(cubic_world.instantiate()) EnumWorld.SMOOTH_WORLD: - if $CubicWorld: - $CubicWorld.queue_free() - add_child(load("res://smooth_world.tscn").instantiate()) + add_child(smooth_world.instantiate()) enabled_world = wanted_world diff --git a/sample_point.gd b/sample_point.gd index 1e63add..ba20341 100644 --- a/sample_point.gd +++ b/sample_point.gd @@ -1,15 +1,3 @@ -@tool -extends Node3D - @export var distance = 0 - -var color = Color.SKY_BLUE - - -func _process(_delta: float) -> void: - if distance > 0: - color = Color.MEDIUM_PURPLE - else: - color = Color.SKY_BLUE - DebugDraw3D.draw_square(position, 0.2, color) - +@export var position = Vector3.ZERO +@export var visible = false diff --git a/sample_point.tscn b/sample_point.tscn index e9c1ac1..2dfc2ba 100644 --- a/sample_point.tscn +++ b/sample_point.tscn @@ -3,4 +3,6 @@ [ext_resource type="Script" uid="uid://likm24qx18tm" path="res://sample_point.gd" id="1_x8428"] [node name="SamplePoint" type="Node3D"] +visible = null script = ExtResource("1_x8428") +visible = null diff --git a/smooth_world.gd b/smooth_world.gd index e525637..5c2a3ac 100644 --- a/smooth_world.gd +++ b/smooth_world.gd @@ -1,37 +1,61 @@ @tool extends Node3D - const CENTER := Vector3.ZERO -@export var RADIUS: float = 5.0 +@export_range(0.0, 6.9999) var RADIUS: float = 5.0 var sample_points = {} +var SamplePoint = preload("res://sample_point.gd") var surface_points = {} +var SurfacePoint = preload("res://surface_point.gd") @export var world_size = 16 +@export var show_sample_points = false +@export var show_surface_points = false +@export var show_surface = true @export var do_the_thing: bool = false @export var clear_the_thing: bool = false +var color = Color.CORAL +var surface_point_color = Color.CRIMSON + var mesh var surface_tool: SurfaceTool = SurfaceTool.new() -var SAMPLE_POINT = preload("res://sample_point.tscn") -var SURFACE_POINT = preload("res://surface_point.tscn") func _ready() -> void: initialize_sample_points() - create_surface_points() - create_surface_mesh(world_size) func _process(_delta: float) -> void: clear() create_surface_points() - create_surface_mesh(world_size) + if show_surface_points: + draw_surface_points() + if show_surface: + create_surface_mesh(world_size) + if show_sample_points: + draw_sample_points() + func clear(): - sample_points = {} + surface_points = {} + mesh = ArrayMesh.new() for child in get_children(): - remove_child(child) - child.queue_free() + if child is MeshInstance3D: + child.queue_free() + +func draw_sample_points(): + for x in range(-world_size + 1, world_size): + for y in range(-world_size + 1, world_size): + for z in range(-world_size + 1, world_size): + DebugDraw3D.draw_square(sample_points[Vector3i(x, y, z)].position, 0.2, color) + +func draw_surface_points(): + for x in range(-world_size + 1, world_size): + for y in range(-world_size + 1, world_size): + for z in range(-world_size + 1, world_size): + if surface_points.has(Vector3i(x, y, z)): + DebugDraw3D.draw_square(surface_points[Vector3i(x, y, z)].position, 0.3, surface_point_color) + func get_sample_value(index: Vector3i) -> float: return CENTER.distance_to(index) - RADIUS @@ -40,11 +64,11 @@ func initialize_sample_points(): for x in range(-world_size + 1, world_size): for y in range(-world_size + 1, world_size): for z in range(-world_size + 1, world_size): - var sample_point = SAMPLE_POINT.instantiate() + var sample_point = SamplePoint.new() sample_point.distance = get_sample_value(Vector3i(x, y, z)) sample_point.position = Vector3(float(x), float(y), float(z)) + sample_point.visible = show_sample_points sample_points[Vector3i(x, y, z)] = sample_point - #add_child(sample_point) func create_surface_points(): for x in range(-world_size + 1, world_size): @@ -53,16 +77,31 @@ func create_surface_points(): create_surface_point(Vector3i(x, y, z)) func create_surface_point(voxel: Vector3i): - var average_distance_from_sample = 0 + var previous_sign = 0 + var previous_sample_point + var previous_sample_point_distance_from_sdf + var intersection_points_sum = Vector3.ZERO + var intersection_points_number = Vector3.ZERO for sample_point_to_check_index in range(SURFACE_AXIS.size()): - var sample_point_to_check = SURFACE_AXIS[sample_point_to_check_index] - average_distance_from_sample += get_sample_value(voxel + sample_point_to_check) - average_distance_from_sample /= 8 - if average_distance_from_sample <= 0: - var surface_point = SURFACE_POINT.instantiate() - surface_point.position = Vector3(voxel) + var sample_point_to_check = voxel + SURFACE_AXIS[sample_point_to_check_index] + var sample_point_distance_from_sdf = get_sample_value(sample_point_to_check) + if previous_sign != 0 && sign(sample_point_distance_from_sdf) != previous_sign: + var intersection_point = (1-previous_sample_point_distance_from_sdf/(previous_sample_point_distance_from_sdf - sample_point_distance_from_sdf))*previous_sample_point+(previous_sample_point_distance_from_sdf/(previous_sample_point_distance_from_sdf-sample_point_distance_from_sdf)*sample_point_to_check) + intersection_points_sum += intersection_point + intersection_points_number += Vector3.ONE + previous_sign = sign(sample_point_distance_from_sdf) + previous_sample_point = sample_point_to_check + previous_sample_point_distance_from_sdf = sample_point_distance_from_sdf + if intersection_points_sum != Vector3.ZERO && intersection_points_number != Vector3.ZERO: + var intersection_points_average = intersection_points_sum/intersection_points_number + var surface_point = SurfacePoint.new() + surface_point.position = intersection_points_average + surface_point.visible = show_surface_points surface_points[voxel] = surface_point - add_child(surface_point) + +func calculate_surface_point_position(voxel: Vector3i): + var final_point = Vector3(voxel) + return final_point func create_surface_mesh(size: int = 6): surface_tool = SurfaceTool.new() @@ -79,6 +118,7 @@ func create_surface_mesh(size: int = 6): func create_surface_mesh_quad(index: Vector3i): for axis_index in range(AXIS.size()): var axis = AXIS[axis_index] + var sample_value1 = get_sample_value(index) var sample_value2 = get_sample_value(index + axis) @@ -106,8 +146,14 @@ const SURFACE_AXIS := [ func add_quad(index: Vector3i, axis_index: int): var points = get_quad_points(index, axis_index) + + var normal = Vector3( + (get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[1])) + (get_sample_value(index + SURFACE_AXIS[3]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[4])), + (get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[0])) + (get_sample_value(index + SURFACE_AXIS[4]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[3])), + (get_sample_value(index + SURFACE_AXIS[7]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[3])) + (get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[4])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[6])) + ) - surface_tool.set_normal(AXIS[axis_index]) + surface_tool.set_normal(normal) surface_tool.add_vertex(points[0]) surface_tool.add_vertex(points[1]) @@ -119,8 +165,14 @@ func add_quad(index: Vector3i, axis_index: int): func add_reversed_quad(index: Vector3i, axis_index: int): var points = get_quad_points(index, axis_index) + + var normal = Vector3( + (get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[1])) + (get_sample_value(index + SURFACE_AXIS[3]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[4])), + (get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[0])) + (get_sample_value(index + SURFACE_AXIS[4]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[3])), + (get_sample_value(index + SURFACE_AXIS[7]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[3])) + (get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[4])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[6])) + ) - surface_tool.set_normal(-AXIS[axis_index]) + surface_tool.set_normal(normal) surface_tool.add_vertex(points[0]) surface_tool.add_vertex(points[2]) @@ -132,10 +184,10 @@ func add_reversed_quad(index: Vector3i, axis_index: int): func get_quad_points(index: Vector3i, axis_index: int): return [ - index + QUAD_POINTS[axis_index][0], - index + QUAD_POINTS[axis_index][1], - index + QUAD_POINTS[axis_index][2], - index + QUAD_POINTS[axis_index][3], + surface_points[index + QUAD_POINTS[axis_index][0]].position, + surface_points[index + QUAD_POINTS[axis_index][1]].position, + surface_points[index + QUAD_POINTS[axis_index][2]].position, + surface_points[index + QUAD_POINTS[axis_index][3]].position, ] const QUAD_POINTS := [ diff --git a/smooth_world.tscn b/smooth_world.tscn index e5ebfbe..4c49bce 100644 --- a/smooth_world.tscn +++ b/smooth_world.tscn @@ -4,6 +4,8 @@ [node name="SmoothWorld" type="Node3D"] script = ExtResource("1_4h467") -RADIUS = 4.182 +RADIUS = 3.971 world_size = 8 +show_sample_points = true +show_surface_points = true do_the_thing = true diff --git a/surface_point.gd b/surface_point.gd index 28499a5..f5a8373 100644 --- a/surface_point.gd +++ b/surface_point.gd @@ -1,8 +1,3 @@ -@tool -extends Node3D - var color = Color.DARK_GOLDENROD - - -func _process(_delta: float) -> void: - DebugDraw3D.draw_square(position, 0.2, color) +@export var position = Vector3.ZERO +@export var visible = false diff --git a/world.tscn b/world.tscn index d7414b3..6cca861 100644 --- a/world.tscn +++ b/world.tscn @@ -29,5 +29,6 @@ shadow_enabled = true [node name="Player" parent="." instance=ExtResource("3_036b0")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.182447, 0.6673207, 0.0726881) +NOCLIP = true [connection signal="change_world" from="." to="." method="_on_change_world"]