mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-30 21:09:19 +01:00
Lots of work on the bindings for the wfc module. Also smaller improvements.
This commit is contained in:
parent
0f1c04e08d
commit
2f81373562
@ -3,8 +3,46 @@
|
||||
|
||||
#include "core/set.h"
|
||||
|
||||
void OverlappingWaveFormCollapse::set_input(const Array2D<int> &data) {
|
||||
input = data;
|
||||
bool OverlappingWaveFormCollapse::get_periodic_input() const {
|
||||
return periodic_input;
|
||||
}
|
||||
void OverlappingWaveFormCollapse::set_periodic_input(const bool val) {
|
||||
periodic_input = val;
|
||||
}
|
||||
|
||||
int OverlappingWaveFormCollapse::get_out_height() const {
|
||||
return out_height;
|
||||
}
|
||||
void OverlappingWaveFormCollapse::set_out_height(const int val) {
|
||||
out_height = val;
|
||||
}
|
||||
|
||||
int OverlappingWaveFormCollapse::get_out_width() const {
|
||||
return out_width;
|
||||
}
|
||||
void OverlappingWaveFormCollapse::set_out_width(const int val) {
|
||||
periodic_output = val;
|
||||
}
|
||||
|
||||
int OverlappingWaveFormCollapse::get_symmetry() const {
|
||||
return symmetry;
|
||||
}
|
||||
void OverlappingWaveFormCollapse::set_symmetry(const int val) {
|
||||
symmetry = val;
|
||||
}
|
||||
|
||||
bool OverlappingWaveFormCollapse::get_ground() const {
|
||||
return ground;
|
||||
}
|
||||
void OverlappingWaveFormCollapse::set_ground(const bool val) {
|
||||
ground = val;
|
||||
}
|
||||
|
||||
int OverlappingWaveFormCollapse::get_pattern_size() const {
|
||||
return pattern_size;
|
||||
}
|
||||
void OverlappingWaveFormCollapse::set_pattern_size(const int val) {
|
||||
pattern_size = val;
|
||||
}
|
||||
|
||||
int OverlappingWaveFormCollapse::get_wave_height() const {
|
||||
@ -17,8 +55,8 @@ int OverlappingWaveFormCollapse::get_wave_width() const {
|
||||
}
|
||||
|
||||
// Run the WFC algorithm, and return the result if the algorithm succeeded.
|
||||
Array2D<int> OverlappingWaveFormCollapse::orun() {
|
||||
Array2D<int> result = run();
|
||||
Array2D<int> OverlappingWaveFormCollapse::run() {
|
||||
Array2D<int> result = WaveFormCollapse::run();
|
||||
|
||||
if (result.width == 0 && result.height == 0) {
|
||||
return Array2D<int>(0, 0);
|
||||
@ -248,7 +286,6 @@ void OverlappingWaveFormCollapse::initialize() {
|
||||
|
||||
OverlappingWaveFormCollapse::OverlappingWaveFormCollapse() {
|
||||
periodic_input = false;
|
||||
periodic_output = false;
|
||||
out_height = 0;
|
||||
out_width = 0;
|
||||
symmetry = 0;
|
||||
@ -259,4 +296,27 @@ OverlappingWaveFormCollapse::~OverlappingWaveFormCollapse() {
|
||||
}
|
||||
|
||||
void OverlappingWaveFormCollapse::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_periodic_input"), &OverlappingWaveFormCollapse::get_periodic_input);
|
||||
ClassDB::bind_method(D_METHOD("set_periodic_input", "value"), &OverlappingWaveFormCollapse::set_periodic_input);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "periodic_input"), "set_periodic_input", "get_periodic_input");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_out_height"), &OverlappingWaveFormCollapse::get_out_height);
|
||||
ClassDB::bind_method(D_METHOD("set_out_height", "value"), &OverlappingWaveFormCollapse::set_out_height);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "out_height"), "set_out_height", "get_out_height");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_out_width"), &OverlappingWaveFormCollapse::get_out_width);
|
||||
ClassDB::bind_method(D_METHOD("set_out_width", "value"), &OverlappingWaveFormCollapse::set_out_width);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "out_width"), "set_out_width", "get_out_width");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_symmetry"), &OverlappingWaveFormCollapse::get_symmetry);
|
||||
ClassDB::bind_method(D_METHOD("set_symmetry", "value"), &OverlappingWaveFormCollapse::set_symmetry);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "symmetry"), "set_symmetry", "get_symmetry");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_ground"), &OverlappingWaveFormCollapse::get_ground);
|
||||
ClassDB::bind_method(D_METHOD("set_ground", "value"), &OverlappingWaveFormCollapse::set_ground);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ground"), "set_ground", "get_ground");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_pattern_size"), &OverlappingWaveFormCollapse::get_pattern_size);
|
||||
ClassDB::bind_method(D_METHOD("set_pattern_size", "value"), &OverlappingWaveFormCollapse::set_pattern_size);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "pattern_size"), "set_pattern_size", "get_pattern_size");
|
||||
}
|
||||
|
@ -10,20 +10,28 @@ class OverlappingWaveFormCollapse : public WaveFormCollapse {
|
||||
GDCLASS(OverlappingWaveFormCollapse, WaveFormCollapse);
|
||||
|
||||
public:
|
||||
bool periodic_input;
|
||||
bool periodic_output;
|
||||
int out_height;
|
||||
int out_width;
|
||||
int symmetry;
|
||||
bool ground;
|
||||
int pattern_size;
|
||||
bool get_periodic_input() const;
|
||||
void set_periodic_input(const bool val);
|
||||
|
||||
void set_input(const Array2D<int> &data);
|
||||
int get_out_height() const;
|
||||
void set_out_height(const int val);
|
||||
|
||||
int get_out_width() const;
|
||||
void set_out_width(const int val);
|
||||
|
||||
int get_symmetry() const;
|
||||
void set_symmetry(const int val);
|
||||
|
||||
bool get_ground() const;
|
||||
void set_ground(const bool val);
|
||||
|
||||
int get_pattern_size() const;
|
||||
void set_pattern_size(const int val);
|
||||
|
||||
int get_wave_height() const;
|
||||
int get_wave_width() const;
|
||||
|
||||
Array2D<int> orun();
|
||||
Array2D<int> run();
|
||||
|
||||
void init_ground();
|
||||
|
||||
@ -48,9 +56,14 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
Array2D<int> input;
|
||||
|
||||
Vector<Array2D<int>> patterns;
|
||||
|
||||
bool periodic_input;
|
||||
int out_height;
|
||||
int out_width;
|
||||
int symmetry;
|
||||
bool ground;
|
||||
int pattern_size;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@ const uint8_t Tile::reflection_map[6][9] = {
|
||||
// Actions 0, 1, 2, and 3 are 0°, 90°, 180°, and 270° anticlockwise rotations.
|
||||
// Actions 4, 5, 6, and 7 are actions 0, 1, 2, and 3 preceded by a reflection
|
||||
// on the x axis.
|
||||
Tile::ActionMap Tile::generate_action_map(const Symmetry &symmetry) {
|
||||
Tile::ActionMap Tile::generate_action_map(const WaveFormCollapse::Symmetry &symmetry) {
|
||||
int sindx = static_cast<int>(symmetry);
|
||||
int size = rotation_map[sindx][0];
|
||||
|
||||
@ -60,22 +60,22 @@ Tile::ActionMap Tile::generate_action_map(const Symmetry &symmetry) {
|
||||
}
|
||||
|
||||
// Generate all distincts rotations of a 2D array given its symmetries;
|
||||
Vector<Array2D<int>> Tile::generate_oriented(Array2D<int> data, Symmetry symmetry) {
|
||||
Vector<Array2D<int>> Tile::generate_oriented(Array2D<int> data, WaveFormCollapse::Symmetry symmetry) {
|
||||
Vector<Array2D<int>> oriented;
|
||||
oriented.push_back(data);
|
||||
|
||||
switch (symmetry) {
|
||||
case SYMMETRY_I:
|
||||
case SYMMETRY_BACKSLASH:
|
||||
case WaveFormCollapse::SYMMETRY_I:
|
||||
case WaveFormCollapse::SYMMETRY_BACKSLASH:
|
||||
oriented.push_back(data.rotated());
|
||||
break;
|
||||
case SYMMETRY_T:
|
||||
case SYMMETRY_L:
|
||||
case WaveFormCollapse::SYMMETRY_T:
|
||||
case WaveFormCollapse::SYMMETRY_L:
|
||||
oriented.push_back(data = data.rotated());
|
||||
oriented.push_back(data = data.rotated());
|
||||
oriented.push_back(data = data.rotated());
|
||||
break;
|
||||
case SYMMETRY_P:
|
||||
case WaveFormCollapse::SYMMETRY_P:
|
||||
oriented.push_back(data = data.rotated());
|
||||
oriented.push_back(data = data.rotated());
|
||||
oriented.push_back(data = data.rotated());
|
||||
@ -92,7 +92,7 @@ Vector<Array2D<int>> Tile::generate_oriented(Array2D<int> data, Symmetry symmetr
|
||||
}
|
||||
|
||||
// Create a tile with its differents orientations, its symmetries and its weight on the distribution of tiles.
|
||||
Tile::Tile(const Vector<Array2D<int>> &p_data, Symmetry p_symmetry, double p_weight) {
|
||||
Tile::Tile(const Vector<Array2D<int>> &p_data, WaveFormCollapse::Symmetry p_symmetry, double p_weight) {
|
||||
data = p_data;
|
||||
symmetry = p_symmetry;
|
||||
weight = p_weight;
|
||||
@ -100,7 +100,7 @@ Tile::Tile(const Vector<Array2D<int>> &p_data, Symmetry p_symmetry, double p_wei
|
||||
|
||||
// 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.
|
||||
Tile::Tile(const Array2D<int> &p_data, Symmetry p_symmetry, double p_weight) {
|
||||
Tile::Tile(const Array2D<int> &p_data, WaveFormCollapse::Symmetry p_symmetry, double p_weight) {
|
||||
data = generate_oriented(p_data, p_symmetry);
|
||||
symmetry = p_symmetry;
|
||||
weight = p_weight;
|
||||
@ -211,8 +211,8 @@ void TilingWaveFormCollapse::set_tile(int tile_id, int i, int j) {
|
||||
}
|
||||
}
|
||||
|
||||
Array2D<int> TilingWaveFormCollapse::do_run() {
|
||||
Array2D<int> a = run();
|
||||
Array2D<int> TilingWaveFormCollapse::run() {
|
||||
Array2D<int> a = WaveFormCollapse::run();
|
||||
|
||||
if (a.width == 0 && a.height == 0) {
|
||||
return Array2D<int>(0, 0);
|
||||
@ -243,6 +243,7 @@ Array2D<int> TilingWaveFormCollapse::id_to_tiling(Array2D<int> ids) {
|
||||
|
||||
void TilingWaveFormCollapse::initialize() {
|
||||
generate_oriented_tile_ids();
|
||||
generate_propagator();
|
||||
|
||||
WaveFormCollapse::initialize();
|
||||
}
|
||||
|
@ -7,14 +7,6 @@
|
||||
#include "wave_form_collapse.h"
|
||||
|
||||
struct Tile {
|
||||
enum Symmetry {
|
||||
SYMMETRY_X = 0,
|
||||
SYMMETRY_T,
|
||||
SYMMETRY_I,
|
||||
SYMMETRY_L,
|
||||
SYMMETRY_BACKSLASH,
|
||||
SYMMETRY_P
|
||||
};
|
||||
|
||||
struct ActionMap {
|
||||
Vector<int> map[8];
|
||||
@ -30,15 +22,15 @@ struct Tile {
|
||||
static const uint8_t reflection_map[6][9];
|
||||
|
||||
Vector<Array2D<int>> data;
|
||||
Symmetry symmetry;
|
||||
WaveFormCollapse::Symmetry symmetry;
|
||||
double weight;
|
||||
|
||||
static ActionMap generate_action_map(const Symmetry &symmetry);
|
||||
static ActionMap generate_action_map(const WaveFormCollapse::Symmetry &symmetry);
|
||||
|
||||
static Vector<Array2D<int>> generate_oriented(Array2D<int> data, Symmetry symmetry);
|
||||
static Vector<Array2D<int>> generate_oriented(Array2D<int> data, WaveFormCollapse::Symmetry symmetry);
|
||||
|
||||
Tile(const Vector<Array2D<int>> &p_data, Symmetry p_symmetry, double p_weight);
|
||||
Tile(const Array2D<int> &p_data, 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);
|
||||
};
|
||||
|
||||
class TilingWaveFormCollapse : public WaveFormCollapse {
|
||||
@ -94,7 +86,7 @@ public:
|
||||
void set_tile(int tile_id, int i, int j);
|
||||
bool set_tile(int tile_id, int orientation, int i, int j);
|
||||
|
||||
Array2D<int> do_run();
|
||||
Array2D<int> run();
|
||||
|
||||
Array2D<int> id_to_tiling(Array2D<int> ids);
|
||||
|
||||
|
@ -77,6 +77,23 @@ void WaveFormCollapse::set_pattern_frequencies(const Vector<double> &p_patterns_
|
||||
}
|
||||
}
|
||||
|
||||
void WaveFormCollapse::set_input(const PoolIntArray &p_data, int p_width, int p_height) {
|
||||
set_size(p_width, p_height);
|
||||
|
||||
input.resize(p_width, p_height);
|
||||
|
||||
ERR_FAIL_COND(input.data.size() != p_data.size());
|
||||
|
||||
int *w = input.data.ptrw();
|
||||
int s = input.data.size();
|
||||
|
||||
PoolIntArray::Read r = p_data.read();
|
||||
|
||||
for (int i = 0; i < s; ++i) {
|
||||
w[i] = r[i];
|
||||
}
|
||||
}
|
||||
|
||||
Array2D<int> WaveFormCollapse::run() {
|
||||
while (true) {
|
||||
// Define the value of an undefined cell.
|
||||
@ -93,6 +110,34 @@ Array2D<int> WaveFormCollapse::run() {
|
||||
}
|
||||
}
|
||||
|
||||
PoolIntArray WaveFormCollapse::generate_image_index_data() {
|
||||
PoolIntArray arr;
|
||||
|
||||
Array2D<int> a = run();
|
||||
|
||||
if (a.width == 0 && a.height == 0) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
print_error(String::num(a.width));
|
||||
print_error(String::num(a.height));
|
||||
print_error("---");
|
||||
|
||||
const int *r = a.data.ptr();
|
||||
int s = a.data.size();
|
||||
|
||||
arr.resize(s);
|
||||
PoolIntArray::Write w = arr.write();
|
||||
|
||||
for (int i = 0; i < s; ++i) {
|
||||
w[i] = r[i];
|
||||
}
|
||||
|
||||
w.release();
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
WaveFormCollapse::ObserveStatus WaveFormCollapse::observe() {
|
||||
// Get the cell with lowest entropy.
|
||||
int argmin = wave_get_min_entropy();
|
||||
@ -299,6 +344,7 @@ void WaveFormCollapse::propagate() {
|
||||
|
||||
void WaveFormCollapse::initialize() {
|
||||
//wave
|
||||
data.resize(0, 0);
|
||||
data.resize_fill(wave_width * wave_height, patterns_frequencies.size(), 1);
|
||||
|
||||
plogp_patterns_frequencies = get_plogp(patterns_frequencies);
|
||||
@ -354,5 +400,28 @@ WaveFormCollapse::WaveFormCollapse() {
|
||||
WaveFormCollapse::~WaveFormCollapse() {
|
||||
}
|
||||
|
||||
void WaveFormCollapse::bind_methods() {
|
||||
void WaveFormCollapse::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_width"), &WaveFormCollapse::get_width);
|
||||
ClassDB::bind_method(D_METHOD("get_height"), &WaveFormCollapse::get_height);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_periodic_output"), &WaveFormCollapse::get_periodic_output);
|
||||
ClassDB::bind_method(D_METHOD("set_periodic_output", "value"), &WaveFormCollapse::set_periodic_output);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "periodic_output"), "set_periodic_output", "get_periodic_output");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &WaveFormCollapse::set_seed);
|
||||
ClassDB::bind_method(D_METHOD("set_size", "width", "height"), &WaveFormCollapse::set_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("propagate"), &WaveFormCollapse::propagate);
|
||||
ClassDB::bind_method(D_METHOD("initialize"), &WaveFormCollapse::initialize);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_input", "data", "width", "height"), &WaveFormCollapse::set_input);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("generate_image_index_data"), &WaveFormCollapse::generate_image_index_data);
|
||||
|
||||
BIND_ENUM_CONSTANT(SYMMETRY_X);
|
||||
BIND_ENUM_CONSTANT(SYMMETRY_T);
|
||||
BIND_ENUM_CONSTANT(SYMMETRY_I);
|
||||
BIND_ENUM_CONSTANT(SYMMETRY_L);
|
||||
BIND_ENUM_CONSTANT(SYMMETRY_BACKSLASH);
|
||||
BIND_ENUM_CONSTANT(SYMMETRY_P);
|
||||
}
|
@ -14,6 +14,15 @@ class WaveFormCollapse : public Reference {
|
||||
GDCLASS(WaveFormCollapse, Reference);
|
||||
|
||||
public:
|
||||
enum Symmetry {
|
||||
SYMMETRY_X = 0,
|
||||
SYMMETRY_T,
|
||||
SYMMETRY_I,
|
||||
SYMMETRY_L,
|
||||
SYMMETRY_BACKSLASH,
|
||||
SYMMETRY_P
|
||||
};
|
||||
|
||||
enum ObserveStatus {
|
||||
OBSERVE_STATUS_SUCCESS,
|
||||
OBSERVE_STATUS_FAILURE,
|
||||
@ -67,7 +76,11 @@ public:
|
||||
void set_propagator_state(const Vector<PropagatorStateEntry> &p_propagator_state);
|
||||
void set_pattern_frequencies(const Vector<double> &p_patterns_frequencies, const bool p_normalize = true);
|
||||
|
||||
Array2D<int> run();
|
||||
virtual void set_input(const PoolIntArray &p_data, int p_width, int p_height);
|
||||
|
||||
virtual Array2D<int> run();
|
||||
|
||||
PoolIntArray generate_image_index_data();
|
||||
|
||||
ObserveStatus observe();
|
||||
|
||||
@ -125,7 +138,11 @@ public:
|
||||
~WaveFormCollapse();
|
||||
|
||||
protected:
|
||||
static void bind_methods();
|
||||
static void _bind_methods();
|
||||
|
||||
Array2D<int> input;
|
||||
|
||||
bool periodic_output;
|
||||
|
||||
private:
|
||||
RandomPCG gen;
|
||||
@ -164,13 +181,11 @@ private:
|
||||
|
||||
// The actual wave. data.get(index, pattern) is equal to 0 if the pattern can
|
||||
// be placed in the cell index.
|
||||
Array2D<uint8_t> data;
|
||||
Array2D<int> data;
|
||||
|
||||
//Propagator
|
||||
Vector<PropagatorStateEntry> propagator_state;
|
||||
|
||||
bool periodic_output;
|
||||
|
||||
// All the tuples (y, x, pattern) that should be propagated.
|
||||
// The tuple should be propagated when wave.get(y, x, pattern) is set to false.
|
||||
Vector<PropagatingEntry> propagating;
|
||||
@ -185,4 +200,6 @@ private:
|
||||
void init_compatible();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(WaveFormCollapse::Symmetry);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user