int hfilt, cfilt;
+ int hscale;
+
/* framebuffer */
uint32_t *fb;
int fbwidth, fbheight;
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];
}
vox->vheight = 80;
- vox->proj_dist = 4; /* TODO */
+ vox->hscale = 140;
return vox;
}
memcpy(vox->height, hpix, width * height);
+ /* swap r/b and discard alpha while copying */
for(i=0; i<width*height; i++) {
- vox->color[i] = cpix[i] & 0xffffff; /* discard alpha */
+ vox->color[i] = (cpix[i] & 0xff00) | ((cpix[i] & 0xff) << 16) |
+ ((cpix[i] & 0xff0000) >> 16);
}
img_free_pixels(hpix);
{
vox->zfog = zstart;
- vox->fogcolor[0] = color >> 16;
+ vox->fogcolor[2] = color >> 16;
vox->fogcolor[1] = (color >> 8) & 0xff;
- vox->fogcolor[2] = color & 0xff;
+ vox->fogcolor[0] = color & 0xff;
}
#define H(x, y) \
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);
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;
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);
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;
}
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;
}
uint32_t *fbptr;
if(vox->zfog > 0 && n > vox->zfog) {
- fog = ((n - vox->zfog) << 8) / (vox->zfar - vox->zfog);
+ fog = ((n - vox->zfog) << 16) / (vox->zfar - vox->zfog);
} else {
fog = 0;
}
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);
grad = alloca(vox->fbheight * sizeof *grad);
- r0 = ctop >> 16;
+ b0 = ctop >> 16;
g0 = (ctop >> 8) & 0xff;
- b0 = ctop & 0xff;
- r1 = chor >> 16;
+ r0 = ctop & 0xff;
+ b1 = chor >> 16;
g1 = (chor >> 8) & 0xff;
- b1 = chor & 0xff;
+ 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);
}
int r = XLERP(r0, r1, t, 16);
int g = XLERP(g0, g1, t, 16);
int b = XLERP(b0, b1, t, 16);
- return (r << 16) | (g << 8) | b;
+ return (b << 16) | (g << 8) | r;
}
static uint32_t lerp_color(uint32_t ca, uint32_t cb, int32_t t)
{
int r0, g0, b0, r1, g1, b1;
- r0 = ca >> 16;
+ b0 = ca >> 16;
g0 = (ca >> 8) & 0xff;
- b0 = ca & 0xff;
- r1 = cb >> 16;
+ r0 = ca & 0xff;
+ b1 = cb >> 16;
g1 = (cb >> 8) & 0xff;
- b1 = cb & 0xff;
+ r1 = cb & 0xff;
return lerp_rgb(r0, g0, b0, r1, g1, b1, t);
}
static uint32_t lerp_pcol_rgb(uint32_t pcol, int r, int g, int b, int32_t t)
{
- int r0 = pcol >> 16;
+ int b0 = pcol >> 16;
int g0 = (pcol >> 8) & 0xff;
- int b0 = pcol & 0xff;
+ int r0 = pcol & 0xff;
return lerp_rgb(r0, g0, b0, r, g, b, t);
}