summaryrefslogtreecommitdiff
path: root/rotord/src/nodes_maths.h
blob: 2696b2e4fd100e366c442c0134a492da1254307a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#ifndef ROTOR_MATHS
#define ROTOR_MATHS

#include "rotor.h"
#include <libnoise/noise.h>
#include <libnoise/mathconsts.h>
#include "Poco/Logger.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.0f);
				create_attribute("operator","Operator for comparison","operator","==",{"==","!=",">","<",">=","<="});
				title="Comparison";
				description="Compares the signal with a value or signal according to the operator";
				UID="e568b918-2d0a-11e3-bc3b-8ff3658b7e6c";
			};
			Comparison(map<string,string> &settings):Comparison() {
				base_settings(settings);
			}
			Comparison* clone(map<string,string> &_settings) { return new Comparison(_settings);};
			const float 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.0f:0.0f;
	                		break;
						case COMPARISON_Not_equal:
							return fequal(parameters["value"]->value,inputs[0]->get(time))?0.0f:1.0f;
	                		break;
						case COMPARISON_Greater:
							return fgreater(parameters["value"]->value,inputs[0]->get(time))?1.0f:0.0f;
	                		break;
						case COMPARISON_Less:
							return fless(parameters["value"]->value,inputs[0]->get(time))?1.0f:0.0f;
	                		break;
						case COMPARISON_Greater_or_equal:
							return fgreater_or_equal(parameters["value"]->value,inputs[0]->get(time))?1.0f:0.0f;
	                		break;
						case COMPARISON_Less_or_equal:
							return fless_or_equal(parameters["value"]->value,inputs[0]->get(time))?1.0f:0.0f;
	                		break;
	                }
	            }

				return 0.0f;
			}
	};
#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
	class Arithmetic: public Signal_node {
		public:
			Arithmetic(){
				create_signal_input("signal","Signal");
				create_parameter("value","number","Value or signal for operation","Value",1.0f);
				create_attribute("operator","operator for image","Operator","+",{"+","-","*","/","%","^","sin","cos","ease","jolt","floor","2pow","reciprocal"});
				title="Arithmetic";
				description="Performs arithmetic on a signal with a signal or value";
				UID="f35e5f82-2d0a-11e3-83d8-0fed336db813";
			};
			Arithmetic(map<string,string> &settings):Arithmetic() {
				base_settings(settings);
			};
			Arithmetic* clone(map<string,string> &_settings) { return new Arithmetic(_settings);};
			const float output(const Time_spec &time) {
				//if (attributes["operator"]->intVal==ARITHMETIC_divide||attributes["operator"]->intVal==ARITHMETIC_modulo){
				//	if (value==0.0f) {
				//		Poco::Logger& logger = Poco::Logger::get("Rotor");
				//		logger.error("Arithmetic node: caught division by zero, frame "+time.frame());
				//		return 0.0f;
				//	}
				//}
				if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml
                    if (inputs[0]->connection) {
                        float 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:
								return sin(in)*parameters["value"]->value;
                        		break;
                        	case ARITHMETIC_cos:
								return cos(in)*parameters["value"]->value;
                        		break;
                        	case ARITHMETIC_ease:
								return ((1.0-parameters["value"]->value)*in)+(parameters["value"]->value*(0.5f+((cos((fmod(in,1.0f)+1.0f)*M_PI))*0.5f)));
                        		break;
                        	case ARITHMETIC_jolt:
								return ((1.0-parameters["value"]->value)*in)+(parameters["value"]->value*(0.5f+((sin((fmod(in,1.0f)+1.0f)*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;
                        }
                    }
			    }
				return 0.0f;
			}
			int op;
			float value;
	};
	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");
				UID="03320e0e-2d0b-11e3-93b2-5f9cfa67d27b";
			};
			Is_new_integer(map<string,string> &settings):Is_new_integer() {
				base_settings(settings);
			};
			Is_new_integer* clone(map<string,string> &_settings) { return new Is_new_integer(_settings);};
			const float output(const Time_spec &time) {
				if (((int)inputs[0]->get(time))>((int)inputs[0]->get(time.lastframe()))) {
					return 1.0f;
				}
				return 0.0f;
			}
	};
	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");
				UID="13c6e212-2d0b-11e3-a3c8-6ffea774de32";
			};
			On_off(map<string,string> &settings):On_off() {
				base_settings(settings);
			};
			On_off* clone(map<string,string> &_settings) { return new On_off(_settings);};
			const float output(const Time_spec &time) {
				if (inputs[0]->connection) {
					float s1=(((Signal_node*)(inputs[0]->connection))->get_output(time));
					if ((int)s1%2) return 1.0f;
				}
				return 0.0f;
			}
	};
	//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);
	}
	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.0f);
				UID="1de86932-2d0b-11e3-96d3-77aa4558e6cd";
			};
			Random(map<string,string> &settings):Random() {
				base_settings(settings);
			};
			Random* clone(map<string,string> &_settings) { return new Random(_settings);};
			const float output(const Time_spec &time) {
				uint32_t seed=Seed+parameters["seed"]->value;
            	//hash the integer part and add the fractional part back on
            	float o=inputs[0]->get(time);
            	uint32_t m=(int)o;
                return ((float)(fnv1a(m,seed)%((uint32_t)time.duration)))+(o-m);
			}
	};
	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.0f);
				create_parameter("octaves","number","Octaves of noise","octaves",6.0f);
				create_parameter("frequency","number","Frequency of noise","frequency",1.0f);
				create_parameter("scale","number","scale of noise","scale",1.0f);
				UID="28b3c154-2d0b-11e3-bdf2-1b9b2678a2f6";
			};
			Noise(map<string,string> &settings):Noise() {
				base_settings(settings);
			};
			Noise* clone(map<string,string> &_settings) { return new Noise(_settings);};
			const float 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;
			}
			uint32_t seed;
		private:
			module::RidgedMulti perlin;
	};

}



#endif