1 #include <math.h>
2 #include "cube.h"
3 #include "item.h"
4 #include "matrix.h"
5 #include "util.h"
6 
make_cube_faces(float * data,float ao[6][4],float light[6][4],int left,int right,int top,int bottom,int front,int back,int wleft,int wright,int wtop,int wbottom,int wfront,int wback,float x,float y,float z,float n)7 void make_cube_faces(
8     float *data, float ao[6][4], float light[6][4],
9     int left, int right, int top, int bottom, int front, int back,
10     int wleft, int wright, int wtop, int wbottom, int wfront, int wback,
11     float x, float y, float z, float n)
12 {
13     static const float positions[6][4][3] = {
14         {{-1, -1, -1}, {-1, -1, +1}, {-1, +1, -1}, {-1, +1, +1}},
15         {{+1, -1, -1}, {+1, -1, +1}, {+1, +1, -1}, {+1, +1, +1}},
16         {{-1, +1, -1}, {-1, +1, +1}, {+1, +1, -1}, {+1, +1, +1}},
17         {{-1, -1, -1}, {-1, -1, +1}, {+1, -1, -1}, {+1, -1, +1}},
18         {{-1, -1, -1}, {-1, +1, -1}, {+1, -1, -1}, {+1, +1, -1}},
19         {{-1, -1, +1}, {-1, +1, +1}, {+1, -1, +1}, {+1, +1, +1}}
20     };
21     static const float normals[6][3] = {
22         {-1, 0, 0},
23         {+1, 0, 0},
24         {0, +1, 0},
25         {0, -1, 0},
26         {0, 0, -1},
27         {0, 0, +1}
28     };
29     static const float uvs[6][4][2] = {
30         {{0, 0}, {1, 0}, {0, 1}, {1, 1}},
31         {{1, 0}, {0, 0}, {1, 1}, {0, 1}},
32         {{0, 1}, {0, 0}, {1, 1}, {1, 0}},
33         {{0, 0}, {0, 1}, {1, 0}, {1, 1}},
34         {{0, 0}, {0, 1}, {1, 0}, {1, 1}},
35         {{1, 0}, {1, 1}, {0, 0}, {0, 1}}
36     };
37     static const float indices[6][6] = {
38         {0, 3, 2, 0, 1, 3},
39         {0, 3, 1, 0, 2, 3},
40         {0, 3, 2, 0, 1, 3},
41         {0, 3, 1, 0, 2, 3},
42         {0, 3, 2, 0, 1, 3},
43         {0, 3, 1, 0, 2, 3}
44     };
45     static const float flipped[6][6] = {
46         {0, 1, 2, 1, 3, 2},
47         {0, 2, 1, 2, 3, 1},
48         {0, 1, 2, 1, 3, 2},
49         {0, 2, 1, 2, 3, 1},
50         {0, 1, 2, 1, 3, 2},
51         {0, 2, 1, 2, 3, 1}
52     };
53     float *d = data;
54     float s = 0.0625;
55     float a = 0 + 1 / 2048.0;
56     float b = s - 1 / 2048.0;
57     int faces[6] = {left, right, top, bottom, front, back};
58     int tiles[6] = {wleft, wright, wtop, wbottom, wfront, wback};
59     for (int i = 0; i < 6; i++) {
60         if (faces[i] == 0) {
61             continue;
62         }
63         float du = (tiles[i] % 16) * s;
64         float dv = (tiles[i] / 16) * s;
65         int flip = ao[i][0] + ao[i][3] > ao[i][1] + ao[i][2];
66         for (int v = 0; v < 6; v++) {
67             int j = flip ? flipped[i][v] : indices[i][v];
68             *(d++) = x + n * positions[i][j][0];
69             *(d++) = y + n * positions[i][j][1];
70             *(d++) = z + n * positions[i][j][2];
71             *(d++) = normals[i][0];
72             *(d++) = normals[i][1];
73             *(d++) = normals[i][2];
74             *(d++) = du + (uvs[i][j][0] ? b : a);
75             *(d++) = dv + (uvs[i][j][1] ? b : a);
76             *(d++) = ao[i][j];
77             *(d++) = light[i][j];
78         }
79     }
80 }
81 
make_cube(float * data,float ao[6][4],float light[6][4],int left,int right,int top,int bottom,int front,int back,float x,float y,float z,float n,int w)82 void make_cube(
83     float *data, float ao[6][4], float light[6][4],
84     int left, int right, int top, int bottom, int front, int back,
85     float x, float y, float z, float n, int w)
86 {
87     int wleft = blocks[w][0];
88     int wright = blocks[w][1];
89     int wtop = blocks[w][2];
90     int wbottom = blocks[w][3];
91     int wfront = blocks[w][4];
92     int wback = blocks[w][5];
93     make_cube_faces(
94         data, ao, light,
95         left, right, top, bottom, front, back,
96         wleft, wright, wtop, wbottom, wfront, wback,
97         x, y, z, n);
98 }
99 
make_plant(float * data,float ao,float light,float px,float py,float pz,float n,int w,float rotation)100 void make_plant(
101     float *data, float ao, float light,
102     float px, float py, float pz, float n, int w, float rotation)
103 {
104     static const float positions[4][4][3] = {
105         {{ 0, -1, -1}, { 0, -1, +1}, { 0, +1, -1}, { 0, +1, +1}},
106         {{ 0, -1, -1}, { 0, -1, +1}, { 0, +1, -1}, { 0, +1, +1}},
107         {{-1, -1,  0}, {-1, +1,  0}, {+1, -1,  0}, {+1, +1,  0}},
108         {{-1, -1,  0}, {-1, +1,  0}, {+1, -1,  0}, {+1, +1,  0}}
109     };
110     static const float normals[4][3] = {
111         {-1, 0, 0},
112         {+1, 0, 0},
113         {0, 0, -1},
114         {0, 0, +1}
115     };
116     static const float uvs[4][4][2] = {
117         {{0, 0}, {1, 0}, {0, 1}, {1, 1}},
118         {{1, 0}, {0, 0}, {1, 1}, {0, 1}},
119         {{0, 0}, {0, 1}, {1, 0}, {1, 1}},
120         {{1, 0}, {1, 1}, {0, 0}, {0, 1}}
121     };
122     static const float indices[4][6] = {
123         {0, 3, 2, 0, 1, 3},
124         {0, 3, 1, 0, 2, 3},
125         {0, 3, 2, 0, 1, 3},
126         {0, 3, 1, 0, 2, 3}
127     };
128     float *d = data;
129     float s = 0.0625;
130     float a = 0;
131     float b = s;
132     float du = (plants[w] % 16) * s;
133     float dv = (plants[w] / 16) * s;
134     for (int i = 0; i < 4; i++) {
135         for (int v = 0; v < 6; v++) {
136             int j = indices[i][v];
137             *(d++) = n * positions[i][j][0];
138             *(d++) = n * positions[i][j][1];
139             *(d++) = n * positions[i][j][2];
140             *(d++) = normals[i][0];
141             *(d++) = normals[i][1];
142             *(d++) = normals[i][2];
143             *(d++) = du + (uvs[i][j][0] ? b : a);
144             *(d++) = dv + (uvs[i][j][1] ? b : a);
145             *(d++) = ao;
146             *(d++) = light;
147         }
148     }
149     float ma[16];
150     float mb[16];
151     mat_identity(ma);
152     mat_rotate(mb, 0, 1, 0, RADIANS(rotation));
153     mat_multiply(ma, mb, ma);
154     mat_apply(data, ma, 24, 3, 10);
155     mat_translate(mb, px, py, pz);
156     mat_multiply(ma, mb, ma);
157     mat_apply(data, ma, 24, 0, 10);
158 }
159 
make_player(float * data,float x,float y,float z,float rx,float ry)160 void make_player(
161     float *data,
162     float x, float y, float z, float rx, float ry)
163 {
164     float ao[6][4] = {0};
165     float light[6][4] = {
166         {0.8, 0.8, 0.8, 0.8},
167         {0.8, 0.8, 0.8, 0.8},
168         {0.8, 0.8, 0.8, 0.8},
169         {0.8, 0.8, 0.8, 0.8},
170         {0.8, 0.8, 0.8, 0.8},
171         {0.8, 0.8, 0.8, 0.8}
172     };
173     make_cube_faces(
174         data, ao, light,
175         1, 1, 1, 1, 1, 1,
176         226, 224, 241, 209, 225, 227,
177         0, 0, 0, 0.4);
178     float ma[16];
179     float mb[16];
180     mat_identity(ma);
181     mat_rotate(mb, 0, 1, 0, rx);
182     mat_multiply(ma, mb, ma);
183     mat_rotate(mb, cosf(rx), 0, sinf(rx), -ry);
184     mat_multiply(ma, mb, ma);
185     mat_apply(data, ma, 36, 3, 10);
186     mat_translate(mb, x, y, z);
187     mat_multiply(ma, mb, ma);
188     mat_apply(data, ma, 36, 0, 10);
189 }
190 
make_cube_wireframe(float * data,float x,float y,float z,float n)191 void make_cube_wireframe(float *data, float x, float y, float z, float n) {
192     static const float positions[8][3] = {
193         {-1, -1, -1},
194         {-1, -1, +1},
195         {-1, +1, -1},
196         {-1, +1, +1},
197         {+1, -1, -1},
198         {+1, -1, +1},
199         {+1, +1, -1},
200         {+1, +1, +1}
201     };
202     static const int indices[24] = {
203         0, 1, 0, 2, 0, 4, 1, 3,
204         1, 5, 2, 3, 2, 6, 3, 7,
205         4, 5, 4, 6, 5, 7, 6, 7
206     };
207     float *d = data;
208     for (int i = 0; i < 24; i++) {
209         int j = indices[i];
210         *(d++) = x + n * positions[j][0];
211         *(d++) = y + n * positions[j][1];
212         *(d++) = z + n * positions[j][2];
213     }
214 }
215 
make_character(float * data,float x,float y,float n,float m,char c)216 void make_character(
217     float *data,
218     float x, float y, float n, float m, char c)
219 {
220     float *d = data;
221     float s = 0.0625;
222     float a = s;
223     float b = s * 2;
224     int w = c - 32;
225     float du = (w % 16) * a;
226     float dv = 1 - (w / 16) * b - b;
227     *(d++) = x - n; *(d++) = y - m;
228     *(d++) = du + 0; *(d++) = dv;
229     *(d++) = x + n; *(d++) = y - m;
230     *(d++) = du + a; *(d++) = dv;
231     *(d++) = x + n; *(d++) = y + m;
232     *(d++) = du + a; *(d++) = dv + b;
233     *(d++) = x - n; *(d++) = y - m;
234     *(d++) = du + 0; *(d++) = dv;
235     *(d++) = x + n; *(d++) = y + m;
236     *(d++) = du + a; *(d++) = dv + b;
237     *(d++) = x - n; *(d++) = y + m;
238     *(d++) = du + 0; *(d++) = dv + b;
239 }
240 
make_character_3d(float * data,float x,float y,float z,float n,int face,char c)241 void make_character_3d(
242     float *data, float x, float y, float z, float n, int face, char c)
243 {
244     static const float positions[8][6][3] = {
245         {{0, -2, -1}, {0, +2, +1}, {0, +2, -1},
246          {0, -2, -1}, {0, -2, +1}, {0, +2, +1}},
247         {{0, -2, -1}, {0, +2, +1}, {0, -2, +1},
248          {0, -2, -1}, {0, +2, -1}, {0, +2, +1}},
249         {{-1, -2, 0}, {+1, +2, 0}, {+1, -2, 0},
250          {-1, -2, 0}, {-1, +2, 0}, {+1, +2, 0}},
251         {{-1, -2, 0}, {+1, -2, 0}, {+1, +2, 0},
252          {-1, -2, 0}, {+1, +2, 0}, {-1, +2, 0}},
253         {{-1, 0, +2}, {+1, 0, +2}, {+1, 0, -2},
254          {-1, 0, +2}, {+1, 0, -2}, {-1, 0, -2}},
255         {{-2, 0, +1}, {+2, 0, -1}, {-2, 0, -1},
256          {-2, 0, +1}, {+2, 0, +1}, {+2, 0, -1}},
257         {{+1, 0, +2}, {-1, 0, -2}, {-1, 0, +2},
258          {+1, 0, +2}, {+1, 0, -2}, {-1, 0, -2}},
259         {{+2, 0, -1}, {-2, 0, +1}, {+2, 0, +1},
260          {+2, 0, -1}, {-2, 0, -1}, {-2, 0, +1}}
261     };
262     static const float uvs[8][6][2] = {
263         {{0, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}, {1, 1}},
264         {{1, 0}, {0, 1}, {0, 0}, {1, 0}, {1, 1}, {0, 1}},
265         {{1, 0}, {0, 1}, {0, 0}, {1, 0}, {1, 1}, {0, 1}},
266         {{0, 0}, {1, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 1}},
267         {{0, 0}, {1, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 1}},
268         {{0, 1}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}},
269         {{0, 1}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}},
270         {{0, 1}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}
271     };
272     static const float offsets[8][3] = {
273         {-1, 0, 0}, {+1, 0, 0}, {0, 0, -1}, {0, 0, +1},
274         {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0},
275     };
276     float *d = data;
277     float s = 0.0625;
278     float pu = s / 5;
279     float pv = s / 2.5;
280     float u1 = pu;
281     float v1 = pv;
282     float u2 = s - pu;
283     float v2 = s * 2 - pv;
284     float p = 0.5;
285     int w = c - 32;
286     float du = (w % 16) * s;
287     float dv = 1 - (w / 16 + 1) * s * 2;
288     x += p * offsets[face][0];
289     y += p * offsets[face][1];
290     z += p * offsets[face][2];
291     for (int i = 0; i < 6; i++) {
292         *(d++) = x + n * positions[face][i][0];
293         *(d++) = y + n * positions[face][i][1];
294         *(d++) = z + n * positions[face][i][2];
295         *(d++) = du + (uvs[face][i][0] ? u2 : u1);
296         *(d++) = dv + (uvs[face][i][1] ? v2 : v1);
297     }
298 }
299 
_make_sphere(float * data,float r,int detail,float * a,float * b,float * c,float * ta,float * tb,float * tc)300 int _make_sphere(
301     float *data, float r, int detail,
302     float *a, float *b, float *c,
303     float *ta, float *tb, float *tc)
304 {
305     if (detail == 0) {
306         float *d = data;
307         *(d++) = a[0] * r; *(d++) = a[1] * r; *(d++) = a[2] * r;
308         *(d++) = a[0]; *(d++) = a[1]; *(d++) = a[2];
309         *(d++) = ta[0]; *(d++) = ta[1];
310         *(d++) = b[0] * r; *(d++) = b[1] * r; *(d++) = b[2] * r;
311         *(d++) = b[0]; *(d++) = b[1]; *(d++) = b[2];
312         *(d++) = tb[0]; *(d++) = tb[1];
313         *(d++) = c[0] * r; *(d++) = c[1] * r; *(d++) = c[2] * r;
314         *(d++) = c[0]; *(d++) = c[1]; *(d++) = c[2];
315         *(d++) = tc[0]; *(d++) = tc[1];
316         return 1;
317     }
318     else {
319         float ab[3], ac[3], bc[3];
320         for (int i = 0; i < 3; i++) {
321             ab[i] = (a[i] + b[i]) / 2;
322             ac[i] = (a[i] + c[i]) / 2;
323             bc[i] = (b[i] + c[i]) / 2;
324         }
325         normalize(ab + 0, ab + 1, ab + 2);
326         normalize(ac + 0, ac + 1, ac + 2);
327         normalize(bc + 0, bc + 1, bc + 2);
328         float tab[2], tac[2], tbc[2];
329         tab[0] = 0; tab[1] = 1 - acosf(ab[1]) / PI;
330         tac[0] = 0; tac[1] = 1 - acosf(ac[1]) / PI;
331         tbc[0] = 0; tbc[1] = 1 - acosf(bc[1]) / PI;
332         int total = 0;
333         int n;
334         n = _make_sphere(data, r, detail - 1, a, ab, ac, ta, tab, tac);
335         total += n; data += n * 24;
336         n = _make_sphere(data, r, detail - 1, b, bc, ab, tb, tbc, tab);
337         total += n; data += n * 24;
338         n = _make_sphere(data, r, detail - 1, c, ac, bc, tc, tac, tbc);
339         total += n; data += n * 24;
340         n = _make_sphere(data, r, detail - 1, ab, bc, ac, tab, tbc, tac);
341         total += n; data += n * 24;
342         return total;
343     }
344 }
345 
make_sphere(float * data,float r,int detail)346 void make_sphere(float *data, float r, int detail) {
347     // detail, triangles, floats
348     // 0, 8, 192
349     // 1, 32, 768
350     // 2, 128, 3072
351     // 3, 512, 12288
352     // 4, 2048, 49152
353     // 5, 8192, 196608
354     // 6, 32768, 786432
355     // 7, 131072, 3145728
356     static int indices[8][3] = {
357         {4, 3, 0}, {1, 4, 0},
358         {3, 4, 5}, {4, 1, 5},
359         {0, 3, 2}, {0, 2, 1},
360         {5, 2, 3}, {5, 1, 2}
361     };
362     static float positions[6][3] = {
363         { 0, 0,-1}, { 1, 0, 0},
364         { 0,-1, 0}, {-1, 0, 0},
365         { 0, 1, 0}, { 0, 0, 1}
366     };
367     static float uvs[6][3] = {
368         {0, 0.5}, {0, 0.5},
369         {0, 0}, {0, 0.5},
370         {0, 1}, {0, 0.5}
371     };
372     int total = 0;
373     for (int i = 0; i < 8; i++) {
374         int n = _make_sphere(
375             data, r, detail,
376             positions[indices[i][0]],
377             positions[indices[i][1]],
378             positions[indices[i][2]],
379             uvs[indices[i][0]],
380             uvs[indices[i][1]],
381             uvs[indices[i][2]]);
382         total += n; data += n * 24;
383     }
384 }
385