164 lines
4.2 KiB
GDScript
164 lines
4.2 KiB
GDScript
@tool
|
|
extends Node3D
|
|
|
|
const CENTER := Vector3.ZERO
|
|
@export var RADIUS: float = 5.0
|
|
|
|
var sample_points = {}
|
|
var surface_points = {}
|
|
|
|
@export var world_size = 16
|
|
|
|
@export var do_the_thing: bool = false
|
|
@export var clear_the_thing: bool = false
|
|
|
|
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)
|
|
|
|
func clear():
|
|
sample_points = {}
|
|
for child in get_children():
|
|
remove_child(child)
|
|
child.queue_free()
|
|
|
|
func get_sample_value(index: Vector3i) -> float:
|
|
return CENTER.distance_to(index) - RADIUS
|
|
|
|
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()
|
|
sample_point.distance = get_sample_value(Vector3i(x, y, z))
|
|
sample_point.position = Vector3(float(x), float(y), float(z))
|
|
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):
|
|
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 average_distance_from_sample = 0
|
|
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)
|
|
surface_points[voxel] = surface_point
|
|
add_child(surface_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):
|
|
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 = get_sample_value(index)
|
|
var sample_value2 = get_sample_value(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.set_normal(AXIS[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])
|
|
|
|
func add_reversed_quad(index: Vector3i, axis_index: int):
|
|
var points = get_quad_points(index, axis_index)
|
|
|
|
surface_tool.set_normal(-AXIS[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])
|
|
|
|
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],
|
|
]
|
|
|
|
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)
|
|
],
|
|
]
|