disabled dep-files when building on dos, because it goes into an infinite loop
[dosdemo] / src / bump.c
index 66c6bbc..b82594b 100644 (file)
@@ -7,12 +7,10 @@
 
 #include "demo.h"
 #include "screen.h"
-#include "tinyfps.h"
 
 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 struct screen scr = {
@@ -20,16 +18,35 @@ static struct screen scr = {
        init,
        destroy,
        start,
-       stop,
+       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;
@@ -37,18 +54,34 @@ struct screen *bump_screen(void)
 
 static int init(void)
 {
+       int i, j, x, y, c, r, g, b;
+
        const int numBlurs = 3;
-       int i, j, x, y;
-       int fb_size = fb_width * fb_height;
+       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;
 
-       initFpsFonts();
+       // 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);
 
-       memset(lightmap, 0, fb_size);
-       memset(bumpOffset, 0, 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++)
@@ -65,11 +98,11 @@ static int init(void)
        {
                for (x = 0; x < fb_width; x++)
                {
-                       const float offsetPower = 2.0f;
+                       const float offsetPower = 0.75f;
                        int dx, dy, xp, yp;
 
-                       dx = (int)((heightmap[i] - heightmap[i + 1]) * offsetPower);
-                       dy = (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower);
+                       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;
@@ -83,19 +116,44 @@ static int init(void)
                }
        }
 
-       // Lightmap test (this will be replaced by code in the main loop later on, the idea is you can render moving lights and other light geometry or sprites in light buffer and the bumpOffset will catch them)
+       // Generate three lights
        i = 0;
-       for (y = 0; y < fb_height; y++)
+       for (y = 0; y < BIG_LIGHT_HEIGHT; y++)
        {
-               int yc = y - (fb_height >> 1);
-               for (x = 0; x < fb_width; x++)
+               int yc = y - (BIG_LIGHT_HEIGHT / 2);
+               for (x = 0; x < BIG_LIGHT_WIDTH; x++)
                {
-                       int xc = x - (fb_width >> 1);
-                       int c = (int)sqrt(xc * xc + yc * yc) << 1;
-                       int r;
-                       if (c > 255) c = 255;
-                       r = 255 - c;
-                       lightmap[i++] = ((r >> 4) << 11) | ((r >> 3) << 5) | (r >> 3);
+                       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);
                }
        }
 
@@ -111,21 +169,160 @@ static void start(long trans_time)
        startingTime = time_msec;
 }
 
-static void stop(long trans_time)
+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 draw(void)
+
+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;
-       unsigned short *vram = (unsigned short*)fb_pixels;
        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();
 
-       drawFps((unsigned short*)fb_pixels);
+       renderBump((unsigned short*)fb_pixels);
 
        swap_buffers(0);
 }