13 typedef struct pvec2 {
18 #define MAT_STACK_SIZE 4
24 static void proc_vertex(const int32_t *vin, pvec3 *vout);
26 void draw_poly(int num, const pvec3 *verts, int color);
27 void draw_point(const pvec3 *v, int color);
30 static int32_t proj_fov = M_PI_X16;
31 static int32_t proj_aspect = 65536;
32 static int32_t inv_proj_aspect = 65536;
33 static int32_t proj_near = ftox16(0.5);
34 static int32_t proj_far = 500 << 16;
35 static int32_t inv_tan_half_xfov, inv_tan_half_yfov;
37 #define ID_INIT {65536, 0, 0, 0, 0, 65536, 0, 0, 0, 0, 65536, 0}
39 static struct matrix identity = { ID_INIT };
42 static struct matrix mstack[MAT_STACK_SIZE] = { {ID_INIT}, {ID_INIT} };
44 static const int32_t *vertex_array;
45 static unsigned short vertex_count;
47 static uint8_t im_color_index;
50 void x3d_projection(int fov, int32_t aspect, int32_t nearz, int32_t farz)
52 proj_fov = (M_PI_X16 * fov) / 180;
54 inv_proj_aspect = x16div(65536, proj_aspect);
58 inv_tan_half_yfov = (int32_t)(65536.0 / tan(0.5 * proj_fov / 65536.0));
59 inv_tan_half_xfov = x16mul(inv_tan_half_yfov, aspect);
62 int x3d_push_matrix(void)
64 short newtop = mtop + 1;
65 if(newtop >= MAT_STACK_SIZE) {
68 memcpy(mstack + newtop, mstack + mtop, sizeof *mstack);
73 int x3d_pop_matrix(void)
82 void x3d_load_matrix(int32_t *m)
84 memcpy(mstack[mtop].m, m, sizeof *mstack);
88 #define M(i,j) (((i) << 2) + (j))
89 void x3d_mult_matrix(int32_t *m)
94 memcpy(tmp.m, mstack[mtop].m, sizeof tmp);
98 mstack[mtop].m[M(i, j)] =
99 x16mul(m[M(0, j)], tmp.m[M(i, 0)]) +
100 x16mul(m[M(1, j)], tmp.m[M(i, 1)]) +
101 x16mul(m[M(2, j)], tmp.m[M(i, 2)]);
103 mstack[mtop].m[M(i, 3)] += tmp.m[M(i, 3)];
107 void x3d_load_identity(void)
109 memcpy(mstack[mtop].m, identity.m, sizeof identity);
112 void x3d_translate(int32_t x, int32_t y, int32_t z)
114 int32_t m[] = ID_INIT;
122 void x3d_rotate(int32_t deg, int32_t x, int32_t y, int32_t z)
124 int32_t xform[] = ID_INIT;
126 int32_t angle = x16mul(M_PI_X16, deg) / 180;
127 int32_t sina = sin_x16(angle);
128 int32_t cosa = cos_x16(angle);
129 int32_t one_minus_cosa = 65536 - cosa;
130 int32_t nxsq = x16sq(x);
131 int32_t nysq = x16sq(y);
132 int32_t nzsq = x16sq(z);
134 xform[0] = nxsq + x16mul(65536 - nxsq, cosa);
135 xform[4] = x16mul(x16mul(x, y), one_minus_cosa) - x16mul(z, sina);
136 xform[8] = x16mul(x16mul(x, z), one_minus_cosa) + x16mul(y, sina);
137 xform[1] = x16mul(x16mul(x, y), one_minus_cosa) + x16mul(z, sina);
138 xform[5] = nysq + x16mul(65536 - nysq, cosa);
139 xform[9] = x16mul(x16mul(y, z), one_minus_cosa) - x16mul(x, sina);
140 xform[2] = x16mul(x16mul(x, z), one_minus_cosa) - x16mul(y, sina);
141 xform[6] = x16mul(x16mul(y, z), one_minus_cosa) + x16mul(x, sina);
142 xform[10] = nzsq + x16mul(65536 - nzsq, cosa);
144 x3d_mult_matrix(xform);
147 void x3d_scale(int32_t x, int32_t y, int32_t z)
149 int32_t m[] = ID_INIT;
158 void x3d_vertex_array(int count, const int32_t *ptr)
161 vertex_count = count;
164 int x3d_draw(int prim, int vnum)
166 int i, j, pverts = prim;
167 const int32_t *vptr = vertex_array;
170 if(!vertex_array) return -1;
172 if(vnum > vertex_count) {
176 for(i=0; i<vnum; i+=pverts) {
177 /* process vertices */
180 for(j=0; j<pverts; j++) {
181 proc_vertex(vptr, vpos + j);
183 if(vpos[j].z <= proj_near) {
190 color = im_color_index;
192 /* project & viewport */
193 for(j=0; j<pverts; j++) {
196 x = x16mul(vpos[j].x, inv_tan_half_xfov);
197 x = x16div(x, vpos[j].z);
198 vpos[j].x = (x16mul(x, inv_proj_aspect) + 65536) * (WIDTH / 2);
200 y = x16mul(vpos[j].y, inv_tan_half_yfov);
201 y = x16div(y, vpos[j].z);
202 vpos[j].y = (65536 - y) * (HEIGHT / 2);
207 draw_point(vpos, color);
215 draw_poly(pverts, vpos, im_color_index);
224 static void proc_vertex(const int32_t *vin, pvec3 *vout)
228 int32_t *mvmat = mstack[mtop].m;
230 /* transform vertex with current matrix */
232 tvert[i] = x16mul(mvmat[0], vin[0]) +
233 x16mul(mvmat[1], vin[1]) +
234 x16mul(mvmat[2], vin[2]) +
244 void x3d_color_index(int cidx)
246 im_color_index = cidx;
250 void draw_poly(int num, const pvec3 *verts, int color)
253 regis_abspos(verts[0].x, verts[0].y);
254 regis_begin_vector(REGIS_BOUNDED);
256 for(i=0; i<num-1; i++) {
258 regis_absv(verts->x, verts->y);
263 void draw_point(const pvec3 *v, int color)