mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-25 18:39:18 +01:00
Initial cleanup to the TilingWFC class.
This commit is contained in:
parent
e6e780291f
commit
89541c361b
3
modules/wfc/tiling_wave_form_collapse.cpp
Normal file
3
modules/wfc/tiling_wave_form_collapse.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
//#include "tiling_wave_form_collapse.h"
|
||||||
|
|
@ -1,45 +1,23 @@
|
|||||||
#ifndef FAST_WFC_TILING_WFC_HPP_
|
#ifndef TILING_WAVE_FORM_COLLAPSE_H
|
||||||
#define FAST_WFC_TILING_WFC_HPP_
|
#define TILING_WAVE_FORM_COLLAPSE_H
|
||||||
|
|
||||||
|
#include "array_2d.h"
|
||||||
#include "core/vector.h"
|
#include "core/vector.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "array_2d.h"
|
#include "wave_form_collapse.h"
|
||||||
#include "wfc.h"
|
|
||||||
|
|
||||||
// The distinct symmetries of a tile.
|
|
||||||
// It represents how the tile behave when it is rotated or reflected
|
|
||||||
enum class Symmetry {
|
|
||||||
X,
|
|
||||||
T,
|
|
||||||
I,
|
|
||||||
L,
|
|
||||||
backslash,
|
|
||||||
P
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
// Return the number of possible distinct orientations for a tile.
|
|
||||||
// An orientation is a combination of rotations and reflections.
|
|
||||||
*/
|
|
||||||
constexpr uint32_t nb_of_possible_orientations(const Symmetry &symmetry) {
|
|
||||||
switch (symmetry) {
|
|
||||||
case Symmetry::X:
|
|
||||||
return 1;
|
|
||||||
case Symmetry::I:
|
|
||||||
case Symmetry::backslash:
|
|
||||||
return 2;
|
|
||||||
case Symmetry::T:
|
|
||||||
case Symmetry::L:
|
|
||||||
return 4;
|
|
||||||
default:
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A tile that can be placed on the board.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Tile {
|
struct Tile {
|
||||||
|
enum Symmetry {
|
||||||
|
SYMMETRY_X,
|
||||||
|
SYMMETRY_T,
|
||||||
|
SYMMETRY_I,
|
||||||
|
SYMMETRY_L,
|
||||||
|
SYMMETRY_BACKSLASH,
|
||||||
|
SYMMETRY_P
|
||||||
|
};
|
||||||
|
|
||||||
Vector<Array2D<T>> data; // The different orientations of the tile
|
Vector<Array2D<T>> data; // The different orientations of the tile
|
||||||
Symmetry symmetry; // The symmetry of the tile
|
Symmetry symmetry; // The symmetry of the tile
|
||||||
double weight; // Its weight on the distribution of presence of tiles
|
double weight; // Its weight on the distribution of presence of tiles
|
||||||
@ -102,14 +80,17 @@ struct Tile {
|
|||||||
action_map[a][i] = rotation_map[action_map[a - 1][i]];
|
action_map[a][i] = rotation_map[action_map[a - 1][i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
action_map[4][i] = reflection_map[action_map[0][i]];
|
action_map[4][i] = reflection_map[action_map[0][i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int a = 5; a < 8; ++a) {
|
for (int a = 5; a < 8; ++a) {
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
action_map[a][i] = rotation_map[action_map[a - 1][i]];
|
action_map[a][i] = rotation_map[action_map[a - 1][i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return action_map;
|
return action_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,38 +126,93 @@ struct Tile {
|
|||||||
return oriented;
|
return oriented;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a tile with its differents orientations, its symmetries and its
|
// Return the number of possible distinct orientations for a tile. An orientation is a combination of rotations and reflections.
|
||||||
// weight on the distribution of tiles.
|
static constexpr uint32_t nb_of_possible_orientations(const Symmetry &symmetry) {
|
||||||
Tile(Vector<Array2D<T>> data, Symmetry symmetry, double weight) :
|
switch (symmetry) {
|
||||||
data(data), symmetry(symmetry), weight(weight) {}
|
case SYMMETRY_X:
|
||||||
|
return 1;
|
||||||
|
case SYMMETRY_I:
|
||||||
|
case SYMMETRY_BACKSLASH:
|
||||||
|
return 2;
|
||||||
|
case SYMMETRY_T:
|
||||||
|
case SYMMETRY_L:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a tile with its base orientation, its symmetries and its
|
// Create a tile with its differents orientations, its symmetries and its weight on the distribution of tiles.
|
||||||
// weight on the distribution of tiles.
|
Tile(const Vector<Array2D<T>> &p_data, Symmetry p_symmetry, double p_weight) {
|
||||||
|
data = p_data;
|
||||||
|
symmetry = p_symmetry;
|
||||||
|
weight = p_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a tile with its base orientation, its symmetries and its weight on the distribution of tiles.
|
||||||
// The other orientations are generated with its first one.
|
// The other orientations are generated with its first one.
|
||||||
Tile(Array2D<T> data, Symmetry symmetry, double weight) :
|
Tile(const Array2D<T> &data, Symmetry p_symmetry, double p_weight) {
|
||||||
data(generate_oriented(data, symmetry)), symmetry(symmetry), weight(weight) {}
|
data = generate_oriented(p_data, p_symmetry);
|
||||||
};
|
symmetry = p_symmetry;
|
||||||
|
weight = p_weight;
|
||||||
struct TilingWFCOptions {
|
}
|
||||||
bool periodic_output;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class generating a new image with the tiling WFC algorithm.
|
// Class generating a new image with the tiling WFC algorithm.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TilingWFC {
|
class TilingWFC {
|
||||||
private:
|
|
||||||
Vector<Tile<T>> tiles;
|
|
||||||
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile;
|
|
||||||
Vector<Vector<uint32_t>> oriented_tile_ids;
|
|
||||||
|
|
||||||
TilingWFCOptions options;
|
|
||||||
|
|
||||||
WFC wfc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
|
|
||||||
|
struct NeighbourData {
|
||||||
|
uint32_t data[4];
|
||||||
|
|
||||||
|
NeighbourData() {
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
direction[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TilingWFC(
|
||||||
|
const Vector<Tile<T>> &tiles,
|
||||||
|
const Vector<NeighbourData> &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) {}
|
||||||
|
|
||||||
|
// Returns false if the given tile and orientation does not exist, or if the coordinates are not in the wave
|
||||||
|
bool 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) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t oriented_tile_id = oriented_tile_ids[tile_id][orientation];
|
||||||
|
set_tile(oriented_tile_id, i, j);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array2D<T> run() {
|
||||||
|
Array2D<uint32_t> a = wfc.run();
|
||||||
|
|
||||||
|
if (a.width == 0 && a.height == 0) {
|
||||||
|
return Array2D<T>(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id_to_tiling(a);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Generate mapping from id to oriented tiles and vice versa.
|
// Generate mapping from id to oriented tiles and vice versa.
|
||||||
static std::pair<Vector<std::pair<uint32_t, uint32_t>>, Vector<Vector<uint32_t>>> generate_oriented_tile_ids(const Vector<Tile<T>> &tiles) {
|
static std::pair<Vector<std::pair<uint32_t, uint32_t>>, Vector<Vector<uint32_t>>> generate_oriented_tile_ids(const Vector<Tile<T>> &tiles) {
|
||||||
@ -213,7 +249,6 @@ private:
|
|||||||
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<DensePropagatorHelper> dense_propagator;
|
Vector<DensePropagatorHelper> dense_propagator;
|
||||||
@ -306,58 +341,13 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
Vector<Tile<T>> tiles;
|
||||||
struct NeighbourData {
|
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile;
|
||||||
uint32_t data[4];
|
Vector<Vector<uint32_t>> oriented_tile_ids;
|
||||||
|
|
||||||
NeighbourData() {
|
bool periodic_output;
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
direction[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Construct the TilingWFC class to generate a tiled image.
|
WFC wfc;
|
||||||
TilingWFC(
|
|
||||||
const Vector<Tile<T>> &tiles,
|
|
||||||
const Vector<NeighbourData> &neighbors,
|
|
||||||
const uint32_t height, const uint32_t width,
|
|
||||||
const TilingWFCOptions &options, 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) {}
|
|
||||||
|
|
||||||
// Set the tile at a specific position.
|
|
||||||
// Returns false if the given tile and orientation does not exist,
|
|
||||||
// or if the coordinates are not in the wave
|
|
||||||
bool 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) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t oriented_tile_id = oriented_tile_ids[tile_id][orientation];
|
|
||||||
set_tile(oriented_tile_id, i, j);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the tiling wfc and return the result if the algorithm succeeded
|
|
||||||
Array2D<T> run() {
|
|
||||||
Array2D<uint32_t> a = wfc.run();
|
|
||||||
|
|
||||||
if (a.width == 0 && a.height == 0) {
|
|
||||||
return Array2D<T>(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return id_to_tiling(a);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FAST_WFC_TILING_WFC_HPP_
|
#endif // FAST_WFC_TILING_WFC_HPP_
|
Loading…
Reference in New Issue
Block a user