porting back some changes from the GBA version
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 7 Nov 2022 23:39:22 +0000 (01:39 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 7 Nov 2022 23:39:22 +0000 (01:39 +0200)
src/main.c
src/voxscape.c
src/voxscape.h

index daa03bf..bbe64fd 100644 (file)
@@ -37,7 +37,8 @@ int mouse_x, mouse_y, mwarp, mbstate[3];
 int hfilt = VOX_LINEAR, cfilt = VOX_LINEAR;
 
 unsigned int input;
-int32_t pos[2], angle;
+int32_t pos[2], theta, phi;
+int horizon;
 
 struct voxscape *vox;
 
@@ -80,8 +81,8 @@ int init(void)
        if(!(vox = vox_open("data/height.png", "data/color.png"))) {
                return -1;
        }
-       vox_framebuf(vox, FB_W, FB_H, fb, -1);
-       vox_proj(vox, 45, 1, 300);
+       vox_framebuf(vox, FB_W, FB_H, fb);
+       vox_proj(vox, 140, 45, 1, 300);
        vox_fog(vox, 260, COLOR_HORIZON);
        vox_filter(vox, hfilt, cfilt);
 
@@ -101,11 +102,11 @@ void update(void)
 {
        int32_t fwd[2], right[2];
 
-       if(input & INP_LTURN) angle += TURN_SPEED;
-       if(input & INP_RTURN) angle -= TURN_SPEED;
+       if(input & INP_LTURN) theta += TURN_SPEED;
+       if(input & INP_RTURN) theta -= TURN_SPEED;
 
-       fwd[0] = -SIN(angle);
-       fwd[1] = COS(angle);
+       fwd[0] = -SIN(theta);
+       fwd[1] = COS(theta);
        right[0] = fwd[1];
        right[1] = -fwd[0];
 
@@ -126,7 +127,7 @@ void update(void)
                pos[1] -= right[1];
        }
 
-       vox_view(vox, pos[0], pos[1], -30, angle);
+       vox_view(vox, pos[0], pos[1], -30, theta, phi);
 }
 
 void display(void)
@@ -263,6 +264,9 @@ void motion(int x, int y)
        if(!(dx | dy)) return;
 
        if(mbstate[0]) {
-               angle -= dx << 6;
+               theta -= dx << 6;
+               phi += dy << 8;
+               if(phi < -0x18000) phi = -0x18000;
+               if(phi > 0x18000) phi = 0x18000;
        }
 }
index 54c0b10..c10b170 100644 (file)
@@ -27,6 +27,8 @@ struct voxscape {
 
        int hfilt, cfilt;
 
+       int hscale;
+
        /* framebuffer */
        uint32_t *fb;
        int fbwidth, fbheight;
@@ -41,7 +43,7 @@ struct voxscape {
        int fov, znear, zfar;
        int nslices;
        int32_t *slicelen;
-       int proj_dist;
+       int *projlut;
 
        int zfog;       /* fog start Z (0: no fog) */
        int fogcolor[3];
@@ -80,7 +82,7 @@ struct voxscape *vox_create(int xsz, int ysz)
        }
 
        vox->vheight = 80;
-       vox->proj_dist = 4;     /* TODO */
+       vox->hscale = 140;
 
        return vox;
 }
@@ -205,7 +207,7 @@ void vox_filter(struct voxscape *vox, int hfilt, int cfilt)
        vox->cfilt = cfilt;
 }
 
