From 137bf204a6683c5ed0a0ba557798f1d4c67b419c Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 22 Apr 2022 02:35:38 +0200 Subject: [PATCH] Finished the first set of cleanups, and added TilingWaveFormCollapse to the build. --- modules/wfc/SCsub | 2 +- modules/wfc/tiling_wave_form_collapse.cpp | 170 +++++++++++----------- modules/wfc/tiling_wave_form_collapse.h | 71 +++++---- modules/wfc/wave_form_collapse.cpp | 24 ++- modules/wfc/wave_form_collapse.h | 5 +- 5 files changed, 153 insertions(+), 119 deletions(-) diff --git a/modules/wfc/SCsub b/modules/wfc/SCsub index b1f639fba..f86fba354 100644 --- a/modules/wfc/SCsub +++ b/modules/wfc/SCsub @@ -8,5 +8,5 @@ env_wfc = env_modules.Clone() env_wfc.add_source_files(env.modules_sources, "register_types.cpp") env_wfc.add_source_files(env.modules_sources, "wave_form_collapse.cpp") -#env_wfc.add_source_files(env.modules_sources, "tiling_wave_form_collapse.cpp") +env_wfc.add_source_files(env.modules_sources, "tiling_wave_form_collapse.cpp") #env_wfc.add_source_files(env.modules_sources, "tiling_wave_form_collapse.cpp") diff --git a/modules/wfc/tiling_wave_form_collapse.cpp b/modules/wfc/tiling_wave_form_collapse.cpp index 42842b349..4773ad61d 100644 --- a/modules/wfc/tiling_wave_form_collapse.cpp +++ b/modules/wfc/tiling_wave_form_collapse.cpp @@ -108,7 +108,7 @@ Tile::Tile(const Array2D &p_data, Symmetry p_symmetry, double p_weight // Returns false if the given tile and orientation does not exist, or if the coordinates are not in the wave bool TilingWaveFormCollapse::set_tile(uint32_t tile_id, uint32_t orientation, uint32_t i, uint32_t j) { - if (tile_id >= oriented_tile_ids.size() || orientation >= oriented_tile_ids[tile_id].size() || i >= height || j >= width) { + if (tile_id >= oriented_tile_ids.size() || orientation >= oriented_tile_ids[tile_id].size() || i >= get_height() || j >= get_width()) { return false; } @@ -118,71 +118,33 @@ bool TilingWaveFormCollapse::set_tile(uint32_t tile_id, uint32_t orientation, ui return true; } -Array2D TilingWaveFormCollapse::do_run() { - Array2D a = run(); - - if (a.width == 0 && a.height == 0) { - return Array2D(0, 0); - } - - return id_to_tiling(a); +void TilingWaveFormCollapse::set_tiles(const Vector &p_tiles) { + tiles = p_tiles; } -/* -TilingWaveFormCollapse::TilingWaveFormCollapse( - const Vector &tiles, - const Vector &neighbors, - const uint32_t height, const uint32_t width, - const bool periodic_output, int seed) : - tiles(tiles), - id_to_oriented_tile(generate_oriented_tile_ids(tiles).first), - oriented_tile_ids(generate_oriented_tile_ids(tiles).second), - options(options), - wfc(options.periodic_output, seed, get_tiles_weights(tiles), - generate_propagator(neighbors, tiles, id_to_oriented_tile, - oriented_tile_ids), - height, width), - height(height), - width(width) {} -*/ - -void TilingWaveFormCollapse::initialize() { - WaveFormCollapse::initialize(); -} - -TilingWaveFormCollapse::TilingWaveFormCollapse() { -} -TilingWaveFormCollapse::~TilingWaveFormCollapse() { -} - -void TilingWaveFormCollapse::_bind_methods() { +void TilingWaveFormCollapse::set_neighbours(const Vector &p_neighbors) { + neighbors = p_neighbors; } // Generate mapping from id to oriented tiles and vice versa. -std::pair>, Vector>> TilingWaveFormCollapse::generate_oriented_tile_ids(const Vector &tiles) { - Vector> id_to_oriented_tile; - Vector> oriented_tile_ids; +void TilingWaveFormCollapse::generate_oriented_tile_ids() { + id_to_oriented_tile.clear(); + oriented_tile_ids.clear(); uint32_t id = 0; for (int i = 0; i < tiles.size(); i++) { oriented_tile_ids.push_back({}); for (int j = 0; j < tiles[i].data.size(); j++) { - id_to_oriented_tile.push_back({ i, j }); - oriented_tile_ids[i].push_back(id); + id_to_oriented_tile.push_back(IdToTilePair(i, j)); + oriented_tile_ids.write[i].push_back(id); id++; } } - - return { id_to_oriented_tile, oriented_tile_ids }; } // Generate the propagator which will be used in the wfc algorithm. -Vector TilingWaveFormCollapse::generate_propagator( - const Vector &neighbors, - Vector tiles, - Vector> id_to_oriented_tile, - Vector> oriented_tile_ids) { - size_t nb_oriented_tiles = id_to_oriented_tile.size(); +void TilingWaveFormCollapse::generate_propagator() { + int nb_oriented_tiles = id_to_oriented_tile.size(); Vector dense_propagator; dense_propagator.resize(nb_oriented_tiles); @@ -190,47 +152,41 @@ Vector TilingWaveFormCollapse::generate_propagator( dense_propagator.write[i].resize(nb_oriented_tiles); } - for (auto neighbor : neighbors) { - uint32_t tile1 = std::get<0>(neighbor); - uint32_t orientation1 = std::get<1>(neighbor); - uint32_t tile2 = std::get<2>(neighbor); - uint32_t orientation2 = std::get<3>(neighbor); - Vector> action_map1 = Tile::generate_action_map(tiles[tile1].symmetry); - Vector> action_map2 = Tile::generate_action_map(tiles[tile2].symmetry); + int size = neighbors.size(); + for (int i = 0; i < size; ++i) { + const NeighbourData &neighbour = neighbors[i]; - auto add = [&](uint32_t action, uint32_t direction) { - uint32_t temp_orientation1 = action_map1[action][orientation1]; - uint32_t temp_orientation2 = action_map2[action][orientation2]; - uint32_t oriented_tile_id1 = oriented_tile_ids[tile1][temp_orientation1]; - uint32_t oriented_tile_id2 = oriented_tile_ids[tile2][temp_orientation2]; - dense_propagator[oriented_tile_id1][direction][oriented_tile_id2] = true; - direction = get_opposite_direction(direction); - dense_propagator[oriented_tile_id2][direction][oriented_tile_id1] = true; - }; + uint32_t tile1 = neighbour.data[0]; + uint32_t tile2 = neighbour.data[2]; + Tile::ActionMap action_map1 = Tile::generate_action_map(tiles[tile1].symmetry); + Tile::ActionMap action_map2 = Tile::generate_action_map(tiles[tile2].symmetry); - add(0, 2); - add(1, 0); - add(2, 1); - add(3, 3); - add(4, 1); - add(5, 3); - add(6, 2); - add(7, 0); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 0, 2); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 1, 0); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 2, 1); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 3, 3); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 4, 1); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 5, 3); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 6, 2); + generate_propagator_add_helper(&action_map1, &action_map2, &dense_propagator, neighbour, 7, 0); } - Vector propagator(nb_oriented_tiles); + Vector propagator; + propagator.resize(nb_oriented_tiles); + + PropagatorStateEntry *propw = propagator.ptrw(); for (size_t i = 0; i < nb_oriented_tiles; ++i) { for (size_t j = 0; j < nb_oriented_tiles; ++j) { for (size_t d = 0; d < 4; ++d) { - if (dense_propagator[i][d][j]) { - propagator[i][d].push_back(j); + if (propw[i].directions[d][j]) { + propw[i].directions[d].push_back(j); } } } } - return propagator; + set_propagator_state(propagator); } // Get probability of presence of tiles. @@ -246,6 +202,24 @@ Vector TilingWaveFormCollapse::get_tiles_weights(const Vector &til return frequencies; } +void TilingWaveFormCollapse::set_tile(uint32_t tile_id, uint32_t i, uint32_t j) { + for (int p = 0; p < id_to_oriented_tile.size(); p++) { + if (tile_id != p) { + remove_wave_pattern(i, j, p); + } + } +} + +Array2D TilingWaveFormCollapse::do_run() { + Array2D a = run(); + + if (a.width == 0 && a.height == 0) { + return Array2D(0, 0); + } + + return id_to_tiling(a); +} + // Translate the generic WFC result into the image result Array2D TilingWaveFormCollapse::id_to_tiling(Array2D ids) { uint32_t size = tiles[0].data[0].height; @@ -253,11 +227,11 @@ Array2D TilingWaveFormCollapse::id_to_tiling(Array2D ids) { for (uint32_t i = 0; i < ids.height; i++) { for (uint32_t j = 0; j < ids.width; j++) { - std::pair oriented_tile = id_to_oriented_tile[ids.get(i, j)]; + IdToTilePair oriented_tile = id_to_oriented_tile[ids.get(i, j)]; for (uint32_t y = 0; y < size; y++) { for (uint32_t x = 0; x < size; x++) { - tiling.get(i * size + y, j * size + x) = tiles[oriented_tile.first].data[oriented_tile.second].get(y, x); + tiling.get(i * size + y, j * size + x) = tiles[oriented_tile.id].data[oriented_tile.oriented_tile].get(y, x); } } } @@ -266,10 +240,34 @@ Array2D TilingWaveFormCollapse::id_to_tiling(Array2D ids) { return tiling; } -void TilingWaveFormCollapse::set_tile(uint32_t tile_id, uint32_t i, uint32_t j) { - for (int p = 0; p < id_to_oriented_tile.size(); p++) { - if (tile_id != p) { - remove_wave_pattern(i, j, p); - } - } +void TilingWaveFormCollapse::initialize() { + generate_oriented_tile_ids(); + + WaveFormCollapse::initialize(); } + +TilingWaveFormCollapse::TilingWaveFormCollapse() { +} +TilingWaveFormCollapse::~TilingWaveFormCollapse() { +} + +void TilingWaveFormCollapse::_bind_methods() { +} + +void TilingWaveFormCollapse::generate_propagator_add_helper(Tile::ActionMap *action_map1, Tile::ActionMap *action_map2, + Vector *dense_propagator, + const NeighbourData &neighbour, uint32_t action, uint32_t direction) { + // -- + uint32_t tile1 = neighbour.data[0]; + uint32_t orientation1 = neighbour.data[1]; + uint32_t tile2 = neighbour.data[2]; + uint32_t orientation2 = neighbour.data[3]; + + uint32_t temp_orientation1 = action_map1->map[action][orientation1]; + uint32_t temp_orientation2 = action_map2->map[action][orientation2]; + uint32_t oriented_tile_id1 = oriented_tile_ids[tile1][temp_orientation1]; + uint32_t oriented_tile_id2 = oriented_tile_ids[tile2][temp_orientation2]; + dense_propagator->write[oriented_tile_id1].directions[direction].write[oriented_tile_id2] = true; + direction = get_opposite_direction(direction); + dense_propagator->write[oriented_tile_id2].directions[direction].write[oriented_tile_id1] = true; +} \ No newline at end of file diff --git a/modules/wfc/tiling_wave_form_collapse.h b/modules/wfc/tiling_wave_form_collapse.h index 717582954..5b4e4a986 100644 --- a/modules/wfc/tiling_wave_form_collapse.h +++ b/modules/wfc/tiling_wave_form_collapse.h @@ -41,8 +41,6 @@ struct Tile { Tile(const Array2D &p_data, Symmetry p_symmetry, double p_weight); }; -// Class generating a new image with the tiling WFC algorithm. - class TilingWaveFormCollapse : WaveFormCollapse { GDCLASS(TilingWaveFormCollapse, WaveFormCollapse); @@ -57,20 +55,6 @@ public: } }; - bool set_tile(uint32_t tile_id, uint32_t orientation, uint32_t i, uint32_t j); - Array2D do_run(); - - void initialize(); - - TilingWaveFormCollapse(); - ~TilingWaveFormCollapse(); - -protected: - static void _bind_methods(); - -private: - static std::pair>, Vector>> generate_oriented_tile_ids(const Vector &tiles); - struct DensePropagatorHelper { Vector directions[4]; @@ -82,22 +66,57 @@ private: } }; - static Vector generate_propagator( - const Vector &neighbors, - Vector tiles, - Vector> id_to_oriented_tile, - Vector> oriented_tile_ids); + struct IdToTilePair { + uint32_t id; + uint32_t oriented_tile; + + IdToTilePair() { + id = 0; + oriented_tile = 0; + } + + IdToTilePair(uint32_t p_id, uint32_t p_oriented_tile) { + id = p_id; + oriented_tile = p_oriented_tile; + } + }; + +public: + void set_tiles(const Vector &p_tiles); + void set_neighbours(const Vector &p_neighbors); + + void generate_oriented_tile_ids(); + + void generate_propagator(); static Vector get_tiles_weights(const Vector &tiles); + void set_tile(uint32_t tile_id, uint32_t i, uint32_t j); + bool set_tile(uint32_t tile_id, uint32_t orientation, uint32_t i, uint32_t j); + + Array2D do_run(); + Array2D id_to_tiling(Array2D ids); - void set_tile(uint32_t tile_id, uint32_t i, uint32_t j); - Vector tiles; - Vector> id_to_oriented_tile; - Vector> oriented_tile_ids; + void initialize(); - bool periodic_output; + TilingWaveFormCollapse(); + ~TilingWaveFormCollapse(); + +protected: + static void _bind_methods(); + +private: + void generate_propagator_add_helper(Tile::ActionMap *action_map1, Tile::ActionMap *action_map2, + Vector *dense_propagator, + const NeighbourData &neighbour, + uint32_t action, uint32_t direction); + + Vector tiles; + Vector neighbors; + + Vector id_to_oriented_tile; + Vector> oriented_tile_ids; }; #endif // FAST_WFC_TILING_WFC_HPP_ diff --git a/modules/wfc/wave_form_collapse.cpp b/modules/wfc/wave_form_collapse.cpp index 4875446d6..19897e265 100644 --- a/modules/wfc/wave_form_collapse.cpp +++ b/modules/wfc/wave_form_collapse.cpp @@ -38,11 +38,18 @@ double WaveFormCollapse::get_min_abs_half(const Vector &v) { return min_abs_half; } -bool WaveFormCollapse::get_eriodic_output() const { - return is_impossible; +uint32_t WaveFormCollapse::get_width() const { + return wave_width; +} +uint32_t WaveFormCollapse::get_height() const { + return wave_height; +} + +bool WaveFormCollapse::get_periodic_output() const { + return periodic_output; } void WaveFormCollapse::set_periodic_output(const bool val) { - is_impossible = val; + periodic_output = val; } void WaveFormCollapse::set_seed(const int seed) { @@ -174,7 +181,7 @@ int WaveFormCollapse::wave_get_min_entropy() const { // The minimum entropy (plus a small noise) double min = Math_INF; - + int argmin = -1; for (uint32_t i = 0; i < wave_size; i++) { @@ -329,9 +336,16 @@ void WaveFormCollapse::initialize() { } WaveFormCollapse::WaveFormCollapse() { - //todo maybe it should be better as true? periodic_output = false; is_impossible = false; + + nb_patterns = 0; + + wave_width = 0; + wave_height = 0; + wave_size = 0; + + min_abs_half_plogp = 0; } WaveFormCollapse::~WaveFormCollapse() { diff --git a/modules/wfc/wave_form_collapse.h b/modules/wfc/wave_form_collapse.h index 609460940..d9911706e 100644 --- a/modules/wfc/wave_form_collapse.h +++ b/modules/wfc/wave_form_collapse.h @@ -54,7 +54,10 @@ public: static constexpr int directions_y[4] = { -1, 0, 0, 1 }; public: - bool get_eriodic_output() const; + uint32_t get_width() const; + uint32_t get_height() const; + + bool get_periodic_output() const; void set_periodic_output(const bool val); void set_seed(const int seed);