From 59682b78987c148f793a6d7d7c60280048ca986c Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 13 Oct 2022 04:10:33 +0300 Subject: [PATCH] foo --- Makefile | 2 +- src/glfb.c | 7 ++- src/main.c | 32 +++++----- src/voxscape.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/voxscape.h | 21 +++++++ 5 files changed, 232 insertions(+), 18 deletions(-) create mode 100644 src/voxscape.c create mode 100644 src/voxscape.h diff --git a/Makefile b/Makefile index 816dbac..2859bb3 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ warn = -pedantic -Wall dbg = -g CFLAGS = $(warn) $(opt) $(dbg) -MMD -LDFLAGS = -lGL -lglut -lm +LDFLAGS = -lGL -lglut -lm -limago $(bin): $(obj) $(CC) -o $@ $(obj) $(LDFLAGS) diff --git a/src/glfb.c b/src/glfb.c index c60715d..a939ba6 100644 --- a/src/glfb.c +++ b/src/glfb.c @@ -98,13 +98,16 @@ void glfb_update(void *pixels) void glfb_display(void) { + glClearColor(0.2, 0.2, 0.2, 1); + glClear(GL_COLOR_BUFFER_BIT); + glBegin(GL_TRIANGLES); glTexCoord2f(0, 0); glVertex2f(-1, -1); glTexCoord2f(tex_sx * 2.0f, 0); - glVertex2f(4, -1); + glVertex2f(3, -1); glTexCoord2f(0, tex_sy * 2.0f); - glVertex2f(-1, 4); + glVertex2f(-1, 3); glEnd(); } diff --git a/src/main.c b/src/main.c index a2440af..5569ae6 100644 --- a/src/main.c +++ b/src/main.c @@ -5,8 +5,10 @@ #include #include #include "glfb.h" +#include "voxscape.h" int init(void); +void cleanup(void); void display(void); void idle(void); void reshape(int x, int y); @@ -18,6 +20,8 @@ int win_width, win_height; #define FB_H 480 unsigned int fb[FB_W * FB_H]; +struct voxscape *vox; + int main(int argc, char **argv) { @@ -34,6 +38,7 @@ int main(int argc, char **argv) if(init() == -1) { return 1; } + atexit(cleanup); glutMainLoop(); return 0; @@ -42,29 +47,26 @@ int main(int argc, char **argv) int init(void) { - int i, j, xor, r, g, b; - unsigned int *ptr; - - ptr = fb; - for(i=0; i> 1) & 0xff; - g = xor & 0xff; - b = (xor << 1) & 0xff; - *ptr++ = b | (g << 8) | (r << 16); - } + if(!(vox = vox_open("data/height.png", "data/color.png"))) { + return -1; } - - win_width = glutGet(GLUT_WINDOW_WIDTH); - win_height = glutGet(GLUT_WINDOW_HEIGHT); + vox_framebuf(vox, FB_W, FB_H, fb); + vox_proj(vox, 45, 5, 100); + vox_view(vox, 512, 512, 0); glfb_setup(FB_W, FB_H, GLFB_RGBA32, FB_W * 4); return 0; } +void cleanup(void) +{ + vox_free(vox); +} + void display(void) { + vox_render(vox); + glfb_update(fb); glfb_display(); diff --git a/src/voxscape.c b/src/voxscape.c new file mode 100644 index 0000000..b9a18c3 --- /dev/null +++ b/src/voxscape.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include "voxscape.h" + +enum { + SLICELEN = 1 +}; + +struct voxscape { + int xsz, ysz; + unsigned char *height; + uint32_t *color; + + /* framebuffer */ + uint32_t *fb; + int fbwidth, fbheight; + int *coltop; + + /* view */ + int32_t x, y, angle; + + /* projection */ + int fov, znear, zfar; + int nslices; + int32_t *slicelen; /* 24.8 */ + + unsigned int valid; +}; + +struct voxscape *vox_create(int xsz, int ysz) +{ + struct voxscape *vox; + + if(!(vox = calloc(1, sizeof *vox))) { + return 0; + } + if(!(vox->height = calloc(1, xsz * ysz))) { + fprintf(stderr, "vox_create: failed to allocate %dx%d heightmap\n", xsz, ysz); + free(vox); + return 0; + } + if(!(vox->color = calloc(xsz * ysz, sizeof *vox->color))) { + fprintf(stderr, "vox_create: failed to allocate %dx%d color map\n", xsz, ysz); + free(vox->height); + free(vox); + return 0; + } + vox->xsz = xsz; + vox->ysz = ysz; + + return vox; +} + +struct voxscape *vox_open(const char *hfile, const char *cfile) +{ + unsigned char *hpix; + uint32_t *cpix; + int width, height, cwidth, cheight; + struct voxscape *vox; + + if(!(hpix = img_load_pixels(hfile, &width, &height, IMG_FMT_GREY8))) { + fprintf(stderr, "vox_open: failed to load heightmap: %s\n", hfile); + return 0; + } + if(!(cpix = img_load_pixels(cfile, &cwidth, &cheight, IMG_FMT_RGBA32))) { + fprintf(stderr, "vox_open: failed to load color map: %s\n", cfile); + img_free_pixels(hpix); + return 0; + } + if(cwidth != width || cheight != height) { + img_free_pixels(hpix); + img_free_pixels(cpix); + fprintf(stderr, "vox_open: %s and %s have different dimensions\n", hfile, cfile); + return 0; + } + + if(!(vox = vox_create(width, height))) { + img_free_pixels(hpix); + img_free_pixels(cpix); + return 0; + } + memcpy(vox->height, hpix, width * height); + memcpy(vox->color, cpix, width * height * sizeof *vox->color); + + img_free_pixels(hpix); + img_free_pixels(cpix); + + return vox; +} + +void vox_free(struct voxscape *vox) +{ + if(!vox) return; + + free(vox->color); + free(vox->height); + free(vox->coltop); + free(vox->slicelen); + free(vox); +} + +void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb) +{ + if(xres != vox->fbwidth) { + free(vox->coltop); + if(!(vox->coltop = malloc(xres * sizeof *vox->coltop))) { + fprintf(stderr, "vox_framebuf: failed to allocate column table (%d)\n", xres); + return; + } + } + vox->fb = fb; + vox->fbwidth = xres; + vox->fbheight = yres; +} + +void vox_view(struct voxscape *vox, int32_t x, int32_t y, int32_t angle) +{ + vox->x = x; + vox->y = y; + vox->angle = angle; + /* TODO precalc stuff */ + + valid &= ~SLICELEN; +} + +void vox_proj(struct voxscape *vox, int fov, int znear, int zfar) +{ + int i; + + vox->fov = fov; + vox->znear = znear; + vox->zfar = zfar; + + vox->nslices = vox->zfar - vox->znear; + free(vox->slicelen); + if(!(vox->slicelen = malloc(vox->nslices * sizeof *vox->slicelen))) { + fprintf(stderr, "vox_proj: failed to allocate slice length table (%d)\n", vox->nslices); + return; + } + + valid &= ~SLICELEN; +} + +/* algorithm: + * calculate extents of horizontal equidistant line from the viewer based on fov + * for each column step along this line and compute height for each pixel + * fill the visible (top) part of each column + */ + +void vox_render(struct voxscape *vox) +{ + int i; + + vox_begin(vox); + for(i=0; inslices; i++) { + vox_render_slice(vox, i); + } +} + +void vox_begin(struct voxscape *vox) +{ + int i; + + for(i=0; ifbwidth; i++) { + vox->coltop[i] = vox->fbheight; + } + + if(!(vox->valid & SLICELEN)) { + float theta = (float)vox->angle * M_PI / 360.0f; /* half angle */ + for(i=0; inslices; i++) { + vox->slicelen[i] = (int32_t)((vox->znear + i) * tan(theta) * 2.0f * 256.0f) + } + vox->valid |= SLICELEN; + } +} + +void vox_render_slice(struct voxscape *vox, int n) +{ + int32_t len; + + len = vox->slicelen[n]; + + /* TODO cont. */ +} diff --git a/src/voxscape.h b/src/voxscape.h new file mode 100644 index 0000000..bd7d3a1 --- /dev/null +++ b/src/voxscape.h @@ -0,0 +1,21 @@ +#ifndef VOXSCAPE_H_ +#define VOXSCAPE_H_ + +#include + +struct voxscape; + +struct voxscape *vox_create(int xsz, int ysz); +struct voxscape *vox_open(const char *hfile, const char *cfile); +void vox_free(struct voxscape *vox); + +void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb); +void vox_view(struct voxscape *vox, int32_t x, int32_t y, int32_t angle); +void vox_proj(struct voxscape *vox, int fov, int znear, int zfar); + +void vox_render(struct voxscape *vox); + +void vox_begin(struct voxscape *vox); +void vox_render_slice(struct voxscape *vox, int n); + +#endif /* VOXSCAPE_H_ */ -- 1.7.10.4