Got rid of std::arrays in the wfc module.

This commit is contained in:
Relintai 2022-04-21 17:05:26 +02:00
parent e4a2429b45
commit bb723e3c44
4 changed files with 50 additions and 22 deletions

View File

@ -43,7 +43,7 @@ private:
const Array2D<T> &input, const OverlappingWFCOptions &options, const Array2D<T> &input, const OverlappingWFCOptions &options,
const int &seed, const int &seed,
const std::pair<Vector<Array2D<T>>, Vector<double>> &patterns, const std::pair<Vector<Array2D<T>>, Vector<double>> &patterns,
const Vector<std::array<Vector<uint32_t>, 4>> &propagator) : const Vector<PropagatorEntry> &propagator) :
input(input), options(options), patterns(patterns.first), wfc(options.periodic_output, seed, patterns.second, propagator, options.get_wave_height(), options.get_wave_width()) { input(input), options(options), patterns(patterns.first), wfc(options.periodic_output, seed, patterns.second, propagator, options.get_wave_height(), options.get_wave_width()) {
// If necessary, the ground is set. // If necessary, the ground is set.
if (options.ground) { if (options.ground) {
@ -156,8 +156,8 @@ private:
// If agrees(pattern1, pattern2, dy, dx), then compatible[pattern1][direction] // If agrees(pattern1, pattern2, dy, dx), then compatible[pattern1][direction]
// contains pattern2, where direction is the direction defined by (dy, dx) // contains pattern2, where direction is the direction defined by (dy, dx)
// (see direction.hpp). // (see direction.hpp).
static Vector<std::array<Vector<uint32_t>, 4>> generate_compatible(const Vector<Array2D<T>> &patterns) { static Vector<PropagatorEntry> generate_compatible(const Vector<Array2D<T>> &patterns) {
Vector<std::array<Vector<uint32_t>, 4>> compatible = Vector<std::array<Vector<uint32_t>, 4>>(patterns.size()); Vector<PropagatorEntry> compatible = Vector<PropagatorEntry>(patterns.size());
// Iterate on every dy, dx, pattern1 and pattern2 // Iterate on every dy, dx, pattern1 and pattern2
for (uint32_t pattern1 = 0; pattern1 < patterns.size(); pattern1++) { for (uint32_t pattern1 = 0; pattern1 < patterns.size(); pattern1++) {

View File

@ -2,13 +2,14 @@
#include "wave.h" #include "wave.h"
void Propagator::init_compatible() { void Propagator::init_compatible() {
std::array<int, 4> value; CompatibilityEntry value;
// We compute the number of pattern compatible in all directions. // We compute the number of pattern compatible in all directions.
for (uint32_t y = 0; y < wave_height; y++) { for (uint32_t y = 0; y < wave_height; y++) {
for (uint32_t x = 0; x < wave_width; x++) { for (uint32_t x = 0; x < wave_width; x++) {
for (uint32_t pattern = 0; pattern < patterns_size; pattern++) { for (uint32_t pattern = 0; pattern < patterns_size; pattern++) {
for (int direction = 0; direction < 4; direction++) { for (int direction = 0; direction < 4; direction++) {
value[direction] = static_cast<uint32_t>(propagator_state[pattern][get_opposite_direction(direction)].size()); value.direction[direction] = static_cast<uint32_t>(propagator_state[pattern].directions[get_opposite_direction(direction)].size());
} }
compatible.get(y, x, pattern) = value; compatible.get(y, x, pattern) = value;
@ -47,7 +48,7 @@ void Propagator::propagate(Wave &wave) {
// The index of the second cell, and the patterns compatible // The index of the second cell, and the patterns compatible
uint32_t i2 = x2 + y2 * wave.width; uint32_t i2 = x2 + y2 * wave.width;
const Vector<uint32_t> &patterns = propagator_state[pattern][direction]; const Vector<uint32_t> &patterns = propagator_state[pattern].directions[direction];
// For every pattern that could be placed in that cell without being in // For every pattern that could be placed in that cell without being in
// contradiction with pattern1 // contradiction with pattern1
@ -58,12 +59,12 @@ void Propagator::propagate(Wave &wave) {
// We decrease the number of compatible patterns in the opposite // We decrease the number of compatible patterns in the opposite
// direction If the pattern was discarded from the wave, the element // direction If the pattern was discarded from the wave, the element
// is still negative, which is not a problem // is still negative, which is not a problem
std::array<int, 4> &value = compatible.get(y2, x2, pattern); CompatibilityEntry &value = compatible.get(y2, x2, pattern);
value[direction]--; value.direction[direction]--;
// If the element was set to 0 with this operation, we need to remove // If the element was set to 0 with this operation, we need to remove
// the pattern from the wave, and propagate the information // the pattern from the wave, and propagate the information
if (value[direction] == 0) { if (value.direction[direction] == 0) {
add_to_propagator(y2, x2, pattern); add_to_propagator(y2, x2, pattern);
wave.set(i2, pattern, false); wave.set(i2, pattern, false);
} }

View File

@ -2,16 +2,19 @@
#define FAST_WFC_PROPAGATOR_HPP_ #define FAST_WFC_PROPAGATOR_HPP_
#include "array_3d.h" #include "array_3d.h"
#include "direction.h"
#include <array>
#include <tuple>
#include "core/vector.h" #include "core/vector.h"
#include "direction.h"
#include <tuple>
class Wave; class Wave;
class Propagator { class Propagator {
public: public:
using PropagatorState = Vector<std::array<Vector<uint32_t>, 4>>; struct PropagatorEntry {
Vector<uint32_t> directions[4];
};
using PropagatorState = Vector<PropagatorEntry>;
private: private:
const uint32_t patterns_size; const uint32_t patterns_size;
@ -28,12 +31,22 @@ private:
// false. // false.
Vector<std::tuple<uint32_t, uint32_t, uint32_t>> propagating; Vector<std::tuple<uint32_t, uint32_t, uint32_t>> propagating;
struct CompatibilityEntry {
int direction[4];
CompatibilityEntry() {
for (int i = 0; i < 4; ++i) {
direction[i] = 0;
}
}
};
// compatible.get(y, x, pattern)[direction] contains the number of patterns // compatible.get(y, x, pattern)[direction] contains the number of patterns
// present in the wave that can be placed in the cell next to (y,x) in the // present in the wave that can be placed in the cell next to (y,x) in the
// opposite direction of direction without being in contradiction with pattern // opposite direction of direction without being in contradiction with pattern
// placed in (y,x). If wave.get(y, x, pattern) is set to false, then // placed in (y,x). If wave.get(y, x, pattern) is set to false, then
// compatible.get(y, x, pattern) has every element negative or null // compatible.get(y, x, pattern) has every element negative or null
Array3D<std::array<int, 4>> compatible; Array3D<CompatibilityEntry> compatible;
void init_compatible(); void init_compatible();
@ -51,9 +64,9 @@ public:
void add_to_propagator(uint32_t y, uint32_t x, uint32_t pattern) { void add_to_propagator(uint32_t y, uint32_t x, uint32_t pattern) {
// All the direction are set to 0, since the pattern cannot be set in (y,x). // All the direction are set to 0, since the pattern cannot be set in (y,x).
std::array<int, 4> temp = {}; CompatibilityEntry temp;
compatible.get(y, x, pattern) = temp; compatible.get(y, x, pattern) = temp;
propagating.push_back(std::tuple<uint32_t, uint32_t, uint32_t>(y, x, pattern)); propagating.push_back(std::tuple<uint32_t, uint32_t, uint32_t>(y, x, pattern));
} }

View File

@ -1,8 +1,8 @@
#ifndef FAST_WFC_TILING_WFC_HPP_ #ifndef FAST_WFC_TILING_WFC_HPP_
#define FAST_WFC_TILING_WFC_HPP_ #define FAST_WFC_TILING_WFC_HPP_
#include <unordered_map>
#include "core/vector.h" #include "core/vector.h"
#include <unordered_map>
#include "array_2d.h" #include "array_2d.h"
#include "wfc.h" #include "wfc.h"
@ -199,16 +199,30 @@ private:
return { id_to_oriented_tile, oriented_tile_ids }; return { id_to_oriented_tile, oriented_tile_ids };
} }
struct DensePropagatorHelper {
Vector<bool> directions[4];
void resize(const int size) {
for (int i = 0; i < 4; ++i) {
directions[i].resize(size);
directions[i].fill(false);
}
}
};
// Generate the propagator which will be used in the wfc algorithm. // Generate the propagator which will be used in the wfc algorithm.
static Vector<std::array<Vector<uint32_t>, 4>> generate_propagator( static Vector<PropagatorEntry> generate_propagator(
const Vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>> &neighbors, const Vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>> &neighbors,
Vector<Tile<T>> tiles, Vector<Tile<T>> tiles,
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile, Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile,
Vector<Vector<uint32_t>> oriented_tile_ids) { Vector<Vector<uint32_t>> oriented_tile_ids) {
size_t nb_oriented_tiles = id_to_oriented_tile.size(); size_t nb_oriented_tiles = id_to_oriented_tile.size();
Vector<std::array<Vector<bool>, 4>> dense_propagator( Vector<DensePropagatorHelper> dense_propagator(nb_oriented_tiles, { Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false) });
nb_oriented_tiles, { Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false) }); dense_propagator.resize(nb_oriented_tiles);
for (int i = 0; i < nb_oriented_tiles; ++i) {
dense_propagator.write[i].resize(nb_oriented_tiles);
}
for (auto neighbor : neighbors) { for (auto neighbor : neighbors) {
uint32_t tile1 = std::get<0>(neighbor); uint32_t tile1 = std::get<0>(neighbor);
@ -240,7 +254,7 @@ private:
add(7, 0); add(7, 0);
} }
Vector<std::array<Vector<uint32_t>, 4>> propagator(nb_oriented_tiles); Vector<PropagatorEntry> propagator(nb_oriented_tiles);
for (size_t i = 0; i < nb_oriented_tiles; ++i) { for (size_t i = 0; i < nb_oriented_tiles; ++i) {
for (size_t j = 0; j < nb_oriented_tiles; ++j) { for (size_t j = 0; j < nb_oriented_tiles; ++j) {