1 #include "PresetFrameIO.hpp"
2 #include "wipemalloc.h"
3 #include <math.h>
4 #include <cassert>
5 #include <iostream>
6 #include <cmath>
7 #include "Renderer/BeatDetect.hpp"
8 
9 #ifdef __SSE2__
10 #include <immintrin.h>
11 #endif
12 
13 
PresetInputs()14 PresetInputs::PresetInputs() : PipelineContext()
15 {
16 }
17 
18 
update(const BeatDetect & music,const PipelineContext & context)19 void PresetInputs::update(const BeatDetect & music, const PipelineContext & context) {
20 
21     // Reflect new values form the beat detection unit
22     this->bass = music.bass;
23     this->mid = music.mid;
24     this->treb = music.treb;
25     this->bass_att = music.bass_att;
26     this->mid_att = music.mid_att;
27     this->treb_att = music.treb_att;
28 
29     // Reflect new values from the pipeline context
30     this->fps = context.fps;
31     this->time = context.time;
32 
33     this->frame = context.frame;
34     this->progress = context.progress;
35 }
36 
37 
alloc_mesh(size_t gx,size_t gy)38 float **alloc_mesh(size_t gx, size_t gy)
39 {
40 	// round gy up to multiple 4 (for possible SSE optimization)
41 	gy = (gy+3) & ~(size_t)3;
42 
43 	float **mesh = (float **)wipe_aligned_alloc(gx * sizeof(float *));
44 	float *m = (float *)wipe_aligned_alloc(gx * gy * sizeof(float));
45 	for (unsigned int x = 0; x < gx; x++ )
46 		mesh[x] = m + (gy * x);
47 	return mesh;
48 }
49 
free_mesh(float ** mesh)50 float **free_mesh(float **mesh)
51 {
52 	wipe_aligned_free(mesh[0]);
53 	wipe_aligned_free(mesh);
54 	return NULL;
55 }
56 
copy_mesh(float ** dst,float ** src,int gx,int gy)57 void copy_mesh(float **dst, float **src, int gx, int gy)
58 {
59 	memcpy(dst[0], src[0], gx*gy*sizeof(float));
60 }
61 
62 
Initialize(int _gx,int _gy)63 void PresetInputs::Initialize ( int _gx, int _gy )
64 {
65 	int x, y;
66 
67     this->gx = _gx;
68     this->gy = _gy;
69 
70 
71 	/// @bug no clue if this block belongs here
72 	// ***
73 	progress = 0;
74 	frame = 1;
75 
76 	x_per_pixel = 0;
77 	y_per_pixel = 0;
78 	rad_per_pixel = 0;
79 	ang_per_pixel = 0;
80 	// ***
81 
82 	this->x_mesh    = alloc_mesh(gx, gy);
83 	this->y_mesh    = alloc_mesh(gx, gy);
84 	this->rad_mesh  = alloc_mesh(gx, gy);
85 	this->theta_mesh= alloc_mesh(gx, gy);
86 	this->origtheta = alloc_mesh(gx, gy);
87 	this->origrad   = alloc_mesh(gx, gy);
88 	this->origx     = alloc_mesh(gx, gy);
89 	this->origy     = alloc_mesh(gx, gy);
90 
91 	for ( x=0;x<gx;x++ )
92 	{
93 		for ( y=0;y<gy;y++ )
94 		{
95 			this->origx[x][y]=x/ ( float ) ( gx-1 );
96 			this->origy[x][y]= - ( ( y/ ( float ) ( gy-1 ) )-1 );
97 			this->origrad[x][y]=hypot ( ( this->origx[x][y]-.5 ) *2, ( this->origy[x][y]-.5 ) *2 ) * .7071067;
98 			this->origtheta[x][y]=atan2 ( ( ( this->origy[x][y]-.5 ) *2 ), ( ( this->origx[x][y]-.5 ) *2 ) );
99 		}
100 	}
101 }
102 
103 
PresetOutputs()104 PresetOutputs::PresetOutputs() : Pipeline()
105 {}
106 
107 
~PresetOutputs()108 PresetOutputs::~PresetOutputs()
109 {
110 	assert(this->gx > 0);
111 
112 	this->rad_mesh = free_mesh(this->rad_mesh);
113 	this->sx_mesh  = free_mesh(this->sx_mesh);
114 	this->sy_mesh  = free_mesh(this->sy_mesh);
115 	this->dy_mesh  = free_mesh(this->dy_mesh);
116 	this->dx_mesh  = free_mesh(this->dx_mesh);
117 	this->cy_mesh  = free_mesh(this->cy_mesh);
118 	this->cx_mesh  = free_mesh(this->cx_mesh);
119 	this->warp_mesh = free_mesh(this->warp_mesh);
120 	this->zoom_mesh = free_mesh(this->zoom_mesh);
121 	this->zoomexp_mesh = free_mesh(this->zoomexp_mesh);
122 	this->rot_mesh = free_mesh(this->rot_mesh);
123 	this->orig_x   = free_mesh(this->orig_x);
124 	this->orig_y   = free_mesh(this->orig_y);
125 
126     customWaves.clear();
127     customShapes.clear();
128     drawables.clear();
129 }
130 
131 
Render(const BeatDetect & music,const PipelineContext & context)132 void PresetOutputs::Render(const BeatDetect &music, const PipelineContext &context)
133 {
134 	PerPixelMath(context);
135 
136 	drawables.clear();
137 
138 	drawables.push_back(&mv);
139 
140 	for (PresetOutputs::cshape_container::iterator pos = customShapes.begin();
141 			pos != customShapes.end(); ++pos)
142 	{
143 		if ((*pos)->enabled==1)
144 			drawables.push_back((*pos));
145 	}
146 
147 	for (PresetOutputs::cwave_container::iterator pos = customWaves.begin();
148 			pos != customWaves.end(); ++pos)
149 	{
150 		if ((*pos)->enabled==1)
151 			drawables.push_back((*pos));
152 	}
153 
154 	drawables.push_back(&wave);
155 
156 	if (bDarkenCenter==1)
157 		drawables.push_back(&darkenCenter);
158 	drawables.push_back(&border);
159 
160 	compositeDrawables.clear();
161 	compositeDrawables.push_back(&videoEcho);
162 
163 	if (bBrighten==1)
164 		compositeDrawables.push_back(&brighten);
165 
166 	if (bDarken==1)
167 		compositeDrawables.push_back(&darken);
168 
169 	if (bSolarize==1)
170 		compositeDrawables.push_back(&solarize);
171 
172 	if (bInvert==1)
173 		compositeDrawables.push_back(&invert);
174 }
175 
176 
177 // N.B. The more optimization that can be done on this method, the better! This is called a lot and can probably be improved.
PerPixelMath_c(const PipelineContext & context)178 void PresetOutputs::PerPixelMath_c(const PipelineContext &context)
179 {
180 	for (int x = 0; x < gx; x++)
181 	{
182 		for (int y = 0; y < gy; y++)
183 		{
184 			const float fZoom2 = std::pow(this->zoom_mesh[x][y], std::pow(this->zoomexp_mesh[x][y],
185 					rad_mesh[x][y] * 2.0f - 1.0f));
186 			const float fZoom2Inv = 1.0f / fZoom2;
187 			this->x_mesh[x][y] = this->orig_x[x][y] * 0.5f * fZoom2Inv + 0.5f;
188 			this->x_mesh[x][y] = (this->x_mesh[x][y] - this->cx_mesh[x][y]) / this->sx_mesh[x][y] + this->cx_mesh[x][y];
189 			this->y_mesh[x][y] = this->orig_y[x][y] * 0.5f * fZoom2Inv + 0.5f;
190 			this->y_mesh[x][y] = (this->y_mesh[x][y] - this->cy_mesh[x][y]) / this->sy_mesh[x][y] + this->cy_mesh[x][y];
191 		}
192 	}
193 
194 	const float fWarpTime = context.time * this->fWarpAnimSpeed;
195 	const float fWarpScaleInv = 1.0f / this->fWarpScale;
196 	float f[4];
197 	f[0] = 11.68f + 4.0f * cosf(fWarpTime * 1.413f + 10);
198 	f[1] = 8.77f + 3.0f * cosf(fWarpTime * 1.113f + 7);
199 	f[2] = 10.54f + 3.0f * cosf(fWarpTime * 1.233f + 3);
200 	f[3] = 11.49f + 4.0f * cosf(fWarpTime * 0.933f + 5);
201 
202 	for (int x = 0; x < gx; x++)
203 	{
204 		for (int y = 0; y < gy; y++)
205 		{
206             const float orig_x2 = this->orig_x[x][y];
207             const float orig_y2 = this->orig_y[x][y];
208             const float warp_mesh2 = this->warp_mesh[x][y] * 0.0035f;
209 
210 			this->x_mesh[x][y] +=
211                 (warp_mesh2 * sinf(fWarpTime * 0.333f + fWarpScaleInv * (orig_x2 * f[0] - orig_y2 * f[3]))) +
212                 (warp_mesh2 * cosf(fWarpTime * 0.753f - fWarpScaleInv * (orig_x2 * f[1] - orig_y2 * f[2])));
213 
214 			this->y_mesh[x][y] +=
215                 (warp_mesh2 * cosf(fWarpTime * 0.375f - fWarpScaleInv * (orig_x2 * f[2] + orig_y2 * f[1]))) +
216                 (warp_mesh2 * sinf(fWarpTime * 0.825f + fWarpScaleInv * (orig_x2 * f[0] + orig_y2 * f[3])));
217 		}
218 	}
219 
220 	for (int x = 0; x < gx; x++)
221 	{
222 		for (int y = 0; y < gy; y++)
223 		{
224 			const float u2 = this->x_mesh[x][y] - this->cx_mesh[x][y];
225 			const float v2 = this->y_mesh[x][y] - this->cy_mesh[x][y];
226 
227             const float rot2 = this->rot_mesh[x][y];
228             const float cos_rot = cosf(rot2);
229             const float sin_rot = sinf(rot2);
230 
231 			this->x_mesh[x][y] = u2 * cos_rot - v2 * sin_rot + this->cx_mesh[x][y] - this->dx_mesh[x][y];
232 			this->y_mesh[x][y] = u2 * sin_rot + v2 * cos_rot + this->cy_mesh[x][y] - this->dy_mesh[x][y];
233 		}
234 	}
235 }
236 
237 
238 #ifdef __SSE2__
239 
240 // is there an SSE way to do this?
_mm_pow(__m128 x,__m128 y)241 inline __m128 _mm_pow(__m128 x, __m128 y)
242 {
243 	float X[4];
244 	float Y[4];
245 	_mm_store_ps(X,x);
246 	_mm_store_ps(Y,y);
247 	X[0] = __builtin_powf(X[0],Y[0]);
248 	X[1] = __builtin_powf(X[1],Y[1]);
249 	X[2] = __builtin_powf(X[2],Y[2]);
250 	X[3] = __builtin_powf(X[3],Y[3]);
251 	return _mm_load_ps(X);
252 }
_mm_sincosf(__m128 x,__m128 & sinx,__m128 & cosx)253 inline void _mm_sincosf(__m128 x, __m128 &sinx, __m128 &cosx)
254 {
255 	float X[4], S[4], C[4];
256 	_mm_store_ps(X,x);
257 	S[0] = sinf(X[0]);
258 	C[0] = cosf(X[0]);
259 	S[1] = sinf(X[1]);
260 	C[1] = cosf(X[1]);
261 	S[2] = sinf(X[2]);
262 	C[2] = cosf(X[2]);
263 	S[3] = sinf(X[3]);
264 	C[3] = cosf(X[3]);
265 	sinx = _mm_load_ps(S);
266 	cosx = _mm_load_ps(C);
267 }
_mm_sinf(__m128 x)268 inline __m128 _mm_sinf(__m128 x)
269 {
270 	float X[4];
271 	_mm_store_ps(X,x);
272 	X[0] = sinf(X[0]);
273 	X[1] = sinf(X[1]);
274 	X[2] = sinf(X[2]);
275 	X[3] = sinf(X[3]);
276 	return _mm_load_ps(X);
277 }
_mm_cosf(__m128 x)278 inline __m128 _mm_cosf(__m128 x)
279 {
280 	float X[4];
281 	_mm_store_ps(X,x);
282 	X[0] = cosf(X[0]);
283 	X[1] = cosf(X[1]);
284 	X[2] = cosf(X[2]);
285 	X[3] = cosf(X[3]);
286 	return _mm_load_ps(X);
287 }
288 
289 
PerPixelMath_sse(const PipelineContext & context)290 void PresetOutputs::PerPixelMath_sse(const PipelineContext &context)
291 {
292 	for (int x = 0; x < gx; x++)
293 	{
294 		for (int y = 0; y < gy; y += 4)
295 		{
296 			// fZoom2 = std::pow(this->zoom_mesh[x][y], std::pow(this->zoomexp_mesh[x][y],
297 			// 		rad_mesh[x][y] * 2.0f - 1.0f));
298 			__m128 rad_mesh_scaled =
299 				_mm_sub_ps(
300 					_mm_mul_ps(
301 						_mm_load_ps(&this->rad_mesh[x][y]),
302 						_mm_set_ps1(2.0f)),
303 					_mm_set_ps1(1.0f));
304             __m128 zoom_mesh2 = _mm_load_ps(&this->zoom_mesh[x][y]);
305             __m128 zoomexp_mesh2 = _mm_load_ps(&this->zoomexp_mesh[x][y]);
306             __m128 fZoom2 = _mm_pow(zoom_mesh2, _mm_pow(zoomexp_mesh2, rad_mesh_scaled));
307 			// fZoom2Inv = 1.0f / fZoom2;
308 			__m128 fZoomInv = _mm_rcp_ps(fZoom2);
309 
310 			// this->x_mesh[x][y] = this->orig_x[x][y] * 0.5f * fZoom2Inv + 0.5f;
311             __m128 x_mesh2 =
312 				_mm_add_ps(
313 					_mm_mul_ps(
314 						_mm_load_ps(&this->orig_x[x][y]),
315 						_mm_mul_ps(fZoomInv,_mm_set_ps1(0.5f))),		// CONSIDER: common sub-expression
316 					_mm_set_ps1(0.5f));
317 			// this->x_mesh[x][y] = (this->x_mesh[x][y] - this->cx_mesh[x][y]) / this->sx_mesh[x][y] + this->cx_mesh[x][y];
318             __m128 cx_mesh2 = _mm_load_ps(&this->cx_mesh[x][y]);
319             __m128 sx_mesh2 = _mm_load_ps(&this->sx_mesh[x][y]);
320 			_mm_store_ps(&this->x_mesh[x][y],
321 				_mm_add_ps(
322 					_mm_div_ps(
323                         _mm_sub_ps(x_mesh2,cx_mesh2),
324                         sx_mesh2),
325                     cx_mesh2
326 				));
327 
328 			// this->y_mesh[x][y] = this->orig_y[x][y] * 0.5f * fZoom2Inv + 0.5f;
329             __m128 y_mesh2 =
330 				_mm_add_ps(
331 					_mm_mul_ps(
332 						_mm_load_ps(&this->orig_y[x][y]),
333 						_mm_mul_ps(fZoomInv,_mm_set_ps1(0.5f))),
334 					_mm_set_ps1(0.5f));
335 			// this->y_mesh[x][y] = (this->y_mesh[x][y] - this->cy_mesh[x][y]) / this->sy_mesh[x][y] + this->cy_mesh[x][y];
336             __m128 cy_mesh2 = _mm_load_ps(&this->cy_mesh[x][y]);
337             __m128 sy_mesh2 = _mm_load_ps(&this->sy_mesh[x][y]);
338 			_mm_store_ps(&this->y_mesh[x][y],
339 				_mm_add_ps(
340 					_mm_div_ps(
341                         _mm_sub_ps(y_mesh2,cy_mesh2),
342                         sy_mesh2),
343                     cy_mesh2
344 				));
345 		}
346 	}
347 
348 	const float fWarpTime = context.time * this->fWarpAnimSpeed;
349 	const float fWarpScaleInv = 1.0f / this->fWarpScale;
350 	const float f[4] =
351 	{
352 		11.68f + 4.0f * cosf(fWarpTime * 1.413f + 10),
353 		 8.77f + 3.0f * cosf(fWarpTime * 1.113f + 7),
354 		10.54f + 3.0f * cosf(fWarpTime * 1.233f + 3),
355 		11.49f + 4.0f * cosf(fWarpTime * 0.933f + 5)
356 	};
357 
358 	for (int x = 0; x < gx; x++)
359 	{
360 		for (int y = 0; y < gy; y+=4)
361 		{
362 			//float orig_x = this->orig_x[x][y];
363 			//float orig_y = this->orig_y[x][y];
364 			//float warp_mesh = this->warp_mesh[x][y] * 0.0035f;
365             const __m128 orig_x2 = _mm_load_ps(&this->orig_x[x][y]);
366             const __m128 orig_y2 = _mm_load_ps(&this->orig_y[x][y]);
367             const __m128 warp_mesh2 = _mm_mul_ps(_mm_load_ps(&this->warp_mesh[x][y]), _mm_set_ps1(0.0035f));
368 
369 			// this->x_mesh[x][y] +=
370 			// 	(warp_mesh * sinf(fWarpTime * 0.333f + fWarpScaleInv * (orig_x * f[0] - orig_y * f[3]))) +
371 			// 	(warp_mesh * cosf(fWarpTime * 0.753f - fWarpScaleInv * (orig_x * f[1] - orig_y * f[2])));
372 			_mm_store_ps(&this->x_mesh[x][y],
373 				_mm_add_ps(_mm_load_ps(&this->x_mesh[x][y]),
374 					_mm_add_ps(
375                         _mm_mul_ps(warp_mesh2, _mm_sinf(
376 							_mm_add_ps(
377 								_mm_set_ps1(fWarpTime*0.333f),
378 								_mm_mul_ps(_mm_set_ps1(fWarpScaleInv),
379 									_mm_sub_ps(
380                                         _mm_mul_ps(orig_x2, _mm_set_ps1(f[0])),
381                                         _mm_mul_ps(orig_y2, _mm_set_ps1(f[3]))
382 									))))),
383                         _mm_mul_ps(warp_mesh2, _mm_cosf(
384 							_mm_sub_ps(
385 								_mm_set_ps1(fWarpTime*0.753f),
386 								_mm_mul_ps(_mm_set_ps1(fWarpScaleInv),
387 									_mm_sub_ps(
388                                         _mm_mul_ps(orig_x2, _mm_set_ps1(f[1])),
389                                         _mm_mul_ps(orig_y2, _mm_set_ps1(f[2]))
390 									))))))));
391 
392 			// this->y_mesh[x][y] +=
393 			// 	(warp_mesh * cosf(fWarpTime * 0.375f - fWarpScaleInv * (orig_x * f[2] + orig_y * f[1]))) +
394 			// 	(warp_mesh * sinf(fWarpTime * 0.825f + fWarpScaleInv * (orig_x * f[0] + orig_y * f[3])));
395 			_mm_store_ps(&this->y_mesh[x][y],
396 				_mm_add_ps(_mm_load_ps(&this->y_mesh[x][y]),
397 					_mm_add_ps(
398                         _mm_mul_ps(warp_mesh2, _mm_cosf(
399 							_mm_sub_ps(
400 								_mm_set_ps1(fWarpTime*0.375f),
401 								_mm_mul_ps(_mm_set_ps1(fWarpScaleInv),
402 									_mm_add_ps(
403                                         _mm_mul_ps(orig_x2, _mm_set_ps1(f[2])),
404                                         _mm_mul_ps(orig_y2, _mm_set_ps1(f[1]))
405 									))))),
406                         _mm_mul_ps(warp_mesh2, _mm_sinf(
407 							_mm_add_ps(
408 								_mm_set_ps1(fWarpTime*0.825f),
409 								_mm_mul_ps(_mm_set_ps1(fWarpScaleInv),
410 									_mm_add_ps(
411                                         _mm_mul_ps(orig_x2, _mm_set_ps1(f[0])),
412                                         _mm_mul_ps(orig_y2, _mm_set_ps1(f[3]))
413 									))))))));
414 		}
415 	}
416 	for (int x = 0; x < gx; x++)
417 	{
418 		for (int y = 0; y < gy; y+=4)
419 		{
420 			// const float u2 = this->x_mesh[x][y] - this->cx_mesh[x][y];
421 			// const float v2 = this->y_mesh[x][y] - this->cy_mesh[x][y];
422 			const __m128 u2 = _mm_sub_ps(_mm_load_ps(&this->x_mesh[x][y]),_mm_load_ps(&this->cx_mesh[x][y]));
423 			const __m128 v2 = _mm_sub_ps(_mm_load_ps(&this->y_mesh[x][y]),_mm_load_ps(&this->cy_mesh[x][y]));
424 
425 			// const float rot = this->rot_mesh[x][y];
426 			// const float cos_rot = cosf(rot);
427 			// const float sin_rot = sinf(rot);
428 			__m128 sin_rot, cos_rot;
429 			_mm_sincosf(_mm_load_ps(&this->rot_mesh[x][y]), sin_rot, cos_rot);
430 
431 			// this->x_mesh[x][y] = u2 * cos_rot - v2 * sin_rot + this->cx_mesh[x][y] - this->dx_mesh[x][y];
432 			_mm_store_ps(&this->x_mesh[x][y],
433 				_mm_add_ps(
434 					_mm_sub_ps(_mm_mul_ps(u2, cos_rot), _mm_mul_ps(v2,sin_rot)),
435 					_mm_sub_ps(_mm_load_ps(&this->cx_mesh[x][y]), _mm_load_ps(&this->dx_mesh[x][y]))
436 					));
437 			// this->y_mesh[x][y] = u2 * sin_rot + v2 * cos_rot + this->cy_mesh[x][y] - this->dy_mesh[x][y];
438 			_mm_store_ps(&this->y_mesh[x][y],
439 				_mm_add_ps(
440 					_mm_add_ps(_mm_mul_ps(u2, sin_rot), _mm_mul_ps(v2,cos_rot)),
441 					_mm_sub_ps(_mm_load_ps(&this->cy_mesh[x][y]), _mm_load_ps(&this->dy_mesh[x][y]))
442 					));
443 		}
444 	}
445 }
446 #endif
447 
448 
PerPixelMath(const PipelineContext & context)449 void PresetOutputs::PerPixelMath(const PipelineContext &context)
450 {
451 #ifdef __SSE2__
452 	PerPixelMath_sse(context);
453 #else
454 	PerPixelMath_c(context);
455 #endif
456 }
457 
458 
Initialize(int _gx,int _gy)459 void PresetOutputs::Initialize ( int _gx, int _gy )
460 {
461     assert(_gx > 0);
462 
463     this->gx = _gx;
464     this->gy = _gy;
465 
466 	staticPerPixel = true;
467 
468 	assert(this->gx > 0);
469 	int x;
470 	this->x_mesh  = alloc_mesh( gx, gy );
471 	this->y_mesh  = alloc_mesh( gx, gy );
472 	this->sx_mesh = alloc_mesh( gx, gy );
473 	this->sy_mesh = alloc_mesh( gx, gy );
474 	this->dx_mesh = alloc_mesh( gx, gy );
475 	this->dy_mesh = alloc_mesh( gx, gy );
476 	this->cx_mesh = alloc_mesh( gx, gy );
477 	this->cy_mesh = alloc_mesh( gx, gy );
478 	this->zoom_mesh = alloc_mesh( gx, gy );
479 	this->zoomexp_mesh = alloc_mesh( gx, gy );
480 	this->rot_mesh = alloc_mesh( gx, gy );
481 
482 	this->warp_mesh = alloc_mesh( gx, gy );
483 	this->rad_mesh = alloc_mesh( gx, gy );
484 	this->orig_x  = alloc_mesh( gx, gy );
485 	this->orig_y  = alloc_mesh( gx, gy );
486 
487 	//initialize reference grid values
488 	for (x = 0; x < gx; x++)
489 	{
490 		for (int y = 0; y < gy; y++)
491 		{
492 			float origx = x / (float) (gx - 1);
493 			float origy = -((y / (float) (gy - 1)) - 1);
494 
495 			rad_mesh[x][y]=hypot ( ( origx-.5 ) *2, ( origy-.5 ) *2 ) * .7071067;
496 			orig_x[x][y] = (origx - .5) * 2;
497 			orig_y[x][y] = (origy - .5) * 2;
498 		}
499 	}
500 }
501 
502 
~PresetInputs()503 PresetInputs::~PresetInputs()
504 {
505 	this->origx = free_mesh ( this->origx );
506 	this->origy = free_mesh ( this->origy );
507 	this->origrad = free_mesh ( this->origrad );
508 	this->origtheta = free_mesh ( this->origtheta );
509 	this->x_mesh = free_mesh ( this->x_mesh );
510 	this->y_mesh = free_mesh ( this->y_mesh );
511 	this->rad_mesh = free_mesh ( this->rad_mesh );
512 	this->theta_mesh = free_mesh ( this->theta_mesh );
513 }
514 
515 
resetMesh()516 void PresetInputs::resetMesh()
517 {
518 	assert ( x_mesh );
519 	assert ( y_mesh );
520 	assert ( rad_mesh );
521 	assert ( theta_mesh );
522 
523 	copy_mesh(this->x_mesh, this->origx, gx, gy);
524 	copy_mesh(this->y_mesh, this->origy, gx, gy);
525 	copy_mesh(this->rad_mesh, this->origrad, gx, gy);
526 	copy_mesh(this->theta_mesh, this->origtheta, gx, gy);
527 }
528 
529 
530 #ifdef USE_MERGE_PRESET_CODE
MergePresets(PresetOutputs & A,PresetOutputs & B,double ratio,int gx,int gy)531 void PresetMerger::MergePresets(PresetOutputs & A, PresetOutputs & B, double ratio, int gx, int gy)
532 {
533 
534 double invratio = 1.0 - ratio;
535   //Merge Simple Waveforms
536   //
537   // All the mess is because of Waveform 7, which is two lines.
538   //
539 
540 
541   //Merge Custom Shapes and Custom Waves
542 
543   for (PresetOutputs::cshape_container::iterator pos = A.customShapes.begin();
544 	pos != A.customShapes.end(); ++pos)
545     {
546        (*pos)->a *= invratio;
547        (*pos)->a2 *= invratio;
548        (*pos)->border_a *= invratio;
549     }
550 
551   for (PresetOutputs::cshape_container::iterator pos = B.customShapes.begin();
552 	pos != B.customShapes.end(); ++pos)
553     {
554        (*pos)->a *= ratio;
555        (*pos)->a2 *= ratio;
556        (*pos)->border_a *= ratio;
557 
558         A.customShapes.push_back(*pos);
559 
560     }
561  for (PresetOutputs::cwave_container::iterator pos = A.customWaves.begin();
562 	pos != A.customWaves.end(); ++pos)
563     {
564        (*pos)->a *= invratio;
565       for (int x=0; x <   (*pos)->samples; x++)
566 	{
567 	   (*pos)->a_mesh[x]= (*pos)->a_mesh[x]*invratio;
568 	}
569     }
570 
571   for (PresetOutputs::cwave_container::iterator pos = B.customWaves.begin();
572 	pos != B.customWaves.end(); ++pos)
573     {
574        (*pos)->a *= ratio;
575       for (int x=0; x < (*pos)->samples; x++)
576 	{
577 	   (*pos)->a_mesh[x]= (*pos)->a_mesh[x]*ratio;
578 	}
579        A.customWaves.push_back(*pos);
580     }
581 
582 
583   //Interpolate Per-Pixel mesh
584 
585   for (int x=0;x<gx;x++)
586     {
587       for(int y=0;y<gy;y++)
588 	{
589 	  A.x_mesh[x][y]  = A.x_mesh[x][y]* invratio + B.x_mesh[x][y]*ratio;
590 	}
591     }
592  for (int x=0;x<gx;x++)
593     {
594       for(int y=0;y<gy;y++)
595 	{
596 	  A.y_mesh[x][y]  = A.y_mesh[x][y]* invratio + B.y_mesh[x][y]*ratio;
597 	}
598     }
599 
600 
601 
602  //Interpolate PerFrame floats
603 
604   A.screenDecay = A.screenDecay * invratio + B.screenDecay * ratio;
605 
606   A.wave.r = A.wave.r* invratio + B.wave.r*ratio;
607   A.wave.g = A.wave.g* invratio + B.wave.g*ratio;
608   A.wave.b = A.wave.b* invratio + B.wave.b*ratio;
609   A.wave.a = A.wave.a* invratio + B.wave.a*ratio;
610   A.wave.x = A.wave.x* invratio + B.wave.x*ratio;
611   A.wave.y = A.wave.y* invratio + B.wave.y*ratio;
612   A.wave.mystery = A.wave.mystery* invratio + B.wave.mystery*ratio;
613 
614   A.border.outer_size = A.border.outer_size* invratio + B.border.outer_size*ratio;
615   A.border.outer_r = A.border.outer_r* invratio + B.border.outer_r*ratio;
616   A.border.outer_g = A.border.outer_g* invratio + B.border.outer_g*ratio;
617   A.border.outer_b = A.border.outer_b* invratio + B.border.outer_b*ratio;
618   A.border.outer_a = A.border.outer_a* invratio + B.border.outer_a*ratio;
619 
620   A.border.inner_size = A.border.inner_size* invratio + B.border.inner_size*ratio;
621   A.border.inner_r = A.border.inner_r* invratio + B.border.inner_r*ratio;
622   A.border.inner_g = A.border.inner_g* invratio + B.border.inner_g*ratio;
623   A.border.inner_b = A.border.inner_b* invratio + B.border.inner_b*ratio;
624   A.border.inner_a = A.border.inner_a* invratio + B.border.inner_a*ratio;
625 
626   A.mv.a  = A.mv.a* invratio + B.mv.a*ratio;
627   A.mv.r  = A.mv.r* invratio + B.mv.r*ratio;
628   A.mv.g  = A.mv.g* invratio + B.mv.g*ratio;
629   A.mv.b  = A.mv.b* invratio + B.mv.b*ratio;
630   A.mv.length = A.mv.length* invratio + B.mv.length*ratio;
631   A.mv.x_num = A.mv.x_num* invratio + B.mv.x_num*ratio;
632   A.mv.y_num = A.mv.y_num* invratio + B.mv.y_num*ratio;
633   A.mv.y_offset = A.mv.y_offset* invratio + B.mv.y_offset*ratio;
634   A.mv.x_offset = A.mv.x_offset* invratio + B.mv.x_offset*ratio;
635 
636 
637   A.fRating = A.fRating* invratio + B.fRating*ratio;
638   A.fGammaAdj = A.fGammaAdj* invratio + B.fGammaAdj*ratio;
639   A.videoEcho.zoom = A.videoEcho.zoom* invratio + B.videoEcho.zoom*ratio;
640   A.videoEcho.a = A.videoEcho.a* invratio + B.videoEcho.a*ratio;
641 
642 
643   A.fWarpAnimSpeed = A.fWarpAnimSpeed* invratio + B.fWarpAnimSpeed*ratio;
644   A.fWarpScale = A.fWarpScale* invratio + B.fWarpScale*ratio;
645   A.fShader = A.fShader* invratio + B.fShader*ratio;
646 
647   //Switch bools and discrete values halfway.  Maybe we should do some interesting stuff here.
648 
649   if (ratio > 0.5)
650     {
651       A.videoEcho.orientation = B.videoEcho.orientation;
652       A.textureWrap = B.textureWrap;
653       A.bDarkenCenter = B.bDarkenCenter;
654       A.bRedBlueStereo = B.bRedBlueStereo;
655       A.bBrighten = B.bBrighten;
656       A.bDarken = B.bDarken;
657       A.bSolarize = B.bSolarize;
658       A.bInvert = B.bInvert;
659       A.bMotionVectorsOn = B.bMotionVectorsOn;
660     }
661 
662   return;
663 }
664 #endif
665