axis gizmo
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 16 Mar 2021 11:52:13 +0000 (13:52 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 16 Mar 2021 11:52:13 +0000 (13:52 +0200)
src/main.c
src/sprites.h
src/xgl.c
src/xgl.h

index 2110b9a..9f42c02 100644 (file)
@@ -32,9 +32,17 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 enum {
        SIDX_DEL0, SIDX_DEL1, SIDX_DEL2,
        SIDX_TIME,
-       SIDX_ICONS_BASE
+       SIDX_ICON_ZOOM,
+       SIDX_ICON_PAN,
+       SIDX_ICON_ORBIT,
+       SIDX_ICON_X,
+       SIDX_ICON_Y,
+       SIDX_ICON_Z,
+       SIDX_DIRTY,
 };
 
+#define SIDX_ICONS_BASE                SIDX_ICON_ZOOM
+
 #define SNAM_START     512
 enum {
        SNAM_DEL0               = SNAM_START,
@@ -45,7 +53,8 @@ enum {
        SNAM_ICON_ORBIT = SNAM_START + 32 * 4 + 24,     /* for tiles down, 24 across */
        SNAM_ICON_X             = SNAM_START + 32 * 8 + 26,
        SNAM_ICON_Y             = SNAM_ICON_X + 2,
-       SNAM_ICON_Z             = SNAM_ICON_Y + 2
+       SNAM_ICON_Z             = SNAM_ICON_Y + 2,
+       SNAM_DIRTY              = SNAM_ICON_ORBIT + 4
 };
 
 #define MENU_HEIGHT            17
@@ -53,6 +62,7 @@ enum {
 #define VP_HEIGHT              (160 - MENU_HEIGHT - TRACK_HEIGHT)
 
 static void handle_keys(void);
+static void upd_rotation(void);
 static void show_msgbox(int en);
 
 extern struct { unsigned char r, g, b; } bgimg_cmap[];
@@ -61,9 +71,11 @@ extern unsigned char bgimg_pixels[];
 static int32_t cam_theta = 0x10000, cam_phi = -0x8000;
 
 static int show_obj = 1, show_del;
+static int32_t rot_matrix[16];
 
 #define AXIS0  0x10000
 #define AXIS1  0x80000
+#define AXIS3  0x2c000
 
 static struct xvertex gridaxes[] = {
        {AXIS0, 0, 0,   0, 0, 0, 92},
@@ -85,13 +97,23 @@ static struct xvertex gridaxes[] = {
        {0, 0, -AXIS1,  0, 0, 0, 93},
 };
 
-#define MAX_SIDX       8
+static struct xvertex small_axes[] = {
+       {0, 0, 0,               0, 0, 0, 92},
+       {AXIS3, 0, 0,   0, 0, 0, 92},
+       {0, 0, 0,               0, 0, 0, 93},
+       {0, 0, AXIS3,   0, 0, 0, 93},
+       {0, 0, 0,               0, 0, 0, 94},
+       {0, AXIS3, 0,   0, 0, 0, 94}
+};
+
+#define MAX_SIDX       16
 static uint16_t oam[4 * MAX_SIDX];
 
 
 int main(void)
 {
        int i;
+       int x, y;
        unsigned int nframes = 0, backbuf;
        uint16_t *cptr;
        unsigned char r, g, b;
@@ -127,14 +149,16 @@ int main(void)
        REG_BLDCNT = BLDCNT_ALPHA | BLDCNT_B_BG2;
        REG_BLDALPHA = 0x040c;
 
-       set_sprite(oam, SIDX_ICONS_BASE, SNAM_ICON_ZOOM, 213, 57, 4, SPR_SZ32);
-       set_sprite(oam, SIDX_ICONS_BASE + 1, SNAM_ICON_PAN, 213, 81, 4, SPR_SZ32);
-       set_sprite(oam, SIDX_ICONS_BASE + 2, SNAM_ICON_ORBIT, 213, 103, 4, SPR_SZ32);
+       set_sprite(oam, SIDX_ICONS_BASE, SNAM_ICON_ZOOM, 213, 57, 4, SPR_SZ32 | SPR_BLEND);
+       set_sprite(oam, SIDX_ICONS_BASE + 1, SNAM_ICON_PAN, 213, 81, 4, SPR_SZ32 | SPR_BLEND);
+       set_sprite(oam, SIDX_ICONS_BASE + 2, SNAM_ICON_ORBIT, 213, 103, 4, SPR_SZ32 | SPR_BLEND);
+       set_sprite(oam, SIDX_DIRTY, SNAM_DIRTY, 192, 9, 4, SPR_SZ16 | SPR_HRECT);
 
        xgl_init();
-       xgl_viewport(0, 0, 240, VP_HEIGHT);
        xgl_enable(XGL_LIGHTING);
 
+       upd_rotation();
+
        key_repeat(75, 75, KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP);
 
        /* every vblank, copy the shadow OAM automatically */
@@ -148,13 +172,12 @@ int main(void)
 
                fb = fbptr[backbuf] + 240 * MENU_HEIGHT;
                polyfill_framebuffer(fb, 240, VP_HEIGHT);
-               //memset(fb, 14, 240 * VP_HEIGHT);
                dma_fill16(3, fb, 0x0e0e, 240 * VP_HEIGHT / 2);
 
+               xgl_viewport(0, 0, 240, VP_HEIGHT);
                xgl_load_identity();
                xgl_translate(0, 0, 8 << 16);
-               xgl_rotate_x(cam_phi);
-               xgl_rotate_y(cam_theta);
+               xgl_mult_matrix(rot_matrix);
 
                if(show_obj) {
                        if(cam_theta < X_PI) {
@@ -186,6 +209,17 @@ int main(void)
                        xgl_draw(XGL_LINES, gridaxes + 8, 8);
                }
 
+               /* small axes */
+               xgl_viewport(176, 2, 64, 32);
+               xgl_draw(XGL_LINES, small_axes, 6);
+
+               xgl_transform(small_axes + 5, &x, &y);
+               set_sprite(oam, SIDX_ICONS_BASE + 3, SNAM_ICON_Z, x - 8, y + 8, 3, SPR_SZ16);
+               xgl_transform(small_axes + 1, &x, &y);
+               set_sprite(oam, SIDX_ICONS_BASE + 4, SNAM_ICON_X, x - 8, y + 8, 1, SPR_SZ16);
+               xgl_transform(small_axes + 3, &x, &y);
+               set_sprite(oam, SIDX_ICONS_BASE + 5, SNAM_ICON_Y, x - 8, y + 8, 2, SPR_SZ16);
+
                wait_vblank();
                present(backbuf);
                dma_copy16(3, (void*)OAM_ADDR, oam, sizeof oam / 2, 0);
@@ -201,18 +235,22 @@ static void handle_keys(void)
        if(KEYPRESS(KEY_UP)) {
                cam_phi += 0x2000;
                if(cam_phi > X_HPI) cam_phi = X_HPI;
+               upd_rotation();
        }
        if(KEYPRESS(KEY_DOWN)) {
                cam_phi -= 0x2000;
                if(cam_phi < -X_HPI) cam_phi = -X_HPI;
+               upd_rotation();
        }
        if(KEYPRESS(KEY_LEFT)) {
                cam_theta += 0x2000;
                if(cam_theta > X_2PI) cam_theta -= X_2PI;
+               upd_rotation();
        }
        if(KEYPRESS(KEY_RIGHT)) {
                cam_theta -= 0x2000;
                if(cam_theta < 0) cam_theta += X_2PI;
+               upd_rotation();
        }
        if(KEYPRESS(KEY_RT)) {
                if(++show_obj > 2) show_obj = 0;
@@ -238,6 +276,14 @@ static void handle_keys(void)
        }
 }
 
+static void upd_rotation(void)
+{
+       xgl_load_identity();
+       xgl_rotate_x(cam_phi);
+       xgl_rotate_y(cam_theta);
+       xgl_get_matrix(rot_matrix);
+}
+
 static void show_msgbox(int en)
 {
        int i;
index 3712aba..f1b9b30 100644 (file)
@@ -36,6 +36,7 @@ enum {
        SPR_SZ32        = 0x800000,
        SPR_SZ64        = 0xc00000
 };
+#define SPR_SZ8                0
 #define SPR_ROTSCL_PARAM(x)    ((unsigned int)(x) << 17)
 #define SPR_PRIO(x)                    ((unsigned int)(x) & 3)
 
index 4880aba..2632473 100644 (file)
--- a/src/xgl.c
+++ b/src/xgl.c
@@ -74,7 +74,7 @@ void xgl_pop_matrix(void)
        if(mtop > 0) mtop--;
 }
 
-static const int32_t id[] = {
+static int32_t id[] = {
        0x10000, 0, 0, 0,
        0, 0x10000, 0, 0,
        0, 0, 0x10000, 0,
@@ -83,7 +83,7 @@ static const int32_t id[] = {
 
 void xgl_load_identity(void)
 {
-       xgl_load_matrix(id);
+       memcpy(mat[mtop], id, sizeof mat[0]);
 }
 
 void xgl_load_matrix(const int32_t *m)
@@ -91,6 +91,11 @@ void xgl_load_matrix(const int32_t *m)
        memcpy(mat[mtop], m, sizeof mat[0]);
 }
 
+void xgl_get_matrix(int32_t *m)
+{
+       memcpy(m, mat[mtop], sizeof mat[0]);
+}
+
 #define M(i,j) (((i) << 2) + (j))
 #define XMUL(a, b)     (((a) >> 8) * ((b) >> 8))
 void xgl_mult_matrix(const int32_t *m2)
@@ -243,6 +248,19 @@ void xgl_draw(int prim, const struct xvertex *varr, int vcount)
        }
 }
 
+void xgl_transform(const struct xvertex *vin, int *x, int *y)
+{
+       struct xvertex v;
+       xform(&v, vin, mat[mtop]);
+
+       v.x = (v.x << 1) / (v.z >> 8);  /* assume aspect: ~2 */
+       v.y = (v.y << 2) / (v.z >> 8);  /* the shift is * PROJ_D */
+       /* projection result is 24.8 */
+       /* viewport */
+       *x = ((((v.x + 0x100) >> 1) * vp[2]) >> 8) + vp[0];
+       *y = ((((0x100 - v.y) >> 1) * vp[3]) >> 8) + vp[1];
+}
+
 static void draw_ptlines(int prim, const struct xvertex *varr, int vcount)
 {
        int i;
index c15231e..6076073 100644 (file)
--- a/src/xgl.h
+++ b/src/xgl.h
@@ -51,6 +51,7 @@ void xgl_push_matrix(void);
 void xgl_pop_matrix(void);
 void xgl_load_identity(void);
 void xgl_load_matrix(const int32_t *m);
+void xgl_get_matrix(int32_t *m);
 void xgl_mult_matrix(const int32_t *m);
 
 void xgl_translate(int32_t x, int32_t y, int32_t z);
@@ -60,5 +61,6 @@ void xgl_rotate_z(int32_t angle);
 void xgl_scale(int32_t x, int32_t y, int32_t z);
 
 void xgl_draw(int prim, const struct xvertex *varr, int vcount);
+void xgl_transform(const struct xvertex *vin, int *x, int *y);
 
 #endif /* XGL_H_ */