#ifndef ROTOR_MATHS #define ROTOR_MATHS #include "rotor.h" #include #include #include "Poco/Logger.h" #include "mtrand.h" using namespace noise; namespace Rotor { #define COMPARISON_Equal 1 #define COMPARISON_Not_equal 2 #define COMPARISON_Greater 3 #define COMPARISON_Less 4 #define COMPARISON_Greater_or_equal 5 #define COMPARISON_Less_or_equal 6 class Comparison: public Signal_node { public: Comparison(){ create_signal_input("signal","Signal"); create_parameter("value","number","Value or signal for operation","Value",0.0); create_attribute("operator","Operator for comparison","operator","==",{"==","!=",">","<",">=","<="}); title="Comparison"; description="Compares the signal with a value or signal according to the operator"; NODEID="e568b918-2d0a-11e3-bc3b-8ff3658b7e6c"; }; Comparison(map &settings):Comparison() { base_settings(settings); } Comparison* clone(map &_settings) { return new Comparison(_settings);}; const double output(const Time_spec &time) { if (inputs[0]->connection) { switch (attributes["operator"]->intVal) { case COMPARISON_Equal: return fequal(parameters["value"]->value,inputs[0]->get(time))?1.0:0.0; break; case COMPARISON_Not_equal: return fequal(parameters["value"]->value,inputs[0]->get(time))?0.0:1.0; break; case COMPARISON_Greater: return fgreater(parameters["value"]->value,inputs[0]->get(time))?1.0:0.0; break; case COMPARISON_Less: return fless(parameters["value"]->value,inputs[0]->get(time))?1.0:0.0; break; case COMPARISON_Greater_or_equal: return fgreater_or_equal(parameters["value"]->value,inputs[0]->get(time))?1.0:0.0; break; case COMPARISON_Less_or_equal: return fless_or_equal(parameters["value"]->value,inputs[0]->get(time))?1.0:0.0; break; } } return 0.0; } }; #define ARITHMETIC_plus 1 #define ARITHMETIC_minus 2 #define ARITHMETIC_multiply 3 #define ARITHMETIC_divide 4 #define ARITHMETIC_modulo 5 #define ARITHMETIC_pow 6 #define ARITHMETIC_sin 7 #define ARITHMETIC_cos 8 #define ARITHMETIC_ease 9 #define ARITHMETIC_jolt 10 #define ARITHMETIC_floor 11 #define ARITHMETIC_2pow 12 #define ARITHMETIC_reciprocal 13 #define ARITHMETIC_rminus 14 class Arithmetic: public Signal_node { public: Arithmetic(){ create_signal_input("signal","Signal"); create_parameter("value","number","Value or signal for operation","Value",1.0); create_parameter("frequency","number","Frequency for trigonometric functions","Frequency",1.0); create_attribute("operator","operator for image","Operator","+",{"+","-","*","/","%","^","sin","cos","ease","jolt","floor","2pow","reciprocal","rminus"}); title="Arithmetic"; description="Performs arithmetic on a signal with a signal or value"; NODEID="f35e5f82-2d0a-11e3-83d8.0ed336db813"; }; Arithmetic(map &settings):Arithmetic() { base_settings(settings); }; void init(){ phase=0.0; } Arithmetic* clone(map &_settings) { return new Arithmetic(_settings);}; const double output(const Time_spec &time) { if (inputs[0]->connection) { double in= inputs[0]->get(time); switch (attributes["operator"]->intVal) { case ARITHMETIC_plus: return in+parameters["value"]->value; break; case ARITHMETIC_minus: return in-parameters["value"]->value; break; case ARITHMETIC_multiply: return in*parameters["value"]->value; break; case ARITHMETIC_divide: return in/parameters["value"]->value; break; case ARITHMETIC_modulo: return fmod(in,parameters["value"]->value); break; case ARITHMETIC_pow: return pow(in,parameters["value"]->value); break; case ARITHMETIC_sin: phase+=(in-inputs[0]->get(time.lastframe()))*parameters["frequency"]->value; return sin(phase)*parameters["value"]->value; break; case ARITHMETIC_cos: phase+=(in-inputs[0]->get(time.lastframe()))*parameters["frequency"]->value; return cos(phase)*parameters["value"]->value; break; case ARITHMETIC_ease: return ((1.0-parameters["value"]->value)*in)+(parameters["value"]->value*(0.5f+((cos((fmod(in,1.0)+1.0)*M_PI))*0.5f))); break; case ARITHMETIC_jolt: return ((1.0-parameters["value"]->value)*in)+(parameters["value"]->value*(0.5f+((sin((fmod(in,1.0)+1.0)*M_PI))*0.5f))); break; case ARITHMETIC_floor: return floor(in); break; case ARITHMETIC_2pow: return pow(2,in); break; case ARITHMETIC_reciprocal: return parameters["value"]->value/in; break; case ARITHMETIC_rminus: return parameters["value"]->value-in; break; } } return 0.0; } int op; double value,phase; }; class Is_new_integer: public Signal_node { public: Is_new_integer(){ title="New integer"; description="Outputs 1 on the frame that a signal becomes a new integer"; create_signal_input("signal","Signal"); NODEID="03320e0e-2d0b-11e3-93b2-5f9cfa67d27b"; }; Is_new_integer(map &settings):Is_new_integer() { base_settings(settings); }; Is_new_integer* clone(map &_settings) { return new Is_new_integer(_settings);}; const double output(const Time_spec &time) { if (((int)inputs[0]->get(time))>((int)inputs[0]->get(time.lastframe()))) { return 1.0; } return 0.0; } }; class On_off: public Signal_node { public: On_off(){ title="On off"; description="Outputs 1 if the integer floor of the signal is even"; create_signal_input("signal","Signal"); NODEID="13c6e212-2d0b-11e3-a3c8-6ffea774de32"; }; On_off(map &settings):On_off() { base_settings(settings); }; On_off* clone(map &_settings) { return new On_off(_settings);}; const double output(const Time_spec &time) { if (inputs[0]->connection) { double s1=(((Signal_node*)(inputs[0]->connection))->get_output(time)); if ((int)s1%2) return 1.0; } return 0.0; } }; //pseudo random hash function //http://create.stephan-brumme.com/fnv-hash/ const uint32_t Prime = 0x01000193; // 16777619 const uint32_t Seed = 0x811C9DC5; // 2166136261 /// hash a byte inline uint32_t fnv1a(unsigned char oneByte, uint32_t hash = Seed) { return (oneByte ^ hash) * Prime; } /// hash a short (two bytes) inline uint32_t fnv1a(unsigned short twoBytes, uint32_t hash = Seed) { const unsigned char* ptr = (const unsigned char*) &twoBytes; hash = fnv1a(*ptr++, hash); return fnv1a(*ptr , hash); } /// hash a 32 bit integer (four bytes) inline uint32_t fnv1a(uint32_t fourBytes, uint32_t hash = Seed) { const unsigned char* ptr = (const unsigned char*) &fourBytes; hash = fnv1a(*ptr++, hash); hash = fnv1a(*ptr++, hash); hash = fnv1a(*ptr++, hash); return fnv1a(*ptr , hash); } uint32_t hash( uint32_t a) { a = (a+0x7ed55d16) + (a<<12); a = (a^0xc761c23c) ^ (a>>19); a = (a+0x165667b1) + (a<<5); a = (a+0xd3a2646c) ^ (a<<9); a = (a+0xfd7046c5) + (a<<3); a = (a^0xb55a4f09) ^ (a>>16); a -= (a>>1); return a; } class Random: public Signal_node { public: Random(){ title="Random"; description="Randomises integer part of signal (seedable)"; create_signal_input("signal","Signal"); create_parameter("seed","number","Seed value","Seed",1.0); NODEID="1de86932-2d0b-11e3-96d3-77aa4558e6cd"; std::uniform_int_distribution<> d(-9999, 9999); }; Random(map &settings):Random() { base_settings(settings); }; Random* clone(map &_settings) { return new Random(_settings);}; const double output(const Time_spec &time) { double o; if (inputs[0]->connection){ o=inputs[0]->get(time); } else o=time.time; uint32_t m=(int)o; PRNG.seed(m^(int)parameters["seed"]->value); return ((double)(PRNG()&0xffff))+(o-m); //uint32_t seed=Seed+parameters["seed"]->value; //hash the integer part and add the fractional part back on // //return ((double)(fnv1a(m,seed)))+(o-m); //%((uint32_t)time.duration)) } MTRand_int32 PRNG; }; class Noise: public Signal_node { //fractal noise public: Noise(){ title="Noise"; description="Fractal noise (seedable)"; create_signal_input("signal","Signal"); create_parameter("seed","number","Seed value","Seed",1.0); create_parameter("octaves","number","Octaves of noise","octaves",6.0); create_parameter("frequency","number","Frequency of noise","frequency",1.0); create_parameter("scale","number","scale of noise","scale",1.0); NODEID="28b3c154-2d0b-11e3-bdf2-1b9b2678a2f6"; }; Noise(map &settings):Noise() { base_settings(settings); }; Noise* clone(map &_settings) { return new Noise(_settings);}; const double output(const Time_spec &time) { perlin.SetOctaveCount(parameters["octaves"]->value); perlin.SetFrequency(parameters["frequency"]->value); perlin.SetSeed(Seed+parameters["seed"]->value); if (inputs[0]->connection){ return perlin.GetValue(inputs[0]->get(time),0,0)*parameters["scale"]->value; } return perlin.GetValue(time.time,0,0)*parameters["scale"]->value; } private: module::Perlin perlin; }; } #endif