pandemonium_engine/modules/wfc/tiling_wave_form_collapse.h

204 lines
7.6 KiB
C++

#ifndef TILING_WAVE_FORM_COLLAPSE_H
#define TILING_WAVE_FORM_COLLAPSE_H
/*************************************************************************/
/* tiling_wave_form_collapse.h */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://github.com/Relintai/pandemonium_engine */
/*************************************************************************/
/* Copyright (c) 2022-present Péter Magyar. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "array_2d.h"
#include "core/containers/vector.h"
#include "wave_form_collapse.h"
struct Tile {
struct ActionMap {
Vector<int> map[8];
void set_size(int size) {
for (int i = 0; i < 8; ++i) {
map[i].resize(size);
}
}
void zero() {
for (int i = 0; i < 8; ++i) {
map[i].fill(0);
}
}
};
static const uint8_t ROTATION_MAP[6][9];
static const uint8_t REFLECTION_MAP[6][9];
String name;
Vector<Array2D<int>> data;
WaveFormCollapse::Symmetry symmetry;
double weight;
static ActionMap generate_action_map(const WaveFormCollapse::Symmetry symmetry);
static Vector<Array2D<int>> generate_oriented(Array2D<int> data, WaveFormCollapse::Symmetry symmetry);
void set_generate_data(const PoolIntArray &p_data, const int width, const int height);
PoolIntArray data_get(const int index);
void data_set(const int index, const PoolIntArray &p_data, const int width, const int height);
void data_remove(const int index);
Tile();
Tile(WaveFormCollapse::Symmetry p_symmetry, double p_weight);
Tile(const Vector<Array2D<int>> &p_data, WaveFormCollapse::Symmetry p_symmetry, double p_weight);
Tile(const Array2D<int> &p_data, WaveFormCollapse::Symmetry p_symmetry, double p_weight);
Tile(const PoolIntArray &p_data, const int width, const int height, WaveFormCollapse::Symmetry p_symmetry, double p_weight);
};
class TilingWaveFormCollapse : public WaveFormCollapse {
GDCLASS(TilingWaveFormCollapse, WaveFormCollapse);
public:
struct NeighbourData {
int data[4];
NeighbourData() {
for (int i = 0; i < 4; ++i) {
data[i] = 0;
}
}
NeighbourData(const int n1, const int n2, const int n3, const int n4) {
data[0] = n1;
data[1] = n2;
data[2] = n3;
data[3] = n4;
}
};
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);
}
}
};
struct IdToTilePair {
int id;
int oriented_tile;
IdToTilePair() {
id = 0;
oriented_tile = 0;
}
IdToTilePair(int p_id, int p_oriented_tile) {
id = p_id;
oriented_tile = p_oriented_tile;
}
};
public:
int tile_add_generated(const PoolIntArray &data, const int width, const int height, const WaveFormCollapse::Symmetry symmetry, const float weight);
int tile_add(const WaveFormCollapse::Symmetry symmetry, const float weight);
int tile_create();
void tile_remove(const int tile_index);
int tile_count_get();
void tile_data_add(const int tile_index, const PoolIntArray &data, const int width, const int height);
void tile_data_generated_add(const int tile_index, const PoolIntArray &data, const int width, const int height);
PoolIntArray tile_data_get(const int tile_index, const int data_index);
void tile_data_set(const int tile_index, const int data_index, const PoolIntArray &data, const int width, const int height);
void tile_data_remove(const int tile_index, const int data_index);
void tile_data_clear(const int tile_index);
int tile_data_count_get(const int tile_index);
int tile_data_required_count_get(const int tile_index);
int tile_width_get(const int tile_index, const int data_index);
int tile_height_get(const int tile_index, const int data_index);
WaveFormCollapse::Symmetry tile_symmetry_get(const int tile_index);
void tile_symmetry_set(const int tile_index, const WaveFormCollapse::Symmetry val);
float tile_weight_get(const int tile_index);
void tile_weight_set(const int tile_index, const float val);
String tile_name_get(const int tile_index);
void tile_name_set(const int tile_index, const String &val);
int tile_index_get(const String &tile_name);
int neighbour_data_add(const int left, const int left_orientation, const int right, const int right_orientation);
int neighbour_data_add_str(const String &left, const int left_orientation, const String &right, const int right_orientation);
PoolIntArray neighbour_data_get(const int index);
void neighbour_data_remove(const int index);
void neighbour_data_set(const int index, const int left, const int left_orientation, const int right, const int right_orientation);
void neighbour_data_set_str(const int index, const String &left, const int left_orientation, const String &right, const int right_orientation);
bool neighbour_data_validate(const int tile_index, const int orientation);
bool neighbour_data_validate_str(const String &tile_name, const int orientation);
void set_tiles(const Vector<Tile> &p_tiles);
void set_neighbours(const Vector<NeighbourData> &p_neighbors);
void generate_oriented_tile_ids();
void generate_propagator();
static Vector<double> get_tiles_weights(const Vector<Tile> &tiles);
void set_tile(int tile_id, int i, int j);
bool set_tile(int tile_id, int orientation, int i, int j);
Array2D<int> run();
Array2D<int> id_to_tiling(Array2D<int> ids);
bool validate();
void initialize();
TilingWaveFormCollapse();
~TilingWaveFormCollapse();
protected:
static void _bind_methods();
private:
void generate_propagator_add_helper(const Tile::ActionMap &action_map1, const Tile::ActionMap &action_map2,
Vector<DensePropagatorHelper> *dense_propagator,
const NeighbourData &neighbour,
int action, int direction);
Vector<Tile> _tiles;
Vector<NeighbourData> _neighbors;
Vector<IdToTilePair> _id_to_oriented_tile;
Vector<Vector<int>> _oriented_tile_ids;
};
#endif