1 /*
2   Plasma 8bit demos-scene effect
3 
4   Copyright (C) 2002 W.P. van Paassen - peter@paassen.tmfweb.nl
5             (C) 2009 Denis Roio - jaromil@dyne.org
6 
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free  Software Foundation; either  version 3 of the  License, or
10   (at your option) any later version.
11 
12   This program is distributed in the  hope that it will be useful, but
13   WITHOUT  ANY   WARRANTY;  without  even  the   implied  warranty  of
14   MERCHANTABILITY or  FITNESS FOR A  PARTICULAR PURPOSE.  See  the GNU
15   General Public License for more details.
16 
17   You should  have received a copy  of the GNU  General Public License
18   along  with  this  program;  if  not, write  to  the  Free  Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <math.h>
27 #include <string.h>
28 #include <inttypes.h>
29 
30 #include <frei0r.hpp>
31 
32 
33 typedef struct {
34   int16_t x; ///< x axis position coordinate
35   int16_t y; ///< y axis position coordinate
36   uint16_t w; ///< width of frame in pixels
37   uint16_t h; ///< height of frame in pixels
38   uint8_t bpp; ///< bits per pixel
39   uint16_t pitch; ///< width of frame in bytes
40   uint32_t size; ///< size of the whole frame in bytes
41 } ScreenGeometry;
42 
43 typedef struct {
44   uint8_t r;
45   uint8_t g;
46   uint8_t b;
47 } Palette;
48 
49 class Plasma: public frei0r::source {
50 
51 public:
52   Plasma(int wdt, int hgt);
53   ~Plasma();
54 
55   virtual void update(double time, uint32_t* out);
56 
57 private:
58 
59   ScreenGeometry geo;
60 
61   void _init(int wdt, int hgt);
62 
63 
64   uint16_t pos1, pos2, pos3, pos4;
65   uint16_t tpos1, tpos2, tpos3, tpos4;
66 
67   int aSin[512];
68 
69   Palette colors[256];
70 
71   uint32_t palette2rgb(uint8_t idx);
72 
73   // vectors (exposed parameters from 0 to 1)
74   double speed1; // 5
75   double speed2; // 3
76   double speed3; // 3
77   double speed4; // 1
78   double move1; // 9
79   double move2; // 8
80 
81   // scalars
82   double _speed1; // 5
83   double _speed2; // 3
84   double _speed3; // 3
85   double _speed4; // 1
86   double _move1; // 9
87   double _move2; // 8
88 
89 };
90 
_init(int wdt,int hgt)91 void Plasma::_init(int wdt, int hgt) {
92   geo.w = wdt;
93   geo.h = hgt;
94   geo.bpp = 32;
95   geo.size = geo.w*geo.h*(geo.bpp/8);
96   geo.pitch = geo.w*(geo.bpp/8);
97 }
98 
Plasma(int wdt,int hgt)99 Plasma::Plasma(int wdt, int hgt) {
100 
101   register_param(speed1, "1_speed", " ");
102   register_param(speed2, "2_speed", " ");
103   register_param(speed3, "3_speed", " ");
104   register_param(speed4, "4_speed", " ");
105 
106   register_param(move1, "1_move", " ");
107   register_param(move2, "2_move", " ");
108 
109 
110   int i;
111   float rad;
112 
113   _init(wdt, hgt);
114 
115 
116   /*create sin lookup table */
117   for (i = 0; i < 512; i++)
118     {
119       /* 360 / 512 * degree to rad,
120 	 360 degrees spread over 512 values
121 	 to be able to use AND 512-1 instead
122 	 of using modulo 360*/
123       rad =  ((float)i * 0.703125) * 0.0174532;
124 
125       /*using fixed point math with 1024 as base*/
126       aSin[i] = sin(rad) * 1024;
127 
128     }
129 
130   /* create palette */
131   for (i = 0; i < 64; ++i)
132     {
133       colors[i].r = i << 2;
134       colors[i].g = 255 - ((i << 2) + 1);
135       colors[i+64].r = 255;
136       colors[i+64].g = (i << 2) + 1;
137       colors[i+128].r = 255 - ((i << 2) + 1);
138       colors[i+128].g = 255 - ((i << 2) + 1);
139       colors[i+192].g = (i << 2) + 1;
140     }
141 
142   speed1 = 1.;
143   speed2 = 1.;
144   speed3 = 1.;
145   speed4 = 1.;
146   move1  = 1.;
147   move2  = 1.;
148 
149   _speed1 = 5;
150   _speed2 = 3;
151   _speed3 = 3;
152   _speed4 = 1;
153   _move1  = 9;
154   _move2  = 8;
155 
156 }
157 
~Plasma()158 Plasma::~Plasma() {
159 
160 }
161 
update(double time,uint32_t * out)162 void Plasma::update(double time, uint32_t* out) {
163   uint16_t i, j;
164   uint8_t index;
165   int x;
166 
167   uint32_t *image = (uint32_t*)out;
168 
169   // number parameters are not good in frei0r
170   // we need types defining multipliers and min/max values
171   // so for now we leave this generator like this
172   // but TODO ASAP new parameter types: fader and minmax
173   // then fix also parameters of the partik0l which is suffering
174   // of the same problem - jaromil
175 
176   // update parameters
177   _speed1 = _speed1 * speed1;
178   _speed2 = _speed2 * speed2;
179   _speed3 = _speed3 * speed3;
180   _speed4 = _speed4 * speed4;
181 
182   _move1 = _move1 * move1;
183   _move2 = _move2 * move2;
184 
185   tpos4 = pos4;
186   tpos3 = pos3;
187 
188   for (i = 0; i < geo.h; ++i) {
189     tpos1 = pos1 + (int)_speed1;
190     tpos2 = pos2 + (int)_speed2;
191 
192     tpos3 &= 511;
193     tpos4 &= 511;
194 
195     for (j = 0; j < geo.w; ++j) {
196       tpos1 &= 511;
197       tpos2 &= 511;
198 
199       x = aSin[tpos1] + aSin[tpos2] + aSin[tpos3] + aSin[tpos4];
200       /*actual plasma calculation*/
201 
202       index = 128 + (x >> 4);
203       /* fixed point multiplication but optimized so basically
204 	 it  says (x  * (64  * 1024)  / (1024  * 1024)),  x is
205 	 already multiplied by 1024*/
206 
207       *image++ = palette2rgb(index);
208 
209       tpos1 += (int)_speed1;
210       tpos2 += (int)_speed2;
211     }
212 
213     tpos4 += (int)_speed3;
214     tpos3 += (int)_speed4;
215   }
216 
217   /* move plasma */
218 
219   pos1 += (int)_move1;
220   pos3 += (int)_move2;
221 }
222 
palette2rgb(uint8_t idx)223 uint32_t Plasma::palette2rgb(uint8_t idx) {
224   uint32_t rgba;
225   // just for little endian
226   // TODO: big endian
227   rgba = (colors[idx].r << 16)
228     | (colors[idx].g << 8)
229     | (colors[idx].b )
230     | (0xff << 24);
231 
232   return rgba;
233 }
234 
235 frei0r::construct<Plasma> plugin("Plasma",
236 				   "Demo scene 8bit plasma",
237 				   "Jaromil",
238 				   0,3);
239