diff --git a/modules/wfc/overlapping_wave_form_collapse.cpp b/modules/wfc/overlapping_wave_form_collapse.cpp index 54610f015..30a3c8fb2 100644 --- a/modules/wfc/overlapping_wave_form_collapse.cpp +++ b/modules/wfc/overlapping_wave_form_collapse.cpp @@ -21,7 +21,7 @@ int OverlappingWaveFormCollapse::get_out_width() const { return out_width; } void OverlappingWaveFormCollapse::set_out_width(const int val) { - periodic_output = val; + out_width = val; } int OverlappingWaveFormCollapse::get_symmetry() const { @@ -87,7 +87,7 @@ void OverlappingWaveFormCollapse::init_ground() { bool OverlappingWaveFormCollapse::set_pattern(const Array2D &pattern, int i, int j) { int pattern_id = get_pattern_id(pattern); - if (pattern_id == static_cast(-1) || i >= get_wave_height() || j >= get_wave_width()) { + if (pattern_id == -1 || i >= get_wave_height() || j >= get_wave_width()) { return false; } @@ -130,9 +130,7 @@ void OverlappingWaveFormCollapse::set_pattern(int pattern_id, int i, int j) { } //Return the list of patterns, as well as their probabilities of apparition. -void OverlappingWaveFormCollapse::get_patterns() { - //OAHashMap, int> patterns_id; - +void OverlappingWaveFormCollapse::init_patterns() { LocalVector> patterns_id; patterns.clear(); @@ -179,6 +177,7 @@ void OverlappingWaveFormCollapse::get_patterns() { } else { patterns.push_back(symmetries[k]); patterns_weight.push_back(1); + patterns_id.push_back(symmetries[k]); } } } @@ -211,7 +210,7 @@ bool OverlappingWaveFormCollapse::agrees(const Array2D &pattern1, const Arr // If agrees(pattern1, pattern2, dy, dx), then compatible[pattern1][direction] // contains pattern2, where direction is the direction defined by (dy, dx) // (see direction.hpp). -Vector OverlappingWaveFormCollapse::generate_compatible() { +void OverlappingWaveFormCollapse::generate_compatible() { Vector compatible; compatible.resize(patterns.size()); @@ -226,12 +225,12 @@ Vector OverlappingWaveFormCollapse::gene } } - return compatible; + set_propagator_state(compatible); } // Transform a 2D array containing the patterns id to a 2D array containing the pixels. Array2D OverlappingWaveFormCollapse::to_image(const Array2D &output_patterns) const { - Array2D output = Array2D(out_height, out_width); + Array2D output(out_height, out_width); if (periodic_output) { for (int y = 0; y < get_wave_height(); y++) { @@ -274,21 +273,24 @@ Array2D OverlappingWaveFormCollapse::to_image(const Array2D &output_pa } void OverlappingWaveFormCollapse::initialize() { + init_patterns(); + generate_compatible(); + + set_wave_size(get_wave_width(), get_wave_height()); + + WaveFormCollapse::initialize(); + // If necessary, the ground is set. if (ground) { init_ground(); } - - set_propagator_state(generate_compatible()); - - WaveFormCollapse::initialize(); } OverlappingWaveFormCollapse::OverlappingWaveFormCollapse() { - periodic_input = false; + periodic_input = true; out_height = 0; out_width = 0; - symmetry = 0; + symmetry = 8; ground = false; pattern_size = 0; } diff --git a/modules/wfc/overlapping_wave_form_collapse.h b/modules/wfc/overlapping_wave_form_collapse.h index 16aee6e71..093ce5244 100644 --- a/modules/wfc/overlapping_wave_form_collapse.h +++ b/modules/wfc/overlapping_wave_form_collapse.h @@ -39,11 +39,12 @@ public: int get_ground_pattern_id(); int get_pattern_id(const Array2D &pattern); void set_pattern(int pattern_id, int i, int j); - void get_patterns(); + + void init_patterns(); bool agrees(const Array2D &pattern1, const Array2D &pattern2, int dy, int dx); - Vector generate_compatible(); + void generate_compatible(); Array2D to_image(const Array2D &output_patterns) const; diff --git a/modules/wfc/tiling_wave_form_collapse.cpp b/modules/wfc/tiling_wave_form_collapse.cpp index f1dae78ba..2a6bd710d 100644 --- a/modules/wfc/tiling_wave_form_collapse.cpp +++ b/modules/wfc/tiling_wave_form_collapse.cpp @@ -109,7 +109,7 @@ Tile::Tile(const Array2D &p_data, WaveFormCollapse::Symmetry p_symmetry, do // Returns false if the given tile and orientation does not exist, or if the coordinates are not in the wave bool TilingWaveFormCollapse::set_tile(int tile_id, int orientation, int i, int j) { if (tile_id >= static_cast(oriented_tile_ids.size()) || orientation >= static_cast(oriented_tile_ids[tile_id].size()) || - i >= get_height() || j >= get_width()) { + i >= _wave_height || j >= _wave_width) { return false; } diff --git a/modules/wfc/wave_form_collapse.cpp b/modules/wfc/wave_form_collapse.cpp index 90d1a9639..325838f37 100644 --- a/modules/wfc/wave_form_collapse.cpp +++ b/modules/wfc/wave_form_collapse.cpp @@ -41,11 +41,18 @@ double WaveFormCollapse::get_min_abs_half(const Vector &v) { return min_abs_half; } -int WaveFormCollapse::get_width() const { - return wave_width; +int WaveFormCollapse::get_wave_width() const { + return _wave_width; } -int WaveFormCollapse::get_height() const { - return wave_height; +void WaveFormCollapse::set_wave_width(const int val) { + _wave_width = val; +} + +int WaveFormCollapse::get_wave_height() const { + return _wave_height; +} +void WaveFormCollapse::set_wave_height(const int val) { + _wave_height = val; } bool WaveFormCollapse::get_periodic_output() const { @@ -59,10 +66,14 @@ void WaveFormCollapse::set_seed(const int seed) { gen.seed(seed); } -void WaveFormCollapse::set_size(int p_width, int p_height) { - wave_width = p_width; - wave_height = p_height; - wave_size = p_height * p_width; +void WaveFormCollapse::set_wave_size(int p_width, int p_height) { + _wave_width = p_width; + _wave_height = p_height; + _wave_size = p_height * p_width; +} + +void WaveFormCollapse::init_wave() { + _wave_size = _wave_height * _wave_width; } void WaveFormCollapse::set_propagator_state(const Vector &p_propagator_state) { @@ -78,8 +89,6 @@ void WaveFormCollapse::set_pattern_frequencies(const Vector &p_patterns_ } void WaveFormCollapse::set_input(const PoolIntArray &p_data, int p_width, int p_height) { - set_size(p_width, p_height); - input.resize(p_width, p_height); ERR_FAIL_COND(input.data.size() != p_data.size()); @@ -102,7 +111,7 @@ Array2D WaveFormCollapse::run() { // Check if the algorithm has terminated. if (result == OBSERVE_STATUS_FAILURE) { return Array2D(0, 0); - } else if (result == OBSERVE_STATUS_FAILURE) { + } else if (result == OBSERVE_STATUS_SUCCESS) { return wave_to_output(); } @@ -119,10 +128,6 @@ PoolIntArray WaveFormCollapse::generate_image_index_data() { return arr; } - print_error(String::num(a.width)); - print_error(String::num(a.height)); - print_error("---"); - const int *r = a.data.ptr(); int s = a.data.size(); @@ -147,8 +152,7 @@ WaveFormCollapse::ObserveStatus WaveFormCollapse::observe() { return OBSERVE_STATUS_FAILURE; } - // If the lowest entropy is 0, then the algorithm has succeeded and - // finished. + // If the lowest entropy is 0, then the algorithm has succeeded and finished. if (argmin == -1) { wave_to_output(); return OBSERVE_STATUS_SUCCESS; @@ -175,7 +179,7 @@ WaveFormCollapse::ObserveStatus WaveFormCollapse::observe() { // And define the cell with the pattern. for (int k = 0; k < patterns_frequencies.size(); k++) { if (wave_get(argmin, k) != (k == chosen_value)) { - add_to_propagator(argmin / wave_width, argmin % wave_width, k); + add_to_propagator(argmin / _wave_width, argmin % _wave_width, k); wave_set(argmin, k, false); } } @@ -184,9 +188,9 @@ WaveFormCollapse::ObserveStatus WaveFormCollapse::observe() { } Array2D WaveFormCollapse::wave_to_output() const { - Array2D output_patterns(wave_height, wave_width); + Array2D output_patterns(_wave_height, _wave_width); - for (int i = 0; i < wave_size; i++) { + for (int i = 0; i < _wave_size; i++) { for (int k = 0; k < patterns_frequencies.size(); k++) { if (wave_get(i, k)) { output_patterns.data.write[i] = k; @@ -198,15 +202,17 @@ Array2D WaveFormCollapse::wave_to_output() const { } void WaveFormCollapse::wave_set(int index, int pattern, bool value) { - bool old_value = data.get(index, pattern); + bool old_value = wave_data.get(index, pattern); // If the value isn't changed, nothing needs to be done. if (old_value == value) { return; } + print_error(String::num(index)); + // Otherwise, the memoisation should be updated. - data.get(index, pattern) = value; + wave_data.get(index, pattern) = value; memoisation_plogp_sum.write[index] -= plogp_patterns_frequencies[pattern]; memoisation_sum.write[index] -= patterns_frequencies[pattern]; @@ -232,9 +238,8 @@ int WaveFormCollapse::wave_get_min_entropy() const { int argmin = -1; - for (int i = 0; i < wave_size; i++) { - // If the cell is decided, we do not compute the entropy (which is equal - // to 0). + for (int i = 0; i < _wave_size; i++) { + // If the cell is decided, we do not compute the entropy (which is equal to 0). double nb_patterns_local = memoisation_nb_patterns[i]; if (nb_patterns_local == 1) { @@ -266,8 +271,8 @@ void WaveFormCollapse::init_compatible() { CompatibilityEntry value; // We compute the number of pattern compatible in all directions. - for (int y = 0; y < wave_height; y++) { - for (int x = 0; x < wave_width; x++) { + for (int y = 0; y < _wave_height; y++) { + for (int x = 0; x < _wave_width; x++) { for (int pattern = 0; pattern < propagator_state.size(); pattern++) { for (int direction = 0; direction < 4; direction++) { value.direction[direction] = static_cast(propagator_state[pattern].directions[get_opposite_direction(direction)].size()); @@ -300,23 +305,23 @@ void WaveFormCollapse::propagate() { int x2, y2; if (periodic_output) { - x2 = ((int)x1 + dx + (int)wave_width) % wave_width; - y2 = ((int)y1 + dy + (int)wave_height) % wave_height; + x2 = ((int)x1 + dx + (int)_wave_width) % _wave_width; + y2 = ((int)y1 + dy + (int)_wave_height) % _wave_height; } else { x2 = x1 + dx; y2 = y1 + dy; - if (x2 < 0 || x2 >= (int)wave_width) { + if (x2 < 0 || x2 >= (int)_wave_width) { continue; } - if (y2 < 0 || y2 >= (int)wave_height) { + if (y2 < 0 || y2 >= (int)_wave_height) { continue; } } // The index of the second cell, and the patterns compatible - int i2 = x2 + y2 * wave_width; + int i2 = x2 + y2 * _wave_width; const Vector &patterns = propagator_state[pattern].directions[direction]; // For every pattern that could be placed in that cell without being in @@ -344,13 +349,15 @@ void WaveFormCollapse::propagate() { void WaveFormCollapse::initialize() { //wave - data.resize(0, 0); - data.resize_fill(wave_width * wave_height, patterns_frequencies.size(), 1); + init_wave(); plogp_patterns_frequencies = get_plogp(patterns_frequencies); min_abs_half_plogp = get_min_abs_half(plogp_patterns_frequencies); is_impossible = false; + nb_patterns = patterns_frequencies.size(); + + wave_data.resize_fill(_wave_width * _wave_height, nb_patterns, true); // Initialize the memoisation of entropy. double base_entropy = 0; @@ -364,35 +371,35 @@ void WaveFormCollapse::initialize() { double log_base_s = log(base_s); double entropy_base = log_base_s - base_entropy / base_s; - memoisation_plogp_sum.resize(wave_width * wave_height); + memoisation_plogp_sum.resize(_wave_width * _wave_height); memoisation_plogp_sum.fill(base_entropy); - memoisation_sum.resize(wave_width * wave_height); + memoisation_sum.resize(_wave_width * _wave_height); memoisation_sum.fill(base_s); - memoisation_log_sum.resize(wave_width * wave_height); + memoisation_log_sum.resize(_wave_width * _wave_height); memoisation_log_sum.fill(log_base_s); - memoisation_nb_patterns.resize(wave_width * wave_height); + memoisation_nb_patterns.resize(_wave_width * _wave_height); memoisation_nb_patterns.fill(static_cast(patterns_frequencies.size())); - memoisation_entropy.resize(wave_width * wave_height); + memoisation_entropy.resize(_wave_width * _wave_height); memoisation_entropy.fill(entropy_base); //propagator - compatible.resize(wave_height, wave_width, propagator_state.size()); + compatible.resize(_wave_height, _wave_width, propagator_state.size()); init_compatible(); } WaveFormCollapse::WaveFormCollapse() { - periodic_output = false; + periodic_output = true; is_impossible = false; nb_patterns = 0; - wave_width = 0; - wave_height = 0; - wave_size = 0; + _wave_width = 0; + _wave_height = 0; + _wave_size = 0; min_abs_half_plogp = 0; } @@ -401,15 +408,20 @@ WaveFormCollapse::~WaveFormCollapse() { } void WaveFormCollapse::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_width"), &WaveFormCollapse::get_width); - ClassDB::bind_method(D_METHOD("get_height"), &WaveFormCollapse::get_height); + ClassDB::bind_method(D_METHOD("get_wave_width"), &WaveFormCollapse::get_wave_width); + ClassDB::bind_method(D_METHOD("set_wave_width", "value"), &WaveFormCollapse::set_wave_width); + ADD_PROPERTY(PropertyInfo(Variant::INT, "wave_width"), "set_wave_width", "get_wave_width"); + + ClassDB::bind_method(D_METHOD("get_wave_height"), &WaveFormCollapse::get_wave_height); + ClassDB::bind_method(D_METHOD("set_wave_height", "value"), &WaveFormCollapse::set_wave_height); + ADD_PROPERTY(PropertyInfo(Variant::INT, "wave_height"), "set_wave_height", "get_wave_height"); ClassDB::bind_method(D_METHOD("get_periodic_output"), &WaveFormCollapse::get_periodic_output); ClassDB::bind_method(D_METHOD("set_periodic_output", "value"), &WaveFormCollapse::set_periodic_output); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "periodic_output"), "set_periodic_output", "get_periodic_output"); ClassDB::bind_method(D_METHOD("set_seed", "seed"), &WaveFormCollapse::set_seed); - ClassDB::bind_method(D_METHOD("set_size", "width", "height"), &WaveFormCollapse::set_size); + //ClassDB::bind_method(D_METHOD("set_wave_size", "width", "height"), &WaveFormCollapse::set_wave_size); ClassDB::bind_method(D_METHOD("propagate"), &WaveFormCollapse::propagate); ClassDB::bind_method(D_METHOD("initialize"), &WaveFormCollapse::initialize); diff --git a/modules/wfc/wave_form_collapse.h b/modules/wfc/wave_form_collapse.h index d6b4ed23e..d21c71812 100644 --- a/modules/wfc/wave_form_collapse.h +++ b/modules/wfc/wave_form_collapse.h @@ -24,7 +24,7 @@ public: }; enum ObserveStatus { - OBSERVE_STATUS_SUCCESS, + OBSERVE_STATUS_SUCCESS = 0, OBSERVE_STATUS_FAILURE, OBSERVE_STATUS_TO_CONTINUE }; @@ -63,15 +63,19 @@ public: static const int DIRECTIONS_Y[4]; public: - int get_width() const; - int get_height() const; + int get_wave_width() const; + void set_wave_width(const int val); + + int get_wave_height() const; + void set_wave_height(const int val); bool get_periodic_output() const; void set_periodic_output(const bool val); void set_seed(const int seed); - void set_size(int p_width, int p_height); + void set_wave_size(int p_width, int p_height); + void init_wave(); void set_propagator_state(const Vector &p_propagator_state); void set_pattern_frequencies(const Vector &p_patterns_frequencies, const bool p_normalize = true); @@ -93,12 +97,12 @@ public: // Return true if pattern can be placed in cell index. bool wave_get(int index, int pattern) const { - return data.get(index, pattern); + return wave_data.get(index, pattern); } // Return true if pattern can be placed in cell (i,j) bool wave_get(int i, int j, int pattern) const { - return wave_get(i * wave_width + j, pattern); + return wave_get(i * _wave_width + j, pattern); } // Set the value of pattern in cell index. @@ -106,7 +110,7 @@ public: // Set the value of pattern in cell (i,j). void wave_set(int i, int j, int pattern, bool value) { - wave_set(i * wave_width + j, pattern, value); + wave_set(i * _wave_width + j, pattern, value); } // Return the index of the cell with lowest entropy different of 0. @@ -144,6 +148,11 @@ protected: bool periodic_output; + //Wave + int _wave_width; + int _wave_height; + int _wave_size; + private: RandomPCG gen; @@ -155,11 +164,6 @@ private: // are defined. Array2D wave_to_output() const; - //Wave - int wave_width; - int wave_height; - int wave_size; - // The patterns frequencies p given to wfc. Vector patterns_frequencies; @@ -179,9 +183,8 @@ private: // This value is set to true if there is a contradiction in the wave (all elements set to false in a cell). bool is_impossible; - // The actual wave. data.get(index, pattern) is equal to 0 if the pattern can - // be placed in the cell index. - Array2D data; + // The actual wave. wave_data.get(index, pattern) is equal to false if the pattern can be placed in the cell index. + Array2D wave_data; //Propagator Vector propagator_state;