-void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb, int horizon)
+void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb)
 {
        if(xres != vox->fbwidth) {
                free(vox->coltop);
@@ -217,10 +219,9 @@ void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb, int ho
        vox->fb = fb;
        vox->fbwidth = xres;
        vox->fbheight = yres;
-       vox->horizon = horizon >= 0 ? horizon : vox->fbheight / 2;
 }
 
-void vox_view(struct voxscape *vox, int32_t x, int32_t y, int h, int32_t angle)
+void vox_view(struct voxscape *vox, int32_t x, int32_t y, int h, int32_t angle, int32_t vangle)
 {
        if(h < 0) {
                h = vox_height(vox, x, y) - h;
@@ -231,14 +232,17 @@ void vox_view(struct voxscape *vox, int32_t x, int32_t y, int h, int32_t angle)
        vox->vheight = h;
        vox->angle = angle;
 
+       vox->horizon = (vox->fbheight * ((vangle + 0x10000) >> 1)) >> 16;
+
        vox->valid &= ~SLICELEN;
 }
 
-void vox_proj(struct voxscape *vox, int fov, int znear, int zfar)
+void vox_proj(struct voxscape *vox, int hscale, int fov, int znear, int zfar)
 {
        vox->fov = fov;
        vox->znear = znear;
        vox->zfar = zfar;
+       vox->hscale = hscale;
 
        vox->nslices = vox->zfar - vox->znear;
        free(vox->slicelen);
@@ -246,6 +250,12 @@ void vox_proj(struct voxscape *vox, int fov, int znear, int zfar)
                fprintf(stderr, "vox_proj: failed to allocate slice length table (%d)\n", vox->nslices);
                return;
        }
+       free(vox->projlut);
+       if(!(vox->projlut = malloc(vox->nslices * sizeof *vox->projlut))) {
+               fprintf(stderr, "vox_proj: failed to allocate projection table (%d)\n", vox->nslices);
+               free(vox->slicelen);
+               return;
+       }
 
        vox->valid &= ~SLICELEN;
 }
@@ -276,6 +286,7 @@ void vox_begin(struct voxscape *vox)
                float theta = (float)vox->fov * M_PI / 360.0f;  /* half angle */
                for(i=0; i<vox->nslices; i++) {
                        vox->slicelen[i] = (int32_t)((vox->znear + i) * tan(theta) * 4.0f * 65536.0f);
+                       vox->projlut[i] = (vox->hscale << 8) / (vox->znear + i);
                }
                vox->valid |= SLICELEN;
        }
@@ -304,7 +315,7 @@ void vox_render_slice(struct voxscape *vox, int n)
        y = vox->y + COS(vox->angle) * z - ystep * (vox->fbwidth >> 1);
        for(i=0; i<vox->fbwidth; i++) {
                hval = vox_height(vox, x, y) - vox->vheight;
-               hval = hval * 160 / (vox->znear + n) + vox->horizon;
+               hval = ((hval * vox->projlut[n]) >> 8) + vox->horizon;
                if(hval > vox->fbheight) hval = vox->fbheight;
                if(hval > vox->coltop[i]) {
                        color = vox_color(vox, x, y);
@@ -360,6 +371,7 @@ void vox_sky_grad(struct voxscape *vox, uint32_t chor, uint32_t ctop)
        r1 = chor & 0xff;
 
        for(i=0; i<d; i++) {
+               if(i >= vox->fbheight) break;
                t = (i << 16) / d;
                grad[i] = lerp_rgb(r0, g0, b0, r1, g1, b1, t);
        }
index 0602831..98d9bf3 100644 (file)
@@ -22,10 +22,10 @@ int vox_height(struct voxscape *vox, int32_t x, int32_t y);
 
 void vox_filter(struct voxscape *vox, int hfilt, int cfilt);
 
-void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb, int horizon);
+void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb);
 /* negative height for auto at -h above terrain */
-void vox_view(struct voxscape *vox, int32_t x, int32_t y, int h, int32_t angle);
-void vox_proj(struct voxscape *vox, int fov, int znear, int zfar);
+void vox_view(struct voxscape *vox, int32_t x, int32_t y, int h, int32_t angle, int32_t vangle);
+void vox_proj(struct voxscape *vox, int hscale, int fov, int znear, int zfar);
 
 void vox_render(struct voxscape *vox);