atomorph/morph.h

148 lines
8.2 KiB
C++

/*
* See Copyright Notice in atomorph.h
*/
#include "atomorph.h"
namespace am {
class morph {
public:
morph();
~morph();
void clear ();
bool add_pixel (size_t frame, pixel px);
bool add_frame (size_t frame);
size_t get_pixel_count (size_t frame);
size_t get_frame_key (double t);
size_t get_blob_count (size_t frame);
size_t get_blob_count ();
pixel get_average_pixel (size_t frame);
pixel get_average_pixel (size_t frame, size_t blob);
pixel get_pixel (size_t frame, size_t position);
color get_background (uint16_t x, uint16_t y, double t);
point interpolate (point pt1, point pt2, double pt1_weight);
pixel interpolate (pixel px1, pixel px2, double px1_weight);
color interpolate (color c1, color c2, double c1_weight);
color interpolate (color c1, color c2, double lag, double slope, double c1_weight);
const blob* get_pixels (size_t blob, double t, std::vector<pixel> *to);
void get_pixels (double t, std::vector<pixel> *to);
void set_seed (unsigned seed);
double get_time (size_t current_frame, size_t total_frames);
double normalize_time (double t);
uint16_t get_width () {return width;}
uint16_t get_height () {return height;}
size_t get_frame_count () {return frames.size();}
unsigned get_state () {return state;}
void next_state () {skip_state = true;}
const blob* get_blob (size_t f, size_t b) {return (has_blob(f, b) ? ((const blob*) frames[f].blobs[b]) : nullptr);}
double get_energy () {return energy;}
pixel blob2pixel (const blob *bl);
void compute (); // If not busy yet, sets worker thread to run indefinitely.
void iterate (size_t iterations); // If not busy yet, sets worker thread to run the defined number of iterations.
void compute (double seconds); // If not busy yet, sets worker thread to run for the defined number of seconds.
void suspend (); // Blocks the calling thread until morph is no longer busy. Returns when worker is paused.
bool suspend (double timeout); // Blocks the calling thread for timeout seconds at maximum. Returns false on timeout.
bool is_busy () const {return (worker.is_running() && !worker.is_paused());}
bool synchronize (); // Synchronizes data with the worker thread. Returns false when worker is busy at the moment.
void set_blob_delimiter (unsigned char d) {blob_delimiter = d;} // Color distance formula.
void set_blob_threshold (double t) {blob_threshold = t;} // Color difference toleration.
void set_blob_max_size (size_t s) {blob_max_size = s;} // Maximum size of a blob.
void set_blob_min_size (size_t s) {blob_min_size = s;} // Minimum size of a blob.
void set_blob_box_grip (uint16_t g) {blob_box_grip = g;} // Defines the bounding box.
void set_blob_box_samples(size_t s) {blob_box_samples=s;} // Number of dust samples.
void set_blob_number (size_t n) {blob_number = n;} // Preferred number of blobs.
void set_blob_rgba_weight(unsigned char w) {blob_rgba_weight=w;} // Blob RGBA weight.
void set_blob_size_weight(unsigned char w) {blob_size_weight=w;} // Blob size weight.
void set_blob_xy_weight (unsigned char w) {blob_xy_weight =w;} // Blob location weight.
void set_degeneration (size_t d) {degeneration =d;} // Solution degeneration period.
void set_motion (unsigned char m) {motion =m;} // How to interpolate movement.
void set_fading (unsigned char f) {fading =f;} // How to interpolate colors.
void set_threads (size_t t) {threads =t;} // How many threads the worker thread can spawn.
void set_cycle_length (size_t c) {cycle_length =c;} // How many times to morph per iteration.
void set_feather (size_t f) {feather =f;} // Blob outer layers to fade out.
void set_keep_background (bool k) {keep_background =k;} // Background is kept and cross-dissolved.
void set_finite (bool f) {finite =f;} // Morph will not repeat itself.
void set_show_blobs (unsigned b) {show_blobs =b;} // Determines how blobs are drawn.
// These change identifier, causing the morph to restart:
void set_fluid (unsigned f); // Steps of fluid simulation per frame.
void set_density (uint16_t d); // Key points per pixel.
void set_resolution (uint16_t w, uint16_t h);
private:
inline bool has_pixel (size_t f, size_t pos) {return (has_frame(f) && frames[f].pixels.find(pos) != frames[f].pixels.end());}
inline bool has_frame (size_t f ) const {return (frames.find(f) != frames.end());}
inline bool has_blob (size_t f, size_t b ) {return (has_frame(f) && frames[f].blobs.size() > b);}
void refresh_frames();
blob * find_blob_by_group(size_t frame_key, size_t group);
void draw_atoms(double t, std::vector<pixel> *image);
void draw_fluid(double t, std::vector<pixel> *image);
void step_fluid(size_t frame_key, double t, double time);
void update_particle (Particle *p, const blob * blob_before, const blob * blob_after, point **points,
std::map<size_t, size_t>& src, std::map<size_t, size_t>& dest, double t, size_t y,
size_t y_next, size_t frame_key, size_t next_frame_key, size_t chain_key, double time);
std::map<size_t, frame> frames;
std::map<size_t, chain> chains; // Key is the blob's group.
unsigned char fading = PERLIN; // Color interpolation.
unsigned char motion = SPLINE; // Trajectory interpolation.
unsigned char blob_delimiter = HSP;
double blob_threshold = 1.0;
size_t blob_number = 1;
size_t blob_max_size = SIZE_MAX;
size_t blob_min_size = 1;
size_t blob_box_samples = 10;
uint16_t blob_box_grip = UINT16_MAX;
unsigned char blob_rgba_weight = 1;
unsigned char blob_size_weight = 1;
unsigned char blob_xy_weight = 1;
size_t degeneration = 0;
uint16_t density = 1;
size_t threads = 0;
size_t cycle_length = 1000;
size_t feather = 0;
bool keep_background = false;
bool blend_blobs = false;
bool finite = false;
unsigned fluidsteps = 0;
unsigned show_blobs = TEXTURE;
unsigned seed;
// Minimum Bounding Box that fits all pixels of all frames:
uint16_t bbox_x1 = UINT16_MAX;
uint16_t bbox_y1 = UINT16_MAX;
uint16_t bbox_x2 = 0;
uint16_t bbox_y2 = 0;
uint16_t width = 0;
uint16_t height = 0;
size_t identifier=0; // Changed when anything changes in the key frames.
unsigned state =STATE_BLOB_DETECTION;
bool skip_state=false;
thread worker;
double energy=0.0;
PerlinNoise lag_map;
PerlinNoise slope_map;
FluidModel *fluid = nullptr;
unsigned sparseness = 1;
std::default_random_engine e1;
};
}