gba-x3dtest

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