Merge branch 'master' of git://git.xonotic.org/xonotic/xonotic
[xonotic/xonotic.git] / misc / tools / brightspot.c
1 #include <stdio.h>
2 #include <math.h>
3
4 // USAGE: see brightspot.sh (and in the future brightspot.bat)
5 // It should output the right parameters for the sun direction in q3map2's format.
6 // But probably is broken.
7
8 #define false 0
9 #define true 1
10
11 int flip[6*3] =
12 {
13         false, false,  true, // "rt"
14          true,  true,  true, // "lf"
15         false,  true, false, // "bk"
16          true, false, false, // "ft"
17         false, false,  true, // "up"
18         false, false,  true  // "dn"
19 };
20
21 static const double skyboxtexcoord2f[6*4*2] =
22 {
23     // skyside[0]
24     0, 1,
25     1, 1,
26     1, 0,
27     0, 0,
28     // skyside[1]
29     1, 0,
30     0, 0,
31     0, 1,
32     1, 1,
33     // skyside[2]
34     1, 1,
35     1, 0,
36     0, 0,
37     0, 1,
38     // skyside[3]
39     0, 0,
40     0, 1,
41     1, 1,
42     1, 0,
43     // skyside[4]
44     0, 1,
45     1, 1,
46     1, 0,
47     0, 0,
48     // skyside[5]
49     0, 1,
50     1, 1,
51     1, 0,
52     0, 0
53 };
54
55 #define GET_SKY_IMAGE(x,y,z) \
56         (fabs(x)>=fabs(y) && fabs(x)>=fabs(z)) ?  (((x) > 0) ? 0 : 1) : \
57         (fabs(y)>=fabs(x) && fabs(y)>=fabs(z)) ?  (((y) > 0) ? 2 : 3) : \
58                                                   (((z) > 0) ? 4 : 5)
59
60 int highest[6] =
61 {
62         0,
63         0,
64         1,
65         1,
66         2,
67         2
68 };
69
70 static const double skyboxvertex3f[6*4*3] =
71 {
72         // skyside[0]
73          16, -16,  16,
74          16, -16, -16,
75          16,  16, -16,
76          16,  16,  16,
77         // skyside[1]
78         -16,  16,  16,
79         -16,  16, -16,
80         -16, -16, -16,
81         -16, -16,  16,
82         // skyside[2]
83          16,  16,  16,
84          16,  16, -16,
85         -16,  16, -16,
86         -16,  16,  16,
87         // skyside[3]
88         -16, -16,  16,
89         -16, -16, -16,
90          16, -16, -16,
91          16, -16,  16,
92         // skyside[4]
93         -16, -16,  16,
94          16, -16,  16,
95          16,  16,  16,
96         -16,  16,  16,
97         // skyside[5]
98          16, -16, -16,
99         -16, -16, -16,
100         -16,  16, -16,
101          16,  16, -16
102 };
103
104 void Unmap2f(double x, double y, const double *corners, double *u, double *v)
105 {
106         // x - corners[0] == *u * (corners[2] - corners[0]) + *v * (corners[4] - corners[2]);
107         // y - corners[1] == *u * (corners[3] - corners[1]) + *v * (corners[5] - corners[3]);
108         
109         double xc0 = x - corners[0];
110         double yc1 = y - corners[1];
111         double c20 = corners[2] - corners[0];
112         double c31 = corners[3] - corners[1];
113         double c42 = corners[4] - corners[2];
114         double c53 = corners[5] - corners[3];
115
116         // xc0 == *u * c20 + *v * c42;
117         // yc1 == *u * c31 + *v * c53;
118
119         double det = c20 * c53 - c31 * c42;
120         double du = xc0 * c53 - yc1 * c42;
121         double dv = c20 * yc1 - c31 * xc0;
122
123         *u = du / det;
124         *v = dv / det;
125 }
126
127 void Map3f(double u, double v, const double *corners, double *x, double *y, double *z)
128 {
129         *x = corners[0] + u * (corners[3] - corners[0]) + v * (corners[6] - corners[3]);
130         *y = corners[1] + u * (corners[4] - corners[1]) + v * (corners[7] - corners[4]);
131         *z = corners[2] + u * (corners[5] - corners[2]) + v * (corners[8] - corners[5]);
132 }
133
134 void Map2f(double u, double v, const double *corners, double *x, double *y)
135 {
136         *x = u * (corners[2] - corners[0]) + v * (corners[4] - corners[2]) + corners[0];
137         *y = u * (corners[3] - corners[1]) + v * (corners[5] - corners[3]) + corners[1];
138 }
139
140 void Unmap3f(double x, double y, double z, const double *corners, double *u, double *v)
141 {
142         //*x = corners[0] + u * (corners[3] - corners[0]) + v * (corners[6] - corners[3]);
143         //*y = corners[1] + u * (corners[4] - corners[1]) + v * (corners[7] - corners[4]);
144         //*z = corners[2] + u * (corners[5] - corners[2]) + v * (corners[8] - corners[5]);
145         // THREE equations, TWO would be better! Let's simply use the two "better" ones
146         
147         double xc0 = x - corners[0];
148         double yc1 = y - corners[1];
149         double zc2 = z - corners[2];
150         double c30 = corners[3] - corners[0];
151         double c41 = corners[4] - corners[1];
152         double c52 = corners[5] - corners[2];
153         double c63 = corners[6] - corners[3];
154         double c74 = corners[7] - corners[4];
155         double c85 = corners[8] - corners[5];
156
157         double det_x = c41 * c85 - c52 * c74;
158         double det_y = c30 * c85 - c52 * c63;
159         double det_z = c30 * c74 - c41 * c63;
160
161         if(fabs(det_x) >= fabs(det_y) && fabs(det_x) >= fabs(det_z))
162         {
163                 double du = yc1 * c85 - zc2 * c74;
164                 double dv = c41 * zc2 - c52 * yc1;
165                 *u = du / det_x;
166                 *v = dv / det_x;
167         }
168         else if(fabs(det_y) >= fabs(det_z))
169         {
170                 double du = xc0 * c85 - zc2 * c63;
171                 double dv = c30 * zc2 - c52 * xc0;
172                 *u = du / det_y;
173                 *v = dv / det_y;
174         }
175         else
176         {
177                 double du = xc0 * c74 - yc1 * c63;
178                 double dv = c30 * yc1 - c41 * xc0;
179                 *u = du / det_z;
180                 *v = dv / det_z;
181         }
182 }
183
184 void MapCoord(int pic, int y, int x, double vec[3])
185 {
186         int h;
187         int flipx = flip[3*pic+0];
188         int flipy = flip[3*pic+1];
189         int flipdiag = flip[3*pic+2];
190         double u, v;
191
192         if(flipx)
193                 x = 511 - x;
194
195         if(flipy)
196                 y = 511 - y;
197
198         if(flipdiag)
199         {
200                 h = x; x = y; y = h;
201         }
202
203         Unmap2f((x + 0.5) / 512.0, (y + 0.5) / 512.0, skyboxtexcoord2f + 4*2*pic, &u, &v);
204         Map3f(u, v, skyboxvertex3f + 6*2*pic, &vec[0], &vec[1], &vec[2]);
205 }
206
207 void UnmapCoord(const double vec_[3], int *pic, int *y, int *x)
208 {
209         int h;
210         int flipx;
211         int flipy;
212         int flipdiag;
213         double u, v, xx, yy;
214         double f;
215         double vec[3];
216
217         // identify which pic it is
218         *pic = GET_SKY_IMAGE(vec_[0], vec_[1], vec_[2]);
219         f = 16.0/fabs(vec_[highest[*pic]]);
220         vec[0] = vec_[0] * f;
221         vec[1] = vec_[1] * f;
222         vec[2] = vec_[2] * f;
223         flipx = flip[3*(*pic)+0];
224         flipy = flip[3*(*pic)+1];
225         flipdiag = flip[3*(*pic)+2];
226
227         *x = *y = 0;
228         Unmap3f(vec[0], vec[1], vec[2], skyboxvertex3f + 6*2*(*pic), &u, &v);
229         Map2f(u, v, skyboxtexcoord2f + 4*2*(*pic), &xx, &yy);
230         *x = (int) (xx * 512.0 + 0.5);
231         *y = (int) (yy * 512.0 + 0.5);
232
233         if(flipdiag)
234         {
235                 h = *x; *x = *y; *y = h;
236         }
237
238         if(flipy)
239                 *y = 511 - *y;
240
241         if(flipx)
242                 *x = 511 - *x;
243 }
244
245 int main(int argc, char **argv)
246 {
247         FILE *f;
248         int i, j, k;
249         unsigned char picture[6][512][512];
250         unsigned char max;
251         double brightvec[3];
252         double pitch, yaw, l;
253
254         if(argc != 2)
255         {
256                 fprintf(stderr, "Usage: %s imagefile.gray\n", *argv);
257                 return 1;
258         }
259
260         f = fopen(argv[1], "rb");
261         if(!f)
262         {
263                 perror("fopen");
264                 return 1;
265         }
266         fread(&picture, sizeof(picture), 1, f);
267         fclose(f);
268
269         brightvec[0] = brightvec[1] = brightvec[2] = 0;
270         max = 0;
271         for(i = 0; i < 6; ++i)
272                 for(j = 0; j < 512; ++j)
273                         for(k = 0; k < 512; ++k)
274                                 if(picture[i][j][k] > max)
275                                         max = picture[i][j][k];
276         for(i = 0; i < 6; ++i)
277                 for(j = 0; j < 512; ++j)
278                         for(k = 0; k < 512; ++k)
279                         {
280                                 double vec[3], f;
281                                 MapCoord(i, j, k, vec);
282                                 f = pow(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2], -1.5); // I know what I am doing.
283                                 f *= exp(10 * (picture[i][j][k] - max));
284                                 brightvec[0] += f * vec[0];
285                                 brightvec[1] += f * vec[1];
286                                 brightvec[2] += f * vec[2];
287                         }
288
289         l = sqrt(brightvec[0]*brightvec[0] + brightvec[1]*brightvec[1] + brightvec[2]*brightvec[2]);
290         l /= 16;
291         brightvec[0] /= l;
292         brightvec[1] /= l;
293         brightvec[2] /= l;
294         fprintf(stderr, "vec = %f %f %f\n", brightvec[0], brightvec[1], brightvec[2]);
295         UnmapCoord(brightvec, &i, &j, &k);
296         fprintf(stderr, "picture %d pixel (%d %d) value %d\n", i, k, j, picture[i][j][k]);
297         
298         pitch = atan2(brightvec[2], sqrt(brightvec[0]*brightvec[0] + brightvec[1]*brightvec[1]));
299         yaw = atan2(brightvec[1], brightvec[0]);
300
301         printf("%f %f\n", yaw * 180 / M_PI, pitch * 180 / M_PI);
302
303         return 0;
304 }