GodotShade/smooth_world.gd
2025-11-30 22:16:33 +01:00

210 lines
6.4 KiB
GDScript

#@tool
extends Node3D
const CENTER := Vector3.ZERO
@export 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")
var ComputeSdf = preload("res://compute_test.gd")
var gpu_sdf
@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 sdf_buffer = []
var color = Color.CORAL
var surface_point_color = Color.CRIMSON
var mesh
var surface_tool: SurfaceTool = SurfaceTool.new()
func _ready() -> void:
gpu_sdf = ComputeSdf.new()
gpu_sdf.create_device()
#initialize_sample_points()
func _process(_delta: float) -> void:
clear()
sdf_buffer = gpu_sdf.compute(world_size * 2, RADIUS)
if !sdf_buffer.is_empty():
create_surface_points()
if show_surface_points:
draw_surface_points()
if show_surface:
create_surface_mesh(world_size)
if show_sample_points:
draw_sample_points()
func clear():
surface_points = {}
mesh = ArrayMesh.new()
for child in get_children():
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):
if sample_points.has(Vector3i(x, y, z)):
DebugDraw3D.draw_square(Vector3i(x, y, z), 0.2, color)
#DebugDraw3D.draw_text(Vector3i(x, y, z), str(Vector3i(x, y, z)))
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(Vector3i(x, y, z), 0.3, surface_point_color)
func initialize_sample_points():
sample_points = gpu_sdf.compute(world_size, RADIUS)
print("sample_points initialized", sample_points)
func create_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):
create_surface_point(Vector3i(x, y, z))
func create_surface_point(voxel: Vector3i):
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 = voxel + SURFACE_AXIS[sample_point_to_check_index]
var normal_x = voxel.x + world_size - 1
var normal_y = voxel.y + world_size - 1
var normal_z = voxel.z + world_size - 1
var buffer_index = normal_x + normal_y * world_size + normal_z * world_size * world_size
if buffer_index < sdf_buffer.size():
var sample_point_distance_from_sdf = sdf_buffer[buffer_index]#get_sample_value(sample_point_to_check)
sample_points[voxel] = sample_point_distance_from_sdf
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_points[voxel] = 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()
surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
for x in range(-size, size):
for y in range(-size, size):
for z in range(-size, size):
if surface_points.has(Vector3i(x, y, z)):
create_surface_mesh_quad(Vector3i(x,y,z));
mesh = surface_tool.commit()
var meshinstance = MeshInstance3D.new()
meshinstance.mesh = mesh
add_child(meshinstance)
func create_surface_mesh_quad(index: Vector3i):
for axis_index in range(AXIS.size()):
var axis = AXIS[axis_index]
var sample_value1 = sample_points[index]
var sample_value2 = sample_points[index + axis]
if sample_value1 < 0 and sample_value2 >= 0:
add_quad(index, axis_index)
elif sample_value1 >= 0 and sample_value2 < 0:
add_reversed_quad(index, axis_index)
const AXIS := [
Vector3i(1,0,0),
Vector3i(0,1,0),
Vector3i(0,0,1),
]
const SURFACE_AXIS := [
Vector3i(1,0,0),
Vector3i(0,1,0),
Vector3i(0,0,1),
Vector3i(1,0,1),
Vector3i(0,1,1),
Vector3i(1,1,0),
Vector3i(1,1,1),
Vector3i(0,0,0),
]
func add_quad(index: Vector3i, axis_index: int):
var points = get_quad_points(index, axis_index)
surface_tool.add_vertex(points[0])
surface_tool.add_vertex(points[1])
surface_tool.add_vertex(points[2])
surface_tool.add_vertex(points[0])
surface_tool.add_vertex(points[2])
surface_tool.add_vertex(points[3])
surface_tool.generate_normals()
func add_reversed_quad(index: Vector3i, axis_index: int):
var points = get_quad_points(index, axis_index)
surface_tool.add_vertex(points[0])
surface_tool.add_vertex(points[2])
surface_tool.add_vertex(points[1])
surface_tool.add_vertex(points[0])
surface_tool.add_vertex(points[3])
surface_tool.add_vertex(points[2])
surface_tool.generate_normals()
func get_quad_points(index: Vector3i, axis_index: int):
return [
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 := [
# x axis
[
Vector3i(0,0,-1),
Vector3i(0,-1,-1),
Vector3i(0,-1,0),
Vector3i(0,0,0)
],
# y axis
[
Vector3i(0,0,-1),
Vector3i(0,0,0),
Vector3i(-1,0,0),
Vector3i(-1,0,-1)
],
# z axis
[
Vector3i(0,0,0),
Vector3i(0,-1,0),
Vector3i(-1,-1,0),
Vector3i(-1,0,0)
],
]