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