source: libcaca/trunk/src/cacademo.c @ 1023

Last change on this file since 1023 was 1023, checked in by Sam Hocevar, 14 years ago
  • Merge cacamoir, cacaball and cacaplas into cacademo. No code cleanup yet.
  • Property svn:keywords set to Id
File size: 14.3 KB
Line 
1/*
2 *  cacademo      various demo effects for libcaca
3 *  Copyright (c) 1998 Michele Bini <mibin@tin.it>
4 *                2004 Sam Hocevar <sam@zoy.org>
5 *                All Rights Reserved
6 *
7 *  $Id: cacademo.c 1023 2006-09-16 09:45:03Z sam $
8 *
9 *  This program is free software; you can redistribute it and/or
10 *  modify it under the terms of the Do What The Fuck You Want To
11 *  Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16#include "common.h"
17
18#if !defined(__KERNEL__)
19#   include <stdio.h>
20#   include <string.h>
21#   include <math.h>
22#   ifndef M_PI
23#       define M_PI 3.14159265358979323846
24#   endif
25#endif
26
27#include "cucul.h"
28#include "caca.h"
29
30/* Virtual buffer size for dither-based demos */
31#define XSIZ 256
32#define YSIZ 256
33static unsigned char screen[XSIZ * YSIZ];
34
35/* The plasma effect */
36#define TABLEX (XSIZ * 2)
37#define TABLEY (YSIZ * 2)
38
39static unsigned char table[TABLEX * TABLEY];
40
41static int main_plasma(int, char **);
42static 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
50static int main_ball(int, char **);
51static void create_ball(void);
52static void draw_ball(unsigned int, unsigned int);
53
54static unsigned char metaball[METASIZE * METASIZE];
55
56/* The moiré effect */
57#define DISCSIZ 512
58#define DISCTHICKNESS 96
59
60static unsigned char disc[DISCSIZ * DISCSIZ];
61
62static int main_moir(int, char **);
63static void put_disc(int, int);
64static void draw_disc(int, char);
65static void draw_line(int, int, char);
66
67int main(int argc, char **argv)
68{
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
82static 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);
94    if(!dp)
95        return 1;
96
97    caca_set_display_time(dp, 20000);
98
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(;;)
129    {
130        caca_event_t ev;
131        if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
132        {
133            switch(ev.data.key.ch)
134            {
135                case CACA_KEY_ESCAPE: goto end;
136                case ' ': pause = !pause;
137            }
138        }
139
140        if(pause)
141            goto paused;
142
143        for(i = 0 ; i < 256; i++)
144        {
145            double z = ((double)i) / 256 * 6 * M_PI;
146
147            red[i] = (1.0 + sin(z + r[1] * frame)) / 2 * 0xfff;
148            blue[i] = (1.0 + cos(z + r[0] * frame)) / 2 * 0xfff;
149            green[i] = (1.0 + cos(z + r[2] * frame)) / 2 * 0xfff;
150        }
151
152        /* Set the palette */
153        cucul_set_dither_palette(dither, red, green, blue, alpha);
154
155        do_plasma(screen,
156                  (1.0 + sin(((double)frame) * R[0])) / 2,
157                  (1.0 + sin(((double)frame) * R[1])) / 2,
158                  (1.0 + sin(((double)frame) * R[2])) / 2,
159                  (1.0 + sin(((double)frame) * R[3])) / 2,
160                  (1.0 + sin(((double)frame) * R[4])) / 2,
161                  (1.0 + sin(((double)frame) * R[5])) / 2);
162        frame++;
163
164paused:
165        cucul_dither_bitmap(cv, 0, 0,
166                            cucul_get_canvas_width(cv),
167                            cucul_get_canvas_height(cv),
168                            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
183end:
184    cucul_free_dither(dither);
185    caca_free_display(dp);
186    cucul_free_canvas(cv);
187
188    return 0;
189}
190
191static void do_plasma(unsigned char *pixels, double x_1, double y_1,
192                      double x_2, double y_2, double x_3, double y_3)
193{
194    unsigned int X1 = x_1 * (TABLEX / 2),
195                 Y1 = y_1 * (TABLEY / 2),
196                 X2 = x_2 * (TABLEX / 2),
197                 Y2 = y_2 * (TABLEY / 2),
198                 X3 = x_3 * (TABLEX / 2),
199                 Y3 = y_3 * (TABLEY / 2);
200    unsigned int y;
201    unsigned char * t1 = table + X1 + Y1 * TABLEX,
202                  * t2 = table + X2 + Y2 * TABLEX,
203                  * t3 = table + X3 + Y3 * TABLEX;
204
205    for(y = 0; y < YSIZ; y++)
206    {
207        unsigned int x;
208        unsigned char * tmp = pixels + y * YSIZ;
209        unsigned int ty = y * TABLEX, tmax = ty + XSIZ;
210        for(x = 0; ty < tmax; ty++, tmp++)
211            tmp[0] = t1[ty] + t2[ty] + t3[ty];
212    }
213}
214
215static 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    double frameOffset40[360];
226    double frameOffset80[360];
227
228    cv = cucul_create_canvas(0, 0);
229    if(!cv)
230        return 1;
231    dp = caca_create_display(cv);
232    if(!dp)
233        return 1;
234
235    caca_set_display_time(dp, 20000);
236
237    /* Make the palette eatable by libcaca */
238    for(p = 0; p < 256; p++)
239        r[p] = g[p] = b[p] = a[p] = 0x0;
240    r[255] = g[255] = b[255] = 0xfff;
241
242    /* Create a libcucul dither smaller than our pixel buffer, so that we
243     * display only the interesting part of it */
244    cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE,
245                                       XSIZ, 0, 0, 0, 0);
246
247    /* Generate ball sprite */
248    create_ball();
249
250    for(p = 0; p < METABALLS; p++)
251    {
252        dd[p] = cucul_rand(0, 100);
253        di[p] = (float)cucul_rand(500, 4000) / 6000.0;
254        dj[p] = (float)cucul_rand(500, 4000) / 6000.0;
255        dk[p] = (float)cucul_rand(500, 4000) / 6000.0;
256    }
257
258    for(frame = 0; frame < 360; frame++) {
259        frameOffset[frame] = frame * M_PI / 60;
260        frameOffset40[frame] = (frame + 40) * M_PI / 60;
261        frameOffset80[frame] = (frame + 80) * M_PI / 60;
262    }
263
264    /* Go ! */
265    for(;;)
266    {
267        caca_event_t ev;
268        if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
269        {
270            switch(ev.data.key.ch)
271            {
272                case CACA_KEY_ESCAPE: goto end;
273                case ' ': pause = !pause;
274            }
275        }
276
277        if(pause)
278            goto paused;
279
280        frame++;
281        if(frame >= 360)
282            frame = 0;
283
284        /* Crop the palette */
285        for(p = CROPBALL; p < 255; p++)
286        {
287            int t1, t2, t3;
288            double c1 = 1.0 + sin((double)frameOffset[frame]);
289            double c2 = 1.0 + sin((double)frameOffset40[frame]);
290            double c3 = 1.0 + sin((double)frameOffset80[frame]);
291
292            t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
293            t2 = p < 0xe0 ? 0 : (p - 0xe0) * 0x80;
294            t3 = p < 0x40 ? p * 0x40 : 0xfff;
295
296            r[p] = (c1 * t1 + c2 * t2 + c3 * t3) / 4;
297            g[p] = (c1 * t2 + c2 * t3 + c3 * t1) / 4;
298            b[p] = (c1 * t3 + c2 * t1 + c3 * t2) / 4;
299        }
300
301        /* Set the palette */
302        cucul_set_dither_palette(cucul_dither, r, g, b, a);
303
304        /* Silly paths for our balls */
305        for(p = 0; p < METABALLS; p++)
306        {
307            float u = di[p] * i + dj[p] * j + dk[p] * sin(di[p] * k);
308            float v = dd[p] + di[p] * j + dj[p] * k + dk[p] * sin(dk[p] * i);
309            u = sin(i + u * 2.1) * (1.0 + sin(u));
310            v = sin(j + v * 1.9) * (1.0 + sin(v));
311            x[p] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
312            y[p] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
313        }
314
315        i += 0.011;
316        j += 0.017;
317        k += 0.019;
318
319        memset(screen, 0, XSIZ * YSIZ);
320
321        /* Here is all the trick. Maybe if you're that
322         * clever you'll understand. */
323        for(p = 0; p < METABALLS; p++)
324            draw_ball(x[p], y[p]);
325
326paused:
327        /* Draw our virtual buffer to screen, letting libcucul resize it */
328        cucul_dither_bitmap(cv, 0, 0,
329                          cucul_get_canvas_width(cv),
330                          cucul_get_canvas_height(cv),
331                          cucul_dither, screen + (METASIZE / 2) * (1 + XSIZ));
332        cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
333        cucul_putstr(cv, cucul_get_canvas_width(cv) - 30,
334                         cucul_get_canvas_height(cv) - 2,
335                         " -=[ Powered by libcaca ]=- ");
336
337        caca_refresh_display(dp);
338    }
339
340    /* End, bye folks */
341end:
342    cucul_free_dither(cucul_dither);
343    caca_free_display(dp);
344    cucul_free_canvas(cv);
345
346    return 0;
347}
348
349/* Generate ball sprite
350 * You should read the comments, I already wrote that before ... */
351static void create_ball(void)
352{
353    int x, y;
354    float distance;
355
356    for(y = 0; y < METASIZE; y++)
357        for(x = 0; x < METASIZE; x++)
358    {
359        distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
360                 + ((METASIZE/2) - y) * ((METASIZE/2) - y);
361        distance = sqrt(distance) * 64 / METASIZE;
362        metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
363    }
364}
365
366/* You missed the trick ? */
367static void draw_ball(unsigned int bx, unsigned int by)
368{
369    unsigned int color;
370    unsigned int i, e = 0;
371    unsigned int b = (by * XSIZ) + bx;
372
373    for(i = 0; i < METASIZE * METASIZE; i++)
374    {
375        color = screen[b] + metaball[i];
376
377        if(color > 255)
378            color = 255;
379
380        screen[b] = color;
381        if(e == METASIZE)
382        {
383            e = 0;
384            b += XSIZ - METASIZE;
385        }
386        b++;
387        e++;
388    }
389}
390
391static int main_moir(int argc, char **argv)
392{
393    cucul_canvas_t *cv; caca_display_t *dp;
394    unsigned int red[256], green[256], blue[256], alpha[256];
395    cucul_dither_t *dither;
396    int i, x, y, frame = 0, pause = 0;
397
398    cv = cucul_create_canvas(0, 0);
399    if(!cv)
400        return 1;
401    dp = caca_create_display(cv);
402    if(!dp)
403        return 1;
404
405    caca_set_display_time(dp, 20000);
406
407    /* Fill various tables */
408    for(i = 0 ; i < 256; i++)
409        red[i] = green[i] = blue[i] = alpha[i] = 0;
410
411    red[0] = green[0] = blue[0] = 0x777;
412    red[1] = green[1] = blue[1] = 0xfff;
413
414    /* Fill the circle */
415    for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS)
416        draw_disc(i, (i / DISCTHICKNESS) % 2);
417
418    /* Create a libcucul dither */
419    dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
420
421    /* Main loop */
422    for(;;)
423    {
424        caca_event_t ev;
425        if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
426        {
427            switch(ev.data.key.ch)
428            {
429                case CACA_KEY_ESCAPE: goto end;
430                case ' ': pause = !pause;
431            }
432        }
433
434        if(pause)
435            goto paused;
436
437        memset(screen, 0, XSIZ * YSIZ);
438
439        /* Set the palette */
440        red[0] = 0.5 * (1 + sin(0.05 * frame)) * 0xfff;
441        green[0] = 0.5 * (1 + cos(0.07 * frame)) * 0xfff;
442        blue[0] = 0.5 * (1 + cos(0.06 * frame)) * 0xfff;
443
444        red[1] = 0.5 * (1 + sin(0.07 * frame + 5.0)) * 0xfff;
445        green[1] = 0.5 * (1 + cos(0.06 * frame + 5.0)) * 0xfff;
446        blue[1] = 0.5 * (1 + cos(0.05 * frame + 5.0)) * 0xfff;
447
448        cucul_set_dither_palette(dither, red, green, blue, alpha);
449
450        /* Draw circles */
451        x = cos(0.07 * frame + 5.0) * 128.0 + (XSIZ / 2);
452        y = sin(0.11 * frame) * 128.0 + (YSIZ / 2);
453        put_disc(x, y);
454
455        x = cos(0.13 * frame + 2.0) * 64.0 + (XSIZ / 2);
456        y = sin(0.09 * frame + 1.0) * 64.0 + (YSIZ / 2);
457        put_disc(x, y);
458
459        frame++;
460
461paused:
462        cucul_dither_bitmap(cv, 0, 0,
463                            cucul_get_canvas_width(cv),
464                            cucul_get_canvas_height(cv),
465                            dither, screen);
466        cucul_set_color(cv, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLUE);
467        cucul_putstr(cv, cucul_get_canvas_width(cv) - 30,
468                         cucul_get_canvas_height(cv) - 2,
469                         " -=[ Powered by libcaca ]=- ");
470        caca_refresh_display(dp);
471    }
472
473end:
474    cucul_free_dither(dither);
475    caca_free_display(dp);
476    cucul_free_canvas(cv);
477
478    return 0;
479}
480
481static void put_disc(int x, int y)
482{
483    char *src = ((char*)disc) + (DISCSIZ / 2 - x) + (DISCSIZ / 2 - y) * DISCSIZ;
484    int i, j;
485
486    for(j = 0; j < YSIZ; j++)
487        for(i = 0; i < XSIZ; i++)
488    {
489        screen[i + XSIZ * j] ^= src[i + DISCSIZ * j];
490    }
491}
492
493static void draw_disc(int r, char color)
494{
495    int t, dx, dy;
496
497    for(t = 0, dx = 0, dy = r; dx <= dy; dx++)
498    {
499        draw_line(dx / 3,   dy / 3, color);
500        draw_line(dy / 3,   dx / 3, color);
501
502        t += t > 0 ? dx - dy-- : dx;
503    }
504}
505
506static void draw_line(int x, int y, char color)
507{
508    if(x == 0 || y == 0 || y > DISCSIZ / 2)
509        return;
510
511    if(x > DISCSIZ / 2)
512        x = DISCSIZ / 2;
513
514    memset(disc + (DISCSIZ / 2) - x + DISCSIZ * ((DISCSIZ / 2) - y),
515           color, 2 * x - 1);
516    memset(disc + (DISCSIZ / 2) - x + DISCSIZ * ((DISCSIZ / 2) + y - 1),
517           color, 2 * x - 1);
518}
519
Note: See TracBrowser for help on using the repository browser.