backdrop
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 28 Aug 2018 13:44:48 +0000 (16:44 +0300)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 28 Aug 2018 13:44:48 +0000 (16:44 +0300)
src/noise.c [new file with mode: 0644]
src/noise.h [new file with mode: 0644]
src/parts/rtxonoff.c

diff --git a/src/noise.c b/src/noise.c
new file mode 100644 (file)
index 0000000..7c1debd
--- /dev/null
@@ -0,0 +1,459 @@
+#include <math.h>
+#include <stdlib.h>
+#include "noise.h"
+
+/* ---- Ken Perlin's implementation of noise ---- */
+#define B      0x100
+#define BM     0xff
+#define N      0x1000
+#define NP     12   /* 2^N */
+#define NM     0xfff
+
+#define s_curve(t) (t * t * (3.0f - 2.0f * t))
+
+#define setup(elem, b0, b1, r0, r1) \
+       do {                                                    \
+               float t = elem + N;             \
+               b0 = ((int)t) & BM;                     \
+               b1 = (b0 + 1) & BM;                     \
+               r0 = t - (int)t;                        \
+               r1 = r0 - 1.0f;                         \
+       } while(0)
+
+#define setup_p(elem, b0, b1, r0, r1, p) \
+       do {                                                    \
+               float t = elem + N;             \
+               b0 = (((int)t) & BM) % p;       \
+               b1 = ((b0 + 1) & BM) % p;       \
+               r0 = t - (int)t;                        \
+               r1 = r0 - 1.0f;                         \
+       } while(0)
+
+
+static int perm[B + B + 2];                    /* permuted index from g_n onto themselves */
+static float grad3[B + B + 2][3];      /* 3D random gradients */
+static float grad2[B + B + 2][2];      /* 2D random gradients */
+static float grad1[B + B + 2];         /* 1D random ... slopes */
+static int tables_valid;
+
+#define init_once()    if(!tables_valid) init_noise()
+
+#define SQ(x)  ((x) * (x))
+#define LERP(a, b, t)  ((a) + ((b) - (a)) * (t))
+
+static void init_noise()
+{
+       int i;
+       float len;
+
+       /* calculate random gradients */
+       for(i=0; i<B; i++) {
+               perm[i] = i;    /* .. and initialize permutation mapping to identity */
+
+               grad1[i] = (float)((rand() % (B + B)) - B) / B;
+
+               grad2[i][0] = (float)((rand() % (B + B)) - B) / B;
+               grad2[i][1] = (float)((rand() % (B + B)) - B) / B;
+               len = sqrt(SQ(grad2[i][0]) + SQ(grad2[i][1]));
+               if(len != 0.0f) {
+                       grad2[i][0] /= len;
+                       grad2[i][1] /= len;
+               }
+
+               grad3[i][0] = (float)((rand() % (B + B)) - B) / B;
+               grad3[i][1] = (float)((rand() % (B + B)) - B) / B;
+               grad3[i][2] = (float)((rand() % (B + B)) - B) / B;
+               len = sqrt(SQ(grad3[i][0]) + SQ(grad3[i][1]) + SQ(grad3[i][2]));
+               if(len != 0.0f) {
+                       grad3[i][0] /= len;
+                       grad3[i][1] /= len;
+                       grad3[i][2] /= len;
+               }
+       }
+
+       /* permute indices by swapping them randomly */
+       for(i=0; i<B; i++) {
+               int rand_idx = rand() % B;
+
+               int tmp = perm[i];
+               perm[i] = perm[rand_idx];
+               perm[rand_idx] = tmp;
+       }
+
+       /* fill up the rest of the arrays by duplicating the existing gradients */
+       /* and permutations */
+       for(i=0; i<B+2; i++) {
+               perm[B + i] = perm[i];
+               grad1[B + i] = grad1[i];
+               grad2[B + i][0] = grad2[i][0];
+               grad2[B + i][1] = grad2[i][1];
+               grad3[B + i][0] = grad3[i][0];
+               grad3[B + i][1] = grad3[i][1];
+               grad3[B + i][2] = grad3[i][2];
+       }
+
+       tables_valid = 1;
+}
+
+
+float noise1(float x)
+{
+       int bx0, bx1;
+       float rx0, rx1, sx, u, v;
+
+       init_once();
+
+       setup(x, bx0, bx1, rx0, rx1);
+       sx = s_curve(rx0);
+       u = rx0 * grad1[perm[bx0]];
+       v = rx1 * grad1[perm[bx1]];
+       return LERP(u, v, sx);
+}
+
+float noise2(float x, float y)
+{
+       int i, j, b00, b10, b01, b11;
+       int bx0, bx1, by0, by1;
+       float rx0, rx1, ry0, ry1;
+       float sx, sy, u, v, a, b;
+
+       init_once();
+
+       setup(x, bx0, bx1, rx0, rx1);
+       setup(y, by0, by1, ry0, ry1);
+
+       i = perm[bx0];
+       j = perm[bx1];
+
+       b00 = perm[i + by0];
+       b10 = perm[j + by0];
+       b01 = perm[i + by1];
+       b11 = perm[j + by1];
+
+       /* calculate hermite inteprolating factors */
+       sx = s_curve(rx0);
+       sy = s_curve(ry0);
+
+       /* interpolate along the left edge */
+       u = grad2[b00][0] * rx0 + grad2[b00][1] * ry0;
+       v = grad2[b10][0] * rx1 + grad2[b10][1] * ry0;
+       a = LERP(u, v, sx);
+
+       /* interpolate along the right edge */
+       u = grad2[b01][0] * rx0 + grad2[b01][1] * ry1;
+       v = grad2[b11][0] * rx1 + grad2[b11][1] * ry1;
+       b = LERP(u, v, sx);
+
+       /* interpolate between them */
+       return LERP(a, b, sy);
+}
+
+float noise3(float x, float y, float z)
+{
+       int i, j;
+       int bx0, bx1, by0, by1, bz0, bz1;
+       int b00, b10, b01, b11;
+       float rx0, rx1, ry0, ry1, rz0, rz1;
+       float sx, sy, sz;
+       float u, v, a, b, c, d;
+
+       init_once();
+
+       setup(x, bx0, bx1, rx0, rx1);
+       setup(y, by0, by1, ry0, ry1);
+       setup(z, bz0, bz1, rz0, rz1);
+
+       i = perm[bx0];
+       j = perm[bx1];
+
+       b00 = perm[i + by0];
+       b10 = perm[j + by0];
+       b01 = perm[i + by1];
+       b11 = perm[j + by1];
+
+       /* calculate hermite interpolating factors */
+       sx = s_curve(rx0);
+       sy = s_curve(ry0);
+       sz = s_curve(rz0);
+
+       /* interpolate along the top slice of the cell */
+       u = grad3[b00 + bz0][0] * rx0 + grad3[b00 + bz0][1] * ry0 + grad3[b00 + bz0][2] * rz0;
+       v = grad3[b10 + bz0][0] * rx1 + grad3[b10 + bz0][1] * ry0 + grad3[b10 + bz0][2] * rz0;
+       a = LERP(u, v, sx);
+
+       u = grad3[b01 + bz0][0] * rx0 + grad3[b01 + bz0][1] * ry1 + grad3[b01 + bz0][2] * rz0;
+       v = grad3[b11 + bz0][0] * rx1 + grad3[b11 + bz0][1] * ry1 + grad3[b11 + bz0][2] * rz0;
+       b = LERP(u, v, sx);
+
+       c = LERP(a, b, sy);
+
+       /* interpolate along the bottom slice of the cell */
+       u = grad3[b00 + bz0][0] * rx0 + grad3[b00 + bz0][1] * ry0 + grad3[b00 + bz0][2] * rz1;
+       v = grad3[b10 + bz0][0] * rx1 + grad3[b10 + bz0][1] * ry0 + grad3[b10 + bz0][2] * rz1;
+       a = LERP(u, v, sx);
+
+       u = grad3[b01 + bz0][0] * rx0 + grad3[b01 + bz0][1] * ry1 + grad3[b01 + bz0][2] * rz1;
+       v = grad3[b11 + bz0][0] * rx1 + grad3[b11 + bz0][1] * ry1 + grad3[b11 + bz0][2] * rz1;
+       b = LERP(u, v, sx);
+
+       d = LERP(a, b, sy);
+
+       /* interpolate between slices */
+       return LERP(c, d, sz);
+}
+
+
+float pnoise1(float x, int period)
+{
+       int bx0, bx1;
+       float rx0, rx1, sx, u, v;
+
+       init_once();
+
+       setup_p(x, bx0, bx1, rx0, rx1, period);
+       sx = s_curve(rx0);
+       u = rx0 * grad1[perm[bx0]];
+       v = rx1 * grad1[perm[bx1]];
+       return LERP(u, v, sx);
+}
+
+float pnoise2(float x, float y, int per_x, int per_y)
+{
+       int i, j, b00, b10, b01, b11;
+       int bx0, bx1, by0, by1;
+       float rx0, rx1, ry0, ry1;
+       float sx, sy, u, v, a, b;
+
+       init_once();
+
+       setup_p(x, bx0, bx1, rx0, rx1, per_x);
+       setup_p(y, by0, by1, ry0, ry1, per_y);
+
+       i = perm[bx0];
+       j = perm[bx1];
+
+       b00 = perm[i + by0];
+       b10 = perm[j + by0];
+       b01 = perm[i + by1];
+       b11 = perm[j + by1];
+
+       /* calculate hermite inteprolating factors */
+       sx = s_curve(rx0);
+       sy = s_curve(ry0);
+
+       /* interpolate along the left edge */
+       u = grad2[b00][0] * rx0 + grad2[b00][1] * ry0;
+       v = grad2[b10][0] * rx1 + grad2[b10][1] * ry0;
+       a = LERP(u, v, sx);
+
+       /* interpolate along the right edge */
+       u = grad2[b01][0] * rx0 + grad2[b01][1] * ry1;
+       v = grad2[b11][0] * rx1 + grad2[b11][1] * ry1;
+       b = LERP(u, v, sx);
+
+       /* interpolate between them */
+       return LERP(a, b, sy);
+}
+
+float pnoise3(float x, float y, float z, int per_x, int per_y, int per_z)
+{
+       int i, j;
+       int bx0, bx1, by0, by1, bz0, bz1;
+       int b00, b10, b01, b11;
+       float rx0, rx1, ry0, ry1, rz0, rz1;
+       float sx, sy, sz;
+       float u, v, a, b, c, d;
+
+       init_once();
+
+       setup_p(x, bx0, bx1, rx0, rx1, per_x);
+       setup_p(y, by0, by1, ry0, ry1, per_y);
+       setup_p(z, bz0, bz1, rz0, rz1, per_z);
+
+       i = perm[bx0];
+       j = perm[bx1];
+
+       b00 = perm[i + by0];
+       b10 = perm[j + by0];
+       b01 = perm[i + by1];
+       b11 = perm[j + by1];
+
+       /* calculate hermite interpolating factors */
+       sx = s_curve(rx0);
+       sy = s_curve(ry0);
+       sz = s_curve(rz0);
+
+       /* interpolate along the top slice of the cell */
+       u = grad3[b00 + bz0][0] * rx0 + grad3[b00 + bz0][1] * ry0 + grad3[b00 + bz0][2] * rz0;
+       v = grad3[b10 + bz0][0] * rx1 + grad3[b10 + bz0][1] * ry0 + grad3[b10 + bz0][2] * rz0;
+       a = LERP(u, v, sx);
+
+       u = grad3[b01 + bz0][0] * rx0 + grad3[b01 + bz0][1] * ry1 + grad3[b01 + bz0][2] * rz0;
+       v = grad3[b11 + bz0][0] * rx1 + grad3[b11 + bz0][1] * ry1 + grad3[b11 + bz0][2] * rz0;
+       b = LERP(u, v, sx);
+
+       c = LERP(a, b, sy);
+
+       /* interpolate along the bottom slice of the cell */
+       u = grad3[b00 + bz0][0] * rx0 + grad3[b00 + bz0][1] * ry0 + grad3[b00 + bz0][2] * rz1;
+       v = grad3[b10 + bz0][0] * rx1 + grad3[b10 + bz0][1] * ry0 + grad3[b10 + bz0][2] * rz1;
+       a = LERP(u, v, sx);
+
+       u = grad3[b01 + bz0][0] * rx0 + grad3[b01 + bz0][1] * ry1 + grad3[b01 + bz0][2] * rz1;
+       v = grad3[b11 + bz0][0] * rx1 + grad3[b11 + bz0][1] * ry1 + grad3[b11 + bz0][2] * rz1;
+       b = LERP(u, v, sx);
+
+       d = LERP(a, b, sy);
+
+       /* interpolate between slices */
+       return LERP(c, d, sz);
+}
+
+
+float fbm1(float x, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += noise1(x * freq) / freq;
+               freq *= 2.0f;
+       }
+       return res;
+}
+
+float fbm2(float x, float y, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += noise2(x * freq, y * freq) / freq;
+               freq *= 2.0f;
+       }
+       return res;
+}
+
+float fbm3(float x, float y, float z, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += noise3(x * freq, y * freq, z * freq) / freq;
+               freq *= 2.0f;
+       }
+       return res;
+
+}
+
+
+float pfbm1(float x, int per, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += pnoise1(x * freq, per) / freq;
+               freq *= 2.0f;
+               per *= 2;
+       }
+       return res;
+}
+
+float pfbm2(float x, float y, int per_x, int per_y, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += pnoise2(x * freq, y * freq, per_x, per_y) / freq;
+               freq *= 2.0f;
+               per_x *= 2;
+               per_y *= 2;
+       }
+       return res;
+}
+
+float pfbm3(float x, float y, float z, int per_x, int per_y, int per_z, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(int i=0; i<octaves; i++) {
+               res += pnoise3(x * freq, y * freq, z * freq, per_x, per_y, per_z) / freq;
+               freq *= 2.0f;
+               per_x *= 2;
+               per_y *= 2;
+               per_z *= 2;
+       }
+       return res;
+}
+
+
+float turbulence1(float x, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += fabs(noise1(x * freq) / freq);
+               freq *= 2.0f;
+       }
+       return res;
+}
+
+float turbulence2(float x, float y, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += fabs(noise2(x * freq, y * freq) / freq);
+               freq *= 2.0f;
+       }
+       return res;
+}
+
+float turbulence3(float x, float y, float z, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += fabs(noise3(x * freq, y * freq, z * freq) / freq);
+               freq *= 2.0f;
+       }
+       return res;
+}
+
+
+float pturbulence1(float x, int per, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += fabs(pnoise1(x * freq, per) / freq);
+               freq *= 2.0f;
+               per *= 2;
+       }
+       return res;
+}
+
+float pturbulence2(float x, float y, int per_x, int per_y, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += fabs(pnoise2(x * freq, y * freq, per_x, per_y) / freq);
+               freq *= 2.0f;
+               per_x *= 2;
+               per_y *= 2;
+       }
+       return res;
+}
+
+float pturbulence3(float x, float y, float z, int per_x, int per_y, int per_z, int octaves)
+{
+       int i;
+       float res = 0.0f, freq = 1.0f;
+       for(i=0; i<octaves; i++) {
+               res += fabs(pnoise3(x * freq, y * freq, z * freq, per_x, per_y, per_z) / freq);
+               freq *= 2.0f;
+               per_x *= 2;
+               per_y *= 2;
+               per_z *= 2;
+       }
+       return res;
+}
diff --git a/src/noise.h b/src/noise.h
new file mode 100644 (file)
index 0000000..24c05f6
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef NOISE_H_
+#define NOISE_H_
+
+float noise1(float x);
+float noise2(float x, float y);
+float noise3(float x, float y, float z);
+
+float pnoise1(float x, int period);
+float pnoise2(float x, float y, int per_x, int per_y);
+float pnoise3(float x, float y, float z, int per_x, int per_y, int per_z);
+
+float fbm1(float x, int octaves);
+float fbm2(float x, float y, int octaves);
+float fbm3(float x, float y, float z, int octaves);
+
+float pfbm1(float x, int per, int octaves);
+float pfbm2(float x, float y, int per_x, int per_y, int octaves);
+float pfbm3(float x, float y, float z, int per_x, int per_y, int per_z, int octaves);
+
+float turbulence1(float x, int octaves);
+float turbulence2(float x, float y, int octaves);
+float turbulence3(float x, float y, float z, int octaves);
+
+float pturbulence1(float x, int per, int octaves);
+float pturbulence2(float x, float y, int per_x, int per_y, int octaves);
+float pturbulence3(float x, float y, float z, int per_x, int per_y, int per_z, int octaves);
+
+#endif /* NOISE_H_ */
index bab4d98..e56baeb 100644 (file)
@@ -1,14 +1,18 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
+#include <assert.h>
 #include "demo.h"
 #include "3dgfx.h"
 #include "screen.h"
 #include "cfgopt.h"
 #include "polyfill.h"
 #include "imago2.h"
