From: John Tsiombikas Date: Sun, 15 Dec 2019 06:43:46 +0000 (+0200) Subject: reorganized the source code X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=commitdiff_plain;h=ba648ddfc62fc6d3f47294aa8bfc10ea6ca3f479 reorganized the source code --- diff --git a/GNUmakefile b/GNUmakefile index f64feca..199fc30 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,9 +1,9 @@ -src = $(wildcard src/*.c) $(wildcard src/sdl/*.c) +src = $(wildcard src/*.c) $(wildcard src/scr/*.c) $(wildcard src/sdl/*.c) obj = $(src:.c=.o) $(asmsrc:.asm=.o) dep = $(obj:.o=.d) bin = demo -inc = -I/usr/local/include -Isrc -Isrc/sdl -Ilibs -Ilibs/imago/src -Ilibs/mikmod/include +inc = -I/usr/local/include -Isrc -Isrc/scr -Isrc/sdl -Ilibs -Ilibs/imago/src -Ilibs/mikmod/include warn = -pedantic -Wall -Wno-unused-variable -Wno-unused-function CFLAGS = $(warn) -g $(inc) `sdl-config --cflags` diff --git a/Makefile b/Makefile index 2faa385..1d0d7da 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,9 @@ $(bin): cflags.occ $(obj) libs/imago/imago.lib %write ldflags.lnk $(LDFLAGS) $(LD) debug all name $@ system dos4g file { @objects } @ldflags -.c: src;src/dos -.cc: src;src/dos -.asm: src;src/dos +.c: src;src/dos;src/scr +.cc: src;src/dos;src/scr +.asm: src;src/dos;src/scr cflags.occ: Makefile %write $@ $(CFLAGS) diff --git a/Makefile.dj b/Makefile.dj index b95f943..9306382 100644 --- a/Makefile.dj +++ b/Makefile.dj @@ -1,5 +1,5 @@ -src = $(wildcard src/*.c) $(wildcard src/dos/*.c) -asmsrc = $(wildcard src/*.asm) $(wildcard src/dos/*.asm) +src = $(wildcard src/*.c) $(wildcard src/scr/*.c) $(wildcard src/dos/*.c) +asmsrc = $(wildcard src/*.asm) $(wildcard src/scr/*.asm) $(wildcard src/dos/*.asm) obj = $(src:.c=.cof) $(asmsrc:.asm=.cof) dep = $(obj:.cof=.dep) bin = demo.exe @@ -11,7 +11,7 @@ else TOOLPREFIX = i586-pc-msdosdjgpp- endif -inc = -Isrc -Isrc/dos -Ilibs -Ilibs/imago/src -Ilibs/anim/src -Ilibs/mikmod/include +inc = -Isrc -Isrc/scr -Isrc/dos -Ilibs -Ilibs/imago/src -Ilibs/anim/src -Ilibs/mikmod/include opt = -O3 -ffast-math -fno-strict-aliasing dbg = -g warn = -pedantic -Wall -Wno-unused-function -Wno-unused-variable diff --git a/README.md b/README.md index 102090e..ec9721f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,17 @@ Unnamed Mindlapse DOS demo for Pentium 133 ------------------------------------------ The demo requires VESA Bios Extensions (VBE) 2.0. If your graphics card doesn't -support VBE 2.0 or greater, then make sure to run the `univbe` TSR first, or -the demo will fail to find a usable LFB video mode. +support VBE 2.0 or greater, then make sure to load the `univbe` TSR first. + +Source structure +---------------- + - src/ cross-platform demo framework and miscellaneous utility code + - src/scr/ demo screens (parts) and effects support code + - src/dos/ DOS platform code + - src/sdl/ SDL 1.x platform code (windows/UNIX version) + - libs/cgmath/ math library, header-file only + - libs/imago/ image loading library (includes libpng, zlib, libjpeg) + - libs/anim/ keyframe animation library Building on DOS with Watcom --------------------------- diff --git a/src/bump.c b/src/bump.c deleted file mode 100644 index b82594b..0000000 --- a/src/bump.c +++ /dev/null @@ -1,328 +0,0 @@ -// Bump effect (not moving yet of course, I have many ideas on this to commit before it's ready) - -#include -#include -#include -#include - -#include "demo.h" -#include "screen.h" - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); - -static struct screen scr = { - "bump", - init, - destroy, - start, - 0, - draw -}; - -struct point { - int x, y; -}; - -#define NUM_BIG_LIGHTS 3 -#define BIG_LIGHT_WIDTH 256 -#define BIG_LIGHT_HEIGHT BIG_LIGHT_WIDTH - -#define NUM_PARTICLES 64 -#define PARTICLE_LIGHT_WIDTH 32 -#define PARTICLE_LIGHT_HEIGHT 32 - - -static unsigned long startingTime; - -static unsigned char *heightmap; -static unsigned short *lightmap; -static int *bumpOffset; - -static unsigned short *bigLight[NUM_BIG_LIGHTS]; -static struct point bigLightPoint[NUM_BIG_LIGHTS]; - -static unsigned short *particleLight; -static struct point particlePoint[NUM_PARTICLES]; - -struct screen *bump_screen(void) -{ - return &scr; -} - -static int init(void) -{ - int i, j, x, y, c, r, g, b; - - const int numBlurs = 3; - const int lightRadius = BIG_LIGHT_WIDTH / 2; - const int particleRadius = PARTICLE_LIGHT_WIDTH / 2; - - const int bigLightSize = BIG_LIGHT_WIDTH * BIG_LIGHT_HEIGHT; - const int particleLightSize = PARTICLE_LIGHT_WIDTH * PARTICLE_LIGHT_HEIGHT; - const int fb_size = fb_width * fb_height; - - // Just some parameters to temporary test the colors of 3 lights - // if every light uses it's own channel bits, it's better - const float rgbMul[9] = { 1.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 1.0f}; - - heightmap = malloc(sizeof(*heightmap) * fb_size); - lightmap = malloc(sizeof(*lightmap) * fb_size); - bumpOffset = malloc(sizeof(*bumpOffset) * fb_size); - - for (i = 0; i < NUM_BIG_LIGHTS; i++) - bigLight[i] = malloc(sizeof(*bigLight[i]) * bigLightSize); - - particleLight = malloc(sizeof(*particleLight) * particleLightSize); - - memset(lightmap, 0, sizeof(*lightmap) * fb_size); - memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size); - memset(particlePoint, 0, sizeof(*particlePoint) * NUM_PARTICLES); - - // Create random junk - for (i = 0; i < fb_size; i++) - heightmap[i] = rand() & 255; - - // Blur to smooth - for (j = 0; j < numBlurs; j++) - for (i = 0; i < fb_size; i++) - heightmap[i] = (heightmap[abs((i - 1) % fb_size)] + heightmap[abs((i + 1) % fb_size)] + heightmap[abs((i - fb_width) % fb_size)] + heightmap[abs((i + fb_width) % fb_size)]) >> 2; - - // Inclination precalculation - i = 0; - for (y = 0; y < fb_height; y++) - { - for (x = 0; x < fb_width; x++) - { - const float offsetPower = 0.75f; - int dx, dy, xp, yp; - - dx = i < fb_size - 1 ? (int)((heightmap[i] - heightmap[i + 1]) * offsetPower) : 0; - dy = i < fb_size - fb_width ? (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower) : 0; - - xp = x + dx; - if (xp < 0) xp = 0; - if (xp > fb_width - 1) xp = fb_width - 1; - - yp = y + dy; - if (yp < 0) yp = 0; - if (yp > fb_height - 1) yp = fb_height - 1; - - bumpOffset[i++] = yp * fb_width + xp; - } - } - - // Generate three lights - i = 0; - for (y = 0; y < BIG_LIGHT_HEIGHT; y++) - { - int yc = y - (BIG_LIGHT_HEIGHT / 2); - for (x = 0; x < BIG_LIGHT_WIDTH; x++) - { - int xc = x - (BIG_LIGHT_WIDTH / 2); - float d = (float)sqrt(xc * xc + yc * yc); - float invDist = ((float)lightRadius - (float)sqrt(xc * xc + yc * yc)) / (float)lightRadius; - if (invDist < 0.0f) invDist = 0.0f; - - c = (int)(invDist * 63); - r = c >> 1; - g = c; - b = c >> 1; - - for (j = 0; j < NUM_BIG_LIGHTS; j++) - { - bigLight[j][i] = ((int)(r * rgbMul[j * 3]) << 11) | ((int)(g * rgbMul[j * 3 + 1]) << 5) | (int)(b * rgbMul[j * 3 + 2]); - } - i++; - } - } - - i = 0; - for (y = 0; y < PARTICLE_LIGHT_HEIGHT; y++) - { - int yc = y - (PARTICLE_LIGHT_HEIGHT / 2); - for (x = 0; x < PARTICLE_LIGHT_WIDTH; x++) - { - int xc = x - (PARTICLE_LIGHT_WIDTH / 2); - - float invDist = ((float)particleRadius - (float)sqrt(xc * xc + yc * yc)) / (float)particleRadius; - if (invDist < 0.0f) invDist = 0.0f; - - c = (int)(pow(invDist, 0.75f) * 63); - particleLight[i++] = ((c >> 1) << 11) | (c << 5) | (c >> 1); - } - } - - return 0; -} - -static void destroy(void) -{ -} - -static void start(long trans_time) -{ - startingTime = time_msec; -} - -static void eraseArea(struct point *p, int width, int height) -{ - int x, y, dx; - unsigned short *dst; - - int x0 = p->x; - int y0 = p->y; - int x1 = p->x + width; - int y1 = p->y + height; - - if (x0 < 0) x0 = 0; - if (y0 < 0) y0 = 0; - if (x1 > fb_width) x1 = fb_width; - if (y1 > fb_height) y1 = fb_height; - - dx = x1 - x0; - - dst = lightmap + y0 * fb_width + x0; - - for (y = y0; y < y1; y++) - { - for (x = x0; x < x1; x++) - { - *dst++ = 0; - } - dst += fb_width - dx; - } -} - - -static void renderLight(struct point *p, int width, int height, unsigned short *light) -{ - int x, y, dx; - unsigned short *src, *dst; - - int x0 = p->x; - int y0 = p->y; - int x1 = p->x + width; - int y1 = p->y + height; - - int xl = 0; - int yl = 0; - - if (x0 < 0) - { - xl = -x0; - x0 = 0; - } - - if (y0 < 0) - { - yl = -y0; - y0 = 0; - } - - if (x1 > fb_width) x1 = fb_width; - if (y1 > fb_height) y1 = fb_height; - - dx = x1 - x0; - - dst = lightmap + y0 * fb_width + x0; - src = light + yl * width + xl; - - for (y = y0; y < y1; y++) - { - for (x = x0; x < x1; x++) - { - *dst++ |= *src++; - } - dst += fb_width - dx; - src += width - dx; - } -} - -static void eraseLights() -{ - int i; - for (i = 0; i < NUM_BIG_LIGHTS; i++) - eraseArea(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT); -} - -static void renderLights() -{ - int i; - for (i = 0; i < NUM_BIG_LIGHTS; i++) - renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]); -} - -static void renderParticles() -{ - int i; - for (i = 0; i < NUM_PARTICLES; i++) - renderLight(&particlePoint[i], PARTICLE_LIGHT_WIDTH, PARTICLE_LIGHT_HEIGHT, particleLight); -} - -static void animateLights() -{ - struct point center; - float dt = (float)(time_msec - startingTime) / 1000.0f; - float tt = 1.0f - sin(dt); - float disperse = tt * 64.0f; - - center.x = (fb_width >> 1) - (BIG_LIGHT_WIDTH / 2); - center.y = (fb_height >> 1) - (BIG_LIGHT_HEIGHT / 2); - - bigLightPoint[0].x = center.x + sin(1.2f * dt) * (144.0f + disperse); - bigLightPoint[0].y = center.y + sin(0.8f * dt) * (148.0f + disperse); - - bigLightPoint[1].x = center.x + sin(1.5f * dt) * (156.0f + disperse); - bigLightPoint[1].y = center.y + sin(1.1f * dt) * (92.0f + disperse); - - bigLightPoint[2].x = center.x + sin(2.0f * dt) * (112.0f + disperse); - bigLightPoint[2].y = center.y + sin(1.3f * dt) * (136.0f + disperse); -} - -static void renderBump(unsigned short *vram) -{ - int i; - for (i = 0; i < fb_width * fb_height; i++) - { - unsigned short c = lightmap[bumpOffset[i]]; - *vram++ = c; - } -} - -static void animateParticles() -{ - int i; - struct point center; - float dt = (float)(time_msec - startingTime) / 2000.0f; - float tt = sin(dt); - - center.x = (fb_width >> 1) - (PARTICLE_LIGHT_WIDTH / 2); - center.y = (fb_height >> 1) - (PARTICLE_LIGHT_HEIGHT / 2); - - for (i = 0; i < NUM_PARTICLES; i++) - { - particlePoint[i].x = center.x + (sin(1.2f * (i*i*i + dt)) * 74.0f + sin(0.6f * (i + dt)) * 144.0f) * tt; - particlePoint[i].y = center.y + (sin(1.8f * (i + dt)) * 68.0f + sin(0.5f * (i*i + dt)) * 132.0f) * tt; - } -} - -static void draw(void) -{ - memset(lightmap, 0, fb_width * fb_height * sizeof(*lightmap)); - - //eraseLights(); - animateLights(); - renderLights(); - - animateParticles(); - renderParticles(); - - renderBump((unsigned short*)fb_pixels); - - swap_buffers(0); -} diff --git a/src/fract.c b/src/fract.c deleted file mode 100644 index 6eeb678..0000000 --- a/src/fract.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include "demo.h" -#include "screen.h" -#include "gfxutil.h" - -struct vec2x { - long x, y; -}; - -static int init(void); -static void destroy(void); -static void draw(void); -static int julia(long x, long y, long cx, long cy, int max_iter); - -static struct screen scr = { - "fract", - init, - destroy, - 0, 0, - draw -}; - -/*static long aspect_24x8 = (long)(1.3333333 * 256.0);*/ -static long xscale_24x8 = (long)(1.3333333 * 1.2 * 256.0); -static long yscale_24x8 = (long)(1.2 * 256.0); -static int cx, cy; -static int max_iter = 50; - -#define WALK_SIZE 20 - -struct screen *fract_screen(void) -{ - return &scr; -} - -static int init(void) -{ - return 0; -} - -static void destroy(void) -{ -} - -static void draw(void) -{ - int i, j; - unsigned short *pixels = fb_pixels; - - cx = mouse_x; - cy = mouse_y; - - for(i=0; i> 3) | ((pidx >> 2) << 5) | ((pidx >> 3) << 11); - } - } - - pixels = fb_pixels; - pixels[mouse_y * fb_width + mouse_x] = 0xffe; - swap_buffers(0); -} - -static long normalize_coord(long x, long range) -{ - /* 2 * x / range - 1*/ - return (x << 17) / range - 65536; -} - -static int julia(long x, long y, long cx, long cy, int max_iter) -{ - int i; - - /* convert to fixed point roughly [-1, 1] */ - x = (normalize_coord(x, fb_width) >> 8) * xscale_24x8; - y = (normalize_coord(y, fb_height) >> 8) * yscale_24x8; - cx = (normalize_coord(cx, fb_width) >> 8) * xscale_24x8; - cy = (normalize_coord(cy, fb_height) >> 8) * yscale_24x8; - - for(i=0; i> 8; - long py = y >> 8; - - if(px * px + py * py > (4 << 16)) { - break; - } - x = px * px - py * py + cx; - y = (px * py << 1) + cy; - } - - return i < max_iter ? (256 * i / max_iter) : 0; -} diff --git a/src/greets.c b/src/greets.c deleted file mode 100644 index 8b128c6..0000000 --- a/src/greets.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include -#include -#include -#include "demo.h" -#include "3dgfx.h" -#include "screen.h" -#include "cfgopt.h" -#include "imago2.h" -#include "util.h" -#include "gfxutil.h" -#include "timer.h" -#include "smoketxt.h" - -#ifdef MSDOS -#include "dos/gfx.h" /* for wait_vsync assembly macro */ -#else -void wait_vsync(void); -#endif - -#define BLUR_RAD 5 - - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); - - -static struct screen scr = { - "greets", - init, - destroy, - start, 0, - draw -}; - -static long start_time; - -static struct smktxt *stx; - -static uint16_t *cur_smokebuf, *prev_smokebuf; -static int smokebuf_size; -#define smokebuf_start (cur_smokebuf < prev_smokebuf ? cur_smokebuf : prev_smokebuf) -#define swap_smoke_buffers() \ - do { \ - uint16_t *tmp = cur_smokebuf; \ - cur_smokebuf = prev_smokebuf; \ - prev_smokebuf = tmp; \ - } while(0) - -static float cam_theta, cam_phi = 25; -static float cam_dist = 3; - -struct screen *greets_screen(void) -{ - return &scr; -} - - -static int init(void) -{ - if(!(stx = create_smktxt("data/greets1.png", "data/vfield1"))) { - return -1; - } - - smokebuf_size = fb_width * fb_height * sizeof *cur_smokebuf; - if(!(cur_smokebuf = malloc(smokebuf_size * 2))) { - perror("failed to allocate smoke framebuffer"); - return -1; - } - prev_smokebuf = cur_smokebuf + fb_width * fb_height; - - return 0; -} - -static void destroy(void) -{ - free(smokebuf_start); - destroy_smktxt(stx); -} - -static void start(long trans_time) -{ - g3d_matrix_mode(G3D_PROJECTION); - g3d_load_identity(); - g3d_perspective(50.0, 1.3333333, 0.5, 100.0); - - memset(smokebuf_start, 0, smokebuf_size * 2); - - start_time = time_msec; -} - -static void update(void) -{ - static long prev_msec; - static int prev_mx, prev_my; - static unsigned int prev_bmask; - - long msec = time_msec - start_time; - float dt = (msec - prev_msec) / 1000.0f; - prev_msec = msec; - - if(mouse_bmask) { - if((mouse_bmask ^ prev_bmask) == 0) { - int dx = mouse_x - prev_mx; - int dy = mouse_y - prev_my; - - if(dx || dy) { - if(mouse_bmask & 1) { - cam_theta += dx * 1.0; - cam_phi += dy * 1.0; - - if(cam_phi < -90) cam_phi = -90; - if(cam_phi > 90) cam_phi = 90; - } - if(mouse_bmask & 4) { - cam_dist += dy * 0.5; - - if(cam_dist < 0) cam_dist = 0; - } - } - } - } - prev_mx = mouse_x; - prev_my = mouse_y; - prev_bmask = mouse_bmask; - - update_smktxt(stx, dt); -} - -static void draw(void) -{ - int i, j; - uint16_t *dest, *src; - unsigned long msec; - static unsigned long last_swap; - - update(); - - g3d_matrix_mode(G3D_MODELVIEW); - g3d_load_identity(); - g3d_translate(0, 0, -cam_dist); - g3d_rotate(cam_phi, 1, 0, 0); - g3d_rotate(cam_theta, 0, 1, 0); - if(opt.sball) { - g3d_mult_matrix(sball_matrix); - } - - memcpy(cur_smokebuf, prev_smokebuf, smokebuf_size); - - g3d_framebuffer(fb_width, fb_height, cur_smokebuf); - draw_smktxt(stx); - g3d_framebuffer(fb_width, fb_height, fb_pixels); - - dest = fb_pixels; - src = cur_smokebuf; - for(i=0; i -#include -#include -#include -#include -#include "imago2.h" -#include "demo.h" -#include "screen.h" - -/* APPROX. 170 FPS Minimum */ - -typedef struct { - unsigned int w, h; - unsigned char *scans; -} RLEBitmap; - -static RLEBitmap *rleCreate(unsigned int w, unsigned int h); -static void rleDestroy(RLEBitmap *b); -static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY); -static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY); -static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY); -static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h); - -static void updatePropeller(float t); - -#define BG_FILENAME "data/grise.png" -#define GROBJ_01_FILENAME "data/grobj_01.png" - -#define BB_SIZE 512 /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */ - -/* Every backBuffer scanline is guaranteed to have that many dummy pixels before and after */ -#define PIXEL_PADDING 32 - -/* Make sure this is less than PIXEL_PADDING*/ -#define MAX_DISPLACEMENT 16 - -#define MIN_SCROLL PIXEL_PADDING -#define MAX_SCROLL (backgroundW - fb_width - MIN_SCROLL) - -#define FAR_SCROLL_SPEED 15.0f -#define NEAR_SCROLL_SPEED 120.0f - -#define HORIZON_HEIGHT 100 -#define REFLECTION_HEIGHT (240 - HORIZON_HEIGHT) - -#define NORMALMAP_SCANLINE 372 - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void stop(long trans_time); -static void draw(void); - -static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned int pixelCount); -static void processNormal(); -static void initScrollTables(); -static void updateScrollTables(float dt); - - - -static unsigned short *background = 0; -static int backgroundW = 0; -static int backgroundH = 0; - -static unsigned int lastFrameTime = 0; -static float lastFrameDuration = 0.0f; - -static short *displacementMap; - -static unsigned short *backBuffer; - -static float scrollScaleTable[REFLECTION_HEIGHT]; -static float scrollTable[REFLECTION_HEIGHT]; -static int scrollTableRounded[REFLECTION_HEIGHT]; -static int scrollModTable[REFLECTION_HEIGHT]; -static float nearScrollAmount = 0.0f; - -static unsigned char miniFXBuffer[1024]; - -static RLEBitmap *grobj = 0; -static RLEBitmap *rlePropeller = 0; - -static struct screen scr = { - "galaxyrise", - init, - destroy, - start, - 0, - draw -}; - -struct screen *grise_screen(void) -{ - return &scr; -} - -static int init(void) -{ - unsigned char *tmpBitmap; - int tmpBitmapW, tmpBitmapH; - - /* Allocate back buffer */ - backBuffer = (unsigned short*) calloc(BB_SIZE * BB_SIZE, sizeof(unsigned short)); - - /* grise.png contains the background (horizon), baked reflection and normalmap for displacement */ - if (!(background = img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) { - fprintf(stderr, "failed to load image " BG_FILENAME "\n"); - return -1; - } - - /* Convert to 16bpp */ - convert32To16((unsigned int*)background, background, backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */ - - /* Load reflected objects */ - if (!(tmpBitmap = img_load_pixels(GROBJ_01_FILENAME, &tmpBitmapW, &tmpBitmapH, IMG_FMT_GREY8))) { - fprintf(stderr, "failed to load image " GROBJ_01_FILENAME "\n"); - return -1; - } - - grobj = rleEncode(0, tmpBitmap, tmpBitmapW, tmpBitmapH); - - img_free_pixels(tmpBitmap); - - initScrollTables(); - - processNormal(); - - return 0; -} - -static void destroy(void) -{ - free(backBuffer); - backBuffer = 0; - - img_free_pixels(background); - - rleDestroy(grobj); -} - -static void start(long trans_time) -{ - lastFrameTime = time_msec; -} - - -static void draw(void) -{ - int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / fb_width; - unsigned short *dst = backBuffer + PIXEL_PADDING; - unsigned short *src = background + scroll; - int scanline = 0; - int i = 0; - short *dispScanline; - int d; - int accum = 0; - int md, sc; - int scrolledIndex; - - lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; - lastFrameTime = time_msec; - - /* Update mini-effects here */ - updatePropeller(4.0f * time_msec / 1000.0f); - - /* First, render the horizon */ - for (scanline = 0; scanline < HORIZON_HEIGHT; scanline++) { - memcpy(dst, src, fb_width * 2); - src += backgroundW; - dst += BB_SIZE; - } - - /* Create scroll offsets for all scanlines of the normalmap */ - updateScrollTables(lastFrameDuration); - - /* Render the baked reflection one scanline below its place, so that - * the displacement that follows will be done in a cache-friendly way - */ - src -= PIXEL_PADDING; /* We want to also fill the PADDING pixels here */ - dst = backBuffer + (HORIZON_HEIGHT + 1) * BB_SIZE; - for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { - memcpy(dst, src, (fb_width + PIXEL_PADDING) * 2); - src += backgroundW; - dst += BB_SIZE; - } - - /* Blit reflections first, to be displaced */ - for (i = 0; i < 5; i++) rleBlitScaleInv(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 200, 1.0f, 1.8f); - - /* Perform displacement */ - dst = backBuffer + HORIZON_HEIGHT * BB_SIZE + PIXEL_PADDING; - src = dst + BB_SIZE; /* The pixels to be displaced are 1 scanline below */ - dispScanline = displacementMap; - for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { - - md = scrollModTable[scanline]; - sc = scrollTableRounded[scanline]; - accum = 0; - - for (i = 0; i < fb_width; i++) { - /* Try to immitate modulo without the division */ - if (i == md) accum += md; - scrolledIndex = i - accum + sc; - if (scrolledIndex >= md) scrolledIndex -= md; - - /* Displace */ - d = dispScanline[scrolledIndex]; - *dst++ = src[i + d]; - } - src += backgroundW; - dst += BB_SIZE - fb_width; - dispScanline += backgroundW; - } - - /* Then after displacement, blit the objects */ - for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 100); - - /* Blit effect to framebuffer */ - src = backBuffer + PIXEL_PADDING; - dst = fb_pixels; - for (scanline = 0; scanline < fb_height; scanline++) { - memcpy(dst, src, fb_width * 2); - src += BB_SIZE; - dst += fb_width; - } - - swap_buffers(0); -} - -/* src and dst can be the same */ -static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned int pixelCount) { - unsigned int p; - while (pixelCount) { - p = *src32++; - *dst16++ = ((p << 8) & 0xF800) /* R */ - | ((p >> 5) & 0x07E0) /* G */ - | ((p >> 19) & 0x001F); /* B */ - pixelCount--; - } -} - -/* Normal map preprocessing */ -/* Scale normal with depth and unpack R component (horizontal component) */ -static void processNormal() { - int scanline; - int i; - int x; - short maxDisplacement = 0; - short minDisplacement = 256; - unsigned short *dst; - short *dst2; - unsigned int *normalmap = (unsigned int*)background; - normalmap += NORMALMAP_SCANLINE * backgroundW; - dst = (unsigned short*)normalmap; - displacementMap = (short*)dst; - dst2 = displacementMap; - - for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { - scrollModTable[scanline] = (int) (backgroundW / scrollScaleTable[scanline] + 0.5f); - for (i = 0; i < backgroundW; i++) { - x = (int)(i * scrollScaleTable[scanline] + 0.5f); - if (x < backgroundW) { - *dst = (unsigned short)(normalmap[x] >> 8) & 0xFF; - if ((short)*dst > maxDisplacement) maxDisplacement = (short)(*dst); - if ((short)*dst < minDisplacement) minDisplacement = (short)(*dst); - } else { - *dst = 0; - } - dst++; - } - normalmap += backgroundW; - } - - if (maxDisplacement == minDisplacement) { - printf("Warning: grise normalmap fucked up\n"); - return; - } - - /* Second pass - subtract half maximum displacement to displace in both directions */ - for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { - for (i = 0; i < backgroundW; i++) { - /* Remember that MIN_SCROLL is the padding around the screen, so ti's the maximum displacement we can get (positive & negative) */ - *dst2 = 2 * MAX_DISPLACEMENT * (*dst2 - minDisplacement) / (maxDisplacement - minDisplacement) - MAX_DISPLACEMENT; - *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] + 0.5f); /* Displacements must also scale with distance*/ - dst2++; - } - } -} - -static float distanceScale(int scanline) { - float farScale, t; - farScale = (float)NEAR_SCROLL_SPEED / (float)FAR_SCROLL_SPEED; - t = (float)scanline / ((float)REFLECTION_HEIGHT - 1); - return 1.0f / (1.0f / farScale + (1.0f - 1.0f / farScale) * t); -} - -static void initScrollTables() { - int i = 0; - for (i = 0; i < REFLECTION_HEIGHT; i++) { - scrollScaleTable[i] = distanceScale(i); - scrollTable[i] = 0.0f; - scrollTableRounded[i] = 0; - } -} - - -static void updateScrollTables(float dt) { - int i = 0; - - nearScrollAmount += dt * NEAR_SCROLL_SPEED; - nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f); - - for (i = 0; i < REFLECTION_HEIGHT; i++) { - scrollTable[i] = nearScrollAmount / scrollScaleTable[i]; - scrollTableRounded[i] = (int)(scrollTable[i] + 0.5f) % scrollModTable[i]; - } -} - -/* ------------------------------------------------------------------------------------------------- - * RLE STUFF - * ------------------------------------------------------------------------------------------------- - */ -/* Limit streak count per scanline so we can directly jump to specific scanline */ -#define RLE_STREAKS_PER_SCANLINE 4 -/* Every streak is encoded by 2 bytes: offset and count of black pixels in the streak */ -#define RLE_BYTES_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 -#define RLE_FILL_COLOR 0 -#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) - -#define RLE_FIXED_BITS 16 - -static int rleByteCount(int w, int h) { - return h * RLE_BYTES_PER_SCANLINE + w; -} - -static RLEBitmap *rleCreate(unsigned int w, unsigned int h) { - RLEBitmap *ret = (RLEBitmap*)malloc(sizeof(RLEBitmap)); - ret->w = w; - ret->h = h; - - /* Add some padding at the end of the buffer, with the worst case for a scanline (w/2 streaks) */ - ret->scans = (unsigned char*) calloc(rleByteCount(w, h), 1); - - return ret; -} - -static void rleDestroy(RLEBitmap *b) { - if (!b) return; - free(b->scans); - free(b); -} - -static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h) { - int scanline; - int i; - int penActive = 0; - int counter = 0; - int accum = 0; - unsigned char *output; - - /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ - if (!b) b = rleCreate(w, h); - else memset(b->scans, 0, rleByteCount(b->w, b->h)); /* The following code assumes cleared array */ - - for (scanline = 0; scanline < h; scanline++) { - output = b->scans + scanline * RLE_BYTES_PER_SCANLINE; - accum = 0; - for (i = 0; i < w; i++) { - if (*pixels++) { - if (penActive) { - if (counter >= PIXEL_PADDING) { - *output++ = (unsigned char) counter; - counter = 0; - *output++ = (unsigned char)accum; - } - counter++; - accum++; - } else { - *output++ = (unsigned char)accum; - counter = 1; - accum++; - penActive = 1; - } - } else { - if (penActive) { - *output++ = (unsigned char)counter; - counter = 1; - accum++; - penActive = 0; - } else { - counter++; - accum++; - } - } - } - - if (penActive) { - *output++ = (unsigned char)counter; - } - penActive = 0; - counter = 0; - } - - return b; -} - -static void rleDistributeStreaks(RLEBitmap *bitmap) { - int scanline, halfW = bitmap->w >> 1; - unsigned char *ptr, tmp; - - ptr = bitmap->scans; - for (scanline = 0; scanline < bitmap->h; scanline++) { - if (ptr[0] >= halfW) { - tmp = ptr[0]; - ptr[0] = ptr[6]; - ptr[6] = tmp; - tmp = ptr[1]; - ptr[1] = ptr[7]; - ptr[7] = tmp; - } - - ptr += 8; - } -} - -static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY) -{ - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned char *input = bitmap->scans; - unsigned short *output; - unsigned int *output32; - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + bitmap->h; scanline++) { - if (scanline < 0 || scanline >= dstH) continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = *input++; - streakLength = *input++; - - if ((streakPos + blitX) <= 0) continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int*) output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - -static void interpolateScan(unsigned char *output, unsigned char *a, unsigned char *b, float t) { - static int div = 1 << 23; - int ti, i; - - t += 1.0f; - ti = (*((unsigned int*)&t)) & 0x7FFFFF; - - for (i = 0; i < RLE_BYTES_PER_SCANLINE; i++) { - if (*a == 0) { - *output++ = *b++; - a++; - } else { - if (*b == 0) { - *output++ = *a++; - b++; - } else { - *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; - } - } - } -} - -static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY) -{ - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/ - int blitH = (int)(bitmap->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + blitH; scanline++) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int*)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - - - -static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride, - RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY) -{ - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/ - int blitH = (int)(bitmap->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline > blitY - blitH; scanline--) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int*)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst -= dstStride; - } -} - -/* ------------------------------------------------------------------------------------------------- -* PROPELLER STUFF -* ------------------------------------------------------------------------------------------------- -*/ - -#define PROPELLER_CIRCLE_RADIUS 18 -#define PROPELLER_CIRCLE_RADIUS_SQ (PROPELLER_CIRCLE_RADIUS * PROPELLER_CIRCLE_RADIUS) - -static struct { - int circleX[3]; - int circleY[3]; -} propellerState; - -static void updatePropeller(float t) { - int i, j; - int cx, cy, count = 0; - unsigned char *dst; - float x = 0.0f; - float y = 18.0f; - float nx, ny; - float cost, sint; - static float sin120 = 0.86602540378f; - static float cos120 = -0.5f; - - /* Rotate */ - sint = sin(t); - cost = cos(t); - nx = x * cost - y * sint; - ny = y * cost + x * sint; - x = nx; - y = ny; - propellerState.circleX[0] = (int)(x + 0.5f) + 16; - propellerState.circleY[0] = (int)(y + 0.5f) + 16; - - /* Rotate by 120 degrees, for the second circle */ - nx = x * cos120 - y * sin120; - ny = y * cos120 + x * sin120; - x = nx; - y = ny; - propellerState.circleX[1] = (int)(x + 0.5f) + 16; - propellerState.circleY[1] = (int)(y + 0.5f) + 16; - - /* 3rd circle */ - nx = x * cos120 - y * sin120; - ny = y * cos120 + x * sin120; - x = nx; - y = ny; - propellerState.circleX[2] = (int)(x + 0.5f) + 16; - propellerState.circleY[2] = (int)(y + 0.5f) + 16; - - /* Write effect to the mini fx buffer*/ - dst = miniFXBuffer; - for (j = 0; j < 32; j++) { - for (i = 0; i < 32; i++) { - count = 0; - - /* First circle */ - cx = propellerState.circleX[0] - i; - cy = propellerState.circleY[0] - j; - if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; - - /* 2nd circle */ - cx = propellerState.circleX[1] - i; - cy = propellerState.circleY[1] - j; - if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; - - /* 3rd circle */ - cx = propellerState.circleX[2] - i; - cy = propellerState.circleY[2] - j; - if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; - - *dst++ = count >= 2; - } - } - - /* Then, encode to rle */ - rlePropeller = rleEncode(rlePropeller, miniFXBuffer, 32, 32); - - /* Distribute the produced streaks so that they don't produce garbage when interpolated */ - rleDistributeStreaks(rlePropeller); -} diff --git a/src/hairball.c b/src/hairball.c deleted file mode 100644 index 89c45c3..0000000 --- a/src/hairball.c +++ /dev/null @@ -1,317 +0,0 @@ -#include -#include -#include -#include -#include "demo.h" -#include "3dgfx.h" -#include "vmath.h" -#include "screen.h" -#include "util.h" -#include "cfgopt.h" -#include "mesh.h" - - -#ifdef MSDOS -#include "dos/gfx.h" /* for wait_vsync assembly macro */ -#else -void wait_vsync(void); -#endif - -#define NSPAWNPOS 64 -#define SPAWN_RATE 16.0f -//#define GRAV (-6.0f) -#define GRAV 0.0f -#define HAIR_LENGTH 20 - -struct particle { - vec3_t pos; - vec3_t vel; - int r, g, b, a; - int life; - - struct particle *next; -}; - -struct hairball { - vec3_t pos; - quat_t rot; - float xform[16]; - - struct particle *plist[NSPAWNPOS]; -}; - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); -static void update_hairball(struct hairball *hb, float dt); -static void draw_hairball(struct hairball *hb); - -static struct particle *palloc(void); -void pfree(struct particle *p); - - -static struct screen scr = { - "hairball", - init, - destroy, - start, 0, - draw -}; - -static long start_time; - -static float cam_theta, cam_phi = 15; -static float cam_dist = 8; - -static vec3_t *spawnpos, *spawndir; -static struct hairball hball; -static struct g3d_mesh sphmesh; - -struct screen *hairball_screen(void) -{ - return &scr; -} - -static int init(void) -{ - int i, j, numpt = 0; - - gen_sphere_mesh(&sphmesh, 1.0f, 12, 6); - - hball.xform[0] = hball.xform[5] = hball.xform[10] = hball.xform[15] = 1.0f; - hball.rot.w = 1.0f; - - if(!(spawnpos = malloc(NSPAWNPOS * sizeof *spawnpos)) || - !(spawndir = malloc(NSPAWNPOS * sizeof *spawndir))) { - fprintf(stderr, "failed to allocate spawnpos/dir array\n"); - return -1; - } - - while(numpt < NSPAWNPOS) { - float best_dist = -1.0f; - for(i=0; i<100; i++) { - vec3_t pos = sphrand(1.0f); - - float mindist = FLT_MAX; - for(j=0; j best_dist) { - spawnpos[numpt] = pos; - best_dist = mindist; - } - } - - spawndir[numpt] = spawnpos[numpt]; - ++numpt; - } - - return 0; -} - -static void destroy(void) -{ -} - -static void start(long trans_time) -{ - g3d_matrix_mode(G3D_PROJECTION); - g3d_load_identity(); - g3d_perspective(50.0, 1.33333, 0.5, 100.0); - - start_time = time_msec; -} - -static void update(void) -{ - static float prev_mx, prev_my; - static long prev_msec; - int mouse_dx, mouse_dy; - long msec = time_msec - start_time; - float dt = (msec - prev_msec) / 1000.0f; - prev_msec = msec; - - mouse_dx = mouse_x - prev_mx; - mouse_dy = mouse_y - prev_my; - prev_mx = mouse_x; - prev_my = mouse_y; - - - if(opt.sball) { - memcpy(hball.xform, sball_matrix, 16 * sizeof(float)); - - hball.pos.x = hball.xform[12]; - hball.pos.y = hball.xform[13]; - hball.pos.z = hball.xform[14]; - } else { - if(mouse_bmask & MOUSE_BN_MIDDLE) { - hball.pos.x += mouse_dx * 0.05; - hball.pos.y -= mouse_dy * 0.05; - } - - quat_to_mat(hball.xform, hball.rot); - hball.xform[12] = hball.pos.x; - hball.xform[13] = hball.pos.y; - hball.xform[14] = hball.pos.z; - } - - update_hairball(&hball, dt); - - mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); -} - -static void draw(void) -{ - unsigned long msec; - static unsigned long last_swap; - - update(); - - memset(fb_pixels, 0, fb_width * fb_height * 2); - - g3d_matrix_mode(G3D_MODELVIEW); - g3d_load_identity(); - g3d_translate(0, 0, -cam_dist); - g3d_rotate(cam_phi, 1, 0, 0); - g3d_rotate(cam_theta, 0, 1, 0); - - draw_hairball(&hball); - - msec = get_msec(); - if(msec - last_swap < 16) { - wait_vsync(); - } - if(!opt.vsync) { - wait_vsync(); - } - swap_buffers(fb_pixels); - last_swap = get_msec(); -} - -static void update_hairball(struct hairball *hb, float dt) -{ - int i, j, spawn_count; - struct particle pdummy, *prev, *p; - static float spawn_acc; - - /* update particles */ - for(i=0; iplist[i]; - prev = &pdummy; - while(prev && prev->next) { - p = prev->next; - if(--p->life <= 0) { - prev->next = p->next; - pfree(p); - prev = prev->next; - continue; - } - - p->pos.x += p->vel.x * dt; - p->pos.y += p->vel.y * dt; - p->pos.z += p->vel.z * dt; - p->vel.y += GRAV * dt; - - p->r = p->g = p->b = (p->life << 8) / HAIR_LENGTH - 1; - - prev = p; - } - - hb->plist[i] = pdummy.next; - } - - /* spawn new particles */ - spawn_acc += dt; - if(spawn_acc >= (1.0f / SPAWN_RATE)) { - for(i=0; ixform; - vec3_t pos = spawnpos[i]; - vec3_t dir = spawndir[i]; - - p->pos.x = mat[0] * pos.x + mat[4] * pos.y + mat[8] * pos.z + mat[12]; - p->pos.y = mat[1] * pos.x + mat[5] * pos.y + mat[9] * pos.z + mat[13]; - p->pos.z = mat[2] * pos.x + mat[6] * pos.y + mat[10] * pos.z + mat[14]; - - p->vel.x = mat[0] * dir.x + mat[4] * dir.y + mat[8] * dir.z; - p->vel.y = mat[1] * dir.x + mat[5] * dir.y + mat[9] * dir.z; - p->vel.z = mat[2] * dir.x + mat[6] * dir.y + mat[10] * dir.z; - p->life = HAIR_LENGTH; - - p->next = hb->plist[i]; - hb->plist[i] = p; - } - spawn_acc -= 1.0f / SPAWN_RATE; - } -} - -static void draw_hairball(struct hairball *hb) -{ - int i, col; - struct particle *p; - vec3_t prevpos; - vec3_t start[NSPAWNPOS]; - - for(i=0; ixform[0] * spawnpos[i].x + hb->xform[4] * spawnpos[i].y + hb->xform[8] * spawnpos[i].z + hb->xform[12]; - start[i].y = hb->xform[1] * spawnpos[i].x + hb->xform[5] * spawnpos[i].y + hb->xform[9] * spawnpos[i].z + hb->xform[13]; - start[i].z = hb->xform[2] * spawnpos[i].x + hb->xform[6] * spawnpos[i].y + hb->xform[10] * spawnpos[i].z + hb->xform[14]; - } - - g3d_begin(G3D_LINES); - for(i=0; i= hb->pos.z) continue; - p = hb->plist[i]; - prevpos = start[i]; - while(p) { - g3d_color3b(p->r, p->g, p->b); - g3d_vertex(prevpos.x, prevpos.y, prevpos.z); - g3d_vertex(p->pos.x, p->pos.y, p->pos.z); - prevpos = p->pos; - p = p->next; - } - } - g3d_end(); - - - g3d_push_matrix(); - g3d_mult_matrix(hb->xform); - zsort_mesh(&sphmesh); - draw_mesh(&sphmesh); - g3d_pop_matrix(); - - g3d_begin(G3D_LINES); - for(i=0; ipos.z) continue; - p = hb->plist[i]; - prevpos = start[i]; - while(p) { - g3d_color3b(p->r, p->g, p->b); - g3d_vertex(prevpos.x, prevpos.y, prevpos.z); - g3d_vertex(p->pos.x, p->pos.y, p->pos.z); - prevpos = p->pos; - p = p->next; - } - } - g3d_end(); - -} - - -static struct particle *palloc(void) -{ - return malloc(sizeof(struct particle)); -} - -void pfree(struct particle *p) -{ - free(p); -} diff --git a/src/infcubes.c b/src/infcubes.c deleted file mode 100644 index dd1bd33..0000000 --- a/src/infcubes.c +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include -#include -#include -#include "demo.h" -#include "3dgfx.h" -#include "screen.h" -#include "cfgopt.h" -#include "polyfill.h" -#include "imago2.h" -#include "gfxutil.h" -#include "mesh.h" - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); -static int gen_phong_tex(struct pimage *img, int xsz, int ysz, float sexp, - float offx, float offy, int dr, int dg, int db, int sr, int sg, int sb); - -static struct screen scr = { - "infcubes", - init, - destroy, - start, 0, - draw -}; - -static float cam_theta = -29, cam_phi = 35; -static float cam_dist = 6; -static struct pimage tex_inner, tex_outer; -static struct g3d_mesh mesh_cube, mesh_cube2; - -struct screen *infcubes_screen(void) -{ - return &scr; -} - -#define PHONG_TEX_SZ 128 - -static int init(void) -{ - static const float scalemat[16] = {-6, 0, 0, 0, 0, -6, 0, 0, 0, 0, -6, 0, 0, 0, 0, 1}; - /* - if(!(tex_inner.pixels = img_load_pixels("data/crate.jpg", &tex_inner.width, - &tex_inner.height, IMG_FMT_RGB24))) { - fprintf(stderr, "infcubes: failed to load crate texture\n"); - return -1; - } - convimg_rgb24_rgb16(tex_inner.pixels, (unsigned char*)tex_inner.pixels, tex_inner.width, tex_inner.height); - */ - gen_phong_tex(&tex_inner, PHONG_TEX_SZ, PHONG_TEX_SZ, 5.0f, 0, 0, 10, 50, 92, 192, 192, 192); - - if(!(tex_outer.pixels = img_load_pixels("data/refmap1.jpg", &tex_outer.width, - &tex_outer.height, IMG_FMT_RGB24))) { - fprintf(stderr, "infcubes: failed to load outer texture\n"); - return -1; - } - convimg_rgb24_rgb16(tex_outer.pixels, (unsigned char*)tex_outer.pixels, tex_outer.width, tex_outer.height); - /*gen_phong_tex(&tex_outer, PHONG_TEX_SZ, PHONG_TEX_SZ, 5.0f, 50, 50, 50, 255, 255, 255);*/ - - /* - if(gen_cube_mesh(&mesh_cube, 1.0f, 3) == -1) { - return -1; - } - */ - if(load_mesh(&mesh_cube, "data/bevelbox.obj") == -1) { - return -1; - } - if(load_mesh(&mesh_cube2, "data/bevelbox.obj") == -1) { - return -1; - } - apply_mesh_xform(&mesh_cube2, scalemat); - normalize_mesh_normals(&mesh_cube2); - return 0; -} - -static void destroy(void) -{ - img_free_pixels(tex_inner.pixels); -} - -static void start(long trans_time) -{ - g3d_matrix_mode(G3D_PROJECTION); - g3d_load_identity(); - g3d_perspective(70.0, 1.3333333, 0.5, 100.0); - - g3d_enable(G3D_CULL_FACE); - g3d_disable(G3D_LIGHTING); - g3d_enable(G3D_LIGHT0); -} - -static void update(void) -{ - mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); -} - -static void draw(void) -{ - float t = (float)time_msec / 16.0f; - update(); - - g3d_matrix_mode(G3D_MODELVIEW); - g3d_load_identity(); - g3d_translate(0, 0, -cam_dist); - g3d_rotate(cam_phi, 1, 0, 0); - g3d_rotate(cam_theta, 0, 1, 0); - if(opt.sball) { - g3d_mult_matrix(sball_matrix); - } - - memset(fb_pixels, 0, fb_width * fb_height * 2); - - g3d_polygon_mode(G3D_FLAT); - g3d_enable(G3D_TEXTURE_2D); - g3d_enable(G3D_TEXTURE_GEN); - - g3d_push_matrix(); - g3d_rotate(t, 1, 0, 0); - g3d_rotate(t, 0, 1, 0); - g3d_set_texture(tex_outer.width, tex_outer.height, tex_outer.pixels); - draw_mesh(&mesh_cube2); - g3d_pop_matrix(); - - g3d_set_texture(tex_inner.width, tex_inner.height, tex_inner.pixels); - draw_mesh(&mesh_cube); - g3d_disable(G3D_TEXTURE_GEN); - - swap_buffers(fb_pixels); -} - -static int gen_phong_tex(struct pimage *img, int xsz, int ysz, float sexp, - float offx, float offy, int dr, int dg, int db, int sr, int sg, int sb) -{ - int i, j; - float u, v, du, dv; - uint16_t *pix; - - if(!(img->pixels = malloc(xsz * ysz * sizeof *pix))) { - return -1; - } - pix = img->pixels; - - du = 2.0f / (float)(xsz - 1); - dv = 2.0f / (float)(ysz - 1); - - v = -1.0f - offy; - for(i=0; i 255) r = 255; - if(g > 255) g = 255; - if(b > 255) b = 255; - - *pix++ = PACK_RGB16(r, g, b); - - u += du; - } - v += dv; - } - - img->width = xsz; - img->height = ysz; - return 0; -} diff --git a/src/metaball.c b/src/metaball.c deleted file mode 100644 index 9404912..0000000 --- a/src/metaball.c +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include -#include -#include "screen.h" -#include "demo.h" -#include "3dgfx.h" -#include "gfxutil.h" -#include "util.h" -#include "metasurf.h" -#include "mesh.h" - -struct metaball { - float energy; - float pos[3]; -}; - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); - -static void calc_voxel_field(void); - -static struct screen scr = { - "metaballs", - init, - destroy, - start, 0, - draw -}; - -static float cam_theta, cam_phi = 25; -static float cam_dist = 10; -static struct g3d_mesh mmesh; - -static struct metasurface *msurf; - -#define VOL_SZ 32 -#define VOL_SCALE 10.0f -#define VOX_DIST (VOL_SCALE / VOL_SZ) -#define VOL_HALF_SCALE (VOL_SCALE * 0.5f) - -#define NUM_MBALLS 3 -static struct metaball mball[NUM_MBALLS]; - -static int dbg; - -struct screen *metaballs_screen(void) -{ - return &scr; -} - -static int init(void) -{ - mball[0].energy = 1.2; - mball[1].energy = 0.8; - mball[2].energy = 1.0; - - if(!(msurf = msurf_create())) { - fprintf(stderr, "failed to initialize metasurf\n"); - return -1; - } - msurf_set_resolution(msurf, VOL_SZ, VOL_SZ, VOL_SZ); - msurf_set_bounds(msurf, -VOL_HALF_SCALE, -VOL_HALF_SCALE, -VOL_HALF_SCALE, - VOL_HALF_SCALE, VOL_HALF_SCALE, VOL_HALF_SCALE); - msurf_set_threshold(msurf, 1.7); - msurf_set_inside(msurf, MSURF_GREATER); - - mmesh.prim = G3D_TRIANGLES; - mmesh.varr = 0; - mmesh.iarr = 0; - mmesh.vcount = mmesh.icount = 0; - - return 0; -} - -static void destroy(void) -{ - msurf_free(msurf); -} - -static void start(long trans_time) -{ - g3d_matrix_mode(G3D_PROJECTION); - g3d_load_identity(); - g3d_perspective(50.0, 1.3333333, 0.5, 100.0); - - g3d_enable(G3D_CULL_FACE); - g3d_enable(G3D_LIGHTING); - g3d_enable(G3D_LIGHT0); - - g3d_polygon_mode(G3D_GOURAUD); -} - -static void update(void) -{ - int i, j; - float tsec = time_msec / 1000.0f; - static float phase[] = {0.0, M_PI / 3.0, M_PI * 0.8}; - static float speed[] = {0.8, 1.4, 1.0}; - static float scale[][3] = {{1, 2, 0.8}, {0.5, 1.6, 0.6}, {1.5, 0.7, 0.5}}; - static float offset[][3] = {{0, 0, 0}, {0.25, 0, 0}, {-0.2, 0.15, 0.2}}; - - mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); - - for(i=0; i -#include - -#include "demo.h" -#include "screen.h" - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); - -static struct screen scr = { - "plasma", - init, - destroy, - start, - 0, - draw -}; - -static unsigned long startingTime; - -#define PSIN_SIZE 4096 -#define PPAL_SIZE 256 - -static unsigned char *psin1, *psin2, *psin3; -static unsigned short *plasmaPal; - -static unsigned short myBuffer[320 * 240]; - - -struct screen *plasma_screen(void) -{ - return &scr; -} - -static int init(void) -{ - int i; - - psin1 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE); - psin2 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE); - psin3 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE); - - for (i = 0; i < PSIN_SIZE; i++) - { - psin1[i] = (unsigned char)(sin((double)i / 45.0) * 63.0 + 63.0); - psin2[i] = (unsigned char)(sin((double)i / 75.0) * 42.0 + 42.0); - psin3[i] = (unsigned char)(sin((double)i / 32.0) * 88.0 + 88.0); - } - - plasmaPal = (unsigned short*)malloc(sizeof(unsigned short) * PPAL_SIZE); - for (i=0; i 127) c = 255 - c; - c >>= 2; - g = 31 - c; - r = c; - b = g; - plasmaPal[i] = (r<<11) | (g<<5) | b; - } - - return 0; -} - -static void destroy(void) -{ - free(psin1); - free(psin2); - free(psin3); -} - -static void start(long trans_time) -{ - startingTime = time_msec; -} - -static void draw(void) -{ - int x, y; - unsigned char c; - unsigned char s1, s2; - - float dt = (float)(time_msec - startingTime) / 1000.0f; - int t1 = sin(0.1f * dt) * 132 + 132; - int t2 = sin(0.2f * dt) * 248 + 248; - int t3 = sin(0.5f * dt) * 380 + 380; - - unsigned int *vram32 = (unsigned int*)fb_pixels; - unsigned int p0, p1; - for (y = 0; y < fb_height; y++) - { - s1 = psin2[y + t2]; - s2 = psin3[y + t1]; - for (x = 0; x < fb_width; x+=2) - { - c = psin1[x + t1] + s1 + psin3[x + y + t3] + psin1[psin2[x + t2] + s2 + t3]; - p0 = plasmaPal[c]; - c = psin1[x + 1 + t1] + s1 + psin3[x + 1 + y + t3] + psin1[psin2[x + 1 + t2] + s2 + t3]; - p1 = plasmaPal[c]; - - *vram32++ = (p1 << 16) | p0; - } - } - - swap_buffers(0); -} diff --git a/src/polytest.c b/src/polytest.c deleted file mode 100644 index 0b05313..0000000 --- a/src/polytest.c +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include -#include -#include -#include "screen.h" -#include "demo.h" -#include "3dgfx.h" -#include "gfxutil.h" -#include "polyfill.h" /* just for struct pimage */ -#include "cfgopt.h" -#include "mesh.h" -#include "bsptree.h" - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void draw(void); -static void draw_lowres_raster(void); -static void keypress(int key); -static int gen_texture(struct pimage *img, int xsz, int ysz); - -static struct screen scr = { - "polytest", - init, - destroy, - start, 0, - draw, - keypress -}; - -static float cam_theta, cam_phi = 25; -static float cam_dist = 3; -static struct g3d_mesh cube, torus; -static struct bsptree torus_bsp; - -static struct pimage tex; - -static int use_bsp = 0; - -#define LOWRES_SCALE 10 -static uint16_t *lowres_pixels; -static int lowres_width, lowres_height; - -struct screen *polytest_screen(void) -{ - return &scr; -} - -static int init(void) -{ - int i; - - gen_cube_mesh(&cube, 1.0, 0); - gen_torus_mesh(&torus, 1.0, 0.25, 24, 12); - /* scale texcoords */ - for(i=0; ipixels = malloc(xsz * ysz * sizeof *pix))) { - return -1; - } - pix = img->pixels; - - for(i=0; iwidth = xsz; - img->height = ysz; - return 0; -} diff --git a/src/scr/bump.c b/src/scr/bump.c new file mode 100644 index 0000000..b82594b --- /dev/null +++ b/src/scr/bump.c @@ -0,0 +1,328 @@ +// Bump effect (not moving yet of course, I have many ideas on this to commit before it's ready) + +#include +#include +#include +#include + +#include "demo.h" +#include "screen.h" + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); + +static struct screen scr = { + "bump", + init, + destroy, + start, + 0, + draw +}; + +struct point { + int x, y; +}; + +#define NUM_BIG_LIGHTS 3 +#define BIG_LIGHT_WIDTH 256 +#define BIG_LIGHT_HEIGHT BIG_LIGHT_WIDTH + +#define NUM_PARTICLES 64 +#define PARTICLE_LIGHT_WIDTH 32 +#define PARTICLE_LIGHT_HEIGHT 32 + + +static unsigned long startingTime; + +static unsigned char *heightmap; +static unsigned short *lightmap; +static int *bumpOffset; + +static unsigned short *bigLight[NUM_BIG_LIGHTS]; +static struct point bigLightPoint[NUM_BIG_LIGHTS]; + +static unsigned short *particleLight; +static struct point particlePoint[NUM_PARTICLES]; + +struct screen *bump_screen(void) +{ + return &scr; +} + +static int init(void) +{ + int i, j, x, y, c, r, g, b; + + const int numBlurs = 3; + const int lightRadius = BIG_LIGHT_WIDTH / 2; + const int particleRadius = PARTICLE_LIGHT_WIDTH / 2; + + const int bigLightSize = BIG_LIGHT_WIDTH * BIG_LIGHT_HEIGHT; + const int particleLightSize = PARTICLE_LIGHT_WIDTH * PARTICLE_LIGHT_HEIGHT; + const int fb_size = fb_width * fb_height; + + // Just some parameters to temporary test the colors of 3 lights + // if every light uses it's own channel bits, it's better + const float rgbMul[9] = { 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f}; + + heightmap = malloc(sizeof(*heightmap) * fb_size); + lightmap = malloc(sizeof(*lightmap) * fb_size); + bumpOffset = malloc(sizeof(*bumpOffset) * fb_size); + + for (i = 0; i < NUM_BIG_LIGHTS; i++) + bigLight[i] = malloc(sizeof(*bigLight[i]) * bigLightSize); + + particleLight = malloc(sizeof(*particleLight) * particleLightSize); + + memset(lightmap, 0, sizeof(*lightmap) * fb_size); + memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size); + memset(particlePoint, 0, sizeof(*particlePoint) * NUM_PARTICLES); + + // Create random junk + for (i = 0; i < fb_size; i++) + heightmap[i] = rand() & 255; + + // Blur to smooth + for (j = 0; j < numBlurs; j++) + for (i = 0; i < fb_size; i++) + heightmap[i] = (heightmap[abs((i - 1) % fb_size)] + heightmap[abs((i + 1) % fb_size)] + heightmap[abs((i - fb_width) % fb_size)] + heightmap[abs((i + fb_width) % fb_size)]) >> 2; + + // Inclination precalculation + i = 0; + for (y = 0; y < fb_height; y++) + { + for (x = 0; x < fb_width; x++) + { + const float offsetPower = 0.75f; + int dx, dy, xp, yp; + + dx = i < fb_size - 1 ? (int)((heightmap[i] - heightmap[i + 1]) * offsetPower) : 0; + dy = i < fb_size - fb_width ? (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower) : 0; + + xp = x + dx; + if (xp < 0) xp = 0; + if (xp > fb_width - 1) xp = fb_width - 1; + + yp = y + dy; + if (yp < 0) yp = 0; + if (yp > fb_height - 1) yp = fb_height - 1; + + bumpOffset[i++] = yp * fb_width + xp; + } + } + + // Generate three lights + i = 0; + for (y = 0; y < BIG_LIGHT_HEIGHT; y++) + { + int yc = y - (BIG_LIGHT_HEIGHT / 2); + for (x = 0; x < BIG_LIGHT_WIDTH; x++) + { + int xc = x - (BIG_LIGHT_WIDTH / 2); + float d = (float)sqrt(xc * xc + yc * yc); + float invDist = ((float)lightRadius - (float)sqrt(xc * xc + yc * yc)) / (float)lightRadius; + if (invDist < 0.0f) invDist = 0.0f; + + c = (int)(invDist * 63); + r = c >> 1; + g = c; + b = c >> 1; + + for (j = 0; j < NUM_BIG_LIGHTS; j++) + { + bigLight[j][i] = ((int)(r * rgbMul[j * 3]) << 11) | ((int)(g * rgbMul[j * 3 + 1]) << 5) | (int)(b * rgbMul[j * 3 + 2]); + } + i++; + } + } + + i = 0; + for (y = 0; y < PARTICLE_LIGHT_HEIGHT; y++) + { + int yc = y - (PARTICLE_LIGHT_HEIGHT / 2); + for (x = 0; x < PARTICLE_LIGHT_WIDTH; x++) + { + int xc = x - (PARTICLE_LIGHT_WIDTH / 2); + + float invDist = ((float)particleRadius - (float)sqrt(xc * xc + yc * yc)) / (float)particleRadius; + if (invDist < 0.0f) invDist = 0.0f; + + c = (int)(pow(invDist, 0.75f) * 63); + particleLight[i++] = ((c >> 1) << 11) | (c << 5) | (c >> 1); + } + } + + return 0; +} + +static void destroy(void) +{ +} + +static void start(long trans_time) +{ + startingTime = time_msec; +} + +static void eraseArea(struct point *p, int width, int height) +{ + int x, y, dx; + unsigned short *dst; + + int x0 = p->x; + int y0 = p->y; + int x1 = p->x + width; + int y1 = p->y + height; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > fb_width) x1 = fb_width; + if (y1 > fb_height) y1 = fb_height; + + dx = x1 - x0; + + dst = lightmap + y0 * fb_width + x0; + + for (y = y0; y < y1; y++) + { + for (x = x0; x < x1; x++) + { + *dst++ = 0; + } + dst += fb_width - dx; + } +} + + +static void renderLight(struct point *p, int width, int height, unsigned short *light) +{ + int x, y, dx; + unsigned short *src, *dst; + + int x0 = p->x; + int y0 = p->y; + int x1 = p->x + width; + int y1 = p->y + height; + + int xl = 0; + int yl = 0; + + if (x0 < 0) + { + xl = -x0; + x0 = 0; + } + + if (y0 < 0) + { + yl = -y0; + y0 = 0; + } + + if (x1 > fb_width) x1 = fb_width; + if (y1 > fb_height) y1 = fb_height; + + dx = x1 - x0; + + dst = lightmap + y0 * fb_width + x0; + src = light + yl * width + xl; + + for (y = y0; y < y1; y++) + { + for (x = x0; x < x1; x++) + { + *dst++ |= *src++; + } + dst += fb_width - dx; + src += width - dx; + } +} + +static void eraseLights() +{ + int i; + for (i = 0; i < NUM_BIG_LIGHTS; i++) + eraseArea(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT); +} + +static void renderLights() +{ + int i; + for (i = 0; i < NUM_BIG_LIGHTS; i++) + renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]); +} + +static void renderParticles() +{ + int i; + for (i = 0; i < NUM_PARTICLES; i++) + renderLight(&particlePoint[i], PARTICLE_LIGHT_WIDTH, PARTICLE_LIGHT_HEIGHT, particleLight); +} + +static void animateLights() +{ + struct point center; + float dt = (float)(time_msec - startingTime) / 1000.0f; + float tt = 1.0f - sin(dt); + float disperse = tt * 64.0f; + + center.x = (fb_width >> 1) - (BIG_LIGHT_WIDTH / 2); + center.y = (fb_height >> 1) - (BIG_LIGHT_HEIGHT / 2); + + bigLightPoint[0].x = center.x + sin(1.2f * dt) * (144.0f + disperse); + bigLightPoint[0].y = center.y + sin(0.8f * dt) * (148.0f + disperse); + + bigLightPoint[1].x = center.x + sin(1.5f * dt) * (156.0f + disperse); + bigLightPoint[1].y = center.y + sin(1.1f * dt) * (92.0f + disperse); + + bigLightPoint[2].x = center.x + sin(2.0f * dt) * (112.0f + disperse); + bigLightPoint[2].y = center.y + sin(1.3f * dt) * (136.0f + disperse); +} + +static void renderBump(unsigned short *vram) +{ + int i; + for (i = 0; i < fb_width * fb_height; i++) + { + unsigned short c = lightmap[bumpOffset[i]]; + *vram++ = c; + } +} + +static void animateParticles() +{ + int i; + struct point center; + float dt = (float)(time_msec - startingTime) / 2000.0f; + float tt = sin(dt); + + center.x = (fb_width >> 1) - (PARTICLE_LIGHT_WIDTH / 2); + center.y = (fb_height >> 1) - (PARTICLE_LIGHT_HEIGHT / 2); + + for (i = 0; i < NUM_PARTICLES; i++) + { + particlePoint[i].x = center.x + (sin(1.2f * (i*i*i + dt)) * 74.0f + sin(0.6f * (i + dt)) * 144.0f) * tt; + particlePoint[i].y = center.y + (sin(1.8f * (i + dt)) * 68.0f + sin(0.5f * (i*i + dt)) * 132.0f) * tt; + } +} + +static void draw(void) +{ + memset(lightmap, 0, fb_width * fb_height * sizeof(*lightmap)); + + //eraseLights(); + animateLights(); + renderLights(); + + animateParticles(); + renderParticles(); + + renderBump((unsigned short*)fb_pixels); + + swap_buffers(0); +} diff --git a/src/scr/fract.c b/src/scr/fract.c new file mode 100644 index 0000000..6eeb678 --- /dev/null +++ b/src/scr/fract.c @@ -0,0 +1,95 @@ +#include +#include +#include "demo.h" +#include "screen.h" +#include "gfxutil.h" + +struct vec2x { + long x, y; +}; + +static int init(void); +static void destroy(void); +static void draw(void); +static int julia(long x, long y, long cx, long cy, int max_iter); + +static struct screen scr = { + "fract", + init, + destroy, + 0, 0, + draw +}; + +/*static long aspect_24x8 = (long)(1.3333333 * 256.0);*/ +static long xscale_24x8 = (long)(1.3333333 * 1.2 * 256.0); +static long yscale_24x8 = (long)(1.2 * 256.0); +static int cx, cy; +static int max_iter = 50; + +#define WALK_SIZE 20 + +struct screen *fract_screen(void) +{ + return &scr; +} + +static int init(void) +{ + return 0; +} + +static void destroy(void) +{ +} + +static void draw(void) +{ + int i, j; + unsigned short *pixels = fb_pixels; + + cx = mouse_x; + cy = mouse_y; + + for(i=0; i> 3) | ((pidx >> 2) << 5) | ((pidx >> 3) << 11); + } + } + + pixels = fb_pixels; + pixels[mouse_y * fb_width + mouse_x] = 0xffe; + swap_buffers(0); +} + +static long normalize_coord(long x, long range) +{ + /* 2 * x / range - 1*/ + return (x << 17) / range - 65536; +} + +static int julia(long x, long y, long cx, long cy, int max_iter) +{ + int i; + + /* convert to fixed point roughly [-1, 1] */ + x = (normalize_coord(x, fb_width) >> 8) * xscale_24x8; + y = (normalize_coord(y, fb_height) >> 8) * yscale_24x8; + cx = (normalize_coord(cx, fb_width) >> 8) * xscale_24x8; + cy = (normalize_coord(cy, fb_height) >> 8) * yscale_24x8; + + for(i=0; i> 8; + long py = y >> 8; + + if(px * px + py * py > (4 << 16)) { + break; + } + x = px * px - py * py + cx; + y = (px * py << 1) + cy; + } + + return i < max_iter ? (256 * i / max_iter) : 0; +} diff --git a/src/scr/greets.c b/src/scr/greets.c new file mode 100644 index 0000000..8b128c6 --- /dev/null +++ b/src/scr/greets.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include "demo.h" +#include "3dgfx.h" +#include "screen.h" +#include "cfgopt.h" +#include "imago2.h" +#include "util.h" +#include "gfxutil.h" +#include "timer.h" +#include "smoketxt.h" + +#ifdef MSDOS +#include "dos/gfx.h" /* for wait_vsync assembly macro */ +#else +void wait_vsync(void); +#endif + +#define BLUR_RAD 5 + + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); + + +static struct screen scr = { + "greets", + init, + destroy, + start, 0, + draw +}; + +static long start_time; + +static struct smktxt *stx; + +static uint16_t *cur_smokebuf, *prev_smokebuf; +static int smokebuf_size; +#define smokebuf_start (cur_smokebuf < prev_smokebuf ? cur_smokebuf : prev_smokebuf) +#define swap_smoke_buffers() \ + do { \ + uint16_t *tmp = cur_smokebuf; \ + cur_smokebuf = prev_smokebuf; \ + prev_smokebuf = tmp; \ + } while(0) + +static float cam_theta, cam_phi = 25; +static float cam_dist = 3; + +struct screen *greets_screen(void) +{ + return &scr; +} + + +static int init(void) +{ + if(!(stx = create_smktxt("data/greets1.png", "data/vfield1"))) { + return -1; + } + + smokebuf_size = fb_width * fb_height * sizeof *cur_smokebuf; + if(!(cur_smokebuf = malloc(smokebuf_size * 2))) { + perror("failed to allocate smoke framebuffer"); + return -1; + } + prev_smokebuf = cur_smokebuf + fb_width * fb_height; + + return 0; +} + +static void destroy(void) +{ + free(smokebuf_start); + destroy_smktxt(stx); +} + +static void start(long trans_time) +{ + g3d_matrix_mode(G3D_PROJECTION); + g3d_load_identity(); + g3d_perspective(50.0, 1.3333333, 0.5, 100.0); + + memset(smokebuf_start, 0, smokebuf_size * 2); + + start_time = time_msec; +} + +static void update(void) +{ + static long prev_msec; + static int prev_mx, prev_my; + static unsigned int prev_bmask; + + long msec = time_msec - start_time; + float dt = (msec - prev_msec) / 1000.0f; + prev_msec = msec; + + if(mouse_bmask) { + if((mouse_bmask ^ prev_bmask) == 0) { + int dx = mouse_x - prev_mx; + int dy = mouse_y - prev_my; + + if(dx || dy) { + if(mouse_bmask & 1) { + cam_theta += dx * 1.0; + cam_phi += dy * 1.0; + + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; + } + if(mouse_bmask & 4) { + cam_dist += dy * 0.5; + + if(cam_dist < 0) cam_dist = 0; + } + } + } + } + prev_mx = mouse_x; + prev_my = mouse_y; + prev_bmask = mouse_bmask; + + update_smktxt(stx, dt); +} + +static void draw(void) +{ + int i, j; + uint16_t *dest, *src; + unsigned long msec; + static unsigned long last_swap; + + update(); + + g3d_matrix_mode(G3D_MODELVIEW); + g3d_load_identity(); + g3d_translate(0, 0, -cam_dist); + g3d_rotate(cam_phi, 1, 0, 0); + g3d_rotate(cam_theta, 0, 1, 0); + if(opt.sball) { + g3d_mult_matrix(sball_matrix); + } + + memcpy(cur_smokebuf, prev_smokebuf, smokebuf_size); + + g3d_framebuffer(fb_width, fb_height, cur_smokebuf); + draw_smktxt(stx); + g3d_framebuffer(fb_width, fb_height, fb_pixels); + + dest = fb_pixels; + src = cur_smokebuf; + for(i=0; i +#include +#include +#include +#include +#include "imago2.h" +#include "demo.h" +#include "screen.h" + +/* APPROX. 170 FPS Minimum */ + +typedef struct { + unsigned int w, h; + unsigned char *scans; +} RLEBitmap; + +static RLEBitmap *rleCreate(unsigned int w, unsigned int h); +static void rleDestroy(RLEBitmap *b); +static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, + RLEBitmap *bitmap, int blitX, int blitY); +static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride, + RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY); +static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride, + RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY); +static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h); + +static void updatePropeller(float t); + +#define BG_FILENAME "data/grise.png" +#define GROBJ_01_FILENAME "data/grobj_01.png" + +#define BB_SIZE 512 /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */ + +/* Every backBuffer scanline is guaranteed to have that many dummy pixels before and after */ +#define PIXEL_PADDING 32 + +/* Make sure this is less than PIXEL_PADDING*/ +#define MAX_DISPLACEMENT 16 + +#define MIN_SCROLL PIXEL_PADDING +#define MAX_SCROLL (backgroundW - fb_width - MIN_SCROLL) + +#define FAR_SCROLL_SPEED 15.0f +#define NEAR_SCROLL_SPEED 120.0f + +#define HORIZON_HEIGHT 100 +#define REFLECTION_HEIGHT (240 - HORIZON_HEIGHT) + +#define NORMALMAP_SCANLINE 372 + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void stop(long trans_time); +static void draw(void); + +static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned int pixelCount); +static void processNormal(); +static void initScrollTables(); +static void updateScrollTables(float dt); + + + +static unsigned short *background = 0; +static int backgroundW = 0; +static int backgroundH = 0; + +static unsigned int lastFrameTime = 0; +static float lastFrameDuration = 0.0f; + +static short *displacementMap; + +static unsigned short *backBuffer; + +static float scrollScaleTable[REFLECTION_HEIGHT]; +static float scrollTable[REFLECTION_HEIGHT]; +static int scrollTableRounded[REFLECTION_HEIGHT]; +static int scrollModTable[REFLECTION_HEIGHT]; +static float nearScrollAmount = 0.0f; + +static unsigned char miniFXBuffer[1024]; + +static RLEBitmap *grobj = 0; +static RLEBitmap *rlePropeller = 0; + +static struct screen scr = { + "galaxyrise", + init, + destroy, + start, + 0, + draw +}; + +struct screen *grise_screen(void) +{ + return &scr; +} + +static int init(void) +{ + unsigned char *tmpBitmap; + int tmpBitmapW, tmpBitmapH; + + /* Allocate back buffer */ + backBuffer = (unsigned short*) calloc(BB_SIZE * BB_SIZE, sizeof(unsigned short)); + + /* grise.png contains the background (horizon), baked reflection and normalmap for displacement */ + if (!(background = img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) { + fprintf(stderr, "failed to load image " BG_FILENAME "\n"); + return -1; + } + + /* Convert to 16bpp */ + convert32To16((unsigned int*)background, background, backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */ + + /* Load reflected objects */ + if (!(tmpBitmap = img_load_pixels(GROBJ_01_FILENAME, &tmpBitmapW, &tmpBitmapH, IMG_FMT_GREY8))) { + fprintf(stderr, "failed to load image " GROBJ_01_FILENAME "\n"); + return -1; + } + + grobj = rleEncode(0, tmpBitmap, tmpBitmapW, tmpBitmapH); + + img_free_pixels(tmpBitmap); + + initScrollTables(); + + processNormal(); + + return 0; +} + +static void destroy(void) +{ + free(backBuffer); + backBuffer = 0; + + img_free_pixels(background); + + rleDestroy(grobj); +} + +static void start(long trans_time) +{ + lastFrameTime = time_msec; +} + + +static void draw(void) +{ + int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / fb_width; + unsigned short *dst = backBuffer + PIXEL_PADDING; + unsigned short *src = background + scroll; + int scanline = 0; + int i = 0; + short *dispScanline; + int d; + int accum = 0; + int md, sc; + int scrolledIndex; + + lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; + lastFrameTime = time_msec; + + /* Update mini-effects here */ + updatePropeller(4.0f * time_msec / 1000.0f); + + /* First, render the horizon */ + for (scanline = 0; scanline < HORIZON_HEIGHT; scanline++) { + memcpy(dst, src, fb_width * 2); + src += backgroundW; + dst += BB_SIZE; + } + + /* Create scroll offsets for all scanlines of the normalmap */ + updateScrollTables(lastFrameDuration); + + /* Render the baked reflection one scanline below its place, so that + * the displacement that follows will be done in a cache-friendly way + */ + src -= PIXEL_PADDING; /* We want to also fill the PADDING pixels here */ + dst = backBuffer + (HORIZON_HEIGHT + 1) * BB_SIZE; + for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { + memcpy(dst, src, (fb_width + PIXEL_PADDING) * 2); + src += backgroundW; + dst += BB_SIZE; + } + + /* Blit reflections first, to be displaced */ + for (i = 0; i < 5; i++) rleBlitScaleInv(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 200, 1.0f, 1.8f); + + /* Perform displacement */ + dst = backBuffer + HORIZON_HEIGHT * BB_SIZE + PIXEL_PADDING; + src = dst + BB_SIZE; /* The pixels to be displaced are 1 scanline below */ + dispScanline = displacementMap; + for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { + + md = scrollModTable[scanline]; + sc = scrollTableRounded[scanline]; + accum = 0; + + for (i = 0; i < fb_width; i++) { + /* Try to immitate modulo without the division */ + if (i == md) accum += md; + scrolledIndex = i - accum + sc; + if (scrolledIndex >= md) scrolledIndex -= md; + + /* Displace */ + d = dispScanline[scrolledIndex]; + *dst++ = src[i + d]; + } + src += backgroundW; + dst += BB_SIZE - fb_width; + dispScanline += backgroundW; + } + + /* Then after displacement, blit the objects */ + for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 100); + + /* Blit effect to framebuffer */ + src = backBuffer + PIXEL_PADDING; + dst = fb_pixels; + for (scanline = 0; scanline < fb_height; scanline++) { + memcpy(dst, src, fb_width * 2); + src += BB_SIZE; + dst += fb_width; + } + + swap_buffers(0); +} + +/* src and dst can be the same */ +static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned int pixelCount) { + unsigned int p; + while (pixelCount) { + p = *src32++; + *dst16++ = ((p << 8) & 0xF800) /* R */ + | ((p >> 5) & 0x07E0) /* G */ + | ((p >> 19) & 0x001F); /* B */ + pixelCount--; + } +} + +/* Normal map preprocessing */ +/* Scale normal with depth and unpack R component (horizontal component) */ +static void processNormal() { + int scanline; + int i; + int x; + short maxDisplacement = 0; + short minDisplacement = 256; + unsigned short *dst; + short *dst2; + unsigned int *normalmap = (unsigned int*)background; + normalmap += NORMALMAP_SCANLINE * backgroundW; + dst = (unsigned short*)normalmap; + displacementMap = (short*)dst; + dst2 = displacementMap; + + for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { + scrollModTable[scanline] = (int) (backgroundW / scrollScaleTable[scanline] + 0.5f); + for (i = 0; i < backgroundW; i++) { + x = (int)(i * scrollScaleTable[scanline] + 0.5f); + if (x < backgroundW) { + *dst = (unsigned short)(normalmap[x] >> 8) & 0xFF; + if ((short)*dst > maxDisplacement) maxDisplacement = (short)(*dst); + if ((short)*dst < minDisplacement) minDisplacement = (short)(*dst); + } else { + *dst = 0; + } + dst++; + } + normalmap += backgroundW; + } + + if (maxDisplacement == minDisplacement) { + printf("Warning: grise normalmap fucked up\n"); + return; + } + + /* Second pass - subtract half maximum displacement to displace in both directions */ + for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { + for (i = 0; i < backgroundW; i++) { + /* Remember that MIN_SCROLL is the padding around the screen, so ti's the maximum displacement we can get (positive & negative) */ + *dst2 = 2 * MAX_DISPLACEMENT * (*dst2 - minDisplacement) / (maxDisplacement - minDisplacement) - MAX_DISPLACEMENT; + *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] + 0.5f); /* Displacements must also scale with distance*/ + dst2++; + } + } +} + +static float distanceScale(int scanline) { + float farScale, t; + farScale = (float)NEAR_SCROLL_SPEED / (float)FAR_SCROLL_SPEED; + t = (float)scanline / ((float)REFLECTION_HEIGHT - 1); + return 1.0f / (1.0f / farScale + (1.0f - 1.0f / farScale) * t); +} + +static void initScrollTables() { + int i = 0; + for (i = 0; i < REFLECTION_HEIGHT; i++) { + scrollScaleTable[i] = distanceScale(i); + scrollTable[i] = 0.0f; + scrollTableRounded[i] = 0; + } +} + + +static void updateScrollTables(float dt) { + int i = 0; + + nearScrollAmount += dt * NEAR_SCROLL_SPEED; + nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f); + + for (i = 0; i < REFLECTION_HEIGHT; i++) { + scrollTable[i] = nearScrollAmount / scrollScaleTable[i]; + scrollTableRounded[i] = (int)(scrollTable[i] + 0.5f) % scrollModTable[i]; + } +} + +/* ------------------------------------------------------------------------------------------------- + * RLE STUFF + * ------------------------------------------------------------------------------------------------- + */ +/* Limit streak count per scanline so we can directly jump to specific scanline */ +#define RLE_STREAKS_PER_SCANLINE 4 +/* Every streak is encoded by 2 bytes: offset and count of black pixels in the streak */ +#define RLE_BYTES_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 +#define RLE_FILL_COLOR 0 +#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) + +#define RLE_FIXED_BITS 16 + +static int rleByteCount(int w, int h) { + return h * RLE_BYTES_PER_SCANLINE + w; +} + +static RLEBitmap *rleCreate(unsigned int w, unsigned int h) { + RLEBitmap *ret = (RLEBitmap*)malloc(sizeof(RLEBitmap)); + ret->w = w; + ret->h = h; + + /* Add some padding at the end of the buffer, with the worst case for a scanline (w/2 streaks) */ + ret->scans = (unsigned char*) calloc(rleByteCount(w, h), 1); + + return ret; +} + +static void rleDestroy(RLEBitmap *b) { + if (!b) return; + free(b->scans); + free(b); +} + +static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w, unsigned int h) { + int scanline; + int i; + int penActive = 0; + int counter = 0; + int accum = 0; + unsigned char *output; + + /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ + if (!b) b = rleCreate(w, h); + else memset(b->scans, 0, rleByteCount(b->w, b->h)); /* The following code assumes cleared array */ + + for (scanline = 0; scanline < h; scanline++) { + output = b->scans + scanline * RLE_BYTES_PER_SCANLINE; + accum = 0; + for (i = 0; i < w; i++) { + if (*pixels++) { + if (penActive) { + if (counter >= PIXEL_PADDING) { + *output++ = (unsigned char) counter; + counter = 0; + *output++ = (unsigned char)accum; + } + counter++; + accum++; + } else { + *output++ = (unsigned char)accum; + counter = 1; + accum++; + penActive = 1; + } + } else { + if (penActive) { + *output++ = (unsigned char)counter; + counter = 1; + accum++; + penActive = 0; + } else { + counter++; + accum++; + } + } + } + + if (penActive) { + *output++ = (unsigned char)counter; + } + penActive = 0; + counter = 0; + } + + return b; +} + +static void rleDistributeStreaks(RLEBitmap *bitmap) { + int scanline, halfW = bitmap->w >> 1; + unsigned char *ptr, tmp; + + ptr = bitmap->scans; + for (scanline = 0; scanline < bitmap->h; scanline++) { + if (ptr[0] >= halfW) { + tmp = ptr[0]; + ptr[0] = ptr[6]; + ptr[6] = tmp; + tmp = ptr[1]; + ptr[1] = ptr[7]; + ptr[7] = tmp; + } + + ptr += 8; + } +} + +static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, + RLEBitmap *bitmap, int blitX, int blitY) +{ + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned char *input = bitmap->scans; + unsigned short *output; + unsigned int *output32; + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + bitmap->h; scanline++) { + if (scanline < 0 || scanline >= dstH) continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = *input++; + streakLength = *input++; + + if ((streakPos + blitX) <= 0) continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int*) output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +static void interpolateScan(unsigned char *output, unsigned char *a, unsigned char *b, float t) { + static int div = 1 << 23; + int ti, i; + + t += 1.0f; + ti = (*((unsigned int*)&t)) & 0x7FFFFF; + + for (i = 0; i < RLE_BYTES_PER_SCANLINE; i++) { + if (*a == 0) { + *output++ = *b++; + a++; + } else { + if (*b == 0) { + *output++ = *a++; + b++; + } else { + *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; + } + } + } +} + +static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride, + RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY) +{ + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/ + int blitH = (int)(bitmap->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + blitH; scanline++) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int*)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + + + +static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStride, + RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY) +{ + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/ + int blitH = (int)(bitmap->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline > blitY - blitH; scanline--) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = bitmap->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int*)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst -= dstStride; + } +} + +/* ------------------------------------------------------------------------------------------------- +* PROPELLER STUFF +* ------------------------------------------------------------------------------------------------- +*/ + +#define PROPELLER_CIRCLE_RADIUS 18 +#define PROPELLER_CIRCLE_RADIUS_SQ (PROPELLER_CIRCLE_RADIUS * PROPELLER_CIRCLE_RADIUS) + +static struct { + int circleX[3]; + int circleY[3]; +} propellerState; + +static void updatePropeller(float t) { + int i, j; + int cx, cy, count = 0; + unsigned char *dst; + float x = 0.0f; + float y = 18.0f; + float nx, ny; + float cost, sint; + static float sin120 = 0.86602540378f; + static float cos120 = -0.5f; + + /* Rotate */ + sint = sin(t); + cost = cos(t); + nx = x * cost - y * sint; + ny = y * cost + x * sint; + x = nx; + y = ny; + propellerState.circleX[0] = (int)(x + 0.5f) + 16; + propellerState.circleY[0] = (int)(y + 0.5f) + 16; + + /* Rotate by 120 degrees, for the second circle */ + nx = x * cos120 - y * sin120; + ny = y * cos120 + x * sin120; + x = nx; + y = ny; + propellerState.circleX[1] = (int)(x + 0.5f) + 16; + propellerState.circleY[1] = (int)(y + 0.5f) + 16; + + /* 3rd circle */ + nx = x * cos120 - y * sin120; + ny = y * cos120 + x * sin120; + x = nx; + y = ny; + propellerState.circleX[2] = (int)(x + 0.5f) + 16; + propellerState.circleY[2] = (int)(y + 0.5f) + 16; + + /* Write effect to the mini fx buffer*/ + dst = miniFXBuffer; + for (j = 0; j < 32; j++) { + for (i = 0; i < 32; i++) { + count = 0; + + /* First circle */ + cx = propellerState.circleX[0] - i; + cy = propellerState.circleY[0] - j; + if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; + + /* 2nd circle */ + cx = propellerState.circleX[1] - i; + cy = propellerState.circleY[1] - j; + if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; + + /* 3rd circle */ + cx = propellerState.circleX[2] - i; + cy = propellerState.circleY[2] - j; + if (cx*cx + cy*cy < PROPELLER_CIRCLE_RADIUS_SQ) count++; + + *dst++ = count >= 2; + } + } + + /* Then, encode to rle */ + rlePropeller = rleEncode(rlePropeller, miniFXBuffer, 32, 32); + + /* Distribute the produced streaks so that they don't produce garbage when interpolated */ + rleDistributeStreaks(rlePropeller); +} diff --git a/src/scr/hairball.c b/src/scr/hairball.c new file mode 100644 index 0000000..89c45c3 --- /dev/null +++ b/src/scr/hairball.c @@ -0,0 +1,317 @@ +#include +#include +#include +#include +#include "demo.h" +#include "3dgfx.h" +#include "vmath.h" +#include "screen.h" +#include "util.h" +#include "cfgopt.h" +#include "mesh.h" + + +#ifdef MSDOS +#include "dos/gfx.h" /* for wait_vsync assembly macro */ +#else +void wait_vsync(void); +#endif + +#define NSPAWNPOS 64 +#define SPAWN_RATE 16.0f +//#define GRAV (-6.0f) +#define GRAV 0.0f +#define HAIR_LENGTH 20 + +struct particle { + vec3_t pos; + vec3_t vel; + int r, g, b, a; + int life; + + struct particle *next; +}; + +struct hairball { + vec3_t pos; + quat_t rot; + float xform[16]; + + struct particle *plist[NSPAWNPOS]; +}; + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); +static void update_hairball(struct hairball *hb, float dt); +static void draw_hairball(struct hairball *hb); + +static struct particle *palloc(void); +void pfree(struct particle *p); + + +static struct screen scr = { + "hairball", + init, + destroy, + start, 0, + draw +}; + +static long start_time; + +static float cam_theta, cam_phi = 15; +static float cam_dist = 8; + +static vec3_t *spawnpos, *spawndir; +static struct hairball hball; +static struct g3d_mesh sphmesh; + +struct screen *hairball_screen(void) +{ + return &scr; +} + +static int init(void) +{ + int i, j, numpt = 0; + + gen_sphere_mesh(&sphmesh, 1.0f, 12, 6); + + hball.xform[0] = hball.xform[5] = hball.xform[10] = hball.xform[15] = 1.0f; + hball.rot.w = 1.0f; + + if(!(spawnpos = malloc(NSPAWNPOS * sizeof *spawnpos)) || + !(spawndir = malloc(NSPAWNPOS * sizeof *spawndir))) { + fprintf(stderr, "failed to allocate spawnpos/dir array\n"); + return -1; + } + + while(numpt < NSPAWNPOS) { + float best_dist = -1.0f; + for(i=0; i<100; i++) { + vec3_t pos = sphrand(1.0f); + + float mindist = FLT_MAX; + for(j=0; j best_dist) { + spawnpos[numpt] = pos; + best_dist = mindist; + } + } + + spawndir[numpt] = spawnpos[numpt]; + ++numpt; + } + + return 0; +} + +static void destroy(void) +{ +} + +static void start(long trans_time) +{ + g3d_matrix_mode(G3D_PROJECTION); + g3d_load_identity(); + g3d_perspective(50.0, 1.33333, 0.5, 100.0); + + start_time = time_msec; +} + +static void update(void) +{ + static float prev_mx, prev_my; + static long prev_msec; + int mouse_dx, mouse_dy; + long msec = time_msec - start_time; + float dt = (msec - prev_msec) / 1000.0f; + prev_msec = msec; + + mouse_dx = mouse_x - prev_mx; + mouse_dy = mouse_y - prev_my; + prev_mx = mouse_x; + prev_my = mouse_y; + + + if(opt.sball) { + memcpy(hball.xform, sball_matrix, 16 * sizeof(float)); + + hball.pos.x = hball.xform[12]; + hball.pos.y = hball.xform[13]; + hball.pos.z = hball.xform[14]; + } else { + if(mouse_bmask & MOUSE_BN_MIDDLE) { + hball.pos.x += mouse_dx * 0.05; + hball.pos.y -= mouse_dy * 0.05; + } + + quat_to_mat(hball.xform, hball.rot); + hball.xform[12] = hball.pos.x; + hball.xform[13] = hball.pos.y; + hball.xform[14] = hball.pos.z; + } + + update_hairball(&hball, dt); + + mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); +} + +static void draw(void) +{ + unsigned long msec; + static unsigned long last_swap; + + update(); + + memset(fb_pixels, 0, fb_width * fb_height * 2); + + g3d_matrix_mode(G3D_MODELVIEW); + g3d_load_identity(); + g3d_translate(0, 0, -cam_dist); + g3d_rotate(cam_phi, 1, 0, 0); + g3d_rotate(cam_theta, 0, 1, 0); + + draw_hairball(&hball); + + msec = get_msec(); + if(msec - last_swap < 16) { + wait_vsync(); + } + if(!opt.vsync) { + wait_vsync(); + } + swap_buffers(fb_pixels); + last_swap = get_msec(); +} + +static void update_hairball(struct hairball *hb, float dt) +{ + int i, j, spawn_count; + struct particle pdummy, *prev, *p; + static float spawn_acc; + + /* update particles */ + for(i=0; iplist[i]; + prev = &pdummy; + while(prev && prev->next) { + p = prev->next; + if(--p->life <= 0) { + prev->next = p->next; + pfree(p); + prev = prev->next; + continue; + } + + p->pos.x += p->vel.x * dt; + p->pos.y += p->vel.y * dt; + p->pos.z += p->vel.z * dt; + p->vel.y += GRAV * dt; + + p->r = p->g = p->b = (p->life << 8) / HAIR_LENGTH - 1; + + prev = p; + } + + hb->plist[i] = pdummy.next; + } + + /* spawn new particles */ + spawn_acc += dt; + if(spawn_acc >= (1.0f / SPAWN_RATE)) { + for(i=0; ixform; + vec3_t pos = spawnpos[i]; + vec3_t dir = spawndir[i]; + + p->pos.x = mat[0] * pos.x + mat[4] * pos.y + mat[8] * pos.z + mat[12]; + p->pos.y = mat[1] * pos.x + mat[5] * pos.y + mat[9] * pos.z + mat[13]; + p->pos.z = mat[2] * pos.x + mat[6] * pos.y + mat[10] * pos.z + mat[14]; + + p->vel.x = mat[0] * dir.x + mat[4] * dir.y + mat[8] * dir.z; + p->vel.y = mat[1] * dir.x + mat[5] * dir.y + mat[9] * dir.z; + p->vel.z = mat[2] * dir.x + mat[6] * dir.y + mat[10] * dir.z; + p->life = HAIR_LENGTH; + + p->next = hb->plist[i]; + hb->plist[i] = p; + } + spawn_acc -= 1.0f / SPAWN_RATE; + } +} + +static void draw_hairball(struct hairball *hb) +{ + int i, col; + struct particle *p; + vec3_t prevpos; + vec3_t start[NSPAWNPOS]; + + for(i=0; ixform[0] * spawnpos[i].x + hb->xform[4] * spawnpos[i].y + hb->xform[8] * spawnpos[i].z + hb->xform[12]; + start[i].y = hb->xform[1] * spawnpos[i].x + hb->xform[5] * spawnpos[i].y + hb->xform[9] * spawnpos[i].z + hb->xform[13]; + start[i].z = hb->xform[2] * spawnpos[i].x + hb->xform[6] * spawnpos[i].y + hb->xform[10] * spawnpos[i].z + hb->xform[14]; + } + + g3d_begin(G3D_LINES); + for(i=0; i= hb->pos.z) continue; + p = hb->plist[i]; + prevpos = start[i]; + while(p) { + g3d_color3b(p->r, p->g, p->b); + g3d_vertex(prevpos.x, prevpos.y, prevpos.z); + g3d_vertex(p->pos.x, p->pos.y, p->pos.z); + prevpos = p->pos; + p = p->next; + } + } + g3d_end(); + + + g3d_push_matrix(); + g3d_mult_matrix(hb->xform); + zsort_mesh(&sphmesh); + draw_mesh(&sphmesh); + g3d_pop_matrix(); + + g3d_begin(G3D_LINES); + for(i=0; ipos.z) continue; + p = hb->plist[i]; + prevpos = start[i]; + while(p) { + g3d_color3b(p->r, p->g, p->b); + g3d_vertex(prevpos.x, prevpos.y, prevpos.z); + g3d_vertex(p->pos.x, p->pos.y, p->pos.z); + prevpos = p->pos; + p = p->next; + } + } + g3d_end(); + +} + + +static struct particle *palloc(void) +{ + return malloc(sizeof(struct particle)); +} + +void pfree(struct particle *p) +{ + free(p); +} diff --git a/src/scr/infcubes.c b/src/scr/infcubes.c new file mode 100644 index 0000000..dd1bd33 --- /dev/null +++ b/src/scr/infcubes.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include "demo.h" +#include "3dgfx.h" +#include "screen.h" +#include "cfgopt.h" +#include "polyfill.h" +#include "imago2.h" +#include "gfxutil.h" +#include "mesh.h" + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); +static int gen_phong_tex(struct pimage *img, int xsz, int ysz, float sexp, + float offx, float offy, int dr, int dg, int db, int sr, int sg, int sb); + +static struct screen scr = { + "infcubes", + init, + destroy, + start, 0, + draw +}; + +static float cam_theta = -29, cam_phi = 35; +static float cam_dist = 6; +static struct pimage tex_inner, tex_outer; +static struct g3d_mesh mesh_cube, mesh_cube2; + +struct screen *infcubes_screen(void) +{ + return &scr; +} + +#define PHONG_TEX_SZ 128 + +static int init(void) +{ + static const float scalemat[16] = {-6, 0, 0, 0, 0, -6, 0, 0, 0, 0, -6, 0, 0, 0, 0, 1}; + /* + if(!(tex_inner.pixels = img_load_pixels("data/crate.jpg", &tex_inner.width, + &tex_inner.height, IMG_FMT_RGB24))) { + fprintf(stderr, "infcubes: failed to load crate texture\n"); + return -1; + } + convimg_rgb24_rgb16(tex_inner.pixels, (unsigned char*)tex_inner.pixels, tex_inner.width, tex_inner.height); + */ + gen_phong_tex(&tex_inner, PHONG_TEX_SZ, PHONG_TEX_SZ, 5.0f, 0, 0, 10, 50, 92, 192, 192, 192); + + if(!(tex_outer.pixels = img_load_pixels("data/refmap1.jpg", &tex_outer.width, + &tex_outer.height, IMG_FMT_RGB24))) { + fprintf(stderr, "infcubes: failed to load outer texture\n"); + return -1; + } + convimg_rgb24_rgb16(tex_outer.pixels, (unsigned char*)tex_outer.pixels, tex_outer.width, tex_outer.height); + /*gen_phong_tex(&tex_outer, PHONG_TEX_SZ, PHONG_TEX_SZ, 5.0f, 50, 50, 50, 255, 255, 255);*/ + + /* + if(gen_cube_mesh(&mesh_cube, 1.0f, 3) == -1) { + return -1; + } + */ + if(load_mesh(&mesh_cube, "data/bevelbox.obj") == -1) { + return -1; + } + if(load_mesh(&mesh_cube2, "data/bevelbox.obj") == -1) { + return -1; + } + apply_mesh_xform(&mesh_cube2, scalemat); + normalize_mesh_normals(&mesh_cube2); + return 0; +} + +static void destroy(void) +{ + img_free_pixels(tex_inner.pixels); +} + +static void start(long trans_time) +{ + g3d_matrix_mode(G3D_PROJECTION); + g3d_load_identity(); + g3d_perspective(70.0, 1.3333333, 0.5, 100.0); + + g3d_enable(G3D_CULL_FACE); + g3d_disable(G3D_LIGHTING); + g3d_enable(G3D_LIGHT0); +} + +static void update(void) +{ + mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); +} + +static void draw(void) +{ + float t = (float)time_msec / 16.0f; + update(); + + g3d_matrix_mode(G3D_MODELVIEW); + g3d_load_identity(); + g3d_translate(0, 0, -cam_dist); + g3d_rotate(cam_phi, 1, 0, 0); + g3d_rotate(cam_theta, 0, 1, 0); + if(opt.sball) { + g3d_mult_matrix(sball_matrix); + } + + memset(fb_pixels, 0, fb_width * fb_height * 2); + + g3d_polygon_mode(G3D_FLAT); + g3d_enable(G3D_TEXTURE_2D); + g3d_enable(G3D_TEXTURE_GEN); + + g3d_push_matrix(); + g3d_rotate(t, 1, 0, 0); + g3d_rotate(t, 0, 1, 0); + g3d_set_texture(tex_outer.width, tex_outer.height, tex_outer.pixels); + draw_mesh(&mesh_cube2); + g3d_pop_matrix(); + + g3d_set_texture(tex_inner.width, tex_inner.height, tex_inner.pixels); + draw_mesh(&mesh_cube); + g3d_disable(G3D_TEXTURE_GEN); + + swap_buffers(fb_pixels); +} + +static int gen_phong_tex(struct pimage *img, int xsz, int ysz, float sexp, + float offx, float offy, int dr, int dg, int db, int sr, int sg, int sb) +{ + int i, j; + float u, v, du, dv; + uint16_t *pix; + + if(!(img->pixels = malloc(xsz * ysz * sizeof *pix))) { + return -1; + } + pix = img->pixels; + + du = 2.0f / (float)(xsz - 1); + dv = 2.0f / (float)(ysz - 1); + + v = -1.0f - offy; + for(i=0; i 255) r = 255; + if(g > 255) g = 255; + if(b > 255) b = 255; + + *pix++ = PACK_RGB16(r, g, b); + + u += du; + } + v += dv; + } + + img->width = xsz; + img->height = ysz; + return 0; +} diff --git a/src/scr/metaball.c b/src/scr/metaball.c new file mode 100644 index 0000000..9404912 --- /dev/null +++ b/src/scr/metaball.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include "screen.h" +#include "demo.h" +#include "3dgfx.h" +#include "gfxutil.h" +#include "util.h" +#include "metasurf.h" +#include "mesh.h" + +struct metaball { + float energy; + float pos[3]; +}; + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); + +static void calc_voxel_field(void); + +static struct screen scr = { + "metaballs", + init, + destroy, + start, 0, + draw +}; + +static float cam_theta, cam_phi = 25; +static float cam_dist = 10; +static struct g3d_mesh mmesh; + +static struct metasurface *msurf; + +#define VOL_SZ 32 +#define VOL_SCALE 10.0f +#define VOX_DIST (VOL_SCALE / VOL_SZ) +#define VOL_HALF_SCALE (VOL_SCALE * 0.5f) + +#define NUM_MBALLS 3 +static struct metaball mball[NUM_MBALLS]; + +static int dbg; + +struct screen *metaballs_screen(void) +{ + return &scr; +} + +static int init(void) +{ + mball[0].energy = 1.2; + mball[1].energy = 0.8; + mball[2].energy = 1.0; + + if(!(msurf = msurf_create())) { + fprintf(stderr, "failed to initialize metasurf\n"); + return -1; + } + msurf_set_resolution(msurf, VOL_SZ, VOL_SZ, VOL_SZ); + msurf_set_bounds(msurf, -VOL_HALF_SCALE, -VOL_HALF_SCALE, -VOL_HALF_SCALE, + VOL_HALF_SCALE, VOL_HALF_SCALE, VOL_HALF_SCALE); + msurf_set_threshold(msurf, 1.7); + msurf_set_inside(msurf, MSURF_GREATER); + + mmesh.prim = G3D_TRIANGLES; + mmesh.varr = 0; + mmesh.iarr = 0; + mmesh.vcount = mmesh.icount = 0; + + return 0; +} + +static void destroy(void) +{ + msurf_free(msurf); +} + +static void start(long trans_time) +{ + g3d_matrix_mode(G3D_PROJECTION); + g3d_load_identity(); + g3d_perspective(50.0, 1.3333333, 0.5, 100.0); + + g3d_enable(G3D_CULL_FACE); + g3d_enable(G3D_LIGHTING); + g3d_enable(G3D_LIGHT0); + + g3d_polygon_mode(G3D_GOURAUD); +} + +static void update(void) +{ + int i, j; + float tsec = time_msec / 1000.0f; + static float phase[] = {0.0, M_PI / 3.0, M_PI * 0.8}; + static float speed[] = {0.8, 1.4, 1.0}; + static float scale[][3] = {{1, 2, 0.8}, {0.5, 1.6, 0.6}, {1.5, 0.7, 0.5}}; + static float offset[][3] = {{0, 0, 0}, {0.25, 0, 0}, {-0.2, 0.15, 0.2}}; + + mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist); + + for(i=0; i +#include + +#include "demo.h" +#include "screen.h" + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); + +static struct screen scr = { + "plasma", + init, + destroy, + start, + 0, + draw +}; + +static unsigned long startingTime; + +#define PSIN_SIZE 4096 +#define PPAL_SIZE 256 + +static unsigned char *psin1, *psin2, *psin3; +static unsigned short *plasmaPal; + +static unsigned short myBuffer[320 * 240]; + + +struct screen *plasma_screen(void) +{ + return &scr; +} + +static int init(void) +{ + int i; + + psin1 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE); + psin2 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE); + psin3 = (unsigned char*)malloc(sizeof(unsigned char) * PSIN_SIZE); + + for (i = 0; i < PSIN_SIZE; i++) + { + psin1[i] = (unsigned char)(sin((double)i / 45.0) * 63.0 + 63.0); + psin2[i] = (unsigned char)(sin((double)i / 75.0) * 42.0 + 42.0); + psin3[i] = (unsigned char)(sin((double)i / 32.0) * 88.0 + 88.0); + } + + plasmaPal = (unsigned short*)malloc(sizeof(unsigned short) * PPAL_SIZE); + for (i=0; i 127) c = 255 - c; + c >>= 2; + g = 31 - c; + r = c; + b = g; + plasmaPal[i] = (r<<11) | (g<<5) | b; + } + + return 0; +} + +static void destroy(void) +{ + free(psin1); + free(psin2); + free(psin3); +} + +static void start(long trans_time) +{ + startingTime = time_msec; +} + +static void draw(void) +{ + int x, y; + unsigned char c; + unsigned char s1, s2; + + float dt = (float)(time_msec - startingTime) / 1000.0f; + int t1 = sin(0.1f * dt) * 132 + 132; + int t2 = sin(0.2f * dt) * 248 + 248; + int t3 = sin(0.5f * dt) * 380 + 380; + + unsigned int *vram32 = (unsigned int*)fb_pixels; + unsigned int p0, p1; + for (y = 0; y < fb_height; y++) + { + s1 = psin2[y + t2]; + s2 = psin3[y + t1]; + for (x = 0; x < fb_width; x+=2) + { + c = psin1[x + t1] + s1 + psin3[x + y + t3] + psin1[psin2[x + t2] + s2 + t3]; + p0 = plasmaPal[c]; + c = psin1[x + 1 + t1] + s1 + psin3[x + 1 + y + t3] + psin1[psin2[x + 1 + t2] + s2 + t3]; + p1 = plasmaPal[c]; + + *vram32++ = (p1 << 16) | p0; + } + } + + swap_buffers(0); +} diff --git a/src/scr/polytest.c b/src/scr/polytest.c new file mode 100644 index 0000000..0b05313 --- /dev/null +++ b/src/scr/polytest.c @@ -0,0 +1,242 @@ +#include +#include +#include +#include +#include "screen.h" +#include "demo.h" +#include "3dgfx.h" +#include "gfxutil.h" +#include "polyfill.h" /* just for struct pimage */ +#include "cfgopt.h" +#include "mesh.h" +#include "bsptree.h" + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void draw(void); +static void draw_lowres_raster(void); +static void keypress(int key); +static int gen_texture(struct pimage *img, int xsz, int ysz); + +static struct screen scr = { + "polytest", + init, + destroy, + start, 0, + draw, + keypress +}; + +static float cam_theta, cam_phi = 25; +static float cam_dist = 3; +static struct g3d_mesh cube, torus; +static struct bsptree torus_bsp; + +static struct pimage tex; + +static int use_bsp = 0; + +#define LOWRES_SCALE 10 +static uint16_t *lowres_pixels; +static int lowres_width, lowres_height; + +struct screen *polytest_screen(void) +{ + return &scr; +} + +static int init(void) +{ + int i; + + gen_cube_mesh(&cube, 1.0, 0); + gen_torus_mesh(&torus, 1.0, 0.25, 24, 12); + /* scale texcoords */ + for(i=0; ipixels = malloc(xsz * ysz * sizeof *pix))) { + return -1; + } + pix = img->pixels; + + for(i=0; iwidth = xsz; + img->height = ysz; + return 0; +} diff --git a/src/scr/smoketxt.c b/src/scr/smoketxt.c new file mode 100644 index 0000000..841ca28 --- /dev/null +++ b/src/scr/smoketxt.c @@ -0,0 +1,371 @@ +#include +#include +#include +#include +#include +#include "imago2.h" +#include "3dgfx.h" +#include "smoketxt.h" +#include "util.h" +#include "noise.h" + +/* if defined, use bilinear interpolation for dispersion field vectors */ +#define BILERP_FIELD +/* if defined randomize field vectors by RAND_FIELD_MAX */ +#define RANDOMIZE_FIELD + +#define RAND_FIELD_MAX 0.7 + +#define DFL_PCOUNT 4000 +#define DFL_MAX_LIFE 7.0f +#define DFL_PALPHA 1.0f +#define DFL_ZBIAS 0.25 +#define DFL_DRAG 0.95 +#define DFL_FORCE 0.07 +#define DFL_FREQ 0.085 + +struct vec2 { + float x, y; +}; + +struct vec3 { + float x, y, z; +}; + +struct particle { + float x, y, z; + float vx, vy, vz; /* velocity */ + int r, g, b; + float life; +}; + +struct emitter { + struct particle *plist; + int pcount; + + struct vec3 wind; + float drag; + float max_life; + + struct g3d_vertex *varr; +}; + +struct vfield { + struct vec2 pos, size; + + int width, height; + int xshift; + struct vec2 *v; +}; + + +struct smktxt { + struct emitter em; + struct vfield vfield; + + unsigned char *img_pixels; + int img_xsz, img_ysz; +}; + +static int init_emitter(struct emitter *em, int num, unsigned char *map, int xsz, int ysz); +static int load_vfield(struct vfield *vf, const char *fname); +static void vfield_eval(struct vfield *vf, float x, float y, struct vec2 *dir); + +struct smktxt *create_smktxt(const char *imgname, const char *vfieldname) +{ + struct smktxt *stx; + + if(!imgname) return 0; + + if(!(stx = calloc(sizeof *stx, 1))) { + return 0; + } + if(!(stx->img_pixels = img_load_pixels(imgname, &stx->img_xsz, &stx->img_ysz, IMG_FMT_GREY8))) { + fprintf(stderr, "create_smktxt: failed to load particle spawnmap: %s\n", imgname); + free(stx); + return 0; + } + + stx->em.pcount = DFL_PCOUNT; + stx->em.wind.z = 0.01; + stx->em.drag = DFL_DRAG; + stx->em.max_life = DFL_MAX_LIFE; + + if(vfieldname) { + if(load_vfield(&stx->vfield, vfieldname) == -1) { + img_free_pixels(stx->img_pixels); + free(stx); + return 0; + } + } + + return stx; +} + +void destroy_smktxt(struct smktxt *stx) +{ + if(!stx) return; + + img_free_pixels(stx->img_pixels); + free(stx); +} + +int gen_smktxt_vfield(struct smktxt *stx, int xres, int yres, float xfreq, float yfreq) +{ + int i, j; + unsigned int tmp; + struct vec2 *vptr; + struct vfield *vf = &stx->vfield; + + if(!(vf->v = malloc(xres * yres * sizeof *vf->v))) { + fprintf(stderr, "failed to allocate %dx%d vector field\n", xres, yres); + return -1; + } + + vf->width = xres; + vf->height = yres; + vf->pos.x = vf->pos.y = 0.0f; + vf->size.x = vf->size.y = 1.0f; + + /* assume xres is pow2 otherwise fuck you */ + tmp = xres - 1; + vf->xshift = 0; + while(tmp) { + ++vf->xshift; + tmp >>= 1; + } + + vptr = vf->v; + for(i=0; ix = x / len; + vptr->y = y / len; + + ++vptr; + } + } + return 0; +} + +int dump_smktxt_vfield(struct smktxt *stx, const char *fname) +{ + FILE *fp; + int xsz, ysz; + + if(!(fp = fopen(fname, "wb"))) { + fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno)); + return -1; + } + + xsz = stx->vfield.width; + ysz = stx->vfield.height; + + fwrite(&xsz, sizeof xsz, 1, fp); + fwrite(&ysz, sizeof ysz, 1, fp); + fwrite(stx->vfield.v, sizeof *stx->vfield.v, xsz * ysz, fp); + fclose(fp); + return 0; +} + +void set_smktxt_wind(struct smktxt *stx, float x, float y, float z) +{ + stx->em.wind.x = x; + stx->em.wind.y = y; + stx->em.wind.z = z; +} + +void set_smktxt_plife(struct smktxt *stx, float life) +{ + stx->em.max_life = life; +} + +void set_smktxt_pcount(struct smktxt *stx, int count) +{ + free(stx->em.plist); + stx->em.plist = 0; + stx->em.pcount = count; +} + +void set_smktxt_drag(struct smktxt *stx, float drag) +{ + stx->em.drag = drag; +} + +void update_smktxt(struct smktxt *stx, float dt) +{ + int i; + struct vec2 accel; + struct particle *p; + struct g3d_vertex *v; + + if(!stx->em.plist) { + if(init_emitter(&stx->em, stx->em.pcount, stx->img_pixels, stx->img_xsz, stx->img_ysz) == -1) { + fprintf(stderr, "failed to initialize emitter with %d particles\n", stx->em.pcount); + return; + } + } + + p = stx->em.plist; + v = stx->em.varr; + + for(i=0; iem.pcount; i++) { + vfield_eval(&stx->vfield, p->x, p->y, &accel); + p->x += p->vx * stx->em.drag * dt; + p->y += p->vy * stx->em.drag * dt; + p->z += p->vz * stx->em.drag * dt; + p->vx += (stx->em.wind.x + accel.x * DFL_FORCE) * dt; + p->vy += (stx->em.wind.y + accel.y * DFL_FORCE) * dt; + p->vz += (stx->em.wind.z + p->z * DFL_ZBIAS) * dt; + p->life -= dt; + if(p->life < 0.0f) p->life = 0.0f; + + v->x = p->x; + v->y = p->y; + v->z = p->z; + v->w = 1.0f; + v->a = cround64(p->life * 255.0f / stx->em.max_life); + v->r = 0; + v->g = (v->a & 0xe0) >> 3; + v->b = (v->a & 0x1f) << 3; + ++v; + + ++p; + } +} + +void draw_smktxt(struct smktxt *stx) +{ + g3d_draw(G3D_POINTS, stx->em.varr, stx->em.pcount); +} + + +static int init_emitter(struct emitter *em, int num, unsigned char *map, int xsz, int ysz) +{ + int i, x, y; + float aspect = (float)xsz / (float)ysz; + struct particle *p; + + free(em->varr); + if(!(em->varr = malloc(num * sizeof *em->varr))) { + fprintf(stderr, "failed to allocate particle vertex array (%d verts)\n", num); + return -1; + } + + free(em->plist); + if(!(em->plist = malloc(num * sizeof *em->plist))) { + free(em->varr); + return -1; + } + em->pcount = num; + + p = em->plist; + for(i=0; ix = (float)x / (float)xsz - 0.5; + p->y = -(float)y / (float)xsz + 0.5 / aspect; + p->z = ((float)i / (float)num * 2.0 - 1.0) * 0.005; + p->r = p->g = p->b = 255; + p->vx = p->vy = p->vz = 0.0f; + p->life = em->max_life; + ++p; + } + return 0; +} + +static int load_vfield(struct vfield *vf, const char *fname) +{ + FILE *fp; + int tmp; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open vector field: %s\n", fname); + return -1; + } + if(fread(&vf->width, sizeof vf->width, 1, fp) < 1 || + fread(&vf->height, sizeof vf->height, 1, fp) < 1) { + fprintf(stderr, "load_vfield: unexpected end of file while reading header\n"); + fclose(fp); + return -1; + } + + /* assume xsz is pow2 otherwise fuck you */ + tmp = vf->width - 1; + vf->xshift = 0; + while(tmp) { + ++vf->xshift; + tmp >>= 1; + } + + if(!(vf->v = malloc(vf->width * vf->height * sizeof *vf->v))) { + fprintf(stderr, "failed to allocate %dx%d vector field\n", vf->width, vf->height); + fclose(fp); + return -1; + } + if(fread(vf->v, sizeof *vf->v, vf->width * vf->height, fp) < vf->width * vf->height) { + fprintf(stderr, "load_vfield: unexpected end of file while reading %dx%d vector field\n", + vf->width, vf->height); + fclose(fp); + return -1; + } + fclose(fp); + + vf->pos.x = vf->pos.y = 0; + vf->size.x = vf->size.y = 1; + return 0; +} + +static void vfield_eval(struct vfield *vf, float x, float y, struct vec2 *dir) +{ + int px, py; + float tx, ty; + struct vec2 *p1, *p2; + struct vec2 left, right; + + x = ((x - vf->pos.x) / vf->size.x + 0.5f) * vf->width; + y = ((y - vf->pos.y) / vf->size.y + 0.5f) * vf->height; + x = floor(x); + y = floor(y); + + if(x < 0) x = 0; + if(y < 0) y = 0; + if(x > vf->width - 2) x = vf->width - 2; + if(y > vf->height - 2) y = vf->height - 2; + + px = (int)x; + py = (int)y; + + p1 = vf->v + (py << vf->xshift) + px; +#ifdef BILERP_FIELD + p2 = p1 + vf->width; + + tx = fmod(x, 1.0f); + ty = fmod(y, 1.0f); + + left.x = p1->x + (p2->x - p1->x) * ty; + left.y = p1->y + (p2->y - p1->y) * ty; + ++p1; + ++p2; + right.x = p1->x + (p2->x - p1->x) * ty; + right.y = p1->y + (p2->y - p1->y) * ty; + + dir->x = left.x + (right.x - left.x) * tx; + dir->y = left.y + (right.y - left.y) * ty; +#else + dir->x = p1->x; + dir->y = p1->y; +#endif + +#ifdef RANDOMIZE_FIELD + dir->x += ((float)rand() / RAND_MAX - 0.5) * RAND_FIELD_MAX; + dir->y += ((float)rand() / RAND_MAX - 0.5) * RAND_FIELD_MAX; +#endif +} diff --git a/src/scr/smoketxt.h b/src/scr/smoketxt.h new file mode 100644 index 0000000..42ba49d --- /dev/null +++ b/src/scr/smoketxt.h @@ -0,0 +1,21 @@ +#ifndef SMOKE_TEXT_H_ +#define SMOKE_TEXT_H_ + +struct smktxt; + +struct smktxt *create_smktxt(const char *imgname, const char *vfieldname); +void destroy_smktxt(struct smktxt *stx); + +int gen_smktxt_vfield(struct smktxt *stx, int xres, int yres, float xfreq, float yfreq); +int dump_smktxt_vfield(struct smktxt *stx, const char *fname); + +void set_smktxt_wind(struct smktxt *stx, float x, float y, float z); +void set_smktxt_plife(struct smktxt *stx, float life); +void set_smktxt_pcount(struct smktxt *stx, int count); +void set_smktxt_drag(struct smktxt *stx, float drag); + +void update_smktxt(struct smktxt *stx, float dt); +void draw_smktxt(struct smktxt *stx); + + +#endif /* SMOKE_TEXT_ */ diff --git a/src/scr/thunder.c b/src/scr/thunder.c new file mode 100644 index 0000000..cacb7b5 --- /dev/null +++ b/src/scr/thunder.c @@ -0,0 +1,441 @@ +/* thunder. c */ +#include +#include +#include +#include +#include +#include "imago2.h" +#include "demo.h" +#include "screen.h" + +/* Render blur in half x half dimenstions. Add one pixel padding in all + * directions (2 pixels horizontally, 2 pixels vertically). + */ +#define BLUR_BUFFER_WIDTH (320/2 + 2) +#define BLUR_BUFFER_HEIGHT (240/2 + 2) +#define BLUR_BUFFER_SIZE (BLUR_BUFFER_WIDTH * BLUR_BUFFER_HEIGHT) +static unsigned char *blurBuffer, *blurBuffer2; + +#define BLUR_DARKEN 4 + +#define THUNDER_RECT_SIZE 2 +#define THUNDER_RANDOMNESS 16 +#define THUNDER_SECONDS 0.075f + +#define VERTEX_COUNT 12 +#define PERSPECTIVE_NEUTRAL_DEPTH 0.5f +#define NEAR_PLANE 0.01f +#define ROTATION_SPEED 1.5f + +#define MESH_RANDOM_SEED 173 + +#define MIN_FOGGED 40 + +#define CAMERA_DISTANCE 1.1f + +/* TODO: Load palette from file */ +static unsigned short palette[256]; + +typedef unsigned int PointSprite; +#define MAX_POINT_SPRITES 1024 +static PointSprite pointSprites[MAX_POINT_SPRITES]; +int pointSpriteCount = 0; +#define PACK_POINT_SPRITE(x, y, col) ((col << 16) | (x << 8) | y) +#define UNPACK_COLOR(ps) (ps >> 16) +#define UNPACK_X(ps) ((ps >> 8) & 0xFF) +#define UNPACK_Y(ps) (ps & 0xFF) + +typedef struct { + float x,y,z; +} MyVertex ; + +MyVertex vertexBuffer[VERTEX_COUNT]; +MyVertex vertexBufferAnimated[VERTEX_COUNT]; +MyVertex vertexBufferProjected[VERTEX_COUNT]; + +void clearBlurBuffer(); +void applyBlur(); +void blitEffect(); +void thunder(int x0, int y0, int x1, int y1, unsigned char c0, unsigned char c1, int seed, int randomness, int depth); + +void initMesh(); +void projectMesh(); +void animateMesh(); +void renderMeshToPointSprites(int seed); +void renderPointSprites(); +unsigned char fog(float z); +void sortPointSprites(); + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void stop(long trans_time); +static void draw(void); + +static unsigned int lastFrameTime = 0; +static float lastFrameDuration = 0.0f; +static struct screen scr = { + "thunder", + init, + destroy, + start, + 0, + draw +}; + +struct screen *thunder_screen(void) +{ + return &scr; +} + +static int init(void) +{ + int i = 0; + + blurBuffer = malloc(BLUR_BUFFER_SIZE); + blurBuffer2 = malloc(BLUR_BUFFER_SIZE); + + clearBlurBuffer(); + + /* For now, map to blue */ + for (i = 0; i < 256; i++) { + palette[i] = (i * i) >> 11; + } + + initMesh(); + + return 0; +} + +static void destroy(void) +{ + free(blurBuffer); + blurBuffer = 0; + + free(blurBuffer2); + blurBuffer2 = 0; +} + +static void start(long trans_time) +{ + lastFrameTime = time_msec; +} + + +static float remainingThunderDuration = THUNDER_SECONDS; +static int thunderPattern = 0; + +static void draw(void) +{ + lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; + lastFrameTime = time_msec; + + remainingThunderDuration -= lastFrameDuration; + if (remainingThunderDuration <= 0) { + thunderPattern++; + remainingThunderDuration = THUNDER_SECONDS; + } + + animateMesh(); + projectMesh(); + renderMeshToPointSprites(thunderPattern); + sortPointSprites(); + renderPointSprites(); + + + applyBlur(); + blitEffect(); + + + + swap_buffers(0); +} + +void clearBlurBuffer() { + /* Clear the whole buffer (including its padding ) */ + memset(blurBuffer, 0, BLUR_BUFFER_SIZE); + memset(blurBuffer2, 0, BLUR_BUFFER_SIZE); +} + + +void applyBlur() { + int i, j; + unsigned char *tmp; + unsigned char *src = blurBuffer + BLUR_BUFFER_WIDTH + 1; + unsigned char *dst = blurBuffer2 + BLUR_BUFFER_WIDTH + 1; + + for (j = 0; j < 120; j++) { + for (i = 0; i < 160; i++) { + *dst = (*(src - 1) + *(src + 1) + *(src - BLUR_BUFFER_WIDTH) + *(src + BLUR_BUFFER_WIDTH)) >> 2; + + if (*dst > BLUR_DARKEN) *dst -= BLUR_DARKEN; + else *dst = 0; + + dst++; + src++; + } + /* Just skip the padding since we went through the scanline in the inner loop (except from the padding) */ + src += 2; + dst += 2; + } + + /* Swap blur buffers */ + tmp = blurBuffer; + blurBuffer = blurBuffer2; + blurBuffer2 = tmp; +} + +void blitEffect() { + unsigned int *dst1 = (unsigned int*) fb_pixels; + unsigned int *dst2 = dst1 + 160; /* We're writing two pixels at once */ + unsigned char *src1 = blurBuffer + BLUR_BUFFER_WIDTH + 1; + unsigned char *src2 = src1 + BLUR_BUFFER_WIDTH; + unsigned char tl, tr, bl, br; + int i, j; + + for (j = 0; j < 120; j++) { + for (i = 0; i < 160; i++) { + tl = *src1; + tr = (*src1 + *(src1 + 1)) >> 1; + bl = (*src1 + *src2) >> 1; + br = (tr + ((*src2 + *(src2 + 1)) >> 1)) >> 1; + + /* Pack 2 pixels in each 32 bit word */ + *dst1 = (palette[tr] << 16) | palette[tl]; + *dst2 = (palette[br] << 16) | palette[bl]; + + dst1++; + src1++; + dst2++; + src2++; + } + /* Again, skip padding */ + src1 += 2; + src2 += 2; + + /* For now, skip a scanline */ + dst1 += 160; + dst2 += 160; + } + +} + +void thunder(int x0, int y0, int x1, int y1, unsigned char c0, unsigned char c1, int seed, int randomness, int depth) { + int mx, my, i, j; + unsigned char *dst; + unsigned char mc; + + if (randomness <= 0) randomness = 1; + mx = ((x0 + x1) >> 1) + rand() % randomness - randomness / 2; + my = ((y0 + y1) >> 1) + rand() % randomness - randomness / 2; + mc = (c0 + c1) >> 1; + + if (depth <= 0) return; + + /* Insert a new sprite */ + if (pointSpriteCount >= MAX_POINT_SPRITES) { + printf("PROBLEM"); + return; + } + pointSprites[pointSpriteCount++] = PACK_POINT_SPRITE(mx, my, mc); + + srand(seed); + + thunder(x0, y0, mx, my, c0, mc, rand(), randomness >> 1, depth-1); + thunder(mx, my, x1, y1, mc, c1, rand(), randomness >> 1, depth - 1); +} + +MyVertex randomVertex() { + MyVertex ret; + float l; + + ret.x = rand() % 200 - 100; if (ret.x == 0) ret.x = 1; + ret.y = rand() % 200 - 100; if (ret.y == 0) ret.y = 1; + ret.z = rand() % 200 - 100; if (ret.z == 0) ret.z = 1; + + // Normalize + l = sqrt(ret.x * ret.x + ret.y * ret.y + ret.z * ret.z); + ret.x /= l; + ret.y /= l; + ret.z /= l; + + return ret; +} + +void initMesh() { + int i; + + srand(MESH_RANDOM_SEED); + + for (i = 0; i < VERTEX_COUNT; i++) { + vertexBuffer[i] = randomVertex(); + } +} + +void animateMesh() { + int i = 0; + MyVertex bx, by, bz; + float yRot; + + yRot = ROTATION_SPEED * time_msec / 1000.0f; + + /* Create rotated basis */ + bx.x = cos(yRot); + bx.y = 0.0f; + bx.z = sin(yRot); + + by.x = 0.0f; + by.y = 1.0f; + by.z = 0.0f; + + bz.x = cos(yRot + M_PI/2.0f); + bz.y = 0.0f; + bz.z = sin(yRot + M_PI/2.0f); + + for (i = 0; i < VERTEX_COUNT; i++) { + MyVertex v1, v2; + v1 = vertexBuffer[i]; + + + v1.y *= sin(time_msec / 1000.0f + v1.x + v1.z); + + /* O re panaia mou */ + v2.x = v1.x * bx.x + v1.y * by.x + v1.z * bz.x; + v2.y = v1.x * bx.y + v1.y * by.y + v1.z * bz.y; + v2.z = v1.x * bx.z + v1.y * by.z + v1.z * bz.z; + + v2.z += CAMERA_DISTANCE; + + vertexBufferAnimated[i] = v2; + } +} + +void projectMesh() { + int i = 0; + + for (i = 0; i < VERTEX_COUNT; i++) { + + if (vertexBufferAnimated[i].z <= NEAR_PLANE) { + vertexBufferProjected[i].x = vertexBufferProjected[i].y = 1000.0f; + vertexBufferProjected[i].z = -1.0f; + continue; + } + + vertexBufferProjected[i].x = vertexBufferAnimated[i].x * PERSPECTIVE_NEUTRAL_DEPTH / vertexBufferAnimated[i].z; + vertexBufferProjected[i].y = vertexBufferAnimated[i].y * PERSPECTIVE_NEUTRAL_DEPTH / vertexBufferAnimated[i].z; + } +} + +void renderMeshToPointSprites(int seed) { + int vertex, j; + int sx, sy; + unsigned char color; + unsigned char *dst; + unsigned char fogAtOrigin; + + fogAtOrigin = fog(CAMERA_DISTANCE); + + pointSpriteCount = 0; + srand(seed); + + for (vertex = 0; vertex < VERTEX_COUNT; vertex++) { + sx = (int)(vertexBufferProjected[vertex].x * 80) + 80; + sy = (int)(vertexBufferProjected[vertex].y * 60) + 60; + + thunder(80, 60, sx, sy, fogAtOrigin, fog(vertexBufferAnimated[vertex].z), rand(), THUNDER_RANDOMNESS, 5); + } +} + +void renderPointSprites() { + int i,j; + PointSprite sprite; + unsigned char *dst; + int sx, sy; + unsigned char color; + + for (i = 0; i < pointSpriteCount; i++) { + sprite = pointSprites[i]; + + sx = UNPACK_X(sprite); + sy = UNPACK_Y(sprite); + + if (sx < THUNDER_RECT_SIZE || sx >= 160 - THUNDER_RECT_SIZE || sy < THUNDER_RECT_SIZE || sy >= 120 - THUNDER_RECT_SIZE) continue; + + dst = blurBuffer + BLUR_BUFFER_WIDTH + 1 + sx + sy * BLUR_BUFFER_WIDTH; + + color = UNPACK_COLOR(sprite); + + for (j = 0; j < THUNDER_RECT_SIZE; j++) { + memset(dst, color, THUNDER_RECT_SIZE); + dst += BLUR_BUFFER_WIDTH; + } + } +} + +unsigned char fog(float z) { + unsigned int ret = (unsigned int) (((-(z - CAMERA_DISTANCE)) * 0.5f + 0.5f) * (255.0f - MIN_FOGGED)) + MIN_FOGGED; + if (ret > 255) ret = 255; + return (unsigned char)ret; +} + +void sort(PointSprite *begin, PointSprite *end) { + PointSprite pivotValue; + size_t sz; + PointSprite *left, *right; + int leftCond, rightCond; + PointSprite tmp; + + sz = end - begin; + + if (sz < 2) return; /* already sorted */ + if (sz == 2) { + /* trivial case */ + if (begin[1] < begin[0]) { + tmp = begin[0]; + begin[0] = begin[1]; + begin[1] = tmp; + return; + } + } + + /* minimum 3 elements from now on */ + + /* choose a pivot near the middle, since we frequently sort already sorted arrays */ + pivotValue = begin[sz / 2]; + + left = begin; + right = end - 1; + + while (right > left) { + /* check if left and right elements meet the conditions */ + leftCond = pivotValue >= *left; + rightCond = pivotValue < *right; + + if (!leftCond && !rightCond) { + tmp = *left; + *left = *right; + *right = tmp; + left++; + right--; + } + else if (leftCond && rightCond) { + left++; + right--; + } + else if (leftCond) { + left++; + } + else { + right--; + } + } + + /* recursion */ + sort(begin, left); + sort(left, end); +} + +void sortPointSprites() { + sort(pointSprites, pointSprites + pointSpriteCount); +} + diff --git a/src/scr/tilemaze.c b/src/scr/tilemaze.c new file mode 100644 index 0000000..6e2aa54 --- /dev/null +++ b/src/scr/tilemaze.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include "tilemaze.h" +#include "mesh.h" +#include "treestor.h" +#include "dynarr.h" +#include "scene.h" + +struct object { + char *name; + struct g3d_mesh mesh; + + void *texels; + int tex_width, tex_height; + + struct object *next; +}; + +struct tile { + char *name; + struct object *objlist; +}; + +struct tilemaze { + struct tile *tileset; + int num_tiles; + + struct object *objects; +}; + +void free_object(struct object *obj); + +struct tilemaze *load_tilemaze(const char *fname) +{ + struct tilemaze *tmz; + + if(!(tmz = calloc(sizeof *tmz, 1))) { + return 0; + } + return tmz; +} + +void destroy_tilemaze(struct tilemaze *tmz) +{ + if(!tmz) return; + + free(tmz->tileset); + + while(tmz->objects) { + struct object *o = tmz->objects; + tmz->objects = tmz->objects->next; + + free(o->mesh.varr); + free(o->mesh.iarr); + free(o); + } + + free(tmz); +} + +void update_tilemaze(struct tilemaze *tmz) +{ +} + +void draw_tilemaze(struct tilemaze *tmz) +{ +} + +struct tile *load_tileset(const char *fname, int *count) +{ + int i; + struct tile *tiles = 0, *tile; + struct ts_node *ts = 0, *node; + struct ts_attr *attr; + struct object *obj; + + if(!(ts = ts_load(fname))) { + fprintf(stderr, "load_tileset: failed to load: %s\n", fname); + goto err; + } + if(strcmp(ts->name, "tileset") != 0) { + fprintf(stderr, "load_tileset: %s is not a tileset file\n", fname); + goto err; + } + + if(!(tiles = dynarr_alloc(sizeof *tiles, 0))) { + fprintf(stderr, "load_tileset: failed to create tiles array\n"); + goto err; + } + + node = ts->child_list; + while(node) { + if(strcmp(node->name, "tile") != 0) { + fprintf(stderr, "load_tileset: skipping unexpected node %s in %s\n", node->name, fname); + node = node->next; + continue; + } + + if(!(tile = malloc(sizeof *tile))) { + fprintf(stderr, "load_tileset: failed to allocate tile\n"); + goto err; + } + if(!(tile->name = malloc(strlen(node->name) + 1))) { + fprintf(stderr, "load_tileset: failed to allocate tile name\n"); + free(tile); + goto err; + } + strcpy(tile->name, node->name); + tile->objlist = 0; + + attr = node->attr_list; + while(attr) { + /* + if(strcmp(attr->name, "scn") == 0) { + struct object *last; + if(!(obj = load_objlist(attr->value.str, &last))) { + free(tile); + goto err; + } + last->next = tile->objlist; + tile->objlist = obj; + } + */ + attr = attr->next; + } + + node = node->next; + } + +err: + if(tiles) { + for(i=0; inext; + free_object(obj); + } + } + dynarr_free(tiles); + } + if(ts) ts_free_tree(ts); + return 0; +} + +void free_object(struct object *obj) +{ + if(!obj) return; + + free(obj->name); + free(obj->texels); + destroy_mesh(&obj->mesh); + + free(obj); +} diff --git a/src/scr/tilemaze.h b/src/scr/tilemaze.h new file mode 100644 index 0000000..a06acd8 --- /dev/null +++ b/src/scr/tilemaze.h @@ -0,0 +1,12 @@ +#ifndef TILEMAZE_H_ +#define TILEMAZE_H_ + +struct tilemaze; + +struct tilemaze *load_tilemaze(const char *fname); +void destroy_tilemaze(struct tilemaze *tmz); + +void update_tilemaze(struct tilemaze *tmz); +void draw_tilemaze(struct tilemaze *tmz); + +#endif /* TILEMAZE_H_ */ diff --git a/src/scr/tunnel.c b/src/scr/tunnel.c new file mode 100644 index 0000000..9071b74 --- /dev/null +++ b/src/scr/tunnel.c @@ -0,0 +1,287 @@ +#include +#include +#include +#include +#include +#include "imago2.h" +#include "demo.h" +#include "screen.h" +#include "gfxutil.h" + +#ifndef M_PI +#define M_PI 3.1415926535 +#endif + +#define VSCALE 1.5 + +#define TEX_FNAME "data/grid.png" +#define TEX_USCALE 4 +#define TEX_VSCALE 2 + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void stop(long trans_time); +static void draw(void); + +static void draw_tunnel_range(unsigned short *pixels, int xoffs, int yoffs, int starty, int num_lines, long tm); +static int count_bits(unsigned int x); +static int count_zeros(unsigned int x); + +static struct screen scr = { + "tunnel", + init, + destroy, + start, + stop, + draw +}; + +static int xsz, ysz, vxsz, vysz; +static int pan_width, pan_height; +static unsigned int *tunnel_map; +static unsigned char *tunnel_fog; + +static int tex_xsz, tex_ysz; +static unsigned int *tex_pixels; +static int tex_xshift, tex_yshift; +static unsigned int tex_xmask, tex_ymask; + +static long trans_start, trans_dur; +static int trans_dir; + + +struct screen *tunnel_screen(void) +{ + return &scr; +} + + +static int init(void) +{ + int i, j, n; + unsigned int *tmap; + unsigned char *fog; + float aspect = (float)fb_width / (float)fb_height; + + xsz = fb_width; + ysz = fb_height; + vxsz = xsz * VSCALE; + vysz = ysz * VSCALE; + + pan_width = vxsz - xsz; + pan_height = vysz - ysz; + + if(!(tunnel_map = malloc(vxsz * vysz * sizeof *tunnel_map))) { + fprintf(stderr, "failed to allocate tunnel map\n"); + return -1; + } + if(!(tunnel_fog = malloc(vxsz * vysz))) { + fprintf(stderr, "failed to allocate tunnel fog map\n"); + return -1; + } + + tmap = tunnel_map; + fog = tunnel_fog; + + for(i=0; i 255 ? 255 : f; + } + } + + if(!(tex_pixels = img_load_pixels(TEX_FNAME, &tex_xsz, &tex_ysz, IMG_FMT_RGBA32))) { + fprintf(stderr, "failed to load image " TEX_FNAME "\n"); + return -1; + } + if((count_bits(tex_xsz) | count_bits(tex_ysz)) != 1) { + fprintf(stderr, "non-pow2 image (%dx%d)\n", tex_xsz, tex_ysz); + return -1; + } + + /*tex_pixels = gen_test_image(&tex_xsz, &tex_ysz);*/ + + n = count_zeros(tex_xsz); + for(i=0; i= num_lines) { + trans_dir = 0; + } + } + + t = time_msec / 10000.0; + xoffs = (int)(cos(t * 3.0) * pan_width / 2) + pan_width / 2; + yoffs = (int)(sin(t * 4.0) * pan_height / 2) + pan_height / 2; + + for(i=0; i> 16) & 0xffff) << tex_xshift) >> 16; + unsigned int ty = ((tpacked & 0xffff) << tex_yshift) >> 16; + tx += toffs; + ty += toffs << 1; + + tx &= tex_xmask; + ty &= tex_ymask; + + col = tex_pixels[(ty << tex_xshift) + tx]; + r = col & 0xff; + g = (col >> 8) & 0xff; + b = (col >> 16) & 0xff; + + *rp = (r * fog) >> 8; + *gp = (g * fog) >> 8; + *bp = (b * fog) >> 8; +} + +static void draw_tunnel_range(unsigned short *pix, int xoffs, int yoffs, int starty, int num_lines, long tm) +{ + int i, j; + unsigned int *tmap = tunnel_map + (starty + yoffs) * vxsz + xoffs; + unsigned char *fog = tunnel_fog + (starty + yoffs) * vxsz + xoffs; + + long toffs = tm / 8; + unsigned int *pixels = (unsigned int*)pix + starty * (fb_width >> 1); + + for(i=0; i>1); j++) { + unsigned int col; + int r, g, b, idx = j << 1; + + tunnel_color(&r, &g, &b, toffs, tmap[idx], fog[idx]); + col = PACK_RGB16(r, g, b); + tunnel_color(&r, &g, &b, toffs, tmap[idx + 1], fog[idx + 1]); + col |= PACK_RGB16(r, g, b) << 16; + *pixels++ = col; + } + tmap += vxsz; + fog += vxsz; + } +} + +static int count_bits(unsigned int x) +{ + int i, nbits = 0; + for(i=0; i<32; i++) { + if(x & 1) ++nbits; + x >>= 1; + } + return nbits; +} + +static int count_zeros(unsigned int x) +{ + int i, num = 0; + for(i=0; i<32; i++) { + if(x & 1) break; + ++num; + x >>= 1; + } + return num; +} + +/* +static unsigned int *gen_test_image(int *wptr, int *hptr) +{ + int i, j; + int xsz = 256, ysz = 256; + unsigned int *pixels, *pix; + + if(!(pixels = malloc(xsz * ysz * sizeof *pix))) { + return 0; + } + pix = pixels; + + for(i=0; i -#include -#include -#include -#include -#include "imago2.h" -#include "3dgfx.h" -#include "smoketxt.h" -#include "util.h" -#include "noise.h" - -/* if defined, use bilinear interpolation for dispersion field vectors */ -#define BILERP_FIELD -/* if defined randomize field vectors by RAND_FIELD_MAX */ -#define RANDOMIZE_FIELD - -#define RAND_FIELD_MAX 0.7 - -#define DFL_PCOUNT 4000 -#define DFL_MAX_LIFE 7.0f -#define DFL_PALPHA 1.0f -#define DFL_ZBIAS 0.25 -#define DFL_DRAG 0.95 -#define DFL_FORCE 0.07 -#define DFL_FREQ 0.085 - -struct vec2 { - float x, y; -}; - -struct vec3 { - float x, y, z; -}; - -struct particle { - float x, y, z; - float vx, vy, vz; /* velocity */ - int r, g, b; - float life; -}; - -struct emitter { - struct particle *plist; - int pcount; - - struct vec3 wind; - float drag; - float max_life; - - struct g3d_vertex *varr; -}; - -struct vfield { - struct vec2 pos, size; - - int width, height; - int xshift; - struct vec2 *v; -}; - - -struct smktxt { - struct emitter em; - struct vfield vfield; - - unsigned char *img_pixels; - int img_xsz, img_ysz; -}; - -static int init_emitter(struct emitter *em, int num, unsigned char *map, int xsz, int ysz); -static int load_vfield(struct vfield *vf, const char *fname); -static void vfield_eval(struct vfield *vf, float x, float y, struct vec2 *dir); - -struct smktxt *create_smktxt(const char *imgname, const char *vfieldname) -{ - struct smktxt *stx; - - if(!imgname) return 0; - - if(!(stx = calloc(sizeof *stx, 1))) { - return 0; - } - if(!(stx->img_pixels = img_load_pixels(imgname, &stx->img_xsz, &stx->img_ysz, IMG_FMT_GREY8))) { - fprintf(stderr, "create_smktxt: failed to load particle spawnmap: %s\n", imgname); - free(stx); - return 0; - } - - stx->em.pcount = DFL_PCOUNT; - stx->em.wind.z = 0.01; - stx->em.drag = DFL_DRAG; - stx->em.max_life = DFL_MAX_LIFE; - - if(vfieldname) { - if(load_vfield(&stx->vfield, vfieldname) == -1) { - img_free_pixels(stx->img_pixels); - free(stx); - return 0; - } - } - - return stx; -} - -void destroy_smktxt(struct smktxt *stx) -{ - if(!stx) return; - - img_free_pixels(stx->img_pixels); - free(stx); -} - -int gen_smktxt_vfield(struct smktxt *stx, int xres, int yres, float xfreq, float yfreq) -{ - int i, j; - unsigned int tmp; - struct vec2 *vptr; - struct vfield *vf = &stx->vfield; - - if(!(vf->v = malloc(xres * yres * sizeof *vf->v))) { - fprintf(stderr, "failed to allocate %dx%d vector field\n", xres, yres); - return -1; - } - - vf->width = xres; - vf->height = yres; - vf->pos.x = vf->pos.y = 0.0f; - vf->size.x = vf->size.y = 1.0f; - - /* assume xres is pow2 otherwise fuck you */ - tmp = xres - 1; - vf->xshift = 0; - while(tmp) { - ++vf->xshift; - tmp >>= 1; - } - - vptr = vf->v; - for(i=0; ix = x / len; - vptr->y = y / len; - - ++vptr; - } - } - return 0; -} - -int dump_smktxt_vfield(struct smktxt *stx, const char *fname) -{ - FILE *fp; - int xsz, ysz; - - if(!(fp = fopen(fname, "wb"))) { - fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno)); - return -1; - } - - xsz = stx->vfield.width; - ysz = stx->vfield.height; - - fwrite(&xsz, sizeof xsz, 1, fp); - fwrite(&ysz, sizeof ysz, 1, fp); - fwrite(stx->vfield.v, sizeof *stx->vfield.v, xsz * ysz, fp); - fclose(fp); - return 0; -} - -void set_smktxt_wind(struct smktxt *stx, float x, float y, float z) -{ - stx->em.wind.x = x; - stx->em.wind.y = y; - stx->em.wind.z = z; -} - -void set_smktxt_plife(struct smktxt *stx, float life) -{ - stx->em.max_life = life; -} - -void set_smktxt_pcount(struct smktxt *stx, int count) -{ - free(stx->em.plist); - stx->em.plist = 0; - stx->em.pcount = count; -} - -void set_smktxt_drag(struct smktxt *stx, float drag) -{ - stx->em.drag = drag; -} - -void update_smktxt(struct smktxt *stx, float dt) -{ - int i; - struct vec2 accel; - struct particle *p; - struct g3d_vertex *v; - - if(!stx->em.plist) { - if(init_emitter(&stx->em, stx->em.pcount, stx->img_pixels, stx->img_xsz, stx->img_ysz) == -1) { - fprintf(stderr, "failed to initialize emitter with %d particles\n", stx->em.pcount); - return; - } - } - - p = stx->em.plist; - v = stx->em.varr; - - for(i=0; iem.pcount; i++) { - vfield_eval(&stx->vfield, p->x, p->y, &accel); - p->x += p->vx * stx->em.drag * dt; - p->y += p->vy * stx->em.drag * dt; - p->z += p->vz * stx->em.drag * dt; - p->vx += (stx->em.wind.x + accel.x * DFL_FORCE) * dt; - p->vy += (stx->em.wind.y + accel.y * DFL_FORCE) * dt; - p->vz += (stx->em.wind.z + p->z * DFL_ZBIAS) * dt; - p->life -= dt; - if(p->life < 0.0f) p->life = 0.0f; - - v->x = p->x; - v->y = p->y; - v->z = p->z; - v->w = 1.0f; - v->a = cround64(p->life * 255.0f / stx->em.max_life); - v->r = 0; - v->g = (v->a & 0xe0) >> 3; - v->b = (v->a & 0x1f) << 3; - ++v; - - ++p; - } -} - -void draw_smktxt(struct smktxt *stx) -{ - g3d_draw(G3D_POINTS, stx->em.varr, stx->em.pcount); -} - - -static int init_emitter(struct emitter *em, int num, unsigned char *map, int xsz, int ysz) -{ - int i, x, y; - float aspect = (float)xsz / (float)ysz; - struct particle *p; - - free(em->varr); - if(!(em->varr = malloc(num * sizeof *em->varr))) { - fprintf(stderr, "failed to allocate particle vertex array (%d verts)\n", num); - return -1; - } - - free(em->plist); - if(!(em->plist = malloc(num * sizeof *em->plist))) { - free(em->varr); - return -1; - } - em->pcount = num; - - p = em->plist; - for(i=0; ix = (float)x / (float)xsz - 0.5; - p->y = -(float)y / (float)xsz + 0.5 / aspect; - p->z = ((float)i / (float)num * 2.0 - 1.0) * 0.005; - p->r = p->g = p->b = 255; - p->vx = p->vy = p->vz = 0.0f; - p->life = em->max_life; - ++p; - } - return 0; -} - -static int load_vfield(struct vfield *vf, const char *fname) -{ - FILE *fp; - int tmp; - - if(!(fp = fopen(fname, "rb"))) { - fprintf(stderr, "failed to open vector field: %s\n", fname); - return -1; - } - if(fread(&vf->width, sizeof vf->width, 1, fp) < 1 || - fread(&vf->height, sizeof vf->height, 1, fp) < 1) { - fprintf(stderr, "load_vfield: unexpected end of file while reading header\n"); - fclose(fp); - return -1; - } - - /* assume xsz is pow2 otherwise fuck you */ - tmp = vf->width - 1; - vf->xshift = 0; - while(tmp) { - ++vf->xshift; - tmp >>= 1; - } - - if(!(vf->v = malloc(vf->width * vf->height * sizeof *vf->v))) { - fprintf(stderr, "failed to allocate %dx%d vector field\n", vf->width, vf->height); - fclose(fp); - return -1; - } - if(fread(vf->v, sizeof *vf->v, vf->width * vf->height, fp) < vf->width * vf->height) { - fprintf(stderr, "load_vfield: unexpected end of file while reading %dx%d vector field\n", - vf->width, vf->height); - fclose(fp); - return -1; - } - fclose(fp); - - vf->pos.x = vf->pos.y = 0; - vf->size.x = vf->size.y = 1; - return 0; -} - -static void vfield_eval(struct vfield *vf, float x, float y, struct vec2 *dir) -{ - int px, py; - float tx, ty; - struct vec2 *p1, *p2; - struct vec2 left, right; - - x = ((x - vf->pos.x) / vf->size.x + 0.5f) * vf->width; - y = ((y - vf->pos.y) / vf->size.y + 0.5f) * vf->height; - x = floor(x); - y = floor(y); - - if(x < 0) x = 0; - if(y < 0) y = 0; - if(x > vf->width - 2) x = vf->width - 2; - if(y > vf->height - 2) y = vf->height - 2; - - px = (int)x; - py = (int)y; - - p1 = vf->v + (py << vf->xshift) + px; -#ifdef BILERP_FIELD - p2 = p1 + vf->width; - - tx = fmod(x, 1.0f); - ty = fmod(y, 1.0f); - - left.x = p1->x + (p2->x - p1->x) * ty; - left.y = p1->y + (p2->y - p1->y) * ty; - ++p1; - ++p2; - right.x = p1->x + (p2->x - p1->x) * ty; - right.y = p1->y + (p2->y - p1->y) * ty; - - dir->x = left.x + (right.x - left.x) * tx; - dir->y = left.y + (right.y - left.y) * ty; -#else - dir->x = p1->x; - dir->y = p1->y; -#endif - -#ifdef RANDOMIZE_FIELD - dir->x += ((float)rand() / RAND_MAX - 0.5) * RAND_FIELD_MAX; - dir->y += ((float)rand() / RAND_MAX - 0.5) * RAND_FIELD_MAX; -#endif -} diff --git a/src/smoketxt.h b/src/smoketxt.h deleted file mode 100644 index 42ba49d..0000000 --- a/src/smoketxt.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SMOKE_TEXT_H_ -#define SMOKE_TEXT_H_ - -struct smktxt; - -struct smktxt *create_smktxt(const char *imgname, const char *vfieldname); -void destroy_smktxt(struct smktxt *stx); - -int gen_smktxt_vfield(struct smktxt *stx, int xres, int yres, float xfreq, float yfreq); -int dump_smktxt_vfield(struct smktxt *stx, const char *fname); - -void set_smktxt_wind(struct smktxt *stx, float x, float y, float z); -void set_smktxt_plife(struct smktxt *stx, float life); -void set_smktxt_pcount(struct smktxt *stx, int count); -void set_smktxt_drag(struct smktxt *stx, float drag); - -void update_smktxt(struct smktxt *stx, float dt); -void draw_smktxt(struct smktxt *stx); - - -#endif /* SMOKE_TEXT_ */ diff --git a/src/thunder.c b/src/thunder.c deleted file mode 100644 index cacb7b5..0000000 --- a/src/thunder.c +++ /dev/null @@ -1,441 +0,0 @@ -/* thunder. c */ -#include -#include -#include -#include -#include -#include "imago2.h" -#include "demo.h" -#include "screen.h" - -/* Render blur in half x half dimenstions. Add one pixel padding in all - * directions (2 pixels horizontally, 2 pixels vertically). - */ -#define BLUR_BUFFER_WIDTH (320/2 + 2) -#define BLUR_BUFFER_HEIGHT (240/2 + 2) -#define BLUR_BUFFER_SIZE (BLUR_BUFFER_WIDTH * BLUR_BUFFER_HEIGHT) -static unsigned char *blurBuffer, *blurBuffer2; - -#define BLUR_DARKEN 4 - -#define THUNDER_RECT_SIZE 2 -#define THUNDER_RANDOMNESS 16 -#define THUNDER_SECONDS 0.075f - -#define VERTEX_COUNT 12 -#define PERSPECTIVE_NEUTRAL_DEPTH 0.5f -#define NEAR_PLANE 0.01f -#define ROTATION_SPEED 1.5f - -#define MESH_RANDOM_SEED 173 - -#define MIN_FOGGED 40 - -#define CAMERA_DISTANCE 1.1f - -/* TODO: Load palette from file */ -static unsigned short palette[256]; - -typedef unsigned int PointSprite; -#define MAX_POINT_SPRITES 1024 -static PointSprite pointSprites[MAX_POINT_SPRITES]; -int pointSpriteCount = 0; -#define PACK_POINT_SPRITE(x, y, col) ((col << 16) | (x << 8) | y) -#define UNPACK_COLOR(ps) (ps >> 16) -#define UNPACK_X(ps) ((ps >> 8) & 0xFF) -#define UNPACK_Y(ps) (ps & 0xFF) - -typedef struct { - float x,y,z; -} MyVertex ; - -MyVertex vertexBuffer[VERTEX_COUNT]; -MyVertex vertexBufferAnimated[VERTEX_COUNT]; -MyVertex vertexBufferProjected[VERTEX_COUNT]; - -void clearBlurBuffer(); -void applyBlur(); -void blitEffect(); -void thunder(int x0, int y0, int x1, int y1, unsigned char c0, unsigned char c1, int seed, int randomness, int depth); - -void initMesh(); -void projectMesh(); -void animateMesh(); -void renderMeshToPointSprites(int seed); -void renderPointSprites(); -unsigned char fog(float z); -void sortPointSprites(); - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void stop(long trans_time); -static void draw(void); - -static unsigned int lastFrameTime = 0; -static float lastFrameDuration = 0.0f; -static struct screen scr = { - "thunder", - init, - destroy, - start, - 0, - draw -}; - -struct screen *thunder_screen(void) -{ - return &scr; -} - -static int init(void) -{ - int i = 0; - - blurBuffer = malloc(BLUR_BUFFER_SIZE); - blurBuffer2 = malloc(BLUR_BUFFER_SIZE); - - clearBlurBuffer(); - - /* For now, map to blue */ - for (i = 0; i < 256; i++) { - palette[i] = (i * i) >> 11; - } - - initMesh(); - - return 0; -} - -static void destroy(void) -{ - free(blurBuffer); - blurBuffer = 0; - - free(blurBuffer2); - blurBuffer2 = 0; -} - -static void start(long trans_time) -{ - lastFrameTime = time_msec; -} - - -static float remainingThunderDuration = THUNDER_SECONDS; -static int thunderPattern = 0; - -static void draw(void) -{ - lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; - lastFrameTime = time_msec; - - remainingThunderDuration -= lastFrameDuration; - if (remainingThunderDuration <= 0) { - thunderPattern++; - remainingThunderDuration = THUNDER_SECONDS; - } - - animateMesh(); - projectMesh(); - renderMeshToPointSprites(thunderPattern); - sortPointSprites(); - renderPointSprites(); - - - applyBlur(); - blitEffect(); - - - - swap_buffers(0); -} - -void clearBlurBuffer() { - /* Clear the whole buffer (including its padding ) */ - memset(blurBuffer, 0, BLUR_BUFFER_SIZE); - memset(blurBuffer2, 0, BLUR_BUFFER_SIZE); -} - - -void applyBlur() { - int i, j; - unsigned char *tmp; - unsigned char *src = blurBuffer + BLUR_BUFFER_WIDTH + 1; - unsigned char *dst = blurBuffer2 + BLUR_BUFFER_WIDTH + 1; - - for (j = 0; j < 120; j++) { - for (i = 0; i < 160; i++) { - *dst = (*(src - 1) + *(src + 1) + *(src - BLUR_BUFFER_WIDTH) + *(src + BLUR_BUFFER_WIDTH)) >> 2; - - if (*dst > BLUR_DARKEN) *dst -= BLUR_DARKEN; - else *dst = 0; - - dst++; - src++; - } - /* Just skip the padding since we went through the scanline in the inner loop (except from the padding) */ - src += 2; - dst += 2; - } - - /* Swap blur buffers */ - tmp = blurBuffer; - blurBuffer = blurBuffer2; - blurBuffer2 = tmp; -} - -void blitEffect() { - unsigned int *dst1 = (unsigned int*) fb_pixels; - unsigned int *dst2 = dst1 + 160; /* We're writing two pixels at once */ - unsigned char *src1 = blurBuffer + BLUR_BUFFER_WIDTH + 1; - unsigned char *src2 = src1 + BLUR_BUFFER_WIDTH; - unsigned char tl, tr, bl, br; - int i, j; - - for (j = 0; j < 120; j++) { - for (i = 0; i < 160; i++) { - tl = *src1; - tr = (*src1 + *(src1 + 1)) >> 1; - bl = (*src1 + *src2) >> 1; - br = (tr + ((*src2 + *(src2 + 1)) >> 1)) >> 1; - - /* Pack 2 pixels in each 32 bit word */ - *dst1 = (palette[tr] << 16) | palette[tl]; - *dst2 = (palette[br] << 16) | palette[bl]; - - dst1++; - src1++; - dst2++; - src2++; - } - /* Again, skip padding */ - src1 += 2; - src2 += 2; - - /* For now, skip a scanline */ - dst1 += 160; - dst2 += 160; - } - -} - -void thunder(int x0, int y0, int x1, int y1, unsigned char c0, unsigned char c1, int seed, int randomness, int depth) { - int mx, my, i, j; - unsigned char *dst; - unsigned char mc; - - if (randomness <= 0) randomness = 1; - mx = ((x0 + x1) >> 1) + rand() % randomness - randomness / 2; - my = ((y0 + y1) >> 1) + rand() % randomness - randomness / 2; - mc = (c0 + c1) >> 1; - - if (depth <= 0) return; - - /* Insert a new sprite */ - if (pointSpriteCount >= MAX_POINT_SPRITES) { - printf("PROBLEM"); - return; - } - pointSprites[pointSpriteCount++] = PACK_POINT_SPRITE(mx, my, mc); - - srand(seed); - - thunder(x0, y0, mx, my, c0, mc, rand(), randomness >> 1, depth-1); - thunder(mx, my, x1, y1, mc, c1, rand(), randomness >> 1, depth - 1); -} - -MyVertex randomVertex() { - MyVertex ret; - float l; - - ret.x = rand() % 200 - 100; if (ret.x == 0) ret.x = 1; - ret.y = rand() % 200 - 100; if (ret.y == 0) ret.y = 1; - ret.z = rand() % 200 - 100; if (ret.z == 0) ret.z = 1; - - // Normalize - l = sqrt(ret.x * ret.x + ret.y * ret.y + ret.z * ret.z); - ret.x /= l; - ret.y /= l; - ret.z /= l; - - return ret; -} - -void initMesh() { - int i; - - srand(MESH_RANDOM_SEED); - - for (i = 0; i < VERTEX_COUNT; i++) { - vertexBuffer[i] = randomVertex(); - } -} - -void animateMesh() { - int i = 0; - MyVertex bx, by, bz; - float yRot; - - yRot = ROTATION_SPEED * time_msec / 1000.0f; - - /* Create rotated basis */ - bx.x = cos(yRot); - bx.y = 0.0f; - bx.z = sin(yRot); - - by.x = 0.0f; - by.y = 1.0f; - by.z = 0.0f; - - bz.x = cos(yRot + M_PI/2.0f); - bz.y = 0.0f; - bz.z = sin(yRot + M_PI/2.0f); - - for (i = 0; i < VERTEX_COUNT; i++) { - MyVertex v1, v2; - v1 = vertexBuffer[i]; - - - v1.y *= sin(time_msec / 1000.0f + v1.x + v1.z); - - /* O re panaia mou */ - v2.x = v1.x * bx.x + v1.y * by.x + v1.z * bz.x; - v2.y = v1.x * bx.y + v1.y * by.y + v1.z * bz.y; - v2.z = v1.x * bx.z + v1.y * by.z + v1.z * bz.z; - - v2.z += CAMERA_DISTANCE; - - vertexBufferAnimated[i] = v2; - } -} - -void projectMesh() { - int i = 0; - - for (i = 0; i < VERTEX_COUNT; i++) { - - if (vertexBufferAnimated[i].z <= NEAR_PLANE) { - vertexBufferProjected[i].x = vertexBufferProjected[i].y = 1000.0f; - vertexBufferProjected[i].z = -1.0f; - continue; - } - - vertexBufferProjected[i].x = vertexBufferAnimated[i].x * PERSPECTIVE_NEUTRAL_DEPTH / vertexBufferAnimated[i].z; - vertexBufferProjected[i].y = vertexBufferAnimated[i].y * PERSPECTIVE_NEUTRAL_DEPTH / vertexBufferAnimated[i].z; - } -} - -void renderMeshToPointSprites(int seed) { - int vertex, j; - int sx, sy; - unsigned char color; - unsigned char *dst; - unsigned char fogAtOrigin; - - fogAtOrigin = fog(CAMERA_DISTANCE); - - pointSpriteCount = 0; - srand(seed); - - for (vertex = 0; vertex < VERTEX_COUNT; vertex++) { - sx = (int)(vertexBufferProjected[vertex].x * 80) + 80; - sy = (int)(vertexBufferProjected[vertex].y * 60) + 60; - - thunder(80, 60, sx, sy, fogAtOrigin, fog(vertexBufferAnimated[vertex].z), rand(), THUNDER_RANDOMNESS, 5); - } -} - -void renderPointSprites() { - int i,j; - PointSprite sprite; - unsigned char *dst; - int sx, sy; - unsigned char color; - - for (i = 0; i < pointSpriteCount; i++) { - sprite = pointSprites[i]; - - sx = UNPACK_X(sprite); - sy = UNPACK_Y(sprite); - - if (sx < THUNDER_RECT_SIZE || sx >= 160 - THUNDER_RECT_SIZE || sy < THUNDER_RECT_SIZE || sy >= 120 - THUNDER_RECT_SIZE) continue; - - dst = blurBuffer + BLUR_BUFFER_WIDTH + 1 + sx + sy * BLUR_BUFFER_WIDTH; - - color = UNPACK_COLOR(sprite); - - for (j = 0; j < THUNDER_RECT_SIZE; j++) { - memset(dst, color, THUNDER_RECT_SIZE); - dst += BLUR_BUFFER_WIDTH; - } - } -} - -unsigned char fog(float z) { - unsigned int ret = (unsigned int) (((-(z - CAMERA_DISTANCE)) * 0.5f + 0.5f) * (255.0f - MIN_FOGGED)) + MIN_FOGGED; - if (ret > 255) ret = 255; - return (unsigned char)ret; -} - -void sort(PointSprite *begin, PointSprite *end) { - PointSprite pivotValue; - size_t sz; - PointSprite *left, *right; - int leftCond, rightCond; - PointSprite tmp; - - sz = end - begin; - - if (sz < 2) return; /* already sorted */ - if (sz == 2) { - /* trivial case */ - if (begin[1] < begin[0]) { - tmp = begin[0]; - begin[0] = begin[1]; - begin[1] = tmp; - return; - } - } - - /* minimum 3 elements from now on */ - - /* choose a pivot near the middle, since we frequently sort already sorted arrays */ - pivotValue = begin[sz / 2]; - - left = begin; - right = end - 1; - - while (right > left) { - /* check if left and right elements meet the conditions */ - leftCond = pivotValue >= *left; - rightCond = pivotValue < *right; - - if (!leftCond && !rightCond) { - tmp = *left; - *left = *right; - *right = tmp; - left++; - right--; - } - else if (leftCond && rightCond) { - left++; - right--; - } - else if (leftCond) { - left++; - } - else { - right--; - } - } - - /* recursion */ - sort(begin, left); - sort(left, end); -} - -void sortPointSprites() { - sort(pointSprites, pointSprites + pointSpriteCount); -} - diff --git a/src/tilemaze.c b/src/tilemaze.c deleted file mode 100644 index 6e2aa54..0000000 --- a/src/tilemaze.c +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include -#include -#include "tilemaze.h" -#include "mesh.h" -#include "treestor.h" -#include "dynarr.h" -#include "scene.h" - -struct object { - char *name; - struct g3d_mesh mesh; - - void *texels; - int tex_width, tex_height; - - struct object *next; -}; - -struct tile { - char *name; - struct object *objlist; -}; - -struct tilemaze { - struct tile *tileset; - int num_tiles; - - struct object *objects; -}; - -void free_object(struct object *obj); - -struct tilemaze *load_tilemaze(const char *fname) -{ - struct tilemaze *tmz; - - if(!(tmz = calloc(sizeof *tmz, 1))) { - return 0; - } - return tmz; -} - -void destroy_tilemaze(struct tilemaze *tmz) -{ - if(!tmz) return; - - free(tmz->tileset); - - while(tmz->objects) { - struct object *o = tmz->objects; - tmz->objects = tmz->objects->next; - - free(o->mesh.varr); - free(o->mesh.iarr); - free(o); - } - - free(tmz); -} - -void update_tilemaze(struct tilemaze *tmz) -{ -} - -void draw_tilemaze(struct tilemaze *tmz) -{ -} - -struct tile *load_tileset(const char *fname, int *count) -{ - int i; - struct tile *tiles = 0, *tile; - struct ts_node *ts = 0, *node; - struct ts_attr *attr; - struct object *obj; - - if(!(ts = ts_load(fname))) { - fprintf(stderr, "load_tileset: failed to load: %s\n", fname); - goto err; - } - if(strcmp(ts->name, "tileset") != 0) { - fprintf(stderr, "load_tileset: %s is not a tileset file\n", fname); - goto err; - } - - if(!(tiles = dynarr_alloc(sizeof *tiles, 0))) { - fprintf(stderr, "load_tileset: failed to create tiles array\n"); - goto err; - } - - node = ts->child_list; - while(node) { - if(strcmp(node->name, "tile") != 0) { - fprintf(stderr, "load_tileset: skipping unexpected node %s in %s\n", node->name, fname); - node = node->next; - continue; - } - - if(!(tile = malloc(sizeof *tile))) { - fprintf(stderr, "load_tileset: failed to allocate tile\n"); - goto err; - } - if(!(tile->name = malloc(strlen(node->name) + 1))) { - fprintf(stderr, "load_tileset: failed to allocate tile name\n"); - free(tile); - goto err; - } - strcpy(tile->name, node->name); - tile->objlist = 0; - - attr = node->attr_list; - while(attr) { - /* - if(strcmp(attr->name, "scn") == 0) { - struct object *last; - if(!(obj = load_objlist(attr->value.str, &last))) { - free(tile); - goto err; - } - last->next = tile->objlist; - tile->objlist = obj; - } - */ - attr = attr->next; - } - - node = node->next; - } - -err: - if(tiles) { - for(i=0; inext; - free_object(obj); - } - } - dynarr_free(tiles); - } - if(ts) ts_free_tree(ts); - return 0; -} - -void free_object(struct object *obj) -{ - if(!obj) return; - - free(obj->name); - free(obj->texels); - destroy_mesh(&obj->mesh); - - free(obj); -} diff --git a/src/tilemaze.h b/src/tilemaze.h deleted file mode 100644 index a06acd8..0000000 --- a/src/tilemaze.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef TILEMAZE_H_ -#define TILEMAZE_H_ - -struct tilemaze; - -struct tilemaze *load_tilemaze(const char *fname); -void destroy_tilemaze(struct tilemaze *tmz); - -void update_tilemaze(struct tilemaze *tmz); -void draw_tilemaze(struct tilemaze *tmz); - -#endif /* TILEMAZE_H_ */ diff --git a/src/tunnel.c b/src/tunnel.c deleted file mode 100644 index 9071b74..0000000 --- a/src/tunnel.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include -#include -#include -#include "imago2.h" -#include "demo.h" -#include "screen.h" -#include "gfxutil.h" - -#ifndef M_PI -#define M_PI 3.1415926535 -#endif - -#define VSCALE 1.5 - -#define TEX_FNAME "data/grid.png" -#define TEX_USCALE 4 -#define TEX_VSCALE 2 - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void stop(long trans_time); -static void draw(void); - -static void draw_tunnel_range(unsigned short *pixels, int xoffs, int yoffs, int starty, int num_lines, long tm); -static int count_bits(unsigned int x); -static int count_zeros(unsigned int x); - -static struct screen scr = { - "tunnel", - init, - destroy, - start, - stop, - draw -}; - -static int xsz, ysz, vxsz, vysz; -static int pan_width, pan_height; -static unsigned int *tunnel_map; -static unsigned char *tunnel_fog; - -static int tex_xsz, tex_ysz; -static unsigned int *tex_pixels; -static int tex_xshift, tex_yshift; -static unsigned int tex_xmask, tex_ymask; - -static long trans_start, trans_dur; -static int trans_dir; - - -struct screen *tunnel_screen(void) -{ - return &scr; -} - - -static int init(void) -{ - int i, j, n; - unsigned int *tmap; - unsigned char *fog; - float aspect = (float)fb_width / (float)fb_height; - - xsz = fb_width; - ysz = fb_height; - vxsz = xsz * VSCALE; - vysz = ysz * VSCALE; - - pan_width = vxsz - xsz; - pan_height = vysz - ysz; - - if(!(tunnel_map = malloc(vxsz * vysz * sizeof *tunnel_map))) { - fprintf(stderr, "failed to allocate tunnel map\n"); - return -1; - } - if(!(tunnel_fog = malloc(vxsz * vysz))) { - fprintf(stderr, "failed to allocate tunnel fog map\n"); - return -1; - } - - tmap = tunnel_map; - fog = tunnel_fog; - - for(i=0; i 255 ? 255 : f; - } - } - - if(!(tex_pixels = img_load_pixels(TEX_FNAME, &tex_xsz, &tex_ysz, IMG_FMT_RGBA32))) { - fprintf(stderr, "failed to load image " TEX_FNAME "\n"); - return -1; - } - if((count_bits(tex_xsz) | count_bits(tex_ysz)) != 1) { - fprintf(stderr, "non-pow2 image (%dx%d)\n", tex_xsz, tex_ysz); - return -1; - } - - /*tex_pixels = gen_test_image(&tex_xsz, &tex_ysz);*/ - - n = count_zeros(tex_xsz); - for(i=0; i= num_lines) { - trans_dir = 0; - } - } - - t = time_msec / 10000.0; - xoffs = (int)(cos(t * 3.0) * pan_width / 2) + pan_width / 2; - yoffs = (int)(sin(t * 4.0) * pan_height / 2) + pan_height / 2; - - for(i=0; i> 16) & 0xffff) << tex_xshift) >> 16; - unsigned int ty = ((tpacked & 0xffff) << tex_yshift) >> 16; - tx += toffs; - ty += toffs << 1; - - tx &= tex_xmask; - ty &= tex_ymask; - - col = tex_pixels[(ty << tex_xshift) + tx]; - r = col & 0xff; - g = (col >> 8) & 0xff; - b = (col >> 16) & 0xff; - - *rp = (r * fog) >> 8; - *gp = (g * fog) >> 8; - *bp = (b * fog) >> 8; -} - -static void draw_tunnel_range(unsigned short *pix, int xoffs, int yoffs, int starty, int num_lines, long tm) -{ - int i, j; - unsigned int *tmap = tunnel_map + (starty + yoffs) * vxsz + xoffs; - unsigned char *fog = tunnel_fog + (starty + yoffs) * vxsz + xoffs; - - long toffs = tm / 8; - unsigned int *pixels = (unsigned int*)pix + starty * (fb_width >> 1); - - for(i=0; i>1); j++) { - unsigned int col; - int r, g, b, idx = j << 1; - - tunnel_color(&r, &g, &b, toffs, tmap[idx], fog[idx]); - col = PACK_RGB16(r, g, b); - tunnel_color(&r, &g, &b, toffs, tmap[idx + 1], fog[idx + 1]); - col |= PACK_RGB16(r, g, b) << 16; - *pixels++ = col; - } - tmap += vxsz; - fog += vxsz; - } -} - -static int count_bits(unsigned int x) -{ - int i, nbits = 0; - for(i=0; i<32; i++) { - if(x & 1) ++nbits; - x >>= 1; - } - return nbits; -} - -static int count_zeros(unsigned int x) -{ - int i, num = 0; - for(i=0; i<32; i++) { - if(x & 1) break; - ++num; - x >>= 1; - } - return num; -} - -/* -static unsigned int *gen_test_image(int *wptr, int *hptr) -{ - int i, j; - int xsz = 256, ysz = 256; - unsigned int *pixels, *pix; - - if(!(pixels = malloc(xsz * ysz * sizeof *pix))) { - return 0; - } - pix = pixels; - - for(i=0; i