From: John Tsiombikas Date: Sun, 9 Apr 2017 11:55:30 +0000 (+0300) Subject: half-assed 3D graphics attempt underway X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=regis;a=commitdiff_plain;h=4ac276ea513d4460f9db8c43b4dbde5ebad652b5 half-assed 3D graphics attempt underway --- diff --git a/Makefile b/Makefile index 33323b6..6352238 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ src = $(wildcard *.c) obj = $(src:.c=.o) bin = regis_test -CFLAGS = -pedantic -Wall -g +CFLAGS = -pedantic -Wall -g -DWIDTH=480 -DHEIGHT=480 LDFLAGS = -lm $(bin): $(obj) diff --git a/fixed.h b/fixed.h new file mode 100644 index 0000000..dbc8bbe --- /dev/null +++ b/fixed.h @@ -0,0 +1,18 @@ +#ifndef FIXED_H_ +#define FIXED_H_ + +#include + +#define ftox16(x) (int32_t)((x) * 65536.0f) +#define itox16(x) (int32_t)((x) << 16) + +#define x16tof(x) (float)((x) / 65536.0f) +#define x16toi(x) ((x) >> 16) + +#define x16mul(a, b) (int32_t)(((int32_t)(a) >> 8) * ((int32_t)(b) >> 8)) +/*int32_t x16div(register int32_t num, register int32_t denom);*/ +#define x16div(a, b) (int32_t)(((int64_t)(a) << 16) / (b)) + +#define x16sq(x) x16mul(x, x) + +#endif /* FIXED_H_ */ diff --git a/sincos.c b/sincos.c new file mode 100644 index 0000000..6ca93ce --- /dev/null +++ b/sincos.c @@ -0,0 +1,85 @@ +#include +#include +#include "fixed.h" +#include "sincos.h" + +int16_t sinlut[SINLUT_SIZE] = { + 0, 6, 12, 18, 25, 31, 37, 43, 50, 56, 62, 68, 75, 81, 87, 93, + 99, 106, 112, 118, 124, 130, 136, 142, 148, 154, 160, 166, 172, 178, 184, 190, + 195, 201, 207, 213, 218, 224, 230, 235, 241, 246, 252, 257, 263, 268, 273, 279, + 284, 289, 294, 299, 304, 310, 314, 319, 324, 329, 334, 339, 343, 348, 353, 357, + 362, 366, 370, 375, 379, 383, 387, 391, 395, 399, 403, 407, 411, 414, 418, 422, + 425, 429, 432, 435, 439, 442, 445, 448, 451, 454, 457, 460, 462, 465, 468, 470, + 473, 475, 477, 479, 482, 484, 486, 488, 489, 491, 493, 495, 496, 498, 499, 500, + 502, 503, 504, 505, 506, 507, 508, 508, 509, 510, 510, 511, 511, 511, 511, 511, + 512, 511, 511, 511, 511, 511, 510, 510, 509, 508, 508, 507, 506, 505, 504, 503, + 502, 500, 499, 498, 496, 495, 493, 491, 489, 488, 486, 484, 482, 479, 477, 475, + 473, 470, 468, 465, 462, 460, 457, 454, 451, 448, 445, 442, 439, 435, 432, 429, + 425, 422, 418, 414, 411, 407, 403, 399, 395, 391, 387, 383, 379, 375, 370, 366, + 362, 357, 353, 348, 343, 339, 334, 329, 324, 319, 314, 310, 304, 299, 294, 289, + 284, 279, 273, 268, 263, 257, 252, 246, 241, 235, 230, 224, 218, 213, 207, 201, + 195, 190, 184, 178, 172, 166, 160, 154, 148, 142, 136, 130, 124, 118, 112, 106, + 99, 93, 87, 81, 75, 68, 62, 56, 50, 43, 37, 31, 25, 18, 12, 6, + 0, -6, -12, -18, -25, -31, -37, -43, -50, -56, -62, -68, -75, -81, -87, -93, + -99, -106, -112, -118, -124, -130, -136, -142, -148, -154, -160, -166, -172, -178, -184, -190, + -195, -201, -207, -213, -218, -224, -230, -235, -241, -246, -252, -257, -263, -268, -273, -279, + -284, -289, -294, -299, -304, -310, -314, -319, -324, -329, -334, -339, -343, -348, -353, -357, + -362, -366, -370, -375, -379, -383, -387, -391, -395, -399, -403, -407, -411, -414, -418, -422, + -425, -429, -432, -435, -439, -442, -445, -448, -451, -454, -457, -460, -462, -465, -468, -470, + -473, -475, -477, -479, -482, -484, -486, -488, -489, -491, -493, -495, -496, -498, -499, -500, + -502, -503, -504, -505, -506, -507, -508, -508, -509, -510, -510, -511, -511, -511, -511, -511, + -512, -511, -511, -511, -511, -511, -510, -510, -509, -508, -508, -507, -506, -505, -504, -503, + -502, -500, -499, -498, -496, -495, -493, -491, -489, -488, -486, -484, -482, -479, -477, -475, + -473, -470, -468, -465, -462, -460, -457, -454, -451, -448, -445, -442, -439, -435, -432, -429, + -425, -422, -418, -414, -411, -407, -403, -399, -395, -391, -387, -383, -379, -375, -370, -366, + -362, -357, -353, -348, -343, -339, -334, -329, -324, -319, -314, -310, -304, -299, -294, -289, + -284, -279, -273, -268, -263, -257, -252, -246, -241, -235, -230, -224, -218, -213, -207, -201, + -195, -190, -184, -178, -172, -166, -160, -154, -148, -142, -136, -130, -124, -118, -112, -106, + -99, -93, -87, -81, -75, -68, -62, -56, -50, -43, -37, -31, -25, -18, -12, -6 +}; + +void sincos_init(void) +{ + int i; + + printf("int16_t sinlut[SINLUT_SIZE] = {"); + + for(i=0; i> 16) << 16) / SINLUT_SCALE; +} + +int32_t cos_x16(int32_t radians) +{ + int32_t na = x16div(radians, M_PI_X16 * 2); + return (cos_int((na * SINLUT_SIZE) >> 16) << 16) / SINLUT_SCALE; +} diff --git a/sincos.h b/sincos.h new file mode 100644 index 0000000..82d7c5e --- /dev/null +++ b/sincos.h @@ -0,0 +1,27 @@ +#ifndef SINCOS_H_ +#define SINCOS_H_ + +#include + +/*#define M_PI_X16 (int32_t)(M_PI * 65536.0) */ +#define M_PI_X16 (int32_t)((31416 << 16) / 10000) + +#define SINLUT_SCALE 512 +#define SINLUT_SIZE 512 +int16_t sinlut[SINLUT_SIZE]; + +void sincos_init(void); + +/* takes angle in [0, SINLUT_SIZE] and returns: + * sin(2 * angle / SINLUT_SIZE / pi) * SINLUT_SCALE + */ +int16_t sin_int(int16_t norm_angle); +int16_t cos_int(int16_t norm_angle); + +/* takes angle in fixed point 16.16 radians [0, 2pi << 16] + * and returns 16.16 fixed point in [-1 << 16, 1 << 16] + */ +int32_t sin_x16(int32_t radians); +int32_t cos_x16(int32_t radians); + +#endif /* SINCOS_H_ */ diff --git a/test.c b/test.c index c134b3f..72b6029 100644 --- a/test.c +++ b/test.c @@ -3,35 +3,38 @@ #include #include #include "regis.h" +#include "sincos.h" +#include "x3d.h" +#define X16INT(x) ((x) << 16) + +static void draw(void); static void sig(int s); static volatile int done; +int tm = 0; int main(int argc, char **argv) { int pg = 1; - float tm = 0.0f; signal(SIGINT, sig); + x3d_projection(45.0, (WIDTH << 16) / HEIGHT, 65536 / 2, 65536 * 500); + while(!done) { - float dx = cos(tm) * 50.0; - float dy = sin(tm * 2.0) * 50.0; - tm += 0.01f; regis_enter(); regis_draw_page(pg); regis_clear(); - regis_abspos(100 + dx, 100 + dy); - regis_begin_vector(REGIS_BOUNDED | REGIS_FILL); - regis_absv(300 + dx, 300 + dy); - regis_absv(80 + dx, 400 + dy); - regis_end_vector(); + + draw(); + regis_show_page(pg); pg = (pg + 1) & 1; regis_leave(); usleep(10000); + ++tm; } regis_enter(); @@ -40,6 +43,17 @@ int main(int argc, char **argv) return 0; } +static void draw(void) +{ + x3d_load_identity(); + x3d_translate(0, 0, X16INT(6)); + x3d_rotate(X16INT(25), 65536, 0, 0); + x3d_rotate(tm << 10, 0, 65536, 0); + + x3d_color_index(3); + +} + static void sig(int s) { done = 1; diff --git a/x3d.c b/x3d.c new file mode 100644 index 0000000..53faa9b --- /dev/null +++ b/x3d.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include "x3d.h" +#include "fixed.h" +#include "sincos.h" +#include "regis.h" + +typedef struct pvec3 { + int32_t x, y, z; +} pvec3; + +typedef struct pvec2 { + int32_t x, y; +} pvec2; + + +#define MAT_STACK_SIZE 4 + +struct matrix { + int32_t m[12]; +}; + +static void proc_vertex(const int32_t *vin, pvec3 *vout); + +void draw_poly(int num, const pvec3 *verts, int color); +void draw_point(const pvec3 *v, int color); + + +static int32_t proj_fov = M_PI_X16; +static int32_t proj_aspect = 65536; +static int32_t inv_proj_aspect = 65536; +static int32_t proj_near = ftox16(0.5); +static int32_t proj_far = 500 << 16; +static int32_t inv_tan_half_xfov, inv_tan_half_yfov; + +#define ID_INIT {65536, 0, 0, 0, 0, 65536, 0, 0, 0, 0, 65536, 0} + +static struct matrix identity = { ID_INIT }; + +static short mtop; +static struct matrix mstack[MAT_STACK_SIZE] = { {ID_INIT}, {ID_INIT} }; + +static const int32_t *vertex_array; +static unsigned short vertex_count; + +static uint8_t im_color_index; + + +void x3d_projection(int fov, int32_t aspect, int32_t nearz, int32_t farz) +{ + proj_fov = (M_PI_X16 * fov) / 180; + proj_aspect = aspect; + inv_proj_aspect = x16div(65536, proj_aspect); + proj_near = nearz; + proj_far = farz; + + inv_tan_half_yfov = (int32_t)(65536.0 / tan(0.5 * proj_fov / 65536.0)); + inv_tan_half_xfov = x16mul(inv_tan_half_yfov, aspect); +} + +int x3d_push_matrix(void) +{ + short newtop = mtop + 1; + if(newtop >= MAT_STACK_SIZE) { + return -1; + } + memcpy(mstack + newtop, mstack + mtop, sizeof *mstack); + mtop = newtop; + return 0; +} + +int x3d_pop_matrix(void) +{ + if(mtop <= 0) { + return -1; + } + --mtop; + return 0; +} + +void x3d_load_matrix(int32_t *m) +{ + memcpy(mstack[mtop].m, m, sizeof *mstack); +} + + +#define M(i,j) (((i) << 2) + (j)) +void x3d_mult_matrix(int32_t *m) +{ + int i, j; + struct matrix tmp; + + memcpy(tmp.m, mstack[mtop].m, sizeof tmp); + + for(i=0; i<3; i++) { + for(j=0; j<4; j++) { + mstack[mtop].m[M(i, j)] = + x16mul(m[M(0, j)], tmp.m[M(i, 0)]) + + x16mul(m[M(1, j)], tmp.m[M(i, 1)]) + + x16mul(m[M(2, j)], tmp.m[M(i, 2)]); + } + mstack[mtop].m[M(i, 3)] += tmp.m[M(i, 3)]; + } +} + +void x3d_load_identity(void) +{ + memcpy(mstack[mtop].m, identity.m, sizeof identity); +} + +void x3d_translate(int32_t x, int32_t y, int32_t z) +{ + int32_t m[] = ID_INIT; + m[3] = x; + m[7] = y; + m[11] = z; + + x3d_mult_matrix(m); +} + +void x3d_rotate(int32_t deg, int32_t x, int32_t y, int32_t z) +{ + int32_t xform[] = ID_INIT; + + int32_t angle = x16mul(M_PI_X16, deg) / 180; + int32_t sina = sin_x16(angle); + int32_t cosa = cos_x16(angle); + int32_t one_minus_cosa = 65536 - cosa; + int32_t nxsq = x16sq(x); + int32_t nysq = x16sq(y); + int32_t nzsq = x16sq(z); + + xform[0] = nxsq + x16mul(65536 - nxsq, cosa); + xform[4] = x16mul(x16mul(x, y), one_minus_cosa) - x16mul(z, sina); + xform[8] = x16mul(x16mul(x, z), one_minus_cosa) + x16mul(y, sina); + xform[1] = x16mul(x16mul(x, y), one_minus_cosa) + x16mul(z, sina); + xform[5] = nysq + x16mul(65536 - nysq, cosa); + xform[9] = x16mul(x16mul(y, z), one_minus_cosa) - x16mul(x, sina); + xform[2] = x16mul(x16mul(x, z), one_minus_cosa) - x16mul(y, sina); + xform[6] = x16mul(x16mul(y, z), one_minus_cosa) + x16mul(x, sina); + xform[10] = nzsq + x16mul(65536 - nzsq, cosa); + + x3d_mult_matrix(xform); +} + +void x3d_scale(int32_t x, int32_t y, int32_t z) +{ + int32_t m[] = ID_INIT; + + m[0] = x; + m[5] = y; + m[10] = z; + + x3d_mult_matrix(m); +} + +void x3d_vertex_array(int count, const int32_t *ptr) +{ + vertex_array = ptr; + vertex_count = count; +} + +int x3d_draw(int prim, int vnum) +{ + int i, j, pverts = prim; + const int32_t *vptr = vertex_array; + uint16_t color; + + if(!vertex_array) return -1; + + if(vnum > vertex_count) { + vnum = vertex_count; + } + + for(i=0; ix = tvert[0]; + vout->y = tvert[1]; + vout->z = tvert[2]; +} + +void x3d_color_index(int cidx) +{ + im_color_index = cidx; +} + + +void draw_poly(int num, const pvec3 *verts, int color) +{ + int i; + regis_abspos(verts[0].x, verts[0].y); + regis_begin_vector(REGIS_BOUNDED); + + for(i=0; ix, verts->y); + } + regis_end_vector(); +} + +void draw_point(const pvec3 *v, int color) +{ +} diff --git a/x3d.h b/x3d.h new file mode 100644 index 0000000..2b5ac2b --- /dev/null +++ b/x3d.h @@ -0,0 +1,31 @@ +#ifndef X3D_H_ +#define X3D_H_ + +#include + +enum { + X3D_POINTS = 1, + X3D_LINES = 2, + X3D_TRIANGLES = 3, + X3D_QUADS = 4 +}; + +void x3d_projection(int fov, int32_t aspect, int32_t nearz, int32_t farz); + +int x3d_push_matrix(void); +int x3d_pop_matrix(void); +void x3d_load_matrix(int32_t *m); +void x3d_mult_matrix(int32_t *m); +void x3d_load_identity(void); +void x3d_translate(int32_t x, int32_t y, int32_t z); +void x3d_rotate(int32_t angle, int32_t x, int32_t y, int32_t z); +void x3d_scale(int32_t x, int32_t y, int32_t z); + +void x3d_vertex_array(int count, const int32_t *ptr); + +int x3d_draw(int prim, int vnum); +int x3d_draw_indexed(int prim, int count, uint16_t *ptr); + +void x3d_color_index(int cidx); + +#endif /* X3D_H_ */