1 /*
2 * fx/Texture.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 "BasicTypes.h"
24 #include "Math3d.h"
25 #include "Texture.h"
26 #include "TCBSpline.h"
27
28 #define RGB2SHORT(r,g,b) ((((r>>3))<<11)+(((g>>2))<<5)+((b>>3)))
29
30 #define MAX_KEYS 50
31 #define MAX_TIME 200
32
setPixel(int * buffer,int x,int y,int r,int g,int b)33 static void setPixel(int* buffer,int x,int y,int r,int g,int b)
34 {
35 int offset = (y&255)*256+(x&255);
36
37 r+=buffer[offset*3]; if (r>65536) r = 65536;
38 g+=buffer[offset*3+1]; if (g>65536) g = 65536;
39 b+=buffer[offset*3+2]; if (b>65536) b = 65536;
40
41 buffer[offset*3] = r;
42 buffer[offset*3+1] = g;
43 buffer[offset*3+2] = b;
44 }
45
setBlock(int * buffer,int x,int y,int blockSize,int r,int g,int b)46 static void setBlock(int* buffer,int x,int y,int blockSize, int r,int g,int b)
47 {
48 for (int i = y; i < y+blockSize; i++)
49 for (int j = x; j < x+blockSize; j++)
50 setPixel(buffer, j, i, r,g,b);
51 }
52
drawSplines(TCBSpline * spline,int maxDots,int maxTime,int * buffer,int blockSize,int r,int g,int b)53 static void drawSplines(TCBSpline* spline, int maxDots, int maxTime, int* buffer, int blockSize, int r, int g, int b)
54 {
55
56 float rMaxdots = (1.0f / (float)maxDots) * maxTime;
57
58 for (int j = 0; j < maxDots; j++)
59 {
60
61 float curTime = (float)j * rMaxdots;
62
63 VectorFloat pos = spline->getPos(curTime);
64
65 //int shade = pos.z*65536.0f;
66
67 setBlock(buffer, (int)pos.x, (int)pos.y, blockSize, r, g, b);
68
69 }
70 }
71
72
createSplineTexture(unsigned char * tex,int numBlocks,int blockSize)73 void Texture::createSplineTexture(unsigned char* tex, int numBlocks, int blockSize)
74 {
75
76 TCBSpline* spline = new TCBSpline(MAX_KEYS);
77
78 int* buffer = new int[256*256*3];
79
80 memset(buffer, 0, 256*256*3*sizeof(int));
81
82 int i;
83
84 for (i = 0; i < MAX_KEYS; i++)
85 {
86 int x = rand()%256;
87 int y = rand()%256;
88
89 int z = rand()%256;
90
91 VectorFloat v((float)x, (float)y, (float)z/255.0f);
92
93 spline->setKey(i, v, (int)(((1.0f/((float)MAX_KEYS-1.0f))*(float)i)*MAX_TIME));
94 }
95
96 drawSplines(spline, numBlocks, MAX_TIME, buffer, blockSize, (5*65536/255)>>1, (4*65536/255)>>1, (65536*2/255)>>1);
97
98 for (i = 0; i < MAX_KEYS; i++)
99 {
100 int x = rand()%256;
101 int y = rand()%256;
102
103 int z = rand()%256;
104
105 VectorFloat v((float)x, (float)y, (float)z/255.0f);
106
107 spline->setKey(i, v, (int)(((1.0f/((float)MAX_KEYS-1.0f))*(float)i)*MAX_TIME));
108 }
109
110 drawSplines(spline, numBlocks, MAX_TIME, buffer, blockSize, (0*65536/255)>>1, (65536/255)>>1, (4*65536/255)>>1);
111
112 for (i = 0; i < 256*256; i++)
113 {
114 tex[i*3] = (int)(buffer[i*3]*255)>>16;
115 tex[i*3+1] = (int)(buffer[i*3+1]*255)>>16;
116 tex[i*3+2] = (int)(buffer[i*3+2]*255)>>16;
117 }
118
119 delete[] buffer;
120
121 delete spline;
122 }
123
createFlareTexture(unsigned char * tex,int r,int g,int b,float pw,unsigned int size)124 void Texture::createFlareTexture(unsigned char* tex,
125 int r,int g,int b,
126 float pw /*= 4.0f*/,
127 unsigned int size /*= 256*/)
128 {
129
130 int hx = size>>1;
131 int hy = size>>1;
132
133 float maxlen = (float)sqrt(pow(size*0.5,2));
134
135 float fac = 1.0f/maxlen;
136
137 for (unsigned int y = 0; y < size; y++)
138 for (unsigned int x = 0; x < size; x++)
139 {
140
141 int offset = (y*size+x)*3;
142
143 int px = x - hx;
144 int py = y - hy;
145
146 float v = (float)(px*px+py*py);
147 float len = (float)sqrt(v);
148
149 if (len > maxlen)
150 len = maxlen;
151
152 v = (float)(sin((1.0f-(len*fac))*(M_PI/2.0f)));
153 float fc = (float)pow(v,pw);
154
155 //float fc = (float)pow(1.0f-(len*fac),pw);
156
157 tex[offset] = (unsigned char)(r*fc);
158 tex[offset+1] = (unsigned char)(g*fc);
159 tex[offset+2] = (unsigned char)(b*fc);
160
161 }
162
163 }
164
CalcLight(unsigned char * heightmap,int texmapsize,int x1,int y1,int x2,int y2,int depth,int smooth)165 static int CalcLight(unsigned char* heightmap, int texmapsize, int x1,int y1,int x2,int y2,int depth, int smooth)
166 {
167 int l,ran;
168 ran = (texmapsize<<smooth)>>depth;
169 l = (((int)heightmap[y1*texmapsize+x1]+(int)heightmap[y2*texmapsize+x2]) >> 1) + (rand()%ran)-(ran>>1);
170 if (l<1)
171 l = 1;
172 else if (l>255)
173 l = 255;
174
175 return l;
176 }
177
GenRandom(unsigned char * heightmap,int texmapsize,int x1,int y1,int x2,int y2,int depth,int smooth)178 static void GenRandom(unsigned char* heightmap, int texmapsize, int x1,int y1,int x2,int y2,int depth, int smooth)
179 {
180 int xh,yh;
181 int light;
182
183 xh = (x1+x2) >> 1;
184 yh = (y1+y2) >> 1;
185 if (heightmap[y1*texmapsize+xh] == 0) heightmap[y1*texmapsize+xh] = CalcLight(heightmap, texmapsize,x1,y1,x2,y1,depth, smooth);
186 if (heightmap[y2*texmapsize+xh] == 0) heightmap[y2*texmapsize+xh] = CalcLight(heightmap, texmapsize,x1,y2,x2,y2,depth, smooth);
187 if (heightmap[yh*texmapsize+x1] == 0) heightmap[yh*texmapsize+x1] = CalcLight(heightmap, texmapsize,x1,y1,x1,y2,depth, smooth);
188 if (heightmap[yh*texmapsize+x2] == 0) heightmap[yh*texmapsize+x2] = CalcLight(heightmap, texmapsize,x2,y1,x2,y2,depth, smooth);
189
190 light = CalcLight(heightmap, texmapsize,x1,y1,x2,y2,depth, smooth) +
191 CalcLight(heightmap, texmapsize,x1,y2,x2,y1,depth, smooth);
192
193 if (light>511)
194 light = 511;
195
196 heightmap[yh*texmapsize+xh] = light >> 1;
197
198 if ((1<<depth) < texmapsize)
199 {
200 GenRandom(heightmap, texmapsize,x1,y1,xh,yh,depth+1, smooth);
201 GenRandom(heightmap, texmapsize,xh,y1,x2,yh,depth+1, smooth);
202 GenRandom(heightmap, texmapsize,x1,yh,xh,y2,depth+1, smooth);
203 GenRandom(heightmap, texmapsize,xh,yh,x2,y2,depth+1, smooth);
204 }
205 }
206
GenPlasma(unsigned char * heightmap,int texmapsize,int smooth)207 static void GenPlasma(unsigned char* heightmap, int texmapsize, int smooth)
208 {
209 int i,x,y;
210
211 memset(heightmap,0,texmapsize*texmapsize);
212 i = rand()&255;
213 heightmap[0*texmapsize+0]=i;
214 heightmap[0*texmapsize+(texmapsize-1)]=i;
215 heightmap[(texmapsize-1)*texmapsize+0]=i;
216 heightmap[(texmapsize-1)*texmapsize+(texmapsize-1)] = i;
217
218 GenRandom(heightmap, texmapsize, 0,0,texmapsize-1,texmapsize-1,1, smooth);
219 for (y=1;y<=texmapsize-2;y++)
220 for (x=1;x<=texmapsize-2;x++)
221 heightmap[y*texmapsize+x] = 0;
222
223 for (x = 0; x<=texmapsize-1; x++) heightmap[(texmapsize-1)*texmapsize+x] = heightmap[0*texmapsize+x];
224 for (y = 0; y<=texmapsize-1; y++) heightmap[y*texmapsize+(texmapsize-1)] = heightmap[y*texmapsize+0];
225 GenRandom(heightmap, texmapsize, 0,0,texmapsize-1,texmapsize-1,1, smooth);
226 }
227
createPlasmaTexture(unsigned char * tex,unsigned int size,int smooth,int r,int g,int b)228 void Texture::createPlasmaTexture(unsigned char* tex, unsigned int size, int smooth, int r, int g, int b)
229 {
230 unsigned char* map = new unsigned char[size*size];
231
232 GenPlasma(map, size, smooth);
233
234 for (unsigned int i = 0; i < size*size; i++)
235 {
236 tex[i*3] = (map[i]*r)/255;
237 tex[i*3+1] = (map[i]*g)/255;
238 tex[i*3+2] = (map[i]*b)/255;
239 }
240
241 delete[] map;
242 }
243
convert24to16(unsigned short * dstImage,unsigned char * srcImage,int size,unsigned int shifter)244 void Texture::convert24to16(unsigned short* dstImage, unsigned char* srcImage, int size, unsigned int shifter)
245 {
246 for (int i = 0; i < size; i++)
247 dstImage[i] = RGB2SHORT(srcImage[i*3]>>shifter,srcImage[i*3+1]>>shifter,srcImage[i*3+2]>>shifter);
248 }
249
blur24(unsigned char * tex,unsigned int width,unsigned int height,unsigned int passes)250 void Texture::blur24(unsigned char* tex, unsigned int width, unsigned int height, unsigned int passes /*= 1*/)
251 {
252 unsigned char* dst = new unsigned char[width*height*3];
253
254 memcpy(dst, tex, width*height*3);
255
256 for (unsigned int j = 0; j < passes; j++)
257 {
258
259 for (unsigned int y = 1; y < height-1; y++)
260 for (unsigned int x = 1; x < width-1; x++)
261 {
262
263 int y1p = (y+1);
264 int y1m = (y-1);
265
266 int x1p = (x+1);
267 int x1m = (x-1);
268
269 for (int i = 0; i < 3; i++)
270 {
271
272 int c = (tex[(y*width+x)*3+i] +
273 tex[(y1m*width+x)*3+i] +
274 tex[(y1p*width+x)*3+i] +
275 tex[(y*width+x1m)*3+i] +
276 tex[(y*width+x1p)*3+i])/5;
277
278 dst[(y*width+x)*3+i] = c;
279 }
280
281 }
282
283
284 memcpy(tex, dst, width*height*3);
285 }
286
287 delete[] dst;
288
289 }
290