source: libcaca/trunk/src/cacaball.c @ 896

Last change on this file since 896 was 859, checked in by Sam Hocevar, 15 years ago
  • Removed duplicate uint*_t defines from *_internal.h and included common.h in all .c files that needed it.
  • Property svn:keywords set to Id
File size: 6.0 KB
RevLine 
[317]1/*
[319]2 *  cacaball      metaballs effect for libcaca
3 *  Copyright (c) 2003-2004 Jean-Yves Lamoureux <jylam@lnxscene.org>
4 *                All Rights Reserved
[317]5 *
[319]6 *  $Id: cacaball.c 859 2006-04-24 20:35:59Z sam $
[317]7 *
[319]8 *  This program is free software; you can redistribute it and/or
[522]9 *  modify it under the terms of the Do What The Fuck You Want To
10 *  Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
[317]12 */
13
[319]14#include "config.h"
[859]15#include "common.h"
[317]16
[581]17#if !defined(__KERNEL__)
[597]18#   include <string.h>
[581]19#   include <math.h>
20#   ifndef M_PI
21#       define M_PI 3.14159265358979323846
22#   endif
[339]23#endif
24
[524]25#include "cucul.h"
[317]26#include "caca.h"
27
28/* Virtual buffer size */
[319]29#define XSIZ 256
30#define YSIZ 256
[317]31
[615]32#define METASIZE 128
33#define METABALLS 12
[317]34
[321]35/* Colour index where to crop balls */
[615]36#define CROPBALL 200
[321]37
[320]38static void create_ball(void);
[319]39static void draw_ball(unsigned int, unsigned int);
[317]40
[319]41static unsigned char pixels[XSIZ * YSIZ];
42static unsigned char metaball[METASIZE * METASIZE];
[317]43
[319]44int main(int argc, char **argv)
[317]45{
[811]46    cucul_canvas_t *cv; caca_display_t *dp;
[514]47    unsigned int r[256], g[256], b[256], a[256];
[811]48    float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
[321]49    unsigned int x[METABALLS], y[METABALLS];
[777]50    cucul_dither_t *cucul_dither;
[321]51    float i = 10.0, j = 17.0, k = 11.0;
[377]52    int p, frame = 0, pause = 0;
[647]53    double frameOffset[360 + 80];
[616]54    double frameOffset40[360];
55    double frameOffset80[360];
[317]56
[813]57    cv = cucul_create_canvas(0, 0);
[811]58    if(!cv)
[319]59        return 1;
[819]60    dp = caca_create_display(cv);
[811]61    if(!dp)
[524]62        return 1;
[317]63
[811]64    caca_set_delay(dp, 20000);
[317]65
[319]66    /* Make the palette eatable by libcaca */
67    for(p = 0; p < 256; p++)
[320]68        r[p] = g[p] = b[p] = a[p] = 0x0;
[339]69    r[255] = g[255] = b[255] = 0xfff;
[320]70
[734]71    /* Create a libcucul dither smaller than our pixel buffer, so that we
[321]72     * display only the interesting part of it */
[734]73    cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE,
[524]74                                       XSIZ, 0, 0, 0, 0);
[317]75
[319]76    /* Generate ball sprite */
[320]77    create_ball();
[317]78
[321]79    for(p = 0; p < METABALLS; p++)
80    {
[811]81        dd[p] = cucul_rand(0, 100);
[524]82        di[p] = (float)cucul_rand(500, 4000) / 6000.0;
83        dj[p] = (float)cucul_rand(500, 4000) / 6000.0;
84        dk[p] = (float)cucul_rand(500, 4000) / 6000.0;
[321]85    }
86
[647]87    for(frame = 0; frame < 360; frame++) {
88        frameOffset[frame] = frame * M_PI / 60;
89        frameOffset40[frame] = (frame + 40) * M_PI / 60;
90        frameOffset80[frame] = (frame + 80) * M_PI / 60;
[616]91    }
92
[319]93    /* Go ! */
[377]94    for(;;)
[317]95    {
[777]96        caca_event_t ev;
[811]97        if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
[377]98        {
[810]99            switch(ev.data.key.ch)
[681]100            {
101                case CACA_KEY_ESCAPE: goto end;
102                case ' ': pause = !pause;
103            }
[377]104        }
105
106        if(pause)
107            goto paused;
108
[339]109        frame++;
[647]110        if(frame >= 360)
111            frame = 0;
[339]112
113        /* Crop the palette */
114        for(p = CROPBALL; p < 255; p++)
115        {
116            int t1, t2, t3;
[616]117            double c1 = 1.0 + sin((double)frameOffset[frame]);
[647]118            double c2 = 1.0 + sin((double)frameOffset40[frame]);
119            double c3 = 1.0 + sin((double)frameOffset80[frame]);
[616]120
[647]121            t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
[339]122            t2 = p < 0xe0 ? 0 : (p - 0xe0) * 0x80;
123            t3 = p < 0x40 ? p * 0x40 : 0xfff;
124
[647]125            r[p] = (c1 * t1 + c2 * t2 + c3 * t3) / 4;
126            g[p] = (c1 * t2 + c2 * t3 + c3 * t1) / 4;
127            b[p] = (c1 * t3 + c2 * t1 + c3 * t2) / 4;
[339]128        }
129
130        /* Set the palette */
[734]131        cucul_set_dither_palette(cucul_dither, r, g, b, a);
[339]132
[319]133        /* Silly paths for our balls */
[321]134        for(p = 0; p < METABALLS; p++)
135        {
136            float u = di[p] * i + dj[p] * j + dk[p] * sin(di[p] * k);
[811]137            float v = dd[p] + di[p] * j + dj[p] * k + dk[p] * sin(dk[p] * i);
[321]138            u = sin(i + u * 2.1) * (1.0 + sin(u));
139            v = sin(j + v * 1.9) * (1.0 + sin(v));
140            x[p] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
141            y[p] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
142        }
[317]143
[319]144        i += 0.011;
[321]145        j += 0.017;
146        k += 0.019;
[317]147
[319]148        memset(pixels, 0, XSIZ * YSIZ);
[317]149
[319]150        /* Here is all the trick. Maybe if you're that
151         * clever you'll understand. */
[321]152        for(p = 0; p < METABALLS; p++)
[319]153            draw_ball(x[p], y[p]);
[317]154
[377]155paused:
[524]156        /* Draw our virtual buffer to screen, letting libcucul resize it */
[811]157        cucul_dither_bitmap(cv, 0, 0,
[816]158                          cucul_get_canvas_width(cv),
159                          cucul_get_canvas_height(cv),
[734]160                          cucul_dither, pixels + (METASIZE / 2) * (1 + XSIZ));
[811]161        cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
[813]162        cucul_putstr(cv, cucul_get_canvas_width(cv) - 30,
163                         cucul_get_canvas_height(cv) - 2,
164                         " -=[ Powered by libcaca ]=- ");
[704]165
[819]166        caca_refresh_display(dp);
[317]167    }
168
[319]169    /* End, bye folks */
[377]170end:
[734]171    cucul_free_dither(cucul_dither);
[819]172    caca_free_display(dp);
[813]173    cucul_free_canvas(cv);
[317]174
[319]175    return 0;
[317]176}
177
[319]178/* Generate ball sprite
179 * You should read the comments, I already wrote that before ... */
[320]180static void create_ball(void)
[317]181{
[319]182    int x, y;
183    float distance;
[317]184
[319]185    for(y = 0; y < METASIZE; y++)
186        for(x = 0; x < METASIZE; x++)
187    {
[613]188        distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
[319]189                 + ((METASIZE/2) - y) * ((METASIZE/2) - y);
190        distance = sqrt(distance) * 64 / METASIZE;
[613]191        metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
[317]192    }
193}
194
[319]195/* You missed the trick ? */
196static void draw_ball(unsigned int bx, unsigned int by)
[317]197{
[319]198    unsigned int color;
199    unsigned int i, e = 0;
200    unsigned int b = (by * XSIZ) + bx;
[317]201
[320]202    for(i = 0; i < METASIZE * METASIZE; i++)
[319]203    {
204        color = pixels[b] + metaball[i];
[317]205
[319]206        if(color > 255)
207            color = 255;
[317]208
[319]209        pixels[b] = color;
210        if(e == METASIZE)
211        {
212            e = 0;
213            b += XSIZ - METASIZE;
214        }
215        b++;
216        e++;
217    }
[317]218}
[320]219
Note: See TracBrowser for help on using the repository browser.