8 typedef float g3d_matrix[16];
13 g3d_matrix mat[G3D_NUM_MATRICES][STACK_SIZE];
14 int mtop[G3D_NUM_MATRICES];
20 static void xform4_vec3(const float *mat, float *vec);
21 static void xform3_vec3(const float *mat, float *vec);
22 static void proc_vertex(struct pvertex *res, const struct g3d_vertex *vert, int space);
24 static struct g3d_state st;
25 static const float idmat[] = {
36 memset(&st, 0, sizeof st);
38 for(i=0; i<G3D_NUM_MATRICES; i++) {
43 void g3d_framebuffer(int width, int height, void *pixels)
50 void g3d_enable(unsigned int opt)
55 void g3d_disable(unsigned int opt)
60 void g3d_setopt(unsigned int opt, unsigned int mask)
62 st.opt = (st.opt & ~mask) | (opt & mask);
65 unsigned int g3d_getopt(unsigned int mask)
70 void g3d_set_matrix(int which, const float *m)
72 int top = st.mtop[which];
75 memcpy(st.mat[which][top], m, 16 * sizeof(float));
78 #define M(i,j) (((i) << 2) + (j))
79 void g3d_mult_matrix(int which, const float *m2)
81 int i, j, top = st.mtop[which];
83 float *dest = st.mat[which][top];
85 memcpy(m1, dest, sizeof m1);
89 *dest++ = m1[M(0,j)] * m2[M(i,0)] +
90 m1[M(1,j)] * m2[M(i,1)] +
91 m1[M(2,j)] * m2[M(i,2)] +
92 m1[M(3,j)] * m2[M(i,3)];
97 void g3d_push_matrix(int which)
99 int top = st.mtop[which];
100 if(top >= G3D_NUM_MATRICES) {
101 fprintf(stderr, "g3d_push_matrix overflow\n");
104 memcpy(st.mat[which][top + 1], st.mat[which][top], 16 * sizeof(float));
105 st.mtop[which] = top + 1;;
108 void g3d_pop_matrix(int which)
110 if(st.mtop[which] <= 0) {
111 fprintf(stderr, "g3d_pop_matrix underflow\n");
117 void g3d_translate(int which, float x, float y, float z)
119 float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
123 g3d_mult_matrix(which, m);
126 void g3d_rotate(int which, float deg, float x, float y, float z)
128 float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
130 float angle = M_PI * deg / 180.0f;
131 float sina = sin(angle);
132 float cosa = cos(angle);
133 float one_minus_cosa = 1.0f - cosa;
138 m[0] = nxsq + (1.0f - nxsq) * cosa;
139 m[4] = x * y * one_minus_cosa - z * sina;
140 m[8] = x * z * one_minus_cosa + y * sina;
141 m[1] = x * y * one_minus_cosa + z * sina;
142 m[5] = nysq + (1.0 - nysq) * cosa;
143 m[9] = y * z * one_minus_cosa - x * sina;
144 m[2] = x * z * one_minus_cosa - y * sina;
145 m[6] = y * z * one_minus_cosa + x * sina;
146 m[10] = nzsq + (1.0 - nzsq) * cosa;
148 g3d_mult_matrix(which, m);
151 void g3d_scale(int which, float x, float y, float z)
153 float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
157 g3d_mult_matrix(which, m);
160 void g3d_ortho(int which, float left, float right, float bottom, float top, float znear, float zfar)
162 float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
164 float dx = right - left;
165 float dy = top - bottom;
166 float dz = zfar - znear;
171 m[12] = -(right + left) / dx;
172 m[13] = -(top + bottom) / dy;
173 m[14] = -(zfar + znear) / dz;
175 g3d_mult_matrix(which, m);
178 void g3d_frustum(int which, float left, float right, float bottom, float top, float nr, float fr)
180 float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
182 float dx = right - left;
183 float dy = top - bottom;
186 float a = (right + left) / dx;
187 float b = (top + bottom) / dy;
188 float c = -(fr + nr) / dz;
189 float d = -2.0 * fr * nr / dz;
191 m[0] = 2.0 * nr / dx;
192 m[5] = 2.0 * nr / dy;
199 g3d_mult_matrix(which, m);
202 void g3d_perspective(int which, float vfov_deg, float aspect, float znear, float zfar)
204 float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
206 float vfov = M_PI * vfov_deg / 180.0f;
207 float s = 1.0f / tan(vfov * 0.5f);
208 float range = znear - zfar;
212 m[10] = (znear + zfar) / range;
214 m[14] = 2.0f * znear * zfar / range;
216 g3d_mult_matrix(which, m);
219 void g3d_draw(int prim, int space, const struct g3d_vertex *varr, int varr_size)
222 int vnum = prim; /* primitive vertex counts correspond to the enum values */
224 while(varr_size >= vnum) {
225 struct pvertex pv[4];
227 for(i=0; i<vnum; i++) {
228 proc_vertex(pv + i, varr++, space);
231 polyfill_wire(pv, vnum);
237 static void xform4_vec3(const float *mat, float *vec)
239 float x = mat[0] * vec[0] + mat[4] * vec[1] + mat[8] * vec[2] + mat[12];
240 float y = mat[1] * vec[0] + mat[5] * vec[1] + mat[9] * vec[2] + mat[13];
241 float z = mat[2] * vec[0] + mat[6] * vec[1] + mat[10] * vec[2] + mat[14];
242 float w = mat[3] * vec[0] + mat[7] * vec[1] + mat[11] * vec[2] + mat[15];
250 static void xform3_vec3(const float *mat, float *vec)
252 float x = mat[0] * vec[0] + mat[4] * vec[1] + mat[8] * vec[2];
253 float y = mat[1] * vec[0] + mat[5] * vec[1] + mat[9] * vec[2];
254 float z = mat[2] * vec[0] + mat[6] * vec[1] + mat[10] * vec[2];
261 #define VEC3(v, x, y, z) do { v[0] = x; v[1] = y; v[2] = z; } while(0)
262 #define VEC4(v, x, y, z, w) do { v[0] = x; v[1] = y; v[2] = z; v[3] = w; } while(0)
264 static void proc_vertex(struct pvertex *res, const struct g3d_vertex *vert, int space)
269 int mvtop = st.mtop[G3D_MODELVIEW];
270 int ptop = st.mtop[G3D_PROJECTION];
273 VEC4(pos, vert->x, vert->y, vert->z, 1.0f);
274 VEC3(norm, vert->nx, vert->ny, vert->nz);
277 case G3D_LOCAL_SPACE:
278 memcpy(norm_mat, st.mat[G3D_MODELVIEW][mvtop], 16 * sizeof(float));
279 norm_mat[12] = norm_mat[13] = norm_mat[14] = 0.0f;
281 xform4_vec3(pos, st.mat[G3D_MODELVIEW][mvtop]);
282 xform3_vec3(norm, norm_mat);
285 if(st.opt & G3D_LIGHTING) {
291 xform4_vec3(pos, st.mat[G3D_PROJECTION][ptop]);
301 case G3D_SCREEN_SPACE:
302 pos[0] = (pos[0] * 0.5 + 0.5) * (float)st.width;
303 pos[1] = (0.5 - pos[0] * 0.5) * (float)st.height;
305 case G3D_PIXEL_SPACE:
309 /* convert pos to 24.8 fixed point */
310 res->x = (int32_t)(pos[0] * 256.0f);
311 res->y = (int32_t)(pos[1] * 256.0f);
313 /* convert tex coords to 16.16 fixed point */
314 res->u = (int32_t)(vert->u * 65536.0f);
315 res->v = (int32_t)(vert->v * 65536.0f);
317 /* pass color through as is */