15 unsigned char *height;
20 int fbwidth, fbheight;
29 int32_t *slicelen; /* 24.8 */
34 struct voxscape *vox_create(int xsz, int ysz)
38 if(!(vox = calloc(1, sizeof *vox))) {
41 if(!(vox->height = calloc(1, xsz * ysz))) {
42 fprintf(stderr, "vox_create: failed to allocate %dx%d heightmap\n", xsz, ysz);
46 if(!(vox->color = calloc(xsz * ysz, sizeof *vox->color))) {
47 fprintf(stderr, "vox_create: failed to allocate %dx%d color map\n", xsz, ysz);
58 struct voxscape *vox_open(const char *hfile, const char *cfile)
62 int width, height, cwidth, cheight;
65 if(!(hpix = img_load_pixels(hfile, &width, &height, IMG_FMT_GREY8))) {
66 fprintf(stderr, "vox_open: failed to load heightmap: %s\n", hfile);
69 if(!(cpix = img_load_pixels(cfile, &cwidth, &cheight, IMG_FMT_RGBA32))) {
70 fprintf(stderr, "vox_open: failed to load color map: %s\n", cfile);
71 img_free_pixels(hpix);
74 if(cwidth != width || cheight != height) {
75 img_free_pixels(hpix);
76 img_free_pixels(cpix);
77 fprintf(stderr, "vox_open: %s and %s have different dimensions\n", hfile, cfile);
81 if(!(vox = vox_create(width, height))) {
82 img_free_pixels(hpix);
83 img_free_pixels(cpix);
86 memcpy(vox->height, hpix, width * height);
87 memcpy(vox->color, cpix, width * height * sizeof *vox->color);
89 img_free_pixels(hpix);
90 img_free_pixels(cpix);
95 void vox_free(struct voxscape *vox)
106 void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb)
108 if(xres != vox->fbwidth) {
110 if(!(vox->coltop = malloc(xres * sizeof *vox->coltop))) {
111 fprintf(stderr, "vox_framebuf: failed to allocate column table (%d)\n", xres);
117 vox->fbheight = yres;
120 void vox_view(struct voxscape *vox, int32_t x, int32_t y, int32_t angle)
125 /* TODO precalc stuff */
130 void vox_proj(struct voxscape *vox, int fov, int znear, int zfar)
138 vox->nslices = vox->zfar - vox->znear;
140 if(!(vox->slicelen = malloc(vox->nslices * sizeof *vox->slicelen))) {
141 fprintf(stderr, "vox_proj: failed to allocate slice length table (%d)\n", vox->nslices);
149 * calculate extents of horizontal equidistant line from the viewer based on fov
150 * for each column step along this line and compute height for each pixel
151 * fill the visible (top) part of each column
154 void vox_render(struct voxscape *vox)
159 for(i=0; i<vox->nslices; i++) {
160 vox_render_slice(vox, i);
164 void vox_begin(struct voxscape *vox)
168 for(i=0; i<vox->fbwidth; i++) {
169 vox->coltop[i] = vox->fbheight;
172 if(!(vox->valid & SLICELEN)) {
173 float theta = (float)vox->angle * M_PI / 360.0f; /* half angle */
174 for(i=0; i<vox->nslices; i++) {
175 vox->slicelen[i] = (int32_t)((vox->znear + i) * tan(theta) * 2.0f * 256.0f)
177 vox->valid |= SLICELEN;
181 void vox_render_slice(struct voxscape *vox, int n)
185 len = vox->slicelen[n];