mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-02-21 07:04:22 +01:00
Use int-s instead of uint32_t-s in the wfc module for better compatibility with scripting.
This commit is contained in:
parent
129ed4e349
commit
e311cacced
@ -6,8 +6,8 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class Array2D {
|
class Array2D {
|
||||||
public:
|
public:
|
||||||
uint32_t height;
|
int height;
|
||||||
uint32_t width;
|
int width;
|
||||||
|
|
||||||
Vector<T> data;
|
Vector<T> data;
|
||||||
|
|
||||||
@ -16,40 +16,40 @@ public:
|
|||||||
width = 0;
|
width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array2D(uint32_t p_height, uint32_t p_width) {
|
Array2D(int p_height, int p_width) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
data.resize(width * height);
|
data.resize(width * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array2D(uint32_t p_height, uint32_t p_width, T p_value) {
|
Array2D(int p_height, int p_width, T p_value) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
data.resize(width * height);
|
data.resize(width * height);
|
||||||
data.fill(p_value);
|
data.fill(p_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(uint32_t p_height, uint32_t p_width) {
|
void resize(int p_height, int p_width) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
data.resize(width * height);
|
data.resize(width * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize_fill(uint32_t p_height, uint32_t p_width, T p_value) {
|
void resize_fill(int p_height, int p_width, T p_value) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
data.resize(width * height);
|
data.resize(width * height);
|
||||||
data.fill(p_value);
|
data.fill(p_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T &get(uint32_t i, uint32_t j) const {
|
const T &get(int i, int j) const {
|
||||||
CRASH_BAD_INDEX(i, height);
|
CRASH_BAD_INDEX(i, height);
|
||||||
CRASH_BAD_INDEX(j, width);
|
CRASH_BAD_INDEX(j, width);
|
||||||
|
|
||||||
return data[j + i * width];
|
return data[j + i * width];
|
||||||
}
|
}
|
||||||
|
|
||||||
T &get(uint32_t i, uint32_t j) {
|
T &get(int i, int j) {
|
||||||
CRASH_BAD_INDEX(i, height);
|
CRASH_BAD_INDEX(i, height);
|
||||||
CRASH_BAD_INDEX(j, width);
|
CRASH_BAD_INDEX(j, width);
|
||||||
|
|
||||||
@ -58,8 +58,8 @@ public:
|
|||||||
|
|
||||||
Array2D<T> reflected() const {
|
Array2D<T> reflected() const {
|
||||||
Array2D<T> result = Array2D<T>(width, height);
|
Array2D<T> result = Array2D<T>(width, height);
|
||||||
for (uint32_t y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (uint32_t x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
result.get(y, x) = get(y, width - 1 - x);
|
result.get(y, x) = get(y, width - 1 - x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,18 +68,18 @@ public:
|
|||||||
|
|
||||||
Array2D<T> rotated() const {
|
Array2D<T> rotated() const {
|
||||||
Array2D<T> result = Array2D<T>(width, height);
|
Array2D<T> result = Array2D<T>(width, height);
|
||||||
for (uint32_t y = 0; y < width; y++) {
|
for (int y = 0; y < width; y++) {
|
||||||
for (uint32_t x = 0; x < height; x++) {
|
for (int x = 0; x < height; x++) {
|
||||||
result.get(y, x) = get(x, width - 1 - y);
|
result.get(y, x) = get(x, width - 1 - y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array2D<T> get_sub_array(uint32_t y, uint32_t x, uint32_t sub_width, uint32_t sub_height) const {
|
Array2D<T> get_sub_array(int y, int x, int sub_width, int sub_height) const {
|
||||||
Array2D<T> sub_array_2d = Array2D<T>(sub_width, sub_height);
|
Array2D<T> sub_array_2d = Array2D<T>(sub_width, sub_height);
|
||||||
for (uint32_t ki = 0; ki < sub_height; ki++) {
|
for (int ki = 0; ki < sub_height; ki++) {
|
||||||
for (uint32_t kj = 0; kj < sub_width; kj++) {
|
for (int kj = 0; kj < sub_width; kj++) {
|
||||||
sub_array_2d.get(ki, kj) = get((y + ki) % height, (x + kj) % width);
|
sub_array_2d.get(ki, kj) = get((y + ki) % height, (x + kj) % width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class Array3D {
|
class Array3D {
|
||||||
public:
|
public:
|
||||||
uint32_t height;
|
int height;
|
||||||
uint32_t width;
|
int width;
|
||||||
uint32_t depth;
|
int depth;
|
||||||
|
|
||||||
Vector<T> data;
|
Vector<T> data;
|
||||||
|
|
||||||
@ -18,14 +18,14 @@ public:
|
|||||||
depth = 0;
|
depth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array3D(uint32_t p_height, uint32_t p_width, uint32_t p_depth) {
|
Array3D(int p_height, int p_width, int p_depth) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
depth = p_depth;
|
depth = p_depth;
|
||||||
data.resize(width * height * depth);
|
data.resize(width * height * depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array3D(uint32_t p_height, uint32_t p_width, uint32_t p_depth, T value) {
|
Array3D(int p_height, int p_width, int p_depth, T value) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
depth = p_depth;
|
depth = p_depth;
|
||||||
@ -33,14 +33,14 @@ public:
|
|||||||
data.fill(value);
|
data.fill(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(uint32_t p_height, uint32_t p_width, uint32_t p_depth) {
|
void resize(int p_height, int p_width, int p_depth) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
depth = p_depth;
|
depth = p_depth;
|
||||||
data.resize(width * height * depth);
|
data.resize(width * height * depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize_fill(uint32_t p_height, uint32_t p_width, uint32_t p_depth, T value) {
|
void resize_fill(int p_height, int p_width, int p_depth, T value) {
|
||||||
height = p_height;
|
height = p_height;
|
||||||
width = p_width;
|
width = p_width;
|
||||||
depth = p_depth;
|
depth = p_depth;
|
||||||
@ -48,7 +48,7 @@ public:
|
|||||||
data.fill(value);
|
data.fill(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T &get(uint32_t i, uint32_t j, uint32_t k) const {
|
const T &get(int i, int j, int k) const {
|
||||||
CRASH_BAD_INDEX(i, height);
|
CRASH_BAD_INDEX(i, height);
|
||||||
CRASH_BAD_INDEX(j, width);
|
CRASH_BAD_INDEX(j, width);
|
||||||
CRASH_BAD_INDEX(k, depth);
|
CRASH_BAD_INDEX(k, depth);
|
||||||
@ -56,7 +56,7 @@ public:
|
|||||||
return data[i * width * depth + j * depth + k];
|
return data[i * width * depth + j * depth + k];
|
||||||
}
|
}
|
||||||
|
|
||||||
T &get(uint32_t i, uint32_t j, uint32_t k) {
|
T &get(int i, int j, int k) {
|
||||||
CRASH_BAD_INDEX(i, height);
|
CRASH_BAD_INDEX(i, height);
|
||||||
CRASH_BAD_INDEX(j, width);
|
CRASH_BAD_INDEX(j, width);
|
||||||
CRASH_BAD_INDEX(k, depth);
|
CRASH_BAD_INDEX(k, depth);
|
||||||
|
@ -3,39 +3,39 @@
|
|||||||
|
|
||||||
#include "core/set.h"
|
#include "core/set.h"
|
||||||
|
|
||||||
void OverlappingWaveFormCollapse::set_input(const Array2D<uint32_t> &data) {
|
void OverlappingWaveFormCollapse::set_input(const Array2D<int> &data) {
|
||||||
input = data;
|
input = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t OverlappingWaveFormCollapse::get_wave_height() const {
|
int OverlappingWaveFormCollapse::get_wave_height() const {
|
||||||
return periodic_output ? out_height : out_height - pattern_size + 1;
|
return periodic_output ? out_height : out_height - pattern_size + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the wave width given these
|
//Get the wave width given these
|
||||||
uint32_t OverlappingWaveFormCollapse::get_wave_width() const {
|
int OverlappingWaveFormCollapse::get_wave_width() const {
|
||||||
return periodic_output ? out_width : out_width - pattern_size + 1;
|
return periodic_output ? out_width : out_width - pattern_size + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the WFC algorithm, and return the result if the algorithm succeeded.
|
// Run the WFC algorithm, and return the result if the algorithm succeeded.
|
||||||
Array2D<uint32_t> OverlappingWaveFormCollapse::orun() {
|
Array2D<int> OverlappingWaveFormCollapse::orun() {
|
||||||
Array2D<uint32_t> result = run();
|
Array2D<int> result = run();
|
||||||
|
|
||||||
if (result.width == 0 && result.height == 0) {
|
if (result.width == 0 && result.height == 0) {
|
||||||
return Array2D<uint32_t>(0, 0);
|
return Array2D<int>(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return to_image(result);
|
return to_image(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlappingWaveFormCollapse::init_ground() {
|
void OverlappingWaveFormCollapse::init_ground() {
|
||||||
uint32_t ground_pattern_id = get_ground_pattern_id();
|
int ground_pattern_id = get_ground_pattern_id();
|
||||||
|
|
||||||
for (uint32_t j = 0; j < get_wave_width(); j++) {
|
for (int j = 0; j < get_wave_width(); j++) {
|
||||||
set_pattern(ground_pattern_id, get_wave_height() - 1, j);
|
set_pattern(ground_pattern_id, get_wave_height() - 1, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < get_wave_height() - 1; i++) {
|
for (int i = 0; i < get_wave_height() - 1; i++) {
|
||||||
for (uint32_t j = 0; j < get_wave_width(); j++) {
|
for (int j = 0; j < get_wave_width(); j++) {
|
||||||
remove_wave_pattern(i, j, ground_pattern_id);
|
remove_wave_pattern(i, j, ground_pattern_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,10 +46,10 @@ void OverlappingWaveFormCollapse::init_ground() {
|
|||||||
// Set the pattern at a specific position.
|
// Set the pattern at a specific position.
|
||||||
// Returns false if the given pattern does not exist, or if the
|
// Returns false if the given pattern does not exist, or if the
|
||||||
// coordinates are not in the wave
|
// coordinates are not in the wave
|
||||||
bool OverlappingWaveFormCollapse::set_pattern(const Array2D<uint32_t> &pattern, uint32_t i, uint32_t j) {
|
bool OverlappingWaveFormCollapse::set_pattern(const Array2D<int> &pattern, int i, int j) {
|
||||||
uint32_t pattern_id = get_pattern_id(pattern);
|
int pattern_id = get_pattern_id(pattern);
|
||||||
|
|
||||||
if (pattern_id == static_cast<uint32_t>(-1) || i >= get_wave_height() || j >= get_wave_width()) {
|
if (pattern_id == static_cast<int>(-1) || i >= get_wave_height() || j >= get_wave_width()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +57,9 @@ bool OverlappingWaveFormCollapse::set_pattern(const Array2D<uint32_t> &pattern,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t OverlappingWaveFormCollapse::get_ground_pattern_id() {
|
int OverlappingWaveFormCollapse::get_ground_pattern_id() {
|
||||||
// Get the pattern.
|
// Get the pattern.
|
||||||
Array2D<uint32_t> ground_pattern = input.get_sub_array(input.height - 1, input.width / 2, pattern_size, pattern_size);
|
Array2D<int> ground_pattern = input.get_sub_array(input.height - 1, input.width / 2, pattern_size, pattern_size);
|
||||||
|
|
||||||
// Retrieve the id of the pattern.
|
// Retrieve the id of the pattern.
|
||||||
for (int i = 0; i < patterns.size(); i++) {
|
for (int i = 0; i < patterns.size(); i++) {
|
||||||
@ -71,7 +71,7 @@ uint32_t OverlappingWaveFormCollapse::get_ground_pattern_id() {
|
|||||||
ERR_FAIL_V(0);
|
ERR_FAIL_V(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t OverlappingWaveFormCollapse::get_pattern_id(const Array2D<uint32_t> &pattern) {
|
int OverlappingWaveFormCollapse::get_pattern_id(const Array2D<int> &pattern) {
|
||||||
for (int i = 0; i < patterns.size(); ++i) {
|
for (int i = 0; i < patterns.size(); ++i) {
|
||||||
if (patterns[i] == pattern) {
|
if (patterns[i] == pattern) {
|
||||||
return i;
|
return i;
|
||||||
@ -83,9 +83,9 @@ uint32_t OverlappingWaveFormCollapse::get_pattern_id(const Array2D<uint32_t> &pa
|
|||||||
|
|
||||||
// Set the pattern at a specific position, given its pattern id
|
// Set the pattern at a specific position, given its pattern id
|
||||||
// pattern_id needs to be a valid pattern id, and i and j needs to be in the wave range
|
// pattern_id needs to be a valid pattern id, and i and j needs to be in the wave range
|
||||||
void OverlappingWaveFormCollapse::set_pattern(uint32_t pattern_id, uint32_t i, uint32_t j) {
|
void OverlappingWaveFormCollapse::set_pattern(int pattern_id, int i, int j) {
|
||||||
for (int p = 0; p < patterns.size(); p++) {
|
for (int p = 0; p < patterns.size(); p++) {
|
||||||
if (pattern_id != static_cast<uint32_t>(p)) {
|
if (pattern_id != static_cast<int>(p)) {
|
||||||
remove_wave_pattern(i, j, p);
|
remove_wave_pattern(i, j, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,27 +93,27 @@ void OverlappingWaveFormCollapse::set_pattern(uint32_t pattern_id, uint32_t i, u
|
|||||||
|
|
||||||
//Return the list of patterns, as well as their probabilities of apparition.
|
//Return the list of patterns, as well as their probabilities of apparition.
|
||||||
void OverlappingWaveFormCollapse::get_patterns() {
|
void OverlappingWaveFormCollapse::get_patterns() {
|
||||||
//OAHashMap<Array2D<uint32_t>, uint32_t> patterns_id;
|
//OAHashMap<Array2D<int>, int> patterns_id;
|
||||||
|
|
||||||
LocalVector<Array2D<uint32_t>> patterns_id;
|
LocalVector<Array2D<int>> patterns_id;
|
||||||
|
|
||||||
patterns.clear();
|
patterns.clear();
|
||||||
|
|
||||||
// The number of time a pattern is seen in the input image.
|
// The number of time a pattern is seen in the input image.
|
||||||
Vector<double> patterns_weight;
|
Vector<double> patterns_weight;
|
||||||
|
|
||||||
Vector<Array2D<uint32_t>> symmetries;
|
Vector<Array2D<int>> symmetries;
|
||||||
symmetries.resize(8);
|
symmetries.resize(8);
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
symmetries.write[i].resize(pattern_size, pattern_size);
|
symmetries.write[i].resize(pattern_size, pattern_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t max_i = periodic_input ? input.height : input.height - pattern_size + 1;
|
int max_i = periodic_input ? input.height : input.height - pattern_size + 1;
|
||||||
uint32_t max_j = periodic_input ? input.width : input.width - pattern_size + 1;
|
int max_j = periodic_input ? input.width : input.width - pattern_size + 1;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < max_i; i++) {
|
for (int i = 0; i < max_i; i++) {
|
||||||
for (uint32_t j = 0; j < max_j; j++) {
|
for (int j = 0; j < max_j; j++) {
|
||||||
// Compute the symmetries of every pattern in the image.
|
// Compute the symmetries of every pattern in the image.
|
||||||
symmetries.write[0].data = input.get_sub_array(i, j, pattern_size, pattern_size).data;
|
symmetries.write[0].data = input.get_sub_array(i, j, pattern_size, pattern_size).data;
|
||||||
symmetries.write[1].data = symmetries[0].reflected().data;
|
symmetries.write[1].data = symmetries[0].reflected().data;
|
||||||
@ -125,7 +125,7 @@ void OverlappingWaveFormCollapse::get_patterns() {
|
|||||||
symmetries.write[7].data = symmetries[6].reflected().data;
|
symmetries.write[7].data = symmetries[6].reflected().data;
|
||||||
|
|
||||||
// The number of symmetries in the option class define which symetries will be used.
|
// The number of symmetries in the option class define which symetries will be used.
|
||||||
for (uint32_t k = 0; k < symmetry; k++) {
|
for (int k = 0; k < symmetry; k++) {
|
||||||
int indx = patterns.size();
|
int indx = patterns.size();
|
||||||
|
|
||||||
for (uint32_t h = 0; h < patterns_id.size(); ++h) {
|
for (uint32_t h = 0; h < patterns_id.size(); ++h) {
|
||||||
@ -150,15 +150,15 @@ void OverlappingWaveFormCollapse::get_patterns() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Return true if the pattern1 is compatible with pattern2 when pattern2 is at a distance (dy,dx) from pattern1.
|
//Return true if the pattern1 is compatible with pattern2 when pattern2 is at a distance (dy,dx) from pattern1.
|
||||||
bool OverlappingWaveFormCollapse::agrees(const Array2D<uint32_t> &pattern1, const Array2D<uint32_t> &pattern2, int dy, int dx) {
|
bool OverlappingWaveFormCollapse::agrees(const Array2D<int> &pattern1, const Array2D<int> &pattern2, int dy, int dx) {
|
||||||
uint32_t xmin = dx < 0 ? 0 : dx;
|
int xmin = dx < 0 ? 0 : dx;
|
||||||
uint32_t xmax = dx < 0 ? dx + pattern2.width : pattern1.width;
|
int xmax = dx < 0 ? dx + pattern2.width : pattern1.width;
|
||||||
uint32_t ymin = dy < 0 ? 0 : dy;
|
int ymin = dy < 0 ? 0 : dy;
|
||||||
uint32_t ymax = dy < 0 ? dy + pattern2.height : pattern1.width;
|
int ymax = dy < 0 ? dy + pattern2.height : pattern1.width;
|
||||||
|
|
||||||
// Iterate on every pixel contained in the intersection of the two pattern.
|
// Iterate on every pixel contained in the intersection of the two pattern.
|
||||||
for (uint32_t y = ymin; y < ymax; y++) {
|
for (int y = ymin; y < ymax; y++) {
|
||||||
for (uint32_t x = xmin; x < xmax; x++) {
|
for (int x = xmin; x < xmax; x++) {
|
||||||
// Check if the color is the same in the two patterns in that pixel.
|
// Check if the color is the same in the two patterns in that pixel.
|
||||||
if (pattern1.get(y, x) != pattern2.get(y - dy, x - dx)) {
|
if (pattern1.get(y, x) != pattern2.get(y - dy, x - dx)) {
|
||||||
return false;
|
return false;
|
||||||
@ -179,9 +179,9 @@ Vector<WaveFormCollapse::PropagatorStateEntry> OverlappingWaveFormCollapse::gene
|
|||||||
|
|
||||||
// Iterate on every dy, dx, pattern1 and pattern2
|
// Iterate on every dy, dx, pattern1 and pattern2
|
||||||
for (int pattern1 = 0; pattern1 < patterns.size(); pattern1++) {
|
for (int pattern1 = 0; pattern1 < patterns.size(); pattern1++) {
|
||||||
for (uint32_t direction = 0; direction < 4; direction++) {
|
for (int direction = 0; direction < 4; direction++) {
|
||||||
for (int pattern2 = 0; pattern2 < patterns.size(); pattern2++) {
|
for (int pattern2 = 0; pattern2 < patterns.size(); pattern2++) {
|
||||||
if (agrees(patterns[pattern1], patterns[pattern2], directions_y[direction], directions_x[direction])) {
|
if (agrees(patterns[pattern1], patterns[pattern2], DIRECTIONS_Y[direction], DIRECTIONS_X[direction])) {
|
||||||
compatible.write[pattern1].directions[direction].push_back(pattern2);
|
compatible.write[pattern1].directions[direction].push_back(pattern2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,41 +192,41 @@ Vector<WaveFormCollapse::PropagatorStateEntry> OverlappingWaveFormCollapse::gene
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transform a 2D array containing the patterns id to a 2D array containing the pixels.
|
// Transform a 2D array containing the patterns id to a 2D array containing the pixels.
|
||||||
Array2D<uint32_t> OverlappingWaveFormCollapse::to_image(const Array2D<uint32_t> &output_patterns) const {
|
Array2D<int> OverlappingWaveFormCollapse::to_image(const Array2D<int> &output_patterns) const {
|
||||||
Array2D<uint32_t> output = Array2D<uint32_t>(out_height, out_width);
|
Array2D<int> output = Array2D<int>(out_height, out_width);
|
||||||
|
|
||||||
if (periodic_output) {
|
if (periodic_output) {
|
||||||
for (uint32_t y = 0; y < get_wave_height(); y++) {
|
for (int y = 0; y < get_wave_height(); y++) {
|
||||||
for (uint32_t x = 0; x < get_wave_width(); x++) {
|
for (int x = 0; x < get_wave_width(); x++) {
|
||||||
output.get(y, x) = patterns[output_patterns.get(y, x)].get(0, 0);
|
output.get(y, x) = patterns[output_patterns.get(y, x)].get(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t y = 0; y < get_wave_height(); y++) {
|
for (int y = 0; y < get_wave_height(); y++) {
|
||||||
for (uint32_t x = 0; x < get_wave_width(); x++) {
|
for (int x = 0; x < get_wave_width(); x++) {
|
||||||
output.get(y, x) = patterns[output_patterns.get(y, x)].get(0, 0);
|
output.get(y, x) = patterns[output_patterns.get(y, x)].get(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t y = 0; y < get_wave_height(); y++) {
|
for (int y = 0; y < get_wave_height(); y++) {
|
||||||
const Array2D<uint32_t> &pattern = patterns[output_patterns.get(y, get_wave_width() - 1)];
|
const Array2D<int> &pattern = patterns[output_patterns.get(y, get_wave_width() - 1)];
|
||||||
for (uint32_t dx = 1; dx < pattern_size; dx++) {
|
for (int dx = 1; dx < pattern_size; dx++) {
|
||||||
output.get(y, get_wave_width() - 1 + dx) = pattern.get(0, dx);
|
output.get(y, get_wave_width() - 1 + dx) = pattern.get(0, dx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t x = 0; x < get_wave_width(); x++) {
|
for (int x = 0; x < get_wave_width(); x++) {
|
||||||
const Array2D<uint32_t> &pattern = patterns[output_patterns.get(get_wave_height() - 1, x)];
|
const Array2D<int> &pattern = patterns[output_patterns.get(get_wave_height() - 1, x)];
|
||||||
for (uint32_t dy = 1; dy < pattern_size; dy++) {
|
for (int dy = 1; dy < pattern_size; dy++) {
|
||||||
output.get(get_wave_height() - 1 + dy, x) =
|
output.get(get_wave_height() - 1 + dy, x) =
|
||||||
pattern.get(dy, 0);
|
pattern.get(dy, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Array2D<uint32_t> &pattern = patterns[output_patterns.get(get_wave_height() - 1, get_wave_width() - 1)];
|
const Array2D<int> &pattern = patterns[output_patterns.get(get_wave_height() - 1, get_wave_width() - 1)];
|
||||||
|
|
||||||
for (uint32_t dy = 1; dy < pattern_size; dy++) {
|
for (int dy = 1; dy < pattern_size; dy++) {
|
||||||
for (uint32_t dx = 1; dx < pattern_size; dx++) {
|
for (int dx = 1; dx < pattern_size; dx++) {
|
||||||
output.get(get_wave_height() - 1 + dy, get_wave_width() - 1 + dx) = pattern.get(dy, dx);
|
output.get(get_wave_height() - 1 + dy, get_wave_width() - 1 + dx) = pattern.get(dy, dx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,32 +12,32 @@ class OverlappingWaveFormCollapse : public WaveFormCollapse {
|
|||||||
public:
|
public:
|
||||||
bool periodic_input;
|
bool periodic_input;
|
||||||
bool periodic_output;
|
bool periodic_output;
|
||||||
uint32_t out_height;
|
int out_height;
|
||||||
uint32_t out_width;
|
int out_width;
|
||||||
uint32_t symmetry;
|
int symmetry;
|
||||||
bool ground;
|
bool ground;
|
||||||
uint32_t pattern_size;
|
int pattern_size;
|
||||||
|
|
||||||
void set_input(const Array2D<uint32_t> &data);
|
void set_input(const Array2D<int> &data);
|
||||||
|
|
||||||
uint32_t get_wave_height() const;
|
int get_wave_height() const;
|
||||||
uint32_t get_wave_width() const;
|
int get_wave_width() const;
|
||||||
|
|
||||||
Array2D<uint32_t> orun();
|
Array2D<int> orun();
|
||||||
|
|
||||||
void init_ground();
|
void init_ground();
|
||||||
|
|
||||||
bool set_pattern(const Array2D<uint32_t> &pattern, uint32_t i, uint32_t j);
|
bool set_pattern(const Array2D<int> &pattern, int i, int j);
|
||||||
uint32_t get_ground_pattern_id();
|
int get_ground_pattern_id();
|
||||||
uint32_t get_pattern_id(const Array2D<uint32_t> &pattern);
|
int get_pattern_id(const Array2D<int> &pattern);
|
||||||
void set_pattern(uint32_t pattern_id, uint32_t i, uint32_t j);
|
void set_pattern(int pattern_id, int i, int j);
|
||||||
void get_patterns();
|
void get_patterns();
|
||||||
|
|
||||||
bool agrees(const Array2D<uint32_t> &pattern1, const Array2D<uint32_t> &pattern2, int dy, int dx);
|
bool agrees(const Array2D<int> &pattern1, const Array2D<int> &pattern2, int dy, int dx);
|
||||||
|
|
||||||
Vector<WaveFormCollapse::PropagatorStateEntry> generate_compatible();
|
Vector<WaveFormCollapse::PropagatorStateEntry> generate_compatible();
|
||||||
|
|
||||||
Array2D<uint32_t> to_image(const Array2D<uint32_t> &output_patterns) const;
|
Array2D<int> to_image(const Array2D<int> &output_patterns) const;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
@ -48,9 +48,9 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Array2D<uint32_t> input;
|
Array2D<int> input;
|
||||||
|
|
||||||
Vector<Array2D<uint32_t>> patterns;
|
Vector<Array2D<int>> patterns;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,8 +60,8 @@ Tile::ActionMap Tile::generate_action_map(const Symmetry &symmetry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate all distincts rotations of a 2D array given its symmetries;
|
// Generate all distincts rotations of a 2D array given its symmetries;
|
||||||
Vector<Array2D<uint32_t>> Tile::generate_oriented(Array2D<uint32_t> data, Symmetry symmetry) {
|
Vector<Array2D<int>> Tile::generate_oriented(Array2D<int> data, Symmetry symmetry) {
|
||||||
Vector<Array2D<uint32_t>> oriented;
|
Vector<Array2D<int>> oriented;
|
||||||
oriented.push_back(data);
|
oriented.push_back(data);
|
||||||
|
|
||||||
switch (symmetry) {
|
switch (symmetry) {
|
||||||
@ -92,7 +92,7 @@ Vector<Array2D<uint32_t>> Tile::generate_oriented(Array2D<uint32_t> data, Symmet
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a tile with its differents orientations, its symmetries and its weight on the distribution of tiles.
|
// Create a tile with its differents orientations, its symmetries and its weight on the distribution of tiles.
|
||||||
Tile::Tile(const Vector<Array2D<uint32_t>> &p_data, Symmetry p_symmetry, double p_weight) {
|
Tile::Tile(const Vector<Array2D<int>> &p_data, Symmetry p_symmetry, double p_weight) {
|
||||||
data = p_data;
|
data = p_data;
|
||||||
symmetry = p_symmetry;
|
symmetry = p_symmetry;
|
||||||
weight = p_weight;
|
weight = p_weight;
|
||||||
@ -100,20 +100,20 @@ Tile::Tile(const Vector<Array2D<uint32_t>> &p_data, Symmetry p_symmetry, double
|
|||||||
|
|
||||||
// Create a tile with its base orientation, its symmetries and its weight on the distribution of tiles.
|
// 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::Tile(const Array2D<uint32_t> &p_data, Symmetry p_symmetry, double p_weight) {
|
Tile::Tile(const Array2D<int> &p_data, Symmetry p_symmetry, double p_weight) {
|
||||||
data = generate_oriented(p_data, p_symmetry);
|
data = generate_oriented(p_data, p_symmetry);
|
||||||
symmetry = p_symmetry;
|
symmetry = p_symmetry;
|
||||||
weight = p_weight;
|
weight = p_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns false if the given tile and orientation does not exist, or if the coordinates are not in the wave
|
// Returns false if the given tile and orientation does not exist, or if the coordinates are not in the wave
|
||||||
bool TilingWaveFormCollapse::set_tile(uint32_t tile_id, uint32_t orientation, uint32_t i, uint32_t j) {
|
bool TilingWaveFormCollapse::set_tile(int tile_id, int orientation, int i, int j) {
|
||||||
if (tile_id >= static_cast<uint32_t>(oriented_tile_ids.size()) || orientation >= static_cast<uint32_t>(oriented_tile_ids[tile_id].size()) ||
|
if (tile_id >= static_cast<int>(oriented_tile_ids.size()) || orientation >= static_cast<int>(oriented_tile_ids[tile_id].size()) ||
|
||||||
i >= get_height() || j >= get_width()) {
|
i >= get_height() || j >= get_width()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t oriented_tile_id = oriented_tile_ids[tile_id][orientation];
|
int oriented_tile_id = oriented_tile_ids[tile_id][orientation];
|
||||||
set_tile(oriented_tile_id, i, j);
|
set_tile(oriented_tile_id, i, j);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -132,7 +132,7 @@ void TilingWaveFormCollapse::generate_oriented_tile_ids() {
|
|||||||
id_to_oriented_tile.clear();
|
id_to_oriented_tile.clear();
|
||||||
oriented_tile_ids.clear();
|
oriented_tile_ids.clear();
|
||||||
|
|
||||||
uint32_t id = 0;
|
int id = 0;
|
||||||
for (int i = 0; i < tiles.size(); i++) {
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
oriented_tile_ids.push_back({});
|
oriented_tile_ids.push_back({});
|
||||||
for (int j = 0; j < tiles[i].data.size(); j++) {
|
for (int j = 0; j < tiles[i].data.size(); j++) {
|
||||||
@ -157,8 +157,8 @@ void TilingWaveFormCollapse::generate_propagator() {
|
|||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
const NeighbourData &neighbour = neighbors[i];
|
const NeighbourData &neighbour = neighbors[i];
|
||||||
|
|
||||||
uint32_t tile1 = neighbour.data[0];
|
int tile1 = neighbour.data[0];
|
||||||
uint32_t tile2 = neighbour.data[2];
|
int tile2 = neighbour.data[2];
|
||||||
Tile::ActionMap action_map1 = Tile::generate_action_map(tiles[tile1].symmetry);
|
Tile::ActionMap action_map1 = Tile::generate_action_map(tiles[tile1].symmetry);
|
||||||
Tile::ActionMap action_map2 = Tile::generate_action_map(tiles[tile2].symmetry);
|
Tile::ActionMap action_map2 = Tile::generate_action_map(tiles[tile2].symmetry);
|
||||||
|
|
||||||
@ -203,35 +203,35 @@ Vector<double> TilingWaveFormCollapse::get_tiles_weights(const Vector<Tile> &til
|
|||||||
return frequencies;
|
return frequencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TilingWaveFormCollapse::set_tile(uint32_t tile_id, uint32_t i, uint32_t j) {
|
void TilingWaveFormCollapse::set_tile(int tile_id, int i, int j) {
|
||||||
for (int p = 0; p < id_to_oriented_tile.size(); p++) {
|
for (int p = 0; p < id_to_oriented_tile.size(); p++) {
|
||||||
if (tile_id != static_cast<uint32_t>(p)) {
|
if (tile_id != static_cast<int>(p)) {
|
||||||
remove_wave_pattern(i, j, p);
|
remove_wave_pattern(i, j, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array2D<uint32_t> TilingWaveFormCollapse::do_run() {
|
Array2D<int> TilingWaveFormCollapse::do_run() {
|
||||||
Array2D<uint32_t> a = run();
|
Array2D<int> a = run();
|
||||||
|
|
||||||
if (a.width == 0 && a.height == 0) {
|
if (a.width == 0 && a.height == 0) {
|
||||||
return Array2D<uint32_t>(0, 0);
|
return Array2D<int>(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return id_to_tiling(a);
|
return id_to_tiling(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate the generic WFC result into the image result
|
// Translate the generic WFC result into the image result
|
||||||
Array2D<uint32_t> TilingWaveFormCollapse::id_to_tiling(Array2D<uint32_t> ids) {
|
Array2D<int> TilingWaveFormCollapse::id_to_tiling(Array2D<int> ids) {
|
||||||
uint32_t size = tiles[0].data[0].height;
|
int size = tiles[0].data[0].height;
|
||||||
Array2D<uint32_t> tiling(size * ids.height, size * ids.width);
|
Array2D<int> tiling(size * ids.height, size * ids.width);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ids.height; i++) {
|
for (int i = 0; i < ids.height; i++) {
|
||||||
for (uint32_t j = 0; j < ids.width; j++) {
|
for (int j = 0; j < ids.width; j++) {
|
||||||
IdToTilePair oriented_tile = id_to_oriented_tile[ids.get(i, j)];
|
IdToTilePair oriented_tile = id_to_oriented_tile[ids.get(i, j)];
|
||||||
|
|
||||||
for (uint32_t y = 0; y < size; y++) {
|
for (int y = 0; y < size; y++) {
|
||||||
for (uint32_t x = 0; x < size; x++) {
|
for (int x = 0; x < size; x++) {
|
||||||
tiling.get(i * size + y, j * size + x) = tiles[oriented_tile.id].data[oriented_tile.oriented_tile].get(y, x);
|
tiling.get(i * size + y, j * size + x) = tiles[oriented_tile.id].data[oriented_tile.oriented_tile].get(y, x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,17 +257,17 @@ void TilingWaveFormCollapse::_bind_methods() {
|
|||||||
|
|
||||||
void TilingWaveFormCollapse::generate_propagator_add_helper(Tile::ActionMap *action_map1, Tile::ActionMap *action_map2,
|
void TilingWaveFormCollapse::generate_propagator_add_helper(Tile::ActionMap *action_map1, Tile::ActionMap *action_map2,
|
||||||
Vector<DensePropagatorHelper> *dense_propagator,
|
Vector<DensePropagatorHelper> *dense_propagator,
|
||||||
const NeighbourData &neighbour, uint32_t action, uint32_t direction) {
|
const NeighbourData &neighbour, int action, int direction) {
|
||||||
// --
|
// --
|
||||||
uint32_t tile1 = neighbour.data[0];
|
int tile1 = neighbour.data[0];
|
||||||
uint32_t orientation1 = neighbour.data[1];
|
int orientation1 = neighbour.data[1];
|
||||||
uint32_t tile2 = neighbour.data[2];
|
int tile2 = neighbour.data[2];
|
||||||
uint32_t orientation2 = neighbour.data[3];
|
int orientation2 = neighbour.data[3];
|
||||||
|
|
||||||
uint32_t temp_orientation1 = action_map1->map[action][orientation1];
|
int temp_orientation1 = action_map1->map[action][orientation1];
|
||||||
uint32_t temp_orientation2 = action_map2->map[action][orientation2];
|
int temp_orientation2 = action_map2->map[action][orientation2];
|
||||||
uint32_t oriented_tile_id1 = oriented_tile_ids[tile1][temp_orientation1];
|
int oriented_tile_id1 = oriented_tile_ids[tile1][temp_orientation1];
|
||||||
uint32_t oriented_tile_id2 = oriented_tile_ids[tile2][temp_orientation2];
|
int oriented_tile_id2 = oriented_tile_ids[tile2][temp_orientation2];
|
||||||
dense_propagator->write[oriented_tile_id1].directions[direction].write[oriented_tile_id2] = true;
|
dense_propagator->write[oriented_tile_id1].directions[direction].write[oriented_tile_id2] = true;
|
||||||
direction = get_opposite_direction(direction);
|
direction = get_opposite_direction(direction);
|
||||||
dense_propagator->write[oriented_tile_id2].directions[direction].write[oriented_tile_id1] = true;
|
dense_propagator->write[oriented_tile_id2].directions[direction].write[oriented_tile_id1] = true;
|
||||||
|
@ -17,7 +17,7 @@ struct Tile {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ActionMap {
|
struct ActionMap {
|
||||||
Vector<uint32_t> map[8];
|
Vector<int> map[8];
|
||||||
|
|
||||||
void set_size(int size) {
|
void set_size(int size) {
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
@ -29,16 +29,16 @@ struct Tile {
|
|||||||
static const uint8_t rotation_map[6][9];
|
static const uint8_t rotation_map[6][9];
|
||||||
static const uint8_t reflection_map[6][9];
|
static const uint8_t reflection_map[6][9];
|
||||||
|
|
||||||
Vector<Array2D<uint32_t>> data;
|
Vector<Array2D<int>> data;
|
||||||
Symmetry symmetry;
|
Symmetry symmetry;
|
||||||
double weight;
|
double weight;
|
||||||
|
|
||||||
static ActionMap generate_action_map(const Symmetry &symmetry);
|
static ActionMap generate_action_map(const Symmetry &symmetry);
|
||||||
|
|
||||||
static Vector<Array2D<uint32_t>> generate_oriented(Array2D<uint32_t> data, Symmetry symmetry);
|
static Vector<Array2D<int>> generate_oriented(Array2D<int> data, Symmetry symmetry);
|
||||||
|
|
||||||
Tile(const Vector<Array2D<uint32_t>> &p_data, Symmetry p_symmetry, double p_weight);
|
Tile(const Vector<Array2D<int>> &p_data, Symmetry p_symmetry, double p_weight);
|
||||||
Tile(const Array2D<uint32_t> &p_data, Symmetry p_symmetry, double p_weight);
|
Tile(const Array2D<int> &p_data, Symmetry p_symmetry, double p_weight);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TilingWaveFormCollapse : public WaveFormCollapse {
|
class TilingWaveFormCollapse : public WaveFormCollapse {
|
||||||
@ -46,7 +46,7 @@ class TilingWaveFormCollapse : public WaveFormCollapse {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
struct NeighbourData {
|
struct NeighbourData {
|
||||||
uint32_t data[4];
|
int data[4];
|
||||||
|
|
||||||
NeighbourData() {
|
NeighbourData() {
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
@ -67,15 +67,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct IdToTilePair {
|
struct IdToTilePair {
|
||||||
uint32_t id;
|
int id;
|
||||||
uint32_t oriented_tile;
|
int oriented_tile;
|
||||||
|
|
||||||
IdToTilePair() {
|
IdToTilePair() {
|
||||||
id = 0;
|
id = 0;
|
||||||
oriented_tile = 0;
|
oriented_tile = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdToTilePair(uint32_t p_id, uint32_t p_oriented_tile) {
|
IdToTilePair(int p_id, int p_oriented_tile) {
|
||||||
id = p_id;
|
id = p_id;
|
||||||
oriented_tile = p_oriented_tile;
|
oriented_tile = p_oriented_tile;
|
||||||
}
|
}
|
||||||
@ -91,12 +91,12 @@ public:
|
|||||||
|
|
||||||
static Vector<double> get_tiles_weights(const Vector<Tile> &tiles);
|
static Vector<double> get_tiles_weights(const Vector<Tile> &tiles);
|
||||||
|
|
||||||
void set_tile(uint32_t tile_id, uint32_t i, uint32_t j);
|
void set_tile(int tile_id, int i, int j);
|
||||||
bool set_tile(uint32_t tile_id, uint32_t orientation, uint32_t i, uint32_t j);
|
bool set_tile(int tile_id, int orientation, int i, int j);
|
||||||
|
|
||||||
Array2D<uint32_t> do_run();
|
Array2D<int> do_run();
|
||||||
|
|
||||||
Array2D<uint32_t> id_to_tiling(Array2D<uint32_t> ids);
|
Array2D<int> id_to_tiling(Array2D<int> ids);
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
@ -110,13 +110,13 @@ private:
|
|||||||
void generate_propagator_add_helper(Tile::ActionMap *action_map1, Tile::ActionMap *action_map2,
|
void generate_propagator_add_helper(Tile::ActionMap *action_map1, Tile::ActionMap *action_map2,
|
||||||
Vector<DensePropagatorHelper> *dense_propagator,
|
Vector<DensePropagatorHelper> *dense_propagator,
|
||||||
const NeighbourData &neighbour,
|
const NeighbourData &neighbour,
|
||||||
uint32_t action, uint32_t direction);
|
int action, int direction);
|
||||||
|
|
||||||
Vector<Tile> tiles;
|
Vector<Tile> tiles;
|
||||||
Vector<NeighbourData> neighbors;
|
Vector<NeighbourData> neighbors;
|
||||||
|
|
||||||
Vector<IdToTilePair> id_to_oriented_tile;
|
Vector<IdToTilePair> id_to_oriented_tile;
|
||||||
Vector<Vector<uint32_t>> oriented_tile_ids;
|
Vector<Vector<int>> oriented_tile_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FAST_WFC_TILING_WFC_HPP_
|
#endif // FAST_WFC_TILING_WFC_HPP_
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include "wave_form_collapse.h"
|
#include "wave_form_collapse.h"
|
||||||
|
|
||||||
|
const int WaveFormCollapse::DIRECTIONS_X[4] = { 0, -1, 1, 0 };
|
||||||
|
const int WaveFormCollapse::DIRECTIONS_Y[4] = { -1, 0, 0, 1 };
|
||||||
|
|
||||||
// Normalize a vector so the sum of its elements is equal to 1.0f
|
// Normalize a vector so the sum of its elements is equal to 1.0f
|
||||||
void WaveFormCollapse::normalize(Vector<double> &v) {
|
void WaveFormCollapse::normalize(Vector<double> &v) {
|
||||||
double sum_weights = 0.0;
|
double sum_weights = 0.0;
|
||||||
@ -38,10 +41,10 @@ double WaveFormCollapse::get_min_abs_half(const Vector<double> &v) {
|
|||||||
return min_abs_half;
|
return min_abs_half;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t WaveFormCollapse::get_width() const {
|
int WaveFormCollapse::get_width() const {
|
||||||
return wave_width;
|
return wave_width;
|
||||||
}
|
}
|
||||||
uint32_t WaveFormCollapse::get_height() const {
|
int WaveFormCollapse::get_height() const {
|
||||||
return wave_height;
|
return wave_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +59,7 @@ void WaveFormCollapse::set_seed(const int seed) {
|
|||||||
gen.seed(seed);
|
gen.seed(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaveFormCollapse::set_size(uint32_t p_width, uint32_t p_height) {
|
void WaveFormCollapse::set_size(int p_width, int p_height) {
|
||||||
wave_width = p_width;
|
wave_width = p_width;
|
||||||
wave_height = p_height;
|
wave_height = p_height;
|
||||||
wave_size = p_height * p_width;
|
wave_size = p_height * p_width;
|
||||||
@ -74,14 +77,14 @@ void WaveFormCollapse::set_pattern_frequencies(const Vector<double> &p_patterns_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array2D<uint32_t> WaveFormCollapse::run() {
|
Array2D<int> WaveFormCollapse::run() {
|
||||||
while (true) {
|
while (true) {
|
||||||
// Define the value of an undefined cell.
|
// Define the value of an undefined cell.
|
||||||
ObserveStatus result = observe();
|
ObserveStatus result = observe();
|
||||||
|
|
||||||
// Check if the algorithm has terminated.
|
// Check if the algorithm has terminated.
|
||||||
if (result == OBSERVE_STATUS_FAILURE) {
|
if (result == OBSERVE_STATUS_FAILURE) {
|
||||||
return Array2D<uint32_t>(0, 0);
|
return Array2D<int>(0, 0);
|
||||||
} else if (result == OBSERVE_STATUS_FAILURE) {
|
} else if (result == OBSERVE_STATUS_FAILURE) {
|
||||||
return wave_to_output();
|
return wave_to_output();
|
||||||
}
|
}
|
||||||
@ -135,10 +138,10 @@ WaveFormCollapse::ObserveStatus WaveFormCollapse::observe() {
|
|||||||
return OBSERVE_STATUS_TO_CONTINUE;
|
return OBSERVE_STATUS_TO_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array2D<uint32_t> WaveFormCollapse::wave_to_output() const {
|
Array2D<int> WaveFormCollapse::wave_to_output() const {
|
||||||
Array2D<uint32_t> output_patterns(wave_height, wave_width);
|
Array2D<int> output_patterns(wave_height, wave_width);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < wave_size; i++) {
|
for (int i = 0; i < wave_size; i++) {
|
||||||
for (int k = 0; k < patterns_frequencies.size(); k++) {
|
for (int k = 0; k < patterns_frequencies.size(); k++) {
|
||||||
if (wave_get(i, k)) {
|
if (wave_get(i, k)) {
|
||||||
output_patterns.data.write[i] = k;
|
output_patterns.data.write[i] = k;
|
||||||
@ -149,7 +152,7 @@ Array2D<uint32_t> WaveFormCollapse::wave_to_output() const {
|
|||||||
return output_patterns;
|
return output_patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaveFormCollapse::wave_set(uint32_t index, uint32_t pattern, bool value) {
|
void WaveFormCollapse::wave_set(int index, int pattern, bool value) {
|
||||||
bool old_value = data.get(index, pattern);
|
bool old_value = data.get(index, pattern);
|
||||||
|
|
||||||
// If the value isn't changed, nothing needs to be done.
|
// If the value isn't changed, nothing needs to be done.
|
||||||
@ -184,7 +187,7 @@ int WaveFormCollapse::wave_get_min_entropy() const {
|
|||||||
|
|
||||||
int argmin = -1;
|
int argmin = -1;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < wave_size; i++) {
|
for (int i = 0; i < wave_size; i++) {
|
||||||
// If the cell is decided, we do not compute the entropy (which is equal
|
// If the cell is decided, we do not compute the entropy (which is equal
|
||||||
// to 0).
|
// to 0).
|
||||||
double nb_patterns_local = memoisation_nb_patterns[i];
|
double nb_patterns_local = memoisation_nb_patterns[i];
|
||||||
@ -218,11 +221,11 @@ void WaveFormCollapse::init_compatible() {
|
|||||||
CompatibilityEntry 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 (int y = 0; y < wave_height; y++) {
|
||||||
for (uint32_t x = 0; x < wave_width; x++) {
|
for (int x = 0; x < wave_width; x++) {
|
||||||
for (int pattern = 0; pattern < propagator_state.size(); pattern++) {
|
for (int pattern = 0; pattern < propagator_state.size(); pattern++) {
|
||||||
for (int direction = 0; direction < 4; direction++) {
|
for (int direction = 0; direction < 4; direction++) {
|
||||||
value.direction[direction] = static_cast<uint32_t>(propagator_state[pattern].directions[get_opposite_direction(direction)].size());
|
value.direction[direction] = static_cast<int>(propagator_state[pattern].directions[get_opposite_direction(direction)].size());
|
||||||
}
|
}
|
||||||
|
|
||||||
compatible.get(y, x, pattern) = value;
|
compatible.get(y, x, pattern) = value;
|
||||||
@ -238,17 +241,17 @@ void WaveFormCollapse::propagate() {
|
|||||||
|
|
||||||
const PropagatingEntry &e = propagating[propagating.size() - 1];
|
const PropagatingEntry &e = propagating[propagating.size() - 1];
|
||||||
|
|
||||||
uint32_t y1 = e.data[0];
|
int y1 = e.data[0];
|
||||||
uint32_t x1 = e.data[1];
|
int x1 = e.data[1];
|
||||||
uint32_t pattern = e.data[2];
|
int pattern = e.data[2];
|
||||||
|
|
||||||
propagating.resize(propagating.size() - 1);
|
propagating.resize(propagating.size() - 1);
|
||||||
|
|
||||||
// We propagate the information in all 4 directions.
|
// We propagate the information in all 4 directions.
|
||||||
for (uint32_t direction = 0; direction < 4; direction++) {
|
for (int direction = 0; direction < 4; direction++) {
|
||||||
// We get the next cell in the direction direction.
|
// We get the next cell in the direction direction.
|
||||||
int dx = directions_x[direction];
|
int dx = DIRECTIONS_X[direction];
|
||||||
int dy = directions_y[direction];
|
int dy = DIRECTIONS_Y[direction];
|
||||||
int x2, y2;
|
int x2, y2;
|
||||||
|
|
||||||
if (periodic_output) {
|
if (periodic_output) {
|
||||||
@ -268,14 +271,14 @@ void WaveFormCollapse::propagate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
int i2 = x2 + y2 * wave_width;
|
||||||
const Vector<uint32_t> &patterns = propagator_state[pattern].directions[direction];
|
const Vector<int> &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
|
||||||
int size = patterns.size();
|
int size = patterns.size();
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
uint32_t pattern_entry = patterns[i];
|
int pattern_entry = patterns[i];
|
||||||
|
|
||||||
// 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
|
||||||
@ -325,7 +328,7 @@ void WaveFormCollapse::initialize() {
|
|||||||
memoisation_log_sum.fill(log_base_s);
|
memoisation_log_sum.fill(log_base_s);
|
||||||
|
|
||||||
memoisation_nb_patterns.resize(wave_width * wave_height);
|
memoisation_nb_patterns.resize(wave_width * wave_height);
|
||||||
memoisation_nb_patterns.fill(static_cast<uint32_t>(patterns_frequencies.size()));
|
memoisation_nb_patterns.fill(static_cast<int>(patterns_frequencies.size()));
|
||||||
|
|
||||||
memoisation_entropy.resize(wave_width * wave_height);
|
memoisation_entropy.resize(wave_width * wave_height);
|
||||||
memoisation_entropy.fill(entropy_base);
|
memoisation_entropy.fill(entropy_base);
|
||||||
|
@ -21,11 +21,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PropagatorStateEntry {
|
struct PropagatorStateEntry {
|
||||||
Vector<uint32_t> directions[4];
|
Vector<int> directions[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PropagatingEntry {
|
struct PropagatingEntry {
|
||||||
uint32_t data[3];
|
int data[3];
|
||||||
|
|
||||||
PropagatingEntry() {
|
PropagatingEntry() {
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PropagatingEntry(uint32_t x, uint32_t y, uint32_t z) {
|
PropagatingEntry(int x, int y, int z) {
|
||||||
data[0] = x;
|
data[0] = x;
|
||||||
data[1] = y;
|
data[1] = y;
|
||||||
data[2] = z;
|
data[2] = z;
|
||||||
@ -50,30 +50,30 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int directions_x[4] = { 0, -1, 1, 0 };
|
static const int DIRECTIONS_X[4];
|
||||||
static constexpr int directions_y[4] = { -1, 0, 0, 1 };
|
static const int DIRECTIONS_Y[4];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t get_width() const;
|
int get_width() const;
|
||||||
uint32_t get_height() const;
|
int get_height() const;
|
||||||
|
|
||||||
bool get_periodic_output() const;
|
bool get_periodic_output() const;
|
||||||
void set_periodic_output(const bool val);
|
void set_periodic_output(const bool val);
|
||||||
|
|
||||||
void set_seed(const int seed);
|
void set_seed(const int seed);
|
||||||
|
|
||||||
void set_size(uint32_t p_width, uint32_t p_height);
|
void set_size(int p_width, int p_height);
|
||||||
|
|
||||||
void set_propagator_state(const Vector<PropagatorStateEntry> &p_propagator_state);
|
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);
|
void set_pattern_frequencies(const Vector<double> &p_patterns_frequencies, const bool p_normalize = true);
|
||||||
|
|
||||||
Array2D<uint32_t> run();
|
Array2D<int> run();
|
||||||
|
|
||||||
ObserveStatus observe();
|
ObserveStatus observe();
|
||||||
|
|
||||||
//dvoid propagate() { propagator.propagate(wave); }
|
//dvoid propagate() { propagator.propagate(wave); }
|
||||||
|
|
||||||
void remove_wave_pattern(uint32_t i, uint32_t j, uint32_t pattern) {
|
void remove_wave_pattern(int i, int j, int pattern) {
|
||||||
if (wave_get(i, j, pattern)) {
|
if (wave_get(i, j, pattern)) {
|
||||||
wave_set(i, j, pattern, false);
|
wave_set(i, j, pattern, false);
|
||||||
add_to_propagator(i, j, pattern);
|
add_to_propagator(i, j, pattern);
|
||||||
@ -81,20 +81,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return true if pattern can be placed in cell index.
|
// Return true if pattern can be placed in cell index.
|
||||||
bool wave_get(uint32_t index, uint32_t pattern) const {
|
bool wave_get(int index, int pattern) const {
|
||||||
return data.get(index, pattern);
|
return data.get(index, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if pattern can be placed in cell (i,j)
|
// Return true if pattern can be placed in cell (i,j)
|
||||||
bool wave_get(uint32_t i, uint32_t j, uint32_t pattern) const {
|
bool wave_get(int i, int j, int pattern) const {
|
||||||
return wave_get(i * wave_width + j, pattern);
|
return wave_get(i * wave_width + j, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the value of pattern in cell index.
|
// Set the value of pattern in cell index.
|
||||||
void wave_set(uint32_t index, uint32_t pattern, bool value);
|
void wave_set(int index, int pattern, bool value);
|
||||||
|
|
||||||
// Set the value of pattern in cell (i,j).
|
// Set the value of pattern in cell (i,j).
|
||||||
void wave_set(uint32_t i, uint32_t j, uint32_t pattern, bool value) {
|
void wave_set(int i, int j, int pattern, bool value) {
|
||||||
wave_set(i * wave_width + j, pattern, value);
|
wave_set(i * wave_width + j, pattern, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ public:
|
|||||||
// If every cell is decided, return -1.
|
// If every cell is decided, return -1.
|
||||||
int wave_get_min_entropy() const;
|
int wave_get_min_entropy() const;
|
||||||
|
|
||||||
void add_to_propagator(uint32_t y, uint32_t x, uint32_t pattern) {
|
void add_to_propagator(int y, int x, int 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).
|
||||||
CompatibilityEntry temp;
|
CompatibilityEntry temp;
|
||||||
compatible.get(y, x, pattern) = temp;
|
compatible.get(y, x, pattern) = temp;
|
||||||
@ -111,7 +111,7 @@ public:
|
|||||||
propagating.push_back(PropagatingEntry(y, x, pattern));
|
propagating.push_back(PropagatingEntry(y, x, pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32_t get_opposite_direction(uint32_t direction) {
|
constexpr int get_opposite_direction(int direction) {
|
||||||
return 3 - direction;
|
return 3 - direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,12 +138,12 @@ private:
|
|||||||
// Transform the wave to a valid output (a 2d array of patterns that aren't in
|
// Transform the wave to a valid output (a 2d array of patterns that aren't in
|
||||||
// contradiction). This function should be used only when all cell of the wave
|
// contradiction). This function should be used only when all cell of the wave
|
||||||
// are defined.
|
// are defined.
|
||||||
Array2D<uint32_t> wave_to_output() const;
|
Array2D<int> wave_to_output() const;
|
||||||
|
|
||||||
//Wave
|
//Wave
|
||||||
uint32_t wave_width;
|
int wave_width;
|
||||||
uint32_t wave_height;
|
int wave_height;
|
||||||
uint32_t wave_size;
|
int wave_size;
|
||||||
|
|
||||||
// The patterns frequencies p given to wfc.
|
// The patterns frequencies p given to wfc.
|
||||||
Vector<double> patterns_frequencies;
|
Vector<double> patterns_frequencies;
|
||||||
@ -158,7 +158,7 @@ private:
|
|||||||
Vector<double> memoisation_plogp_sum; // The sum of p'(pattern)// log(p'(pattern)).
|
Vector<double> memoisation_plogp_sum; // The sum of p'(pattern)// log(p'(pattern)).
|
||||||
Vector<double> memoisation_sum; // The sum of p'(pattern).
|
Vector<double> memoisation_sum; // The sum of p'(pattern).
|
||||||
Vector<double> memoisation_log_sum; // The log of sum.
|
Vector<double> memoisation_log_sum; // The log of sum.
|
||||||
Vector<uint32_t> memoisation_nb_patterns; // The number of patterns present
|
Vector<int> memoisation_nb_patterns; // The number of patterns present
|
||||||
Vector<double> memoisation_entropy; // The entropy of the cell.
|
Vector<double> memoisation_entropy; // The entropy of the cell.
|
||||||
|
|
||||||
// This value is set to true if there is a contradiction in the wave (all elements set to false in a cell).
|
// This value is set to true if there is a contradiction in the wave (all elements set to false in a cell).
|
||||||
|
Loading…
Reference in New Issue
Block a user