diff options
Diffstat (limited to 'rotord/rotor.h')
| -rwxr-xr-x | rotord/rotor.h | 126 |
1 files changed, 115 insertions, 11 deletions
diff --git a/rotord/rotor.h b/rotord/rotor.h index b681e72..0c16df7 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -4,6 +4,9 @@ nodes can have many inputs but only 1 output image nodes that use an image as input can pass on the incoming image only if its unchanged. TODO - parameter class that automatically links variable to correctly named inputs +TODO - use try.. catch and dynamic_cast to verify node connections rather than checking 'type' tag + +TODO - put the boilerplate code for checking inputs into the base class, finally call checked_output */ #include <unordered_map> @@ -111,6 +114,34 @@ namespace Rotor { AVPacket packet; }; + class pixeltables{ + //handy pixel arithmetic lookup tables as nested arrays + //so - pixels.add[0x78][0x66]; will give the precalculated result of adding with saturation + public: + pixeltables(){ + add=new uint8_t*[0xFF]; + multiply=new uint8_t*[0xFF]; + for (int i=0;i<0xFF;i++){ + add[i]=new uint8_t[0xFF]; + multiply[i]=new uint8_t[0xFF]; + for (int j=0;j<0xFF;j++){ + add[i][j]=(uint8_t)min(i+j,0xFF); + multiply[i][j]=(uint8_t)((((float)i)/255.0f)*(((float)j)/255.0f)*255.0f); + } + } + } + virtual ~pixeltables(){ + for (int i=0;i<0xFF;i++){ + delete[] add[i]; + delete[] multiply[i]; + } + delete[] add; + delete[] multiply; + } + uint8_t **add; + uint8_t **multiply; + }; + static pixeltables pixels; class Time_spec{ public: Time_spec(){}; @@ -221,8 +252,20 @@ namespace Rotor { } else { for (int i=0;i<w*h*3;i++){ - //creates rainbow overload RGBdata[i]=(unsigned char)(((int)other.RGBdata[i]+(int)RGBdata[i])&0x00FF); - RGBdata[i]=(unsigned char)min((int)other.RGBdata[i]+(int)RGBdata[i],0x00FF); + //calculate with tables + RGBdata[i]=pixels.add[RGBdata[i]][other.RGBdata[i]]; + } + } + return *this; + } + Image & operator*=(const Image &other) { + if (other.w!=w||other.h!=h) { + cerr<<"Rotor: cannot multiply images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; + } + else { + for (int i=0;i<w*h*3;i++){ + //calculate with tables + RGBdata[i]=pixels.multiply[RGBdata[i]][other.RGBdata[i]]; } } return *this; @@ -424,6 +467,17 @@ namespace Rotor { vampHost::Analyser analyser; map <string,float> params; }; + class Time: public Signal_node { + public: + Time(){}; + Time(map<string,string> &settings) { + base_settings(settings); + }; + Time* clone(map<string,string> &_settings) { return new Time(_settings);}; + const float output(const Time_spec &time) { + return time.time; + } + }; class Track_time: public Signal_node { public: Track_time(){}; @@ -629,27 +683,24 @@ namespace Rotor { Random(){}; Random(map<string,string> &settings) { base_settings(settings); - seed=(float)find_setting(settings,"seed",Seed); - for (auto p:parameter_inputs){ - if (p->parameter=="seed") p->receiver=&seed; - } - key=0xffffffff; + seed=(Seed+find_setting(settings,"seed",0)); + cerr<<"random:: seed "<<seed<<" ("<<Seed<<")"<<endl; }; Random* clone(map<string,string> &_settings) { return new Random(_settings);}; const float output(const Time_spec &time) { if (inputs.size()) { if (inputs[0]->connection) { + //hash the integer part and add the fractional part back on float o=(((Signal_node*)inputs[0]->connection)->get_output(time)); uint32_t m=(int)o; - return ((float)fnv1a(m,(uint32_t)(seed+0.5f)))+(o-m); + return ((float)(fnv1a(m,seed)%((uint32_t)time.duration)))+(o-m); } } return 0.0f; } - float seed; + uint32_t seed; private: - }; class Signal_output: public Signal_node { public: @@ -706,7 +757,7 @@ namespace Rotor { ~Invert(){ delete image;}; Invert* clone(map<string,string> &_settings) { return new Invert(_settings);}; Image *output(const Frame_spec &frame){ - if (inputs.size()) { + if (image_inputs.size()) { if (image_inputs[0]->connection){ if (inputs[0]->connection) { if (fgreater_or_equal(1.0f,(((Signal_node*)inputs[0]->connection)->get_output((Time_spec)frame)))) { @@ -1118,6 +1169,59 @@ namespace Rotor { unordered_map<int,Image*> images; float mode; //TODO make int, enum string parameter types }; + #define BLEND_screen 1 + #define BLEND_multiply 2 + #define BLEND_blend 3 + class Blend: public Image_node { + public: + Blend(){}; + Blend(map<string,string> &settings) { + base_settings(settings); + image=new Image(); + amount=find_setting(settings,"amount",1.0f); + string _mode=find_setting(settings,"mode","screen"); + if (_mode=="screen") mode=BLEND_screen; + if (_mode=="multiply") mode=BLEND_multiply; + if (_mode=="blend") mode=BLEND_blend; + }; + void link_params() { + for (auto p:parameter_inputs){ + if (p->parameter=="amount") p->receiver=&amount; + } + }; + ~Blend(){ delete image;}; + Blend* clone(map<string,string> &_settings) { return new Blend(_settings);}; + Image *output(const Frame_spec &frame){ + if (image_inputs.size()) { + if (image_inputs[0]->connection){ + if (inputs.size()>1) { + if (image_inputs[1]->connection) { + //copy incoming image **writable + image->free(); + image=(((Image_node*)image_inputs[0]->connection)->get_output(frame))->clone(); + switch(mode){ + case BLEND_screen: + (*image)+=(*(((Image_node*)image_inputs[1]->connection)->get_output(frame))); + break; + case BLEND_multiply: + (*image)*=(*(((Image_node*)image_inputs[1]->connection)->get_output(frame))); + break; + + } + return image; + } + } + //if there aren't 2 image inputs connected just return the first + return (((Image_node*)image_inputs[0]->connection)->get_output(frame)); + } + } + return nullptr; + } + private: + Image *image; //is an image generator + int mode; + float amount; //for blend + }; //------------------------------------------------------------------- class Node_factory{ public: |
