gba-x3dtest

view src/x3d.c @ 9:b0ed38f13261

working on the rasterizer
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Jun 2014 05:16:10 +0300
parents fb0a0d6a8b52
children ecc022a21279
line source
1 #include "config.h"
2 #include <string.h>
3 #include "x3d.h"
4 #include "fixed.h"
5 #include "sincos.h"
6 #include "logger.h"
7 #include "polyfill.h"
8 #include "gbasys.h"
10 #define MAT_STACK_SIZE 4
12 struct matrix {
13 int32_t m[12];
14 };
16 static void proc_vertex(const int32_t *vin, const int32_t *cin, pvec3 *vout, pvec3 *cout);
19 static int32_t proj_fov = M_PI_X16;
20 static int32_t proj_aspect = 65536;
21 static int32_t proj_near = ftox16(0.5);
22 static int32_t proj_far = 500 << 16;
24 #define ID_INIT {65536, 0, 0, 0, 0, 65536, 0, 0, 0, 0, 65536, 0}
26 static struct matrix identity = { ID_INIT };
28 static short mtop;
29 static struct matrix mstack[MAT_STACK_SIZE] = { {ID_INIT}, {ID_INIT} };
31 static const int32_t *vertex_array;
32 static unsigned short vertex_count;
33 static const int32_t *color_array;
34 static unsigned short color_count;
36 static int32_t im_color[3];
37 static uint8_t im_color_index;
39 void x3d_projection(int32_t fov, int32_t aspect, int32_t nearz, int32_t farz)
40 {
41 proj_fov = fov;
42 proj_aspect = aspect;
43 proj_near = nearz;
44 proj_far = farz;
45 }
47 int x3d_push_matrix(void)
48 {
49 short newtop = mtop + 1;
50 if(newtop >= MAT_STACK_SIZE) {
51 return -1;
52 }
53 memcpy(mstack + newtop, mstack + mtop, sizeof *mstack);
54 mtop = newtop;
55 return 0;
56 }
58 int x3d_pop_matrix(void)
59 {
60 if(mtop <= 0) {
61 return -1;
62 }
63 --mtop;
64 return 0;
65 }
67 void x3d_load_matrix(int32_t *m)
68 {
69 memcpy(mstack[mtop].m, m, sizeof *mstack);
70 }
73 #define M(i,j) (((i) << 2) + (j))
74 void x3d_mult_matrix(int32_t *m)
75 {
76 int i, j;
77 struct matrix tmp;
79 memcpy(tmp.m, mstack[mtop].m, sizeof tmp);
81 for(i=0; i<3; i++) {
82 for(j=0; j<4; j++) {
83 mstack[mtop].m[M(i, j)] =
84 x16mul(tmp.m[M(0, j)], m[M(i, 0)]) +
85 x16mul(tmp.m[M(1, j)], m[M(i, 1)]) +
86 x16mul(tmp.m[M(2, j)], m[M(i, 2)]);
87 }
88 mstack[mtop].m[M(i, 3)] += m[M(i, 3)];
89 }
90 }
92 void x3d_load_identity(void)
93 {
94 memcpy(mstack[mtop].m, identity.m, sizeof identity);
95 }
97 void x3d_translate(int32_t x, int32_t y, int32_t z)
98 {
99 int32_t m[] = ID_INIT;
100 m[3] = x;
101 m[7] = y;
102 m[11] = z;
104 x3d_mult_matrix(m);
105 }
107 void x3d_rotate(int32_t deg, int32_t x, int32_t y, int32_t z)
108 {
109 int32_t xform[] = ID_INIT;
111 int32_t angle = x16mul(M_PI_X16, deg) / 180;
112 int32_t sina = sin_x16(angle);
113 int32_t cosa = cos_x16(angle);
114 int32_t one_minus_cosa = 65536 - cosa;
115 int32_t nxsq = x16sq(x);
116 int32_t nysq = x16sq(y);
117 int32_t nzsq = x16sq(z);
119 xform[0] = nxsq + x16mul(65536 - nxsq, cosa);
120 xform[4] = x16mul(x16mul(x, y), one_minus_cosa) - x16mul(z, sina);
121 xform[8] = x16mul(x16mul(x, z), one_minus_cosa) + x16mul(y, sina);
122 xform[1] = x16mul(x16mul(x, y), one_minus_cosa) + x16mul(z, sina);
123 xform[5] = nysq + x16mul(65536 - nysq, cosa);
124 xform[9] = x16mul(x16mul(y, z), one_minus_cosa) - x16mul(x, sina);
125 xform[2] = x16mul(x16mul(x, z), one_minus_cosa) - x16mul(y, sina);
126 xform[6] = x16mul(x16mul(y, z), one_minus_cosa) + x16mul(x, sina);
127 xform[10] = nzsq + x16mul(65536 - nzsq, cosa);
129 x3d_mult_matrix(xform);
130 }
132 void x3d_scale(int32_t x, int32_t y, int32_t z)
133 {
134 int32_t m[] = ID_INIT;
136 m[0] = x;
137 m[5] = y;
138 m[10] = z;
140 x3d_mult_matrix(m);
141 }
143 void x3d_vertex_array(int count, const int32_t *ptr)
144 {
145 vertex_array = ptr;
146 vertex_count = count;
147 }
149 void x3d_color_array(int count, const int32_t *ptr)
150 {
151 color_array = ptr;
152 color_count = count;
153 }
155 int x3d_draw_arrays(int prim, int vnum)
156 {
157 int i, j, pverts = prim;
158 const int32_t *vptr = vertex_array;
159 const int32_t *cptr = color_array;
160 #ifndef PALMODE
161 short cr, cg, cb;
162 #endif
163 uint16_t color;
165 if(!vertex_array) return -1;
167 if(vnum > vertex_count) {
168 logmsg(LOG_DBG, "%s called with vnum=%d, but current vertex array has %d vertices\n",
169 __FUNCTION__, vnum, vertex_count);
170 vnum = vertex_count;
171 }
172 if(color_array && vnum > color_count) {
173 logmsg(LOG_DBG, "%s called with vnum=%d, but current color array has %d elements\n",
174 __FUNCTION__, vnum, color_count);
175 vnum = color_count;
176 }
178 for(i=0; i<vnum; i+=pverts) {
179 /* process vertices */
180 pvec3 vpos[4];
181 pvec3 col[4];
183 for(j=0; j<pverts; j++) {
184 proc_vertex(vptr, cptr, vpos + j, col + j);
185 vptr += 3;
186 if(cptr) cptr += 3;
187 }
189 #ifdef PALMODE
190 color = im_color_index;
191 #else
192 cr = col[0].x >> 8;
193 cg = col[0].y >> 8;
194 cb = col[0].z >> 8;
196 if(cr > 255) cr = 255;
197 if(cg > 255) cg = 255;
198 if(cb > 255) cb = 255;
200 color = RGB(cr, cg, cb);
201 #endif
203 switch(pverts) {
204 case X3D_POINTS:
205 draw_point(vpos, color);
206 break;
208 case X3D_LINES:
209 break;
211 case X3D_TRIANGLES:
212 case X3D_QUADS:
213 draw_poly(pverts, vpos, color);
214 break;
215 }
216 }
217 return 0;
218 }
220 static void proc_vertex(const int32_t *vin, const int32_t *cin, pvec3 *vout, pvec3 *cout)
221 {
222 int i;
223 int32_t tvert[3];
224 int32_t *mvmat = mstack[mtop].m;
226 /* transform vertex with current matrix */
227 for(i=0; i<3; i++) {
228 tvert[i] = x16mul(mvmat[0], vin[0]) +
229 x16mul(mvmat[1], vin[1]) +
230 x16mul(mvmat[2], vin[2]) +
231 mvmat[3];
232 mvmat += 4;
233 }
235 vout->x = tvert[0];
236 vout->y = tvert[1];
237 vout->z = tvert[2];
238 /*logmsg(LOG_DBG, "%s: (%g %g %g) -> (%g %g %g)\n", __FUNCTION__,
239 x16tof(vin[0]), x16tof(vin[1]), x16tof(vin[2]),
240 x16tof(vout->x), x16tof(vout->y), x16tof(vout->z));*/
242 if(color_array) {
243 cout->x = cin[0];
244 cout->y = cin[1];
245 cout->z = cin[2];
246 } else {
247 cout->x = im_color[0];
248 cout->y = im_color[1];
249 cout->z = im_color[2];
250 }
251 }
253 void x3d_color_index(int cidx)
254 {
255 im_color_index = cidx;
256 }
258 void x3d_color(int32_t r, int32_t g, int32_t b)
259 {
260 im_color[0] = r;
261 im_color[1] = g;
262 im_color[2] = b;
263 }