gba-trycatch
view src/x3d.c @ 8:fb0a0d6a8b52
sortof works
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 19 Jun 2014 05:53:46 +0300 |
parents | 158d23956801 |
children | b0ed38f13261 |
line source
1 #include <string.h>
2 #include "x3d.h"
3 #include "fixed.h"
4 #include "sincos.h"
5 #include "logger.h"
6 #include "polyfill.h"
7 #include "gbasys.h"
9 #define MAT_STACK_SIZE 4
11 struct matrix {
12 int32_t m[12];
13 };
15 static void proc_vertex(const int32_t *vin, const int32_t *cin, pvec3 *vout, pvec3 *cout);
18 static int32_t proj_fov = M_PI_X16;
19 static int32_t proj_aspect = 65536;
20 static int32_t proj_near = ftox16(0.5);
21 static int32_t proj_far = 500 << 16;
23 #define ID_INIT {65536, 0, 0, 0, 0, 65536, 0, 0, 0, 0, 65536, 0}
25 static struct matrix identity = { ID_INIT };
27 static short mtop;
28 static struct matrix mstack[MAT_STACK_SIZE] = { {ID_INIT}, {ID_INIT} };
30 static const int32_t *vertex_array;
31 static unsigned short vertex_count;
32 static const int32_t *color_array;
33 static unsigned short color_count;
35 static int32_t im_color[3];
37 void x3d_projection(int32_t fov, int32_t aspect, int32_t nearz, int32_t farz)
38 {
39 proj_fov = fov;
40 proj_aspect = aspect;
41 proj_near = nearz;
42 proj_far = farz;
43 }
45 int x3d_push_matrix(void)
46 {
47 short newtop = mtop + 1;
48 if(newtop >= MAT_STACK_SIZE) {
49 return -1;
50 }
51 memcpy(mstack + newtop, mstack + mtop, sizeof *mstack);
52 mtop = newtop;
53 return 0;
54 }
56 int x3d_pop_matrix(void)
57 {
58 if(mtop <= 0) {
59 return -1;
60 }
61 --mtop;
62 return 0;
63 }
65 void x3d_load_matrix(int32_t *m)
66 {
67 memcpy(mstack[mtop].m, m, sizeof *mstack);
68 }
71 #define M(i,j) (((i) << 2) + (j))
72 void x3d_mult_matrix(int32_t *m)
73 {
74 int i, j;
75 struct matrix tmp;
77 memcpy(tmp.m, mstack[mtop].m, sizeof tmp);
79 for(i=0; i<3; i++) {
80 for(j=0; j<4; j++) {
81 mstack[mtop].m[M(i, j)] =
82 x16mul(tmp.m[M(0, j)], m[M(i, 0)]) +
83 x16mul(tmp.m[M(1, j)], m[M(i, 1)]) +
84 x16mul(tmp.m[M(2, j)], m[M(i, 2)]);
85 }
86 mstack[mtop].m[M(i, 3)] += m[M(i, 3)];
87 }
88 }
90 void x3d_load_identity(void)
91 {
92 memcpy(mstack[mtop].m, identity.m, sizeof identity);
93 }
95 void x3d_translate(int32_t x, int32_t y, int32_t z)
96 {
97 int32_t m[] = ID_INIT;
98 m[3] = x;
99 m[7] = y;
100 m[11] = z;
102 x3d_mult_matrix(m);
103 }
105 void x3d_rotate(int32_t deg, int32_t x, int32_t y, int32_t z)
106 {
107 int32_t xform[] = ID_INIT;
109 int32_t angle = x16mul(M_PI_X16, deg) / 180;
110 int32_t sina = sin_x16(angle);
111 int32_t cosa = cos_x16(angle);
112 int32_t one_minus_cosa = 65536 - cosa;
113 int32_t nxsq = x16sq(x);
114 int32_t nysq = x16sq(y);
115 int32_t nzsq = x16sq(z);
117 xform[0] = nxsq + x16mul(65536 - nxsq, cosa);
118 xform[4] = x16mul(x16mul(x, y), one_minus_cosa) - x16mul(z, sina);
119 xform[8] = x16mul(x16mul(x, z), one_minus_cosa) + x16mul(y, sina);
120 xform[1] = x16mul(x16mul(x, y), one_minus_cosa) + x16mul(z, sina);
121 xform[5] = nysq + x16mul(65536 - nysq, cosa);
122 xform[9] = x16mul(x16mul(y, z), one_minus_cosa) - x16mul(x, sina);
123 xform[2] = x16mul(x16mul(x, z), one_minus_cosa) - x16mul(y, sina);
124 xform[6] = x16mul(x16mul(y, z), one_minus_cosa) + x16mul(x, sina);
125 xform[10] = nzsq + x16mul(65536 - nzsq, cosa);
127 x3d_mult_matrix(xform);
128 }
130 void x3d_scale(int32_t x, int32_t y, int32_t z)
131 {
132 int32_t m[] = ID_INIT;
134 m[0] = x;
135 m[5] = y;
136 m[10] = z;
138 x3d_mult_matrix(m);
139 }
141 void x3d_vertex_array(int count, const int32_t *ptr)
142 {
143 vertex_array = ptr;
144 vertex_count = count;
145 }
147 void x3d_color_array(int count, const int32_t *ptr)
148 {
149 color_array = ptr;
150 color_count = count;
151 }
153 int x3d_draw_arrays(int prim, int vnum)
154 {
155 int i, j, pverts = prim;
156 const int32_t *vptr = vertex_array;
157 const int32_t *cptr = color_array;
158 short cr, cg, cb;
160 if(!vertex_array) return -1;
162 if(vnum > vertex_count) {
163 logmsg(LOG_DBG, "%s called with vnum=%d, but current vertex array has %d vertices\n",
164 __FUNCTION__, vnum, vertex_count);
165 vnum = vertex_count;
166 }
167 if(color_array && vnum > color_count) {
168 logmsg(LOG_DBG, "%s called with vnum=%d, but current color array has %d elements\n",
169 __FUNCTION__, vnum, color_count);
170 vnum = color_count;
171 }
173 for(i=0; i<vnum; i+=pverts) {
174 /* process vertices */
175 pvec3 vpos[4];
176 pvec3 col[4];
178 for(j=0; j<pverts; j++) {
179 proc_vertex(vptr, cptr, vpos + j, col + j);
180 vptr += 3;
181 if(cptr) cptr += 3;
182 }
184 cr = col[0].x >> 8;
185 cg = col[0].y >> 8;
186 cb = col[0].z >> 8;
188 if(cr > 255) cr = 255;
189 if(cg > 255) cg = 255;
190 if(cb > 255) cb = 255;
192 switch(pverts) {
193 case X3D_POINTS:
194 draw_point(vpos, RGB(cr, cg, cb));
195 break;
197 case X3D_LINES:
198 break;
200 case X3D_TRIANGLES:
201 case X3D_QUADS:
202 draw_poly(pverts, vpos, RGB(cr, cg, cb));
203 break;
204 }
205 }
206 return 0;
207 }
209 static void proc_vertex(const int32_t *vin, const int32_t *cin, pvec3 *vout, pvec3 *cout)
210 {
211 int i;
212 int32_t tvert[3];
213 int32_t *mvmat = mstack[mtop].m;
215 /* transform vertex with current matrix */
216 for(i=0; i<3; i++) {
217 tvert[i] = x16mul(mvmat[0], vin[0]) +
218 x16mul(mvmat[1], vin[1]) +
219 x16mul(mvmat[2], vin[2]) +
220 mvmat[3];
221 mvmat += 4;
222 }
224 vout->x = tvert[0];
225 vout->y = tvert[1];
226 vout->z = tvert[2];
227 /*logmsg(LOG_DBG, "%s: (%g %g %g) -> (%g %g %g)\n", __FUNCTION__,
228 x16tof(vin[0]), x16tof(vin[1]), x16tof(vin[2]),
229 x16tof(vout->x), x16tof(vout->y), x16tof(vout->z));*/
231 if(color_array) {
232 cout->x = cin[0];
233 cout->y = cin[1];
234 cout->z = cin[2];
235 } else {
236 cout->x = im_color[0];
237 cout->y = im_color[1];
238 cout->z = im_color[2];
239 }
240 }
242 void x3d_color(int32_t r, int32_t g, int32_t b)
243 {
244 im_color[0] = r;
245 im_color[1] = g;
246 im_color[2] = b;
247 }