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