+#include "util.h"
 #include "gfxutil.h"
 #include "mesh.h"
+#include "noise.h"
 
 static int init(void);
 static void destroy(void);
@@ -33,6 +37,16 @@ static const char *cartex_fname[2] = {"data/ldiablo.png", 0};
 static struct g3d_mesh mesh_car[2];
 static struct pimage tex_car[2];
 
+#define BGCOL_SIZE     128
+#define BGOFFS_SIZE    1024
+static uint16_t bgcol[BGCOL_SIZE];
+static uint16_t bgcol_mir[BGCOL_SIZE];
+static int bgoffs[BGOFFS_SIZE];
+static const int colzen[] = {98, 64, 192};
+static const int colhor[] = {128, 80, 64};
+static const int colmnt[] = {16, 9, 24};
+static uint16_t mountcol, mountcol_mir;
+
 static int shading = G3D_TEX_GOURAUD;
 static int do_clip = 1;
 
@@ -45,6 +59,25 @@ struct screen *rtxonoff_screen(void)
 static int init(void)
 {
        int i;
+       int col[3];
+
+       mountcol = PACK_RGB16(colmnt[0], colmnt[1], colmnt[2]);
+       mountcol_mir = PACK_RGB16(colmnt[0] / 2, colmnt[1] / 2, colmnt[2] / 2);
+
+       for(i=0; i<BGCOL_SIZE; i++) {
+               int32_t t = (i << 8) / BGCOL_SIZE;
+               col[0] = colhor[0] + ((colzen[0] - colhor[0]) * t >> 8);
+               col[1] = colhor[1] + ((colzen[1] - colhor[1]) * t >> 8);
+               col[2] = colhor[2] + ((colzen[2] - colhor[2]) * t >> 8);
+               bgcol[i] = PACK_RGB16(col[0], col[1], col[2]);
+               bgcol_mir[i] = PACK_RGB16(col[0] / 2, col[1] / 2, col[2] / 2);
+       }
+
+       for(i=0; i<BGOFFS_SIZE; i++) {
+               float x = 8.0f * (float)i / (float)BGOFFS_SIZE;
+
+               bgoffs[i] = pfbm1(x, 8.0f, 5) * 32 + 16;
+       }
 
        for(i=0; i<sizeof car_fname / sizeof car_fname[0]; i++) {
                if(cartex_fname[i]) {
@@ -75,33 +108,88 @@ static void destroy(void)
        }
 }
 
+#define VFOV   60
 static void start(long trans_time)
 {
        g3d_matrix_mode(G3D_PROJECTION);
        g3d_load_identity();
-       g3d_perspective(60.0, 1.3333333, 0.5, 100.0);
+       g3d_perspective(VFOV, 1.3333333, 0.5, 100.0);
 
        g3d_enable(G3D_CULL_FACE);
        g3d_enable(G3D_LIGHTING);
        g3d_enable(G3D_LIGHT0);
-
-       g3d_polygon_mode(shading);
 }
 
 static void update(void)
 {
        mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
+
+       cam_theta = fmod(cam_theta, 360.0f);
+       if(cam_theta < 0) cam_theta += 360.0f;
+
+       if(cam_phi < 0) cam_phi = 0;
+}
+
+static void backdrop(void)
+{
+       static const int colzen[] = {98, 64, 192};
+       static const int colhor[] = {128, 80, 64};
+       int i, j, hory, start[3], end[3], col[3];
+       uint16_t *fbptr, pcol;
+       int cidx, offs = -10;
+       int startidx;
+
+       startidx = cround64(cam_theta * (float)BGOFFS_SIZE) / 360;
+
+       hory = (fb_height - 2 * fb_height * cround64(cam_phi) / VFOV) / 2;
+       if(hory > fb_height) hory = fb_height;
+
+       if(hory > 0) {
+               fbptr = fb_pixels + (hory - 1) * fb_width;
+               cidx = offs;
+               i = 0;
+               while(fbptr >= fb_pixels) {
+                       pcol = bgcol[cidx < 0 ? 0 : (cidx >= BGCOL_SIZE ? BGCOL_SIZE - 1 : cidx)];
+                       for(j=0; j<fb_width; j++) {
+                               if(cidx < bgoffs[(startidx + j) & (BGOFFS_SIZE - 1)]) {
+                                       fbptr[j] = mountcol;
+                               } else {
+                                       fbptr[j] = pcol;
+                               }
+                       }
+                       fbptr -= fb_width;
+                       cidx++;
+               }
+               cidx = offs;
+       } else {
+               cidx = offs - hory;
+               hory = 0;
+       }
+
+       fbptr = fb_pixels + hory * fb_width;
+       for(i=hory; i<fb_height; i++) {
+               pcol = bgcol_mir[cidx < 0 ? 0 : (cidx >= BGCOL_SIZE ? BGCOL_SIZE - 1 : cidx)];
+               for(j=0; j<fb_width; j++) {
+                       if(cidx < bgoffs[(startidx + j) & (BGOFFS_SIZE - 1)]) {
+                               *fbptr++ = mountcol_mir;
+                       } else {
+                               *fbptr++ = pcol;
+                       }
+               }
+               cidx++;
+       }
 }
 
 static void draw(void)
 {
-       int i;
+       int i, j;
+       uint16_t *fbptr = fb_pixels;
        static float vdir[3];
        float t = (float)time_msec / 16.0f;
 
        update();
 
-       memset(fb_pixels, 0, fb_width * fb_height * 2);
+       backdrop();
 
        g3d_matrix_mode(G3D_MODELVIEW);
        g3d_load_identity();
@@ -109,6 +197,7 @@ static void draw(void)
        g3d_rotate(cam_phi, 1, 0, 0);
        g3d_rotate(cam_theta, 0, 1, 0);
 
+       g3d_polygon_mode(shading);
        g3d_set_texture(tex_car[0].width, tex_car[0].height, tex_car[0].pixels);
        zsort_mesh(&mesh_car[0]);