1 /*
2 * fx/TexturedGrid.cpp
3 *
4 * Copyright 2009 Peter Barth
5 *
6 * This file is part of Milkytracker.
7 *
8 * Milkytracker is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Milkytracker is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Milkytracker. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "TexturedGrid.h"
24 #include "Math3d.h"
25 #include "Filter.h"
26 #include "Texture.h"
27
28 #define PRGB2SHORT(r,g,b) ((((r))<<11)+(((g))<<5)+((b)))
29 #define RGB2SHORT(r,g,b) ((((r>>3))<<11)+(((g>>2))<<5)+((b>>3)))
30
31 #define TEXTURESIZE 256
32
33 #define REDMASK (0x1F<<11)
34 #define GREENMASK (0x3F<<5)
35 #define BLUEMASK 0x1F
36
TexturedGrid(int width,int height,int gridshift)37 TexturedGrid::TexturedGrid(int width, int height, int gridshift)
38 {
39 this->width = width;
40 this->height = height;
41
42 this->gridshift = gridshift;
43 this->gridsize = 1 << gridshift;
44
45 this->gridWidth = (width>>gridshift)+1;
46 this->gridHeight = (height>>gridshift)+1;
47
48 grid = new VectorFP[gridWidth*gridHeight];
49
50 this->texture = NULL; // we're not rendering anything until texture is set
51
52 this->buffer = new unsigned short[width*height];
53
54 // for debugging, load texture
55 int i;
56
57 /*unsigned char *texture = new unsigned char[TEXTURESIZE*TEXTURESIZE*3];
58
59 //FILE* f = fopen("/demo/t2new.tga","rb");
60 //fseek(f,18,SEEK_SET);
61 //fread(texture,TEXTURESIZE*TEXTURESIZE,3,f);
62 //fclose(f);
63 Texture::createSplineTexture(texture);
64
65
66 this->texture = new unsigned short[TEXTURESIZE*TEXTURESIZE];
67
68 for (i = 0; i < TEXTURESIZE*TEXTURESIZE; i++) {
69 this->texture[i] = RGB2SHORT(texture[i*3]>>0,texture[i*3+1]>>0,texture[i*3+2]>>0);
70 }
71
72 delete texture;*/
73
74 unsigned char* rgbTex = new unsigned char[256*256*3];
75 unsigned char* rgbTex2 = new unsigned char[256*256*3];
76
77 texture = new unsigned short[256*256];
78
79 Texture::createSplineTexture(rgbTex);
80
81 /*Texture::createPlasmaTexture(rgbTex2, 256, 3, 255, 255, 255);
82
83 for (i = 0; i < 256*256; i++)
84 {
85 int r = (rgbTex2[i*3]>>0) - (rgbTex[i*3]>>0) + 63*2;
86 int g = (rgbTex2[i*3+1]>>0) - (rgbTex[i*3+1]>>0) + 31*2;
87 int b = (rgbTex2[i*3+2]>>0) - (rgbTex[i*3+2]>>0) + 9*2;
88
89 if (r < 0) r = 0; if (r > 255) r = 255;
90 if (g < 0) g = 0; if (g > 255) g = 255;
91 if (b < 0) b = 0; if (b > 255) b = 255;
92
93 rgbTex[i*3] = r;
94 rgbTex[i*3+1] = g;
95 rgbTex[i*3+2] = b;
96 }*/
97
98 Texture::convert24to16(texture, rgbTex, 256*256, 1);
99
100 delete[] rgbTex;
101 delete[] rgbTex2;
102
103 for (i = 0; i < 1024; i++)
104 sintab[i] = (int)(sin((float)i/512.0f*M_PI)*65536.0f);
105
106 }
107
~TexturedGrid()108 TexturedGrid::~TexturedGrid()
109 {
110 if (grid)
111 delete[] grid;
112
113 if (buffer)
114 delete[] buffer;
115
116 if (texture)
117 delete[] texture;
118 }
119
120 struct Blob
121 {
122 int x,y,z;
123 int strength;
124 };
125
126 static Blob blobs[] = {{128,128,0,65536/16},{100,100,0,65536/16},{100,100,0,65536/16}};
127
128 #define MAXCLAMP 65536
129
update(float syncFrac)130 void TexturedGrid::update(float syncFrac)
131 {
132 int gridSizeX = gridWidth;
133 int gridSizeY = gridHeight;
134
135 int x,y;
136
137 VectorFP* gridPt = grid;
138
139 float phi = ::PPGetTickCount()*0.001f*0.5f;;
140
141 blobs[0].x = (int)(sin(phi*4.0f)*8.0f*65536.0f);
142 blobs[0].y = (int)(cos(phi*4.0f)*8.0f*65536.0f);
143 blobs[0].z = (int)(sin(phi*4.0f)*8.0f*65536.0f);
144
145 blobs[1].x = (int)(cos(-phi*2.0f)*8.0f*65536.0f);
146 blobs[1].y = (int)(sin(phi*2.0f)*8.0f*65536.0f);
147 blobs[1].z = (int)(cos(phi*2.0f)*8.0f*65536.0f);
148
149 blobs[2].x = (int)(cos(-phi*3.0f)*12.0f*65536.0f);
150 blobs[2].y = (int)(cos(phi*3.0f)*6.0f*65536.0f);
151 blobs[2].z = (int)(sin(phi*3.0f)*10.0f*65536.0f);
152
153 int numBlobs = sizeof(blobs)/sizeof(Blob);
154
155 int pulse = (int)((sin(phi*16.0f)+1.0f)*32768.0f);
156
157 int phiFP = (int)(phi*1024.0f);
158
159 MatrixFP m;
160 m.setRotZ(phi);
161
162 for (y = 0; y < gridSizeY; y++)
163 for ( x = 0; x < gridSizeX; x++)
164 {
165 VectorFP p;
166 p.x = ((x-(gridSizeX>>1))<<16);
167 p.y = ((y-(gridSizeY>>1))<<16);
168 p.z = 0;
169
170 p = m*p;
171
172 int xOffset = /*0*/sintab[((p.x>>11)+phiFP)&1023]*32;
173 int yOffset = /*0*/sintab[((p.y>>11)+phiFP)&1023]*32;
174
175 //int xOffset = 0;
176 //int yOffset = 0;
177
178 gridPt->x = (((p.x>>1)-(gridSizeX<<15))<<4)+yOffset;
179 gridPt->y = (((p.y>>1)-(gridSizeY<<15))<<4)+xOffset;
180 gridPt->z = 256*65536;
181
182 //////////////////////////////////////////////////////////////////////
183 // blob stuff
184 //////////////////////////////////////////////////////////////////////
185
186 /*VectorFP p;
187 p.x = ((x-(gridSizeX>>1))<<16);
188 p.y = ((y-(gridSizeY>>1))<<16);
189 p.z = 0.0f;
190
191 int scale = 32768;
192 for (int j = 0; j < numBlobs; j++) {
193 int dx = fpmul((blobs[j].x-p.x),blobs[j].strength);
194 int dy = fpmul((blobs[j].y-p.y),blobs[j].strength);
195 int dz = fpmul((blobs[j].z-p.z),blobs[j].strength);
196
197 int sd = fpmul(dx,dx)+fpmul(dy,dy)+fpmul(dz,dz);
198
199 if (sd<(0.707f*0.707f*65536))
200 scale += (fpmul(sd,sd)-sd+16384)*4;
201 }
202
203 if (scale>=MAXCLAMP) scale = MAXCLAMP;
204 scale = fpmul(scale,scale);
205 scale = fpmul(scale,scale);
206
207 gridPt->x = fpdiv(p.x,scale+32768)<<4;
208 gridPt->y = fpdiv(p.y,scale+32768)<<4;
209 gridPt->z = 256*65536;*/
210
211 //////////////////////////////////////////////////////////////////////
212 // airbag
213 //////////////////////////////////////////////////////////////////////
214 /*int len = fpsqrt(fpmul(p.x-blobs[0].x,p.x-blobs[0].x)+fpmul(p.y-blobs[0].y,p.y-blobs[0].y));
215
216 if (len>16*65536) len = 16*65536;
217
218 int scale = len>>4;
219
220 scale = fpmul(scale,scale);
221 scale = fpmul(scale,scale);
222 scale = fpmul(scale,scale);
223
224 scale = 65536-fpmul((65536-scale),pulse);
225
226 gridPt->x = fpmul(p.x,(scale<<2)+165536);
227 gridPt->y = fpmul(p.y,(scale<<2)+165536);
228 gridPt->z = 256*65536;*/
229
230 //////////////////////////////////////////////////////////////////////
231 // scale waves
232 //////////////////////////////////////////////////////////////////////
233 /*int len = fpsqrt(fpmul(p.x-blobs[0].x,p.x-blobs[0].x)+fpmul(p.y-blobs[0].y,p.y-blobs[0].y)+fpmul(p.z,p.z));
234
235 int scale = 65536-((sintab[((len>>10)+phiFP)&1023]+65536)>>1);
236
237 scale = fpmul(scale,scale);
238 //scale = fpmul(scale,scale);
239 //scale = fpmul(scale,scale);
240
241 //scale = 65536-fpmul((65536-scale),pulse);
242
243 gridPt->x = fpmul(p.x,(scale<<2)+165536);
244 gridPt->y = fpmul(p.y,(scale<<2)+165536);
245 gridPt->z = 256*65536;*/
246
247 //////////////////////////////////////////////////////////////////////
248 // displacement waves
249 //////////////////////////////////////////////////////////////////////
250 /*int cx = 0;//blobs[0].x;
251 int cy = 0;//blobs[0].y;
252
253 int dx = cx - p.x;
254 int dy = cy - p.y;
255
256 int len = fpsqrt(fpmul(dx,dx)+fpmul(dy,dy));
257
258 if (len)
259 {
260 dx = fpdiv(dx, len);
261 dy = fpdiv(dy, len);
262 }
263
264 int scale = sintab[((len>>10)-(phiFP<<1))&1023];
265
266 //scale = fpmul(scale,scale);
267 //scale = fpmul(scale,scale);
268 //scale = fpmul(scale,scale);
269
270 //scale = 65536-fpmul((65536-scale),pulse);
271
272 gridPt->x = ((p.x+(phiFP<<4))<<3)+(fpmul(dx,scale<<5));
273 gridPt->y = (p.y<<3)+(fpmul(dy,scale<<5));
274 gridPt->z = 128*(scale+65536+8192);*/
275
276 gridPt++;
277 }
278
279 phi+=0.1f;
280
281 }
282
render(unsigned short * vscreen,unsigned int pitch)283 void TexturedGrid::render(unsigned short* vscreen, unsigned int pitch)
284 {
285 if (texture == NULL)
286 return;
287
288 int x,y;
289
290 unsigned short* tex = texture;
291
292 int GRIDSIZE = gridsize;
293 int GRIDSHIFT = gridshift;
294 int PITCH = pitch;
295
296 int gridSizeX = gridWidth-1;
297 int gridSizeY = gridHeight-1;
298
299 for (y=0;y<gridSizeY;y++)
300 {
301 for (x=0;x<gridSizeX;x++)
302 {
303
304 VectorFP *gridul = grid+(y*(gridSizeX+1)+x);
305 VectorFP *gridur = gridul+1;
306 VectorFP *gridll = gridul+(gridSizeX+1);
307 VectorFP *gridlr = gridul+(gridSizeX+2);
308
309 unsigned short *vscreenPtr = vscreen+((y*GRIDSIZE)*PITCH+(x*GRIDSIZE));
310
311 int su1 = gridul->x;
312 int sv1 = gridul->y;
313 int si1 = gridul->z;
314
315 int su2 = gridur->x;
316 int sv2 = gridur->y;
317 int si2 = gridur->z;
318
319 int du1 = (gridll->x-gridul->x)>>GRIDSHIFT;
320 int dv1 = (gridll->y-gridul->y)>>GRIDSHIFT;
321 int di1 = (gridll->z-gridul->z)>>GRIDSHIFT;
322
323 int du2 = (gridlr->x-gridur->x)>>GRIDSHIFT;
324 int dv2 = (gridlr->y-gridur->y)>>GRIDSHIFT;
325 int di2 = (gridlr->z-gridur->z)>>GRIDSHIFT;
326
327 int y2,x2;
328 for (y2=0;y2<GRIDSIZE;y2++)
329 {
330 int fu = (su2-su1)>>GRIDSHIFT;
331 int su = su1;
332 int fv = (sv2-sv1)>>GRIDSHIFT;
333 int sv = sv1;
334 int fi = (si2-si1)>>GRIDSHIFT;
335 int si = si1;
336
337 for (x2=0;x2<GRIDSIZE;x2++)
338 {
339 //int ofs = ((((sv>>8)&0xff00)+((su>>16)&0xff)));
340 //unsigned int rgb = tex[ofs];
341
342 //int r = ((rgb>>11)*si)>>24;
343 //int g = (((rgb>>5)&0x3f)*si)>>24;
344 //int b = ((rgb&0x1f)*si)>>24;
345
346 //*vscreenPtr = PRGB2Short(r,g,b);
347
348 //if (si <= 256*65536)
349 //{
350 unsigned int wRGB = tex[((((sv>>8)&0xff00)+((su>>16)&0xff)))];
351 unsigned int lTemp = (((wRGB&(REDMASK|BLUEMASK))<<11)|((wRGB & GREENMASK) >> 5))*(si>>19);
352 *vscreenPtr = ((lTemp >> (11 + 5)) & (REDMASK | BLUEMASK))|(lTemp & GREENMASK);
353 /*}
354 else
355 {
356 int shade = (si-256*65536)>>16;
357
358 unsigned int rgb16_1 = tex[((((sv>>8)&0xff00)+((su>>16)&0xff)))];
359 unsigned int rgb16_2 = RGB2SHORT(shade,shade,shade);
360
361 unsigned int result = (rgb16_1&0xF800)+(rgb16_2&0xF800);
362 if (result>0xF800) result = 0xF800;
363 unsigned int t = (rgb16_1&0x7E0)+(rgb16_2&0x7E0); if (t>0x7E0) t = 0x7E0; result|=t;
364 t = (rgb16_1&0x1F)+(rgb16_2&0x1F); if (t>0x1F) t = 0x1F; result|=t;
365
366 *vscreenPtr = result;
367 }*/
368
369 //*vscreenPtr = tex[((((sv>>8)&0xff00)+((su>>16)&0xff)))];
370
371 // enable for motion blur
372 /*unsigned int mask=0x07e0f81f;
373
374 int texel = tex[((((sv>>8)&0xff00)+((su>>16)&0xff)))];
375 int pixel = *vscreenPtr;
376
377 texel = ((texel<<16) | texel)&mask;
378 pixel = ((pixel<<16) | pixel)&mask;
379
380 int mix =((((texel-pixel)*(10))>>5)+pixel)&mask;
381 *vscreenPtr = (mix | (mix>>16))&0xffff;*/
382
383 su+=fu;
384 sv+=fv;
385 si+=fi;
386 vscreenPtr++;
387 }
388
389 su1+=du1;
390 su2+=du2;
391 sv1+=dv1;
392 sv2+=dv2;
393 si1+=di1;
394 si2+=di2;
395 vscreenPtr+=(PITCH-GRIDSIZE);
396
397 }
398
399 }
400
401 }
402
403 /*double phi = GetTickCount()*0.01f;
404 int scale = (sin(phi)+1.0f) * 65536.0f * 2.0f;
405
406 Filter::glow(vscreen, width, height, pitch, glowBuffer1, glowBuffer2, 2, scale);*/
407
408 double phi = ::PPGetTickCount()*0.001f;
409
410 //phi = 0.0f;
411
412 int cx = (int)(sin(-phi)*(width*(1.0/3.0f))+(width*(1.0/2.0f)));
413 int cy = (int)(cos(-phi)*(height*(1.0/3.0f))+(height*(1.0/2.0f)));
414
415 //int radius = sin(phi)*2048 + 2048;
416 int radius = 2048;
417
418 Filter::applyRadial(vscreen, width, height, pitch, cx, cy, radius, 1);
419
420 //Filter::applyBoxed(vscreen, buffer, width, height, pitch, 2);
421
422 //Filter<160,120>::applyBoxed(vscreen, buffer, 4);
423
424 //memcpy(vscreen, buffer, width*height*2);
425
426 }
427
428
429