1 /* 3dflippo.c */
2
3 /*
4 * 25/01/2006 c.e. prelz
5 *
6 * My second frei0r effect - more complex flipping
7 *
8 * Copyright (C) 2006 BEK - Bergen Senter for Elektronisk Kunst <bek@bek.no>
9 * This file is a Frei0r plugin.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "frei0r.h"
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #if defined(_MSC_VER)
31 #define _USE_MATH_DEFINES
32 #endif /* _MSC_VER */
33 #include <math.h>
34
35 #define MSIZE 4
36 #define TWO_PI (M_PI*2.0)
37
38 enum axis
39 {
40 AXIS_X,
41 AXIS_Y,
42 AXIS_Z
43 };
44
45 #include <assert.h>
46
47 typedef struct tdflippo_instance
48 {
49 unsigned int width,height,fsize;
50 int *mask;
51 float flip[3],rate[3],center[2];
52 unsigned char invertrot,dontblank,fillblack,mustrecompute;
53 } tdflippo_instance_t;
54
55 static float **newmat(unsigned char unit_flg);
56 static void matfree(float **mat);
57 static float **mat_translate(float tx,float ty,float tz);
58 static float **mat_rotate(enum axis ax,float angle);
59 static float **matmult(float **mat1,float **mat2);
60 static void vetmat(float **mat,float *x,float *y,float *z);
61 static void recompute_mask(tdflippo_instance_t* inst);
62
f0r_init()63 int f0r_init()
64 {
65 return 1;
66 }
67
f0r_deinit()68 void f0r_deinit()
69 {
70 }
71
f0r_get_plugin_info(f0r_plugin_info_t * flippoInfo)72 void f0r_get_plugin_info(f0r_plugin_info_t* flippoInfo)
73 {
74 flippoInfo->name="3dflippo";
75 flippoInfo->author="c.e. prelz AS FLUIDO <fluido@fluido.as>";
76 flippoInfo->plugin_type=F0R_PLUGIN_TYPE_FILTER;
77 flippoInfo->color_model=F0R_COLOR_MODEL_PACKED32;
78 flippoInfo->frei0r_version=FREI0R_MAJOR_VERSION;
79 flippoInfo->major_version=0;
80 flippoInfo->minor_version=1;
81 flippoInfo->num_params=11;
82 flippoInfo->explanation="Frame rotation in 3d-space";
83 }
84
f0r_get_param_info(f0r_param_info_t * info,int param_index)85 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
86 {
87 switch(param_index)
88 {
89 case 0:
90 info->name="X axis rotation";
91 info->type=F0R_PARAM_DOUBLE;
92 info->explanation="Rotation on the X axis";
93 break;
94 case 1:
95 info->name="Y axis rotation";
96 info->type=F0R_PARAM_DOUBLE;
97 info->explanation="Rotation on the Y axis";
98 break;
99 case 2:
100 info->name="Z axis rotation";
101 info->type=F0R_PARAM_DOUBLE;
102 info->explanation="Rotation on the Z axis";
103 break;
104 case 3:
105 info->name="X axis rotation rate";
106 info->type=F0R_PARAM_DOUBLE;
107 info->explanation="Rotation rate on the X axis";
108 break;
109 case 4:
110 info->name="Y axis rotation rate";
111 info->type=F0R_PARAM_DOUBLE;
112 info->explanation="Rotation rate on the Y axis";
113 break;
114 case 5:
115 info->name="Z axis rotation rate";
116 info->type=F0R_PARAM_DOUBLE;
117 info->explanation="Rotation rate on the Z axis";
118 break;
119 case 6:
120 info->name="Center position (X)";
121 info->type=F0R_PARAM_DOUBLE;
122 info->explanation="Position of the center of rotation on the X axis";
123 break;
124 case 7:
125 info->name="Center position (Y)";
126 info->type=F0R_PARAM_DOUBLE;
127 info->explanation="Position of the center of rotation on the Y axis";
128 break;
129 case 8:
130 info->name="Invert rotation assignment";
131 info->type=F0R_PARAM_BOOL;
132 info->explanation="If true, when mapping rotation, make inverted (wrong) assignment";
133 break;
134 case 9:
135 info->name="Don't blank mask";
136 info->type=F0R_PARAM_BOOL;
137 info->explanation="Mask for frame transposition is not blanked, so a trace of old transpositions is maintained";
138 break;
139 case 10:
140 info->name="Fill with image or black";
141 info->type=F0R_PARAM_BOOL;
142 info->explanation="If true, pixels that are not transposed are black, otherwise, they are copied with the original";
143 break;
144 }
145 }
146
f0r_construct(unsigned int width,unsigned int height)147 f0r_instance_t f0r_construct(unsigned int width,unsigned int height)
148 {
149 tdflippo_instance_t *inst=(tdflippo_instance_t*)calloc(1, sizeof(*inst));
150 inst->width=width;
151 inst->height=height;
152 inst->fsize=width*height;
153
154 inst->flip[0]=inst->flip[1]=inst->flip[2]=inst->rate[0]=inst->rate[1]=inst->rate[2]=0.5;
155
156 inst->mask=(int*)malloc(sizeof(int)*inst->fsize);
157
158 return (f0r_instance_t)inst;
159 }
160
f0r_destruct(f0r_instance_t instance)161 void f0r_destruct(f0r_instance_t instance)
162 {
163 tdflippo_instance_t* inst=(tdflippo_instance_t*)instance;
164
165 free(inst->mask);
166 free(inst);
167 }
168
f0r_set_param_value(f0r_instance_t instance,f0r_param_t param,int param_index)169 void f0r_set_param_value(f0r_instance_t instance,
170 f0r_param_t param,int param_index)
171 {
172 assert(instance);
173
174 tdflippo_instance_t *inst=(tdflippo_instance_t*)instance;
175
176 switch(param_index)
177 {
178 case 0:
179 inst->flip[0]=(float)(*((double*)param));
180 break;
181 case 1:
182 inst->flip[1]=(float)(*((double*)param));
183 break;
184 case 2:
185 inst->flip[2]=(float)(*((double*)param));
186 break;
187 case 3:
188 inst->rate[0]=(float)(*((double*)param));
189 break;
190 case 4:
191 inst->rate[1]=(float)(*((double*)param));
192 break;
193 case 5:
194 inst->rate[2]=(float)(*((double*)param));
195 break;
196 case 6:
197 inst->center[0]=(float)(*((double*)param));
198 break;
199 case 7:
200 inst->center[1]=(float)(*((double*)param));
201 break;
202 case 8:
203 inst->invertrot=(*((double*)param)>=0.5);
204 break;
205 case 9:
206 inst->dontblank=(*((double*)param)>=0.5);
207 break;
208 case 10:
209 inst->fillblack=(*((double*)param)>=0.5);
210 break;
211 }
212
213 if((param_index>=0 && param_index<=2) || (param_index>=6 && param_index<=9))
214 inst->mustrecompute=1;
215 }
216
f0r_get_param_value(f0r_instance_t instance,f0r_param_t param,int param_index)217 void f0r_get_param_value(f0r_instance_t instance,
218 f0r_param_t param,int param_index)
219 {
220 assert(instance);
221
222 tdflippo_instance_t *inst=(tdflippo_instance_t*)instance;
223
224 switch(param_index)
225 {
226 case 0:
227 *((double*)param)=inst->flip[0];
228 break;
229 case 1:
230 *((double*)param)=inst->flip[1];
231 break;
232 case 2:
233 *((double*)param)=inst->flip[2];
234 break;
235 case 3:
236 *((double*)param)=inst->rate[0];
237 break;
238 case 4:
239 *((double*)param)=inst->rate[1];
240 break;
241 case 5:
242 *((double*)param)=inst->rate[2];
243 break;
244 case 6:
245 *((double*)param)=inst->center[0];
246 break;
247 case 7:
248 *((double*)param)=inst->center[1];
249 break;
250 case 8:
251 *((double*)param)=(inst->invertrot ? 1.0 : 0.0);
252 break;
253 case 9:
254 *((double*)param)=(inst->dontblank ? 1.0 : 0.0);
255 break;
256 case 10:
257 *((double*)param)=(inst->fillblack ? 1.0 : 0.0);
258 break;
259 }
260 }
261
f0r_update(f0r_instance_t instance,double time,const uint32_t * inframe,uint32_t * outframe)262 void f0r_update(f0r_instance_t instance,double time,
263 const uint32_t *inframe, uint32_t *outframe)
264 {
265 assert(instance);
266
267 tdflippo_instance_t* inst=(tdflippo_instance_t*)instance;
268 int i;
269
270 if(inst->rate[0]!=0.5 || inst->rate[1]!=0.5 || inst->rate[2]!=0.5 || inst->mustrecompute)
271 {
272 inst->mustrecompute=0;
273
274 /*
275 * We are changing: apply change and recompute mask
276 */
277
278 for(i=0;i<3;i++)
279 {
280 inst->flip[i]+=inst->rate[i]-0.5;
281 if(inst->flip[i]<0.0)
282 inst->flip[i]+=1.0;
283 else if(inst->flip[i]>=1.0)
284 inst->flip[i]-=1.0;
285 }
286 recompute_mask(inst);
287 }
288
289 for(i=0;i<inst->fsize;i++)
290 {
291 if(inst->mask[i]>=0)
292 outframe[i]=inframe[inst->mask[i]];
293 else if(!inst->fillblack)
294 outframe[i]=inframe[i];
295 else
296 outframe[i]=0;
297 }
298 }
299
newmat(unsigned char unit_flg)300 static float **newmat(unsigned char unit_flg)
301 {
302 int i;
303 float **to_ret=(float**)malloc(sizeof(float *)*MSIZE);
304
305 for(i=0;i<MSIZE;i++)
306 {
307 to_ret[i]=(float*)calloc(MSIZE,sizeof(float));
308 if(unit_flg)
309 to_ret[i][i]=1.0;
310 }
311
312 return to_ret;
313 }
314
matfree(float ** mat)315 static void matfree(float **mat)
316 {
317 int i;
318
319 for(i=0;i<MSIZE;i++)
320 free(mat[i]);
321
322 free(mat);
323 }
324
mat_translate(float tx,float ty,float tz)325 static float **mat_translate(float tx,float ty,float tz)
326 {
327 float **mat=newmat(1);
328
329 mat[0][3]=tx;
330 mat[1][3]=ty;
331 mat[2][3]=tz;
332
333 return mat;
334 }
335
mat_rotate(enum axis ax,float angle)336 static float **mat_rotate(enum axis ax,float angle)
337 {
338 float **mat=newmat(1);
339 float sf=sinf(angle);
340 float cf=cosf(angle);
341
342 switch(ax)
343 {
344 case AXIS_X:
345 mat[1][1]=cf;
346 mat[1][2]=-sf;
347 mat[2][1]=sf;
348 mat[2][2]=cf;
349 break;
350 case AXIS_Y:
351 mat[0][0]=cf;
352 mat[0][2]=sf;
353 mat[2][0]=-sf;
354 mat[2][2]=cf;
355 break;
356 case AXIS_Z:
357 mat[0][0]=cf;
358 mat[0][1]=-sf;
359 mat[1][0]=sf;
360 mat[1][1]=cf;
361 break;
362 }
363 return mat;
364 }
365
matmult(float ** mat1,float ** mat2)366 static float **matmult(float **mat1,float **mat2)
367 {
368 float **mat=newmat(0);
369 int i,j,k;
370
371 for(i=0;i<MSIZE;i++)
372 for(j=0;j<MSIZE;j++)
373 for(k=0;k<MSIZE;k++)
374 mat[i][j]+=mat1[i][k]*mat2[k][j];
375
376 matfree(mat1);
377 matfree(mat2);
378
379 return mat;
380 }
381
vetmat(float ** mat,float * x,float * y,float * z)382 static void vetmat(float **mat,float *x,float *y,float *z)
383 {
384 float v;
385 float vet[]={*x,*y,*z,1.0};
386 float *vetp[]={x,y,z,&v};
387 int i,j;
388
389 for(i=0;i<MSIZE;i++)
390 {
391 *(vetp[i])=0.0;
392
393 for(j=0;j<MSIZE;j++)
394 *(vetp[i])+=mat[i][j]*vet[j];
395 }
396 }
397
recompute_mask(tdflippo_instance_t * inst)398 static void recompute_mask(tdflippo_instance_t* inst)
399 {
400 float xpos=(float)inst->width*inst->center[0];
401 float ypos=(float)inst->height*inst->center[1];
402 float **mat=mat_translate(xpos,ypos,0.0);
403
404 if(inst->flip[0]!=0.5)
405 mat=matmult(mat,mat_rotate(AXIS_X,(inst->flip[0]-0.5)*TWO_PI));
406 if(inst->flip[1]!=0.5)
407 mat=matmult(mat,mat_rotate(AXIS_Y,(inst->flip[1]-0.5)*TWO_PI));
408 if(inst->flip[2]!=0.5)
409 mat=matmult(mat,mat_rotate(AXIS_Z,(inst->flip[2]-0.5)*TWO_PI));
410
411 mat=matmult(mat,mat_translate(-xpos,-ypos,0.0));
412
413 #if 0
414 fprintf(stderr,"Resarra %.2f %.2f %.2f %.2f | %.2f %.2f %.2f %.2f | %.2f %.2f %.2f %.2f | %.2f %.2f %.2f %.2f\n",
415 mat[0][0],mat[0][1],mat[0][2],mat[0][3],
416 mat[1][0],mat[1][1],mat[1][2],mat[1][3],
417 mat[2][0],mat[2][1],mat[2][2],mat[2][3],
418 mat[3][0],mat[3][1],mat[3][2],mat[3][3]);
419 #endif
420
421 int x,y,nx,ny,pos;
422 float xf,yf,zf;
423
424 if(!inst->dontblank)
425 memset(inst->mask,0xff,sizeof(int)*inst->fsize);
426
427 for(y=0,pos=0;y<inst->height;y++)
428 for(x=0;x<inst->width;x++,pos++)
429 {
430 xf=x;
431 yf=y;
432 zf=0.0;
433 vetmat(mat,&xf,&yf,&zf);
434 nx=(int)(xf+0.5);
435 ny=(int)(yf+0.5);
436
437 if(nx>=0 && nx<inst->width && ny>=0 && ny<inst->height)
438 {
439 if(!inst->invertrot)
440 inst->mask[ny*inst->width+nx]=pos;
441 else
442 inst->mask[pos]=ny*inst->width+nx;
443 }
444 }
445 matfree(mat);
446 }
447