187 lines
5.1 KiB
GDScript
187 lines
5.1 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
|
|
|
|
var generate_mesh_shader = preload("res://generate_mesh.tres")
|
|
|
|
var regenerate_mesh = false
|
|
|
|
|
|
@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 meshinstance = MeshInstance3D.new()
|
|
var material = ShaderMaterial.new()
|
|
|
|
func _ready() -> void:
|
|
material.shader = generate_mesh_shader
|
|
meshinstance.material_override = material
|
|
add_child(meshinstance)
|
|
gpu_sdf = ComputeSdf.new()
|
|
gpu_sdf.create_device()
|
|
var dictionaries = gpu_sdf.compute(world_size, RADIUS)
|
|
surface_points = dictionaries.surface_points_dict
|
|
sample_points = dictionaries.sample_points_dict
|
|
create_surface_mesh()
|
|
|
|
func _process(_delta: float) -> void:
|
|
|
|
if !surface_points.is_empty():
|
|
#create_surface_points_gpu()
|
|
#create_surface_points()
|
|
if show_surface_points:
|
|
draw_surface_points()
|
|
if show_surface && regenerate_mesh:
|
|
clear()
|
|
var dictionaries = gpu_sdf.compute(world_size, RADIUS)
|
|
surface_points = dictionaries.surface_points_dict
|
|
sample_points = dictionaries.sample_points_dict
|
|
create_surface_mesh()
|
|
if show_sample_points:
|
|
draw_sample_points()
|
|
|
|
|
|
func clear():
|
|
surface_points = {}
|
|
sample_points = {}
|
|
mesh = ArrayMesh.new()
|
|
|
|
|
|
func get_index_from_coords(coords: Vector3i):
|
|
return coords.x + coords.y * world_size + coords.z * world_size * world_size
|
|
|
|
func draw_sample_points():
|
|
for x in range(world_size):
|
|
for y in range(world_size):
|
|
for z in range(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 surface_point in surface_points:
|
|
if surface_points[surface_point] != Vector3(0, 0, 0):
|
|
DebugDraw3D.draw_square(surface_points[surface_point] , 0.3, surface_point_color)
|
|
DebugDraw3D.draw_text(surface_points[surface_point], str(surface_points[surface_point]))
|
|
|
|
func calculate_surface_point_position(voxel: Vector3i):
|
|
var final_point = Vector3(voxel)
|
|
return final_point
|
|
|
|
func create_surface_mesh():
|
|
surface_tool = SurfaceTool.new()
|
|
surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
for x in range(world_size):
|
|
for y in range(world_size):
|
|
for z in range(world_size):
|
|
if surface_points.has(Vector3i(x, y, z)):
|
|
create_surface_mesh_quad(Vector3i(x,y,z));
|
|
mesh = surface_tool.commit()
|
|
meshinstance.mesh = mesh
|
|
|
|
func create_surface_mesh_quad(index: Vector3i):
|
|
for axis_index in range(AXIS.size()):
|
|
var axis = AXIS[axis_index]
|
|
if sample_points.has(index + axis):
|
|
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)
|
|
if points != null:
|
|
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)
|
|
|
|
if points != null:
|
|
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):
|
|
if surface_points.has(index + QUAD_POINTS[axis_index][0]) and surface_points.has(index + QUAD_POINTS[axis_index][1]) and surface_points.has(index + QUAD_POINTS[axis_index][2]) and surface_points.has(index + QUAD_POINTS[axis_index][3]):
|
|
return [
|
|
surface_points[index + QUAD_POINTS[axis_index][0]],
|
|
surface_points[index + QUAD_POINTS[axis_index][1]],
|
|
surface_points[index + QUAD_POINTS[axis_index][2]],
|
|
surface_points[index + QUAD_POINTS[axis_index][3]],
|
|
]
|
|
|
|
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)
|
|
],
|
|
]
|