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

View File

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

View File

@ -2,16 +2,19 @@
#define FAST_WFC_PROPAGATOR_HPP_
#include "array_3d.h"
#include "direction.h"
#include <array>
#include <tuple>
#include "core/vector.h"
#include "direction.h"
#include <tuple>
class Wave;
class Propagator {
public:
using PropagatorState = Vector<std::array<Vector<uint32_t>, 4>>;
struct PropagatorEntry {
Vector<uint32_t> directions[4];
};
using PropagatorState = Vector<PropagatorEntry>;
private:
const uint32_t patterns_size;
@ -28,12 +31,22 @@ private:
// false.
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
// 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
// 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
Array3D<std::array<int, 4>> compatible;
Array3D<CompatibilityEntry> compatible;
void init_compatible();
@ -51,9 +64,9 @@ public:
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).
std::array<int, 4> temp = {};
CompatibilityEntry temp;
compatible.get(y, x, pattern) = temp;
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_
#define FAST_WFC_TILING_WFC_HPP_
#include <unordered_map>
#include "core/vector.h"
#include <unordered_map>
#include "array_2d.h"
#include "wfc.h"
@ -199,16 +199,30 @@ private:
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.
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,
Vector<Tile<T>> tiles,
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile,
Vector<Vector<uint32_t>> oriented_tile_ids) {
size_t nb_oriented_tiles = id_to_oriented_tile.size();
Vector<std::array<Vector<bool>, 4>> 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) });
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) });
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) {
uint32_t tile1 = std::get<0>(neighbor);
@ -240,7 +254,7 @@ private:
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 j = 0; j < nb_oriented_tiles; ++j) {