wave function collapse give some results
but still very buggy
This commit is contained in:
parent
7bb7ea54af
commit
018ab6e087
228 changed files with 13252 additions and 3 deletions
139
wavefunctioncollapse/grid_map_wave_func.gd
Normal file
139
wavefunctioncollapse/grid_map_wave_func.gd
Normal file
|
@ -0,0 +1,139 @@
|
|||
@tool
|
||||
extends GridMap
|
||||
|
||||
# Godot ne supporte pas les types nested, c'est triste mais on fait un tool button pour nous aider
|
||||
#@export var adjacency : Array[Array]
|
||||
@export var adjacency : Dictionary[Globals.Blocks, AdjacencyRessource]
|
||||
@export_tool_button("Step") var step_action = step
|
||||
|
||||
var dict_grid_map : Dictionary[Vector3i, Array] = {}
|
||||
|
||||
|
||||
func get_cell_neighbor(cell_coords : Vector3i) -> Dictionary[Vector3i, Globals.Blocks]:
|
||||
var neighbor : Dictionary[Vector3i, Globals.Blocks]
|
||||
var delta : Vector3i
|
||||
for dx in [-1, 0, 1]:
|
||||
for dy in [-1, 0, 1]:
|
||||
for dz in [-1, 0, 1]:
|
||||
delta = Vector3i(dx, dy, dz)
|
||||
if delta == Vector3i(0, 0, 0): continue
|
||||
var cell_item = get_cell_item(delta)
|
||||
neighbor[delta] = cell_item
|
||||
|
||||
return neighbor
|
||||
|
||||
func get_proba():
|
||||
var used_cells := get_used_cells()
|
||||
print("used_cells")
|
||||
print(used_cells)
|
||||
dict_grid_map = {}
|
||||
#var adjacent_cells : Dictionary[Vector3i, bool] = {} # Cells sur la bordure
|
||||
var used_cells_hah_set : Dictionary[Vector3i, bool] = {} # For fast look up
|
||||
for cell in used_cells:
|
||||
used_cells_hah_set.set(cell, true)
|
||||
|
||||
for cell_coords in used_cells:
|
||||
var neighbors := get_cell_neighbor(cell_coords)
|
||||
var current_cell := get_cell_item(cell_coords)
|
||||
var adj_at_cell_coords := adjacency[current_cell].get_adjacency_dict()
|
||||
#print("adj_at_cell_coords")
|
||||
#print(adj_at_cell_coords)
|
||||
|
||||
for diff_n in neighbors:
|
||||
var neighbor_pos = cell_coords + diff_n
|
||||
if used_cells_hah_set.get(neighbor_pos): continue
|
||||
|
||||
if not neighbor_pos in dict_grid_map:
|
||||
dict_grid_map.set(neighbor_pos, [])
|
||||
dict_grid_map[neighbor_pos].resize(Globals.Blocks.size())
|
||||
dict_grid_map[neighbor_pos].fill(1.0)
|
||||
|
||||
var proba_neighbor = dict_grid_map[neighbor_pos]
|
||||
#print(adj_at_cell_coords[diff_n])
|
||||
for block in range(dict_grid_map[neighbor_pos].size()):
|
||||
if block in adj_at_cell_coords[diff_n]:
|
||||
dict_grid_map[neighbor_pos][block] *= adj_at_cell_coords[diff_n][block]
|
||||
else:
|
||||
dict_grid_map[neighbor_pos][block] *= 0.0
|
||||
|
||||
|
||||
#for block in range(proba_neighbor.size()):
|
||||
#var proba_adj = adj_at_cell_coords[diff_n][current_cell] if\
|
||||
#current_cell in adj_at_cell_coords[diff_n] else 0.0
|
||||
#dict_grid_map[neighbor_pos][block] *= proba_adj
|
||||
|
||||
# Normalisation des probas
|
||||
for cell_cooords in dict_grid_map:
|
||||
var probas_array = dict_grid_map[cell_cooords]
|
||||
var sum = probas_array.reduce(func(a, b): return a+b)
|
||||
for block in range(probas_array.size()):
|
||||
if sum < 0.001:
|
||||
dict_grid_map[cell_cooords][block] = 1.0 / Globals.Blocks.size()
|
||||
else:
|
||||
dict_grid_map[cell_cooords][block] /= sum
|
||||
|
||||
print(dict_grid_map)
|
||||
print("----\n---\n---\n---")
|
||||
|
||||
# Oui on utilise Shanon comme des sigma, les autres betas sur internet disent "entropy = nb de possibilites", mais on est sigma ici
|
||||
func calculate_entropy(cell_coords : Vector3i):
|
||||
var proba_array := dict_grid_map[cell_coords]
|
||||
print(proba_array)
|
||||
var entropy = 0.0
|
||||
for prob in proba_array:
|
||||
entropy += -(prob+0.001) * log(prob+0.001) # I'm afraid of log(0) guys
|
||||
return entropy
|
||||
|
||||
func weighted_random_choice_index(weights: Array[float]) -> int:
|
||||
if weights.is_empty():
|
||||
printerr("weighted_random_choice_index: Input weights array cannot be empty.")
|
||||
return -1
|
||||
|
||||
var total_weight: float = 0.0
|
||||
for w in weights:
|
||||
if w < 0.0:
|
||||
printerr("weighted_random_choice_index: Weights cannot be negative.")
|
||||
return -1
|
||||
total_weight += w
|
||||
|
||||
if total_weight <= 0.0:
|
||||
return randi() % weights.size()
|
||||
|
||||
var rnd: float = randf() * total_weight
|
||||
for i in range(weights.size()):
|
||||
var w = weights[i]
|
||||
rnd -= w
|
||||
if rnd <= 0.0:
|
||||
return i
|
||||
|
||||
# Fallback (due to potential float inaccuracies)
|
||||
return weights.size() - 1
|
||||
|
||||
func step():
|
||||
get_proba()
|
||||
print(dict_grid_map)
|
||||
var lowest_entropy = 100.0
|
||||
var best_cell_coords : Vector3i
|
||||
for cell_coords in dict_grid_map.keys():
|
||||
var entropy = calculate_entropy(cell_coords)
|
||||
print("cell_coords {} entropy {}".format([cell_coords, entropy], "{}"))
|
||||
if entropy < lowest_entropy:
|
||||
lowest_entropy = entropy
|
||||
best_cell_coords = cell_coords
|
||||
|
||||
var arr_float : Array[float] = Array(dict_grid_map[best_cell_coords], TYPE_FLOAT, "", null)
|
||||
var best_cell = weighted_random_choice_index(arr_float)
|
||||
|
||||
|
||||
if not best_cell in Globals.ShouldRotate:
|
||||
set_cell_item(best_cell_coords, best_cell)
|
||||
else:
|
||||
# Rotate 90 degrees around the Y-axis
|
||||
var rotation_axis = Vector3.UP
|
||||
var rotation_angle_rad = deg_to_rad(90)
|
||||
var desired_basis = Basis.IDENTITY.rotated(rotation_axis, rotation_angle_rad)
|
||||
var orientation_index = get_orthogonal_index_from_basis(desired_basis)
|
||||
|
||||
set_cell_item(best_cell_coords, best_cell, orientation_index)
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue