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