Ignore:
Timestamp:
Sep 16, 2006, 3:12:11 PM (14 years ago)
Author:
Sam Hocevar
Message:
  • Factor most of the cacademo code.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/src/cacademo.c

    r1026 r1027  
    22 *  cacademo      various demo effects for libcaca
    33 *  Copyright (c) 1998 Michele Bini <mibin@tin.it>
     4 *                2003-2004 Jean-Yves Lamoureux <jylam@lnxscene.org>
    45 *                2004 Sam Hocevar <sam@zoy.org>
    56 *                All Rights Reserved
     
    1819#if !defined(__KERNEL__)
    1920#   include <stdio.h>
     21#   include <stdlib.h>
    2022#   include <string.h>
    2123#   include <math.h>
     
    2830#include "caca.h"
    2931
    30 /* Virtual buffer size for dither-based demos */
     32enum action { INIT, UPDATE, DRAW, FREE };
     33
     34void plasma(enum action, cucul_canvas_t *);
     35void metaballs(enum action, cucul_canvas_t *);
     36void moire(enum action, cucul_canvas_t *);
     37
     38void (*demo_list[])(enum action, cucul_canvas_t *) =
     39{
     40    plasma,
     41    metaballs,
     42    moire,
     43};
     44
     45/* Common macros for dither-based demos */
    3146#define XSIZ 256
    3247#define YSIZ 256
    33 static unsigned char screen[XSIZ * YSIZ];
    34 
    35 /* The plasma effect */
    36 #define TABLEX (XSIZ * 2)
    37 #define TABLEY (YSIZ * 2)
    38 
    39 static unsigned char table[TABLEX * TABLEY];
    40 
    41 static int main_plasma(int, char **);
    42 static void do_plasma(unsigned char *,
    43                       double, double, double, double, double, double);
    44 
    45 /* The metaball effect */
    46 #define METASIZE 128
    47 #define METABALLS 12
    48 #define CROPBALL 200 /* Colour index where to crop balls */
    49 
    50 static int main_ball(int, char **);
    51 static void create_ball(void);
    52 static void draw_ball(unsigned int, unsigned int);
    53 
    54 static unsigned char metaball[METASIZE * METASIZE];
    55 
    56 /* The moiré effect */
    57 #define DISCSIZ 512
    58 #define DISCTHICKNESS 96
    59 
    60 static unsigned char disc[DISCSIZ * DISCSIZ];
    61 
    62 static int main_moir(int, char **);
    63 static void put_disc(int, int);
    64 static void draw_disc(int, char);
    65 static void draw_line(int, int, char);
     48
     49/* Global variables */
     50static int frame = 0;
    6651
    6752int main(int argc, char **argv)
    6853{
    69     switch(cucul_rand(0, 3))
    70     {
    71         case 0:
    72             return main_plasma(argc, argv);
    73         case 1:
    74             return main_ball(argc, argv);
    75         case 2:
    76             return main_moir(argc, argv);
    77     }
    78 
    79     return -1;
    80 }
    81 
    82 static int main_plasma(int argc, char **argv)
    83 {
    84     cucul_canvas_t *cv, *c2, *mask; caca_display_t *dp;
    85     unsigned int red[256], green[256], blue[256], alpha[256];
    86     double r[3], R[6];
    87     cucul_dither_t *dither;
    88     int i, x, y, frame = 0, pause = 0;
    89 
    90     cv = cucul_create_canvas(0, 0);
    91     if(!cv)
    92         return 1;
    93     dp = caca_create_display(cv);
     54    static caca_display_t *dp;
     55    static cucul_canvas_t *frontcv, *backcv, *mask;
     56    int demo = 0, pause = 0;
     57
     58    /* Set up two canvases, a mask, and attach a display to the front one */
     59    frontcv = cucul_create_canvas(0, 0);
     60    backcv = cucul_create_canvas(0, 0);
     61    mask = cucul_create_canvas(0, 0);
     62
     63    dp = caca_create_display(frontcv);
    9464    if(!dp)
    9565        return 1;
    9666
     67    cucul_set_canvas_size(backcv, cucul_get_canvas_width(frontcv),
     68                                  cucul_get_canvas_height(frontcv));
     69    cucul_set_canvas_size(mask, cucul_get_canvas_width(frontcv),
     70                                cucul_get_canvas_height(frontcv));
     71
    9772    caca_set_display_time(dp, 20000);
    9873
    99     c2 = cucul_create_canvas(cucul_get_canvas_width(cv),
    100                              cucul_get_canvas_height(cv));
    101     mask = cucul_create_canvas(cucul_get_canvas_width(cv),
    102                                cucul_get_canvas_height(cv));
    103 
    104     /* Fill various tables */
    105     for(i = 0 ; i < 256; i++)
    106         red[i] = green[i] = blue[i] = alpha[i] = 0;
    107 
    108     for(i = 0; i < 3; i++)
    109         r[i] = (double)(cucul_rand(1, 1000)) / 60000 * M_PI;
    110 
    111     for(i = 0; i < 6; i++)
    112         R[i] = (double)(cucul_rand(1, 1000)) / 10000;
    113 
    114     for(y = 0 ; y < TABLEY ; y++)
    115         for(x = 0 ; x < TABLEX ; x++)
    116     {
    117         double tmp = (((double)((x - (TABLEX / 2)) * (x - (TABLEX / 2))
    118                               + (y - (TABLEX / 2)) * (y - (TABLEX / 2))))
    119                       * (M_PI / (TABLEX * TABLEX + TABLEY * TABLEY)));
    120 
    121         table[x + y * TABLEX] = (1.0 + sin(12.0 * sqrt(tmp))) * 256 / 6;
    122     }
    123 
    124     /* Create a libcucul dither */
    125     dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
    126 
    127     /* Main loop */
    128     for(;;)
     74    demo = cucul_rand(0, 3);
     75
     76    demo_list[demo](INIT, NULL);
     77
     78    for(;;)
    12979    {
    13080        caca_event_t ev;
     
    14191            goto paused;
    14292
     93        demo_list[demo](UPDATE, NULL);
     94        frame++;
     95paused:
     96        demo_list[demo](DRAW, frontcv);
     97        cucul_set_color(frontcv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
     98        cucul_putstr(frontcv, cucul_get_canvas_width(frontcv) - 30,
     99                              cucul_get_canvas_height(frontcv) - 2,
     100                              " -=[ Powered by libcaca ]=- ");
     101        caca_refresh_display(dp);
     102    }
     103end:
     104    demo_list[demo](FREE, NULL);
     105
     106    caca_free_display(dp);
     107    cucul_free_canvas(mask);
     108    cucul_free_canvas(backcv);
     109    cucul_free_canvas(frontcv);
     110
     111    return 0;
     112}
     113
     114/* The plasma effect */
     115#define TABLEX (XSIZ * 2)
     116#define TABLEY (YSIZ * 2)
     117static uint8_t table[TABLEX * TABLEY];
     118
     119static void do_plasma(uint8_t *,
     120                      double, double, double, double, double, double);
     121
     122void plasma(enum action action, cucul_canvas_t *cv)
     123{
     124    static cucul_dither_t *dither;
     125    static uint8_t *screen;
     126    static unsigned int red[256], green[256], blue[256], alpha[256];
     127    static double r[3], R[6];
     128
     129    int i, x, y;
     130
     131    switch(action)
     132    {
     133    case INIT:
     134        screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
     135
     136        /* Fill various tables */
     137        for(i = 0 ; i < 256; i++)
     138            red[i] = green[i] = blue[i] = alpha[i] = 0;
     139
     140        for(i = 0; i < 3; i++)
     141            r[i] = (double)(cucul_rand(1, 1000)) / 60000 * M_PI;
     142
     143        for(i = 0; i < 6; i++)
     144            R[i] = (double)(cucul_rand(1, 1000)) / 10000;
     145
     146        for(y = 0 ; y < TABLEY ; y++)
     147            for(x = 0 ; x < TABLEX ; x++)
     148        {
     149            double tmp = (((double)((x - (TABLEX / 2)) * (x - (TABLEX / 2))
     150                                  + (y - (TABLEX / 2)) * (y - (TABLEX / 2))))
     151                          * (M_PI / (TABLEX * TABLEX + TABLEY * TABLEY)));
     152
     153            table[x + y * TABLEX] = (1.0 + sin(12.0 * sqrt(tmp))) * 256 / 6;
     154        }
     155
     156        /* Create a libcucul dither */
     157        dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
     158        break;
     159
     160    case UPDATE:
    143161        for(i = 0 ; i < 256; i++)
    144162        {
     
    160178                  (1.0 + sin(((double)frame) * R[4])) / 2,
    161179                  (1.0 + sin(((double)frame) * R[5])) / 2);
    162         frame++;
    163 
    164 paused:
     180        break;
     181    case DRAW:
    165182        cucul_dither_bitmap(cv, 0, 0,
    166183                            cucul_get_canvas_width(cv),
    167184                            cucul_get_canvas_height(cv),
    168185                            dither, screen);
    169 
    170         cucul_blit(c2, 0, 0, cv, NULL);
    171         cucul_invert(c2);
    172 
    173 
    174         cucul_blit(cv, 0, 0, c2, mask);
    175 
    176         cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
    177         cucul_putstr(cv, cucul_get_canvas_width(cv) - 30,
    178                          cucul_get_canvas_height(cv) - 2,
    179                          " -=[ Powered by libcaca ]=- ");
    180         caca_refresh_display(dp);
    181     }
    182 
    183 end:
    184     cucul_free_dither(dither);
    185     caca_free_display(dp);
    186     cucul_free_canvas(cv);
    187 
    188     return 0;
    189 }
    190 
    191 static void do_plasma(unsigned char *pixels, double x_1, double y_1,
     186        break;
     187    case FREE:
     188        free(screen);
     189        cucul_free_dither(dither);
     190        break;
     191    }
     192}
     193
     194static void do_plasma(uint8_t *pixels, double x_1, double y_1,
    192195                      double x_2, double y_2, double x_3, double y_3)
    193196{
     
    199202                 Y3 = y_3 * (TABLEY / 2);
    200203    unsigned int y;
    201     unsigned char * t1 = table + X1 + Y1 * TABLEX,
    202                   * t2 = table + X2 + Y2 * TABLEX,
    203                   * t3 = table + X3 + Y3 * TABLEX;
     204    uint8_t * t1 = table + X1 + Y1 * TABLEX,
     205            * t2 = table + X2 + Y2 * TABLEX,
     206            * t3 = table + X3 + Y3 * TABLEX;
    204207
    205208    for(y = 0; y < YSIZ; y++)
    206209    {
    207210        unsigned int x;
    208         unsigned char * tmp = pixels + y * YSIZ;
     211        uint8_t * tmp = pixels + y * YSIZ;
    209212        unsigned int ty = y * TABLEX, tmax = ty + XSIZ;
    210213        for(x = 0; ty < tmax; ty++, tmp++)
     
    213216}
    214217
    215 static int main_ball(int argc, char **argv)
    216 {
    217     cucul_canvas_t *cv; caca_display_t *dp;
    218     unsigned int r[256], g[256], b[256], a[256];
    219     float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
    220     unsigned int x[METABALLS], y[METABALLS];
    221     cucul_dither_t *cucul_dither;
    222     float i = 10.0, j = 17.0, k = 11.0;
    223     int p, frame = 0, pause = 0;
    224     double frameOffset[360 + 80];
    225 
    226     cv = cucul_create_canvas(0, 0);
    227     if(!cv)
    228         return 1;
    229     dp = caca_create_display(cv);
    230     if(!dp)
    231         return 1;
    232 
    233     caca_set_display_time(dp, 20000);
    234 
    235     /* Make the palette eatable by libcaca */
    236     for(p = 0; p < 256; p++)
    237         r[p] = g[p] = b[p] = a[p] = 0x0;
    238     r[255] = g[255] = b[255] = 0xfff;
    239 
    240     /* Create a libcucul dither smaller than our pixel buffer, so that we
    241      * display only the interesting part of it */
    242     cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE,
    243                                        XSIZ, 0, 0, 0, 0);
    244 
    245     /* Generate ball sprite */
    246     create_ball();
    247 
    248     for(p = 0; p < METABALLS; p++)
    249     {
    250         dd[p] = cucul_rand(0, 100);
    251         di[p] = (float)cucul_rand(500, 4000) / 6000.0;
    252         dj[p] = (float)cucul_rand(500, 4000) / 6000.0;
    253         dk[p] = (float)cucul_rand(500, 4000) / 6000.0;
    254     }
    255 
    256     for(frame = 0; frame < 360 + 80; frame++)
    257         frameOffset[frame] = 1.0 + sin((double)(frame * M_PI / 60));
    258 
    259     /* Go ! */
    260     for(;;)
    261     {
    262         caca_event_t ev;
    263         if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
    264         {
    265             switch(ev.data.key.ch)
    266             {
    267                 case CACA_KEY_ESCAPE: goto end;
    268                 case ' ': pause = !pause;
    269             }
    270         }
    271 
    272         if(pause)
    273             goto paused;
    274 
    275         frame++;
    276         if(frame >= 360)
    277             frame = 0;
     218/* The metaball effect */
     219#define METASIZE (XSIZ/2)
     220#define METABALLS 12
     221#define CROPBALL 200 /* Colour index where to crop balls */
     222static uint8_t metaball[METASIZE * METASIZE];
     223
     224static void create_ball(void);
     225static void draw_ball(uint8_t *, unsigned int, unsigned int);
     226
     227void metaballs(enum action action, cucul_canvas_t *cv)
     228{
     229    static cucul_dither_t *cucul_dither;
     230    static uint8_t *screen;
     231    static unsigned int r[256], g[256], b[256], a[256];
     232    static float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
     233    static unsigned int x[METABALLS], y[METABALLS];
     234    static float i = 10.0, j = 17.0, k = 11.0;
     235    static double offset[360 + 80];
     236
     237    int p, angle;
     238
     239    switch(action)
     240    {
     241    case INIT:
     242        screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
     243
     244        /* Make the palette eatable by libcaca */
     245        for(p = 0; p < 256; p++)
     246            r[p] = g[p] = b[p] = a[p] = 0x0;
     247        r[255] = g[255] = b[255] = 0xfff;
     248
     249        /* Create a libcucul dither smaller than our pixel buffer, so that we
     250         * display only the interesting part of it */
     251        cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE,
     252                                           XSIZ, 0, 0, 0, 0);
     253        /* Generate ball sprite */
     254        create_ball();
     255
     256        for(p = 0; p < METABALLS; p++)
     257        {
     258            dd[p] = cucul_rand(0, 100);
     259            di[p] = (float)cucul_rand(500, 4000) / 6000.0;
     260            dj[p] = (float)cucul_rand(500, 4000) / 6000.0;
     261            dk[p] = (float)cucul_rand(500, 4000) / 6000.0;
     262        }
     263
     264        for(p = 0; p < 360 + 80; p++)
     265            offset[p] = 1.0 + sin((double)(p * M_PI / 60));
     266        break;
     267
     268    case UPDATE:
     269        angle = frame % 360;
    278270
    279271        /* Crop the palette */
     
    281273        {
    282274            int t1, t2, t3;
    283             double c1 = frameOffset[frame];
    284             double c2 = frameOffset[frame+40];
    285             double c3 = frameOffset[frame+80];
     275            double c1 = offset[angle];
     276            double c2 = offset[angle + 40];
     277            double c3 = offset[angle + 80];
    286278
    287279            t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
     
    317309         * clever you'll understand. */
    318310        for(p = 0; p < METABALLS; p++)
    319             draw_ball(x[p], y[p]);
    320 
    321 paused:
    322         /* Draw our virtual buffer to screen, letting libcucul resize it */
     311            draw_ball(screen, x[p], y[p]);
     312        break;
     313
     314    case DRAW:
    323315        cucul_dither_bitmap(cv, 0, 0,
    324316                          cucul_get_canvas_width(cv),
    325317                          cucul_get_canvas_height(cv),
    326318                          cucul_dither, screen + (METASIZE / 2) * (1 + XSIZ));
    327         cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
    328         cucul_putstr(cv, cucul_get_canvas_width(cv) - 30,
    329                          cucul_get_canvas_height(cv) - 2,
    330                          " -=[ Powered by libcaca ]=- ");
    331 
    332         caca_refresh_display(dp);
    333     }
    334 
    335     /* End, bye folks */
    336 end:
    337     cucul_free_dither(cucul_dither);
    338     caca_free_display(dp);
    339     cucul_free_canvas(cv);
    340 
    341     return 0;
     319        break;
     320
     321    case FREE:
     322        free(screen);
     323        cucul_free_dither(cucul_dither);
     324        break;
     325    }
    342326}
    343327
     
    360344
    361345/* You missed the trick ? */
    362 static void draw_ball(unsigned int bx, unsigned int by)
     346static void draw_ball(uint8_t *screen, unsigned int bx, unsigned int by)
    363347{
    364348    unsigned int color;
     
    384368}
    385369
    386 static int main_moir(int argc, char **argv)
    387 {
    388     cucul_canvas_t *cv; caca_display_t *dp;
    389     unsigned int red[256], green[256], blue[256], alpha[256];
    390     cucul_dither_t *dither;
    391     int i, x, y, frame = 0, pause = 0;
    392 
    393     cv = cucul_create_canvas(0, 0);
    394     if(!cv)
    395         return 1;
    396     dp = caca_create_display(cv);
    397     if(!dp)
    398         return 1;
    399 
    400     caca_set_display_time(dp, 20000);
    401 
    402     /* Fill various tables */
    403     for(i = 0 ; i < 256; i++)
    404         red[i] = green[i] = blue[i] = alpha[i] = 0;
    405 
    406     red[0] = green[0] = blue[0] = 0x777;
    407     red[1] = green[1] = blue[1] = 0xfff;
    408 
    409     /* Fill the circle */
    410     for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS)
    411         draw_disc(i, (i / DISCTHICKNESS) % 2);
    412 
    413     /* Create a libcucul dither */
    414     dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
    415 
    416     /* Main loop */
    417     for(;;)
    418     {
    419         caca_event_t ev;
    420         if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
    421         {
    422             switch(ev.data.key.ch)
    423             {
    424                 case CACA_KEY_ESCAPE: goto end;
    425                 case ' ': pause = !pause;
    426             }
    427         }
    428 
    429         if(pause)
    430             goto paused;
    431 
     370/* The moiré effect */
     371#define DISCSIZ (XSIZ*2)
     372#define DISCTHICKNESS (XSIZ*15/40)
     373static uint8_t disc[DISCSIZ * DISCSIZ];
     374
     375static void put_disc(uint8_t *, int, int);
     376static void draw_disc(int, char);
     377static void draw_line(int, int, char);
     378
     379void moire(enum action action, cucul_canvas_t *cv)
     380{
     381    static cucul_dither_t *dither;
     382    static uint8_t *screen;
     383    static unsigned int red[256], green[256], blue[256], alpha[256];
     384
     385    int i, x, y;
     386
     387    switch(action)
     388    {
     389    case INIT:
     390        screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
     391
     392        /* Fill various tables */
     393        for(i = 0 ; i < 256; i++)
     394            red[i] = green[i] = blue[i] = alpha[i] = 0;
     395
     396        red[0] = green[0] = blue[0] = 0x777;
     397        red[1] = green[1] = blue[1] = 0xfff;
     398
     399        /* Fill the circle */
     400        for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS)
     401            draw_disc(i, (i / DISCTHICKNESS) % 2);
     402
     403        /* Create a libcucul dither */
     404        dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
     405        break;
     406
     407    case UPDATE:
    432408        memset(screen, 0, XSIZ * YSIZ);
    433409
     
    446422        x = cos(0.07 * frame + 5.0) * 128.0 + (XSIZ / 2);
    447423        y = sin(0.11 * frame) * 128.0 + (YSIZ / 2);
    448         put_disc(x, y);
     424        put_disc(screen, x, y);
    449425
    450426        x = cos(0.13 * frame + 2.0) * 64.0 + (XSIZ / 2);
    451427        y = sin(0.09 * frame + 1.0) * 64.0 + (YSIZ / 2);
    452         put_disc(x, y);
    453 
    454         frame++;
    455 
    456 paused:
     428        put_disc(screen, x, y);
     429        break;
     430
     431    case DRAW:
    457432        cucul_dither_bitmap(cv, 0, 0,
    458433                            cucul_get_canvas_width(cv),
    459434                            cucul_get_canvas_height(cv),
    460435                            dither, screen);
    461         cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
    462         cucul_putstr(cv, cucul_get_canvas_width(cv) - 30,
    463                          cucul_get_canvas_height(cv) - 2,
    464                          " -=[ Powered by libcaca ]=- ");
    465         caca_refresh_display(dp);
    466     }
    467 
    468 end:
    469     cucul_free_dither(dither);
    470     caca_free_display(dp);
    471     cucul_free_canvas(cv);
    472 
    473     return 0;
    474 }
    475 
    476 static void put_disc(int x, int y)
     436        break;
     437
     438    case FREE:
     439        free(screen);
     440        cucul_free_dither(dither);
     441        break;
     442    }
     443}
     444
     445static void put_disc(uint8_t *screen, int x, int y)
    477446{
    478447    char *src = ((char*)disc) + (DISCSIZ / 2 - x) + (DISCSIZ / 2 - y) * DISCSIZ;
Note: See TracChangeset for help on using the changeset viewer.