Renamed WFC to WaveFunctionCollapse, asn started transforming it.

This commit is contained in:
Relintai 2022-04-21 20:00:42 +02:00
parent 96738f5783
commit a501292046
2 changed files with 57 additions and 51 deletions

View File

@ -1,4 +1,5 @@
#include "wfc.h" #include "wave_form_collapse.h"
#include <limits> #include <limits>
namespace { namespace {
@ -6,12 +7,12 @@ namespace {
Vector<double> &normalize(Vector<double> &v) { Vector<double> &normalize(Vector<double> &v) {
double sum_weights = 0.0; double sum_weights = 0.0;
int size = v.size(); int size = v.size();
const double* vpr = v.ptr(); const double *vpr = v.ptr();
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
sum_weights += vpr[i]; sum_weights += vpr[i];
} }
double* vpw = v.ptrw(); double *vpw = v.ptrw();
double inv_sum_weights = 1.0 / sum_weights; double inv_sum_weights = 1.0 / sum_weights;
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
vpw[i] *= inv_sum_weights; vpw[i] *= inv_sum_weights;
@ -21,7 +22,7 @@ Vector<double> &normalize(Vector<double> &v) {
} }
} //namespace } //namespace
Array2D<uint32_t> WFC::wave_to_output() const { Array2D<uint32_t> WaveFormCollapse::wave_to_output() const {
Array2D<uint32_t> output_patterns(wave.height, wave.width); Array2D<uint32_t> output_patterns(wave.height, wave.width);
for (uint32_t i = 0; i < wave.size; i++) { for (uint32_t i = 0; i < wave.size; i++) {
@ -34,20 +35,24 @@ Array2D<uint32_t> WFC::wave_to_output() const {
return output_patterns; return output_patterns;
} }
WFC::WFC(bool periodic_output, int seed, //WaveFormCollapse::WaveFormCollapse() {
//}
WaveFormCollapse::WaveFormCollapse(bool periodic_output, int seed,
Vector<double> patterns_frequencies, Vector<double> patterns_frequencies,
Vector<Propagator::PropagatorEntry> propagator, uint32_t wave_height, uint32_t wave_width) : Vector<Propagator::PropagatorEntry> propagator, uint32_t wave_height, uint32_t wave_width) :
gen(seed), patterns_frequencies(normalize(patterns_frequencies)), wave(wave_height, wave_width, patterns_frequencies), nb_patterns(propagator.size()), propagator(wave.height, wave.width, periodic_output, propagator) {} gen(seed), patterns_frequencies(normalize(patterns_frequencies)), wave(wave_height, wave_width, patterns_frequencies), nb_patterns(propagator.size()), propagator(wave.height, wave.width, periodic_output, propagator) {
}
Array2D<uint32_t> WFC::run() { Array2D<uint32_t> 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 == failure) { if (result == OBSERVE_STATUS_FAILURE) {
return Array2D<uint32_t>(0, 0); return Array2D<uint32_t>(0, 0);
} else if (result == success) { } else if (result == OBSERVE_STATUS_FAILURE) {
return wave_to_output(); return wave_to_output();
} }
@ -56,20 +61,20 @@ Array2D<uint32_t> WFC::run() {
} }
} }
WFC::ObserveStatus WFC::observe() { WaveFormCollapse::ObserveStatus WaveFormCollapse::observe() {
// Get the cell with lowest entropy. // Get the cell with lowest entropy.
int argmin = wave.get_min_entropy(gen); int argmin = wave.get_min_entropy(gen);
// If there is a contradiction, the algorithm has failed. // If there is a contradiction, the algorithm has failed.
if (argmin == -2) { if (argmin == -2) {
return failure; return OBSERVE_STATUS_FAILURE;
} }
// If the lowest entropy is 0, then the algorithm has succeeded and // If the lowest entropy is 0, then the algorithm has succeeded and
// finished. // finished.
if (argmin == -1) { if (argmin == -1) {
wave_to_output(); wave_to_output();
return success; return OBSERVE_STATUS_SUCCESS;
} }
// Choose an element according to the pattern distribution // Choose an element according to the pattern distribution
@ -98,5 +103,8 @@ WFC::ObserveStatus WFC::observe() {
} }
} }
return to_continue; return OBSERVE_STATUS_TO_CONTINUE;
}
void WaveFormCollapse::bind_methods() {
} }

View File

@ -1,5 +1,7 @@
#ifndef FAST_WFC_WFC_HPP_ #ifndef WAVE_FORM_COLLAPSE_H
#define FAST_WFC_WFC_HPP_ #define WAVE_FORM_COLLAPSE_H
#include "core/reference.h"
#include <optional> #include <optional>
#include <random> #include <random>
@ -8,13 +10,40 @@
#include "propagator.h" #include "propagator.h"
#include "wave.h" #include "wave.h"
// Class containing the generic WFC algorithm. class WaveFormCollapse : public Reference {
class WFC { GDCLASS(WaveFormCollapse, Reference);
public:
enum ObserveStatus {
OBSERVE_STATUS_SUCCESS,
OBSERVE_STATUS_FAILURE,
OBSERVE_STATUS_TO_CONTINUE
};
Array2D<uint32_t> run();
ObserveStatus observe();
void propagate() { propagator.propagate(wave); }
void remove_wave_pattern(uint32_t i, uint32_t j, uint32_t pattern) {
if (wave.get(i, j, pattern)) {
wave.set(i, j, pattern, false);
propagator.add_to_propagator(i, j, pattern);
}
}
WaveFormCollapse();
WaveFormCollapse(bool periodic_output, int seed, Vector<double> patterns_frequencies,
Vector<Propagator::PropagatorEntry> propagator, uint32_t wave_height,
uint32_t wave_width);
protected:
static void bind_methods();
private: private:
// The random number generator.
std::minstd_rand gen; std::minstd_rand gen;
// The distribution of the patterns as given in input.
const Vector<double> patterns_frequencies; const Vector<double> patterns_frequencies;
Wave wave; Wave wave;
@ -22,43 +51,12 @@ private:
// The number of distinct patterns. // The number of distinct patterns.
const size_t nb_patterns; const size_t nb_patterns;
// The propagator, used to propagate the information in the wave.
Propagator propagator; Propagator propagator;
// 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<uint32_t> wave_to_output() const;
public:
// Basic constructor initializing the algorithm.
WFC(bool periodic_output, int seed, Vector<double> patterns_frequencies,
Vector<Propagator::PropagatorEntry> propagator, uint32_t wave_height,
uint32_t wave_width);
// Run the algorithm, and return a result if it succeeded.
Array2D<uint32_t> run();
// Return value of observe.
enum ObserveStatus {
success, // WFC has finished and has succeeded.
failure, // WFC has finished and failed.
to_continue // WFC isn't finished.
};
// Define the value of the cell with lowest entropy.
ObserveStatus observe();
// Propagate the information of the wave.
void propagate() { propagator.propagate(wave); }
// Remove pattern from cell (i,j).
void remove_wave_pattern(uint32_t i, uint32_t j, uint32_t pattern) {
if (wave.get(i, j, pattern)) {
wave.set(i, j, pattern, false);
propagator.add_to_propagator(i, j, pattern);
}
}
}; };
#endif // FAST_WFC_WFC_HPP_ #endif