wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmdots / wmdots.c
blob28654fd2ee270592425374bb68c981023f9e7029
1 // WM-Dots the Window Maker 3d Rotating Dots Demo by Mark I Manning IV
2 // =======================================================================
4 // This demo is based on an old DOS demo I did a number of years ago. The
5 // trick was to get it to work in an 64 x 64 window instead of the
6 // 320 x 200 of the original. (and in 16 instead of 256 colours :)
8 // Much of these sources are based on other dockable application sources.
9 // For this reason, and because it is the right thing to do, this file is
10 // distributed under the GPL. Use it and abuse it as you will.
12 // Flames, critisizm and general nukings can be sent to....
14 // i440r@mailcity.com
16 // I have included the sources (in 100% pure ASM) to the afore mentioned
17 // original demo. These you can also consider covered by the GPL.
19 // Maybe someone can help me convert the bump mapping in the original to
20 // use only 16 colours :) (actually, I have space in the master.xpm for
21 // 32 colours if I retain a 2 x 2 pixle size. If i go to 1 x 1 i can
22 // fit 64 colours in there :)
24 // Yea... I know... Im supposed to be sparing of system resources like
25 // colour allocations but come on guys... this IS a demo after all :)
26 // Demos are supposed to be abusive of system resources eh??? :)
28 // This source file is 100% TAB FREE. Use any editor/viewer you want
29 // to view it with and set ANY size tabs and it will STILL look right.
30 // TABS ARE EVIL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
32 // Also Linus T is wrong. Indentations of 8 are an abomination and so is
33 // k&r source formatting. So There!
35 // Apart from that... Linus for president :)
36 // or George W. Bush!!!
38 // -----------------------------------------------------------------------
39 // blah :)
41 // Version 0.1 beta Released Saturday October 9 1999
43 // To do... Fix bug that causes core dump when the "cross" object
44 // rotates outside window (its not a clipping problem).
45 // Find out why the "cross" object is not cross shaped in
46 // this demo when it is in the dos version.
47 // Change pixle sizes to 1 x 1 for objects that are in
48 // the distance.
49 // Move all object definitions out of this file and into
50 // some kind of rc file and allow user defined objects
51 // Add greets to the credits display :)
52 // Impliment better light shading (in object space?)
53 // Prevent dark pixles overwriting light ones
55 // Done... Scrapped idea about different pixle sizez, it didn't look
56 // as good as i thunked it would :)
57 // Fixed adjust_angle() to be angle +128 not angle +127
58 // Fixed cross by defining xyz as char instead of int
59 // Fixed core dump problem with cross: Oopts it was a
60 // clipping problem, z clipping points behind camera! :)
61 // Added size macro (prolly a bad name for it tho :)
62 // Implimented better light shading but its still not
63 // quite right yet...
64 // Removed math.h from includes as im not using any
65 // functions therein. Saved a whopping 4 bytes :)
66 // Added code to draw_point() to prevent dark pels from
67 // being drawn over lighter pels. Dark pels are further
68 // away and should be BEHIND the lighter ones. There is
69 // almost no cpu bash here and I dont need to z sort pels
72 // Version 0.2 beta Released Saturday October 9 1999
74 // To do.. Still gotta move objects to rc file....
78 // Done...
80 // -----------------------------------------------------------------------
81 // includes
83 #include <stdlib.h>
84 #include <stdio.h>
85 #include <unistd.h>
86 #include <string.h>
87 #include <X11/xpm.h>
88 #include <libdockapp/wmgeneral.h>
89 #include "master.xpm"
90 #include "sintab.c" // sin() and cos() are crap!
92 // -----------------------------------------------------------------------
93 // defines
95 #define PEL_SIZE 2 // 1 or 2 only
97 #define MAX_POINTS 125 // max # pels in an object
99 #define MASK_WIDTH 64 // window bitmap mask dimentions
100 #define MASK_HEIGHT 64
101 #define MASK_SIZE MASK_WIDTH * MASK_HEIGHT
103 // adjust angle for cos table lookup. cos = right angle further
104 // on in sin table, circle = 512 degrees...
106 #define adjust(angle) ((angle + 128) & 0x1ff)
107 #define size(array) ((sizeof(array) / sizeof(array[0])))
109 // -----------------------------------------------------------------------
110 // typedefs...
112 typedef struct // a point in 3d space
114 char x, y, z;
115 }xyz;
117 typedef struct // a point in 2d space
119 int x, y;
120 }xy;
122 typedef struct
124 int counter; // count down to next speed/shape change
125 int reset; // initial value of counter
126 int *ptr; // pointer to item to modify
127 int delta; // ammount to change item by
128 int upper; // upper limit for item
129 int lower; // lower limit for item
130 }modifier;
132 // -----------------------------------------------------------------------
133 // object structures...
135 xyz cube[]=
137 {-35,-35,-35},{-35,-35,-15},{-35,-35, 05},{-35,-35, 25},{-35,-35, 45},
138 {-35,-15,-35},{-35,-15,-15},{-35,-15, 05},{-35,-15, 25},{-35,-15, 45},
139 {-35, 05,-35},{-35, 05,-15},{-35, 05, 05},{-35, 05, 25},{-35, 05, 45},
140 {-35, 25,-35},{-35, 25,-15},{-35, 25, 05},{-35, 25, 25},{-35, 25, 45},
141 {-35, 45,-35},{-35, 45,-15},{-35, 45, 05},{-35, 45, 25},{-35, 45, 45},
142 {-15,-35,-35},{-15,-35,-15},{-15,-35, 05},{-15,-35, 25},{-15,-35, 45},
143 {-15,-15,-35},{-15,-15,-15},{-15,-15, 05},{-15,-15, 25},{-15,-15, 45},
144 {-15, 05,-35},{-15, 05,-15},{-15, 05, 05},{-15, 05, 25},{-15, 05, 45},
145 {-15, 25,-35},{-15, 25,-15},{-15, 25, 05},{-15, 25, 25},{-15, 25, 45},
146 {-15, 45,-35},{-15, 45,-15},{-15, 45, 05},{-15, 45, 25},{-15, 45, 45},
147 { 05,-35,-35},{ 05,-35,-15},{ 05,-35, 05},{ 05,-35, 25},{ 05,-35, 45},
148 { 05,-15,-35},{ 05,-15,-15},{ 05,-15, 05},{ 05,-15, 25},{ 05,-15, 45},
149 { 05, 05,-35},{ 05, 05,-15},{ 05, 05, 05},{ 05, 05, 25},{ 05, 05, 45},
150 { 05, 25,-35},{ 05, 25,-15},{ 05, 25, 05},{ 05, 25, 25},{ 05, 25, 45},
151 { 05, 45,-35},{ 05, 45,-15},{ 05, 45, 05},{ 05, 45, 25},{ 05, 45, 45},
152 { 25,-35,-35},{ 25,-35,-15},{ 25,-35, 05},{ 25,-35, 25},{ 25,-35, 45},
153 { 25,-15,-35},{ 25,-15,-15},{ 25,-15, 05},{ 25,-15, 25},{ 25,-15, 45},
154 { 25, 05,-35},{ 25, 05,-15},{ 25, 05, 05},{ 25, 05, 25},{ 25, 05, 45},
155 { 25, 25,-35},{ 25, 25,-15},{ 25, 25, 05},{ 25, 25, 25},{ 25, 25, 45},
156 { 25, 45,-35},{ 25, 45,-15},{ 25, 45, 05},{ 25, 45, 25},{ 25, 45, 45},
157 { 45,-35,-35},{ 45,-35,-15},{ 45,-35, 05},{ 45,-35, 25},{ 45,-35, 45},
158 { 45,-15,-35},{ 45,-15,-15},{ 45,-15, 05},{ 45,-15, 25},{ 45,-15, 45},
159 { 45, 05,-35},{ 45, 05,-15},{ 45, 05, 05},{ 45, 05, 25},{ 45, 05, 45},
160 { 45, 25,-35},{ 45, 25,-15},{ 45, 25, 05},{ 45, 25, 25},{ 45, 25, 45},
161 { 45, 45,-35},{ 45, 45,-15},{ 45, 45, 05},{ 45, 45, 25},{ 45, 45, 45}
164 xyz star[]=
166 {-35,-35, 05},{-35,-15, 05},{-35, 05, 05},{-35, 25, 05},{-35, 45, 05},
167 {-15,-35, 05},{-15,-15, 05},{-15, 05, 05},{-15, 25, 05},{-15, 45, 05},
168 { 05,-35, 05},{ 05,-15, 05},{ 05, 05, 05},{ 05, 25, 05},{ 05, 45, 05},
169 { 25,-35, 05},{ 25,-15, 05},{ 25, 05, 05},{ 25, 25, 05},{ 25, 45, 05},
170 { 45,-35, 05},{ 45,-15, 05},{ 45, 05, 05},{ 45, 25, 05},{ 45, 45, 05},
171 { 05,-35,-35},{ 05,-35,-15},{ 05,-35, 25},{ 05,-35, 45},{-35, 05,-35},
172 { 05,-15,-35},{ 05,-15,-15},{ 05,-15, 25},{ 05,-15, 45},{-15, 05,-35},
173 { 05, 05,-35},{ 05, 05,-15},{ 05, 05, 25},{ 05, 05, 45},{ 05, 05,-35},
174 { 05, 25,-35},{ 05, 25,-15},{ 05, 25, 25},{ 05, 25, 45},{ 25, 05,-35},
175 { 05, 45,-35},{ 05, 45,-15},{ 05, 45, 25},{ 05, 45, 45},{ 45, 05,-35},
176 {-35, 05,-15},{-35, 05, 25},{-35, 05, 45},{-15, 05,-15},{-15, 05, 25},
177 {-15, 05, 45},{ 05, 05,-15},{ 05, 05, 25},{ 05, 05, 45},{ 25, 05,-15},
178 { 25, 05, 25},{ 25, 05, 45},{ 45, 05,-15},{ 45, 05, 25},{ 45, 05, 45}
181 xyz dots[]=
183 {-35,-35,-35},{-35,-35, 45},{ 45, 45,-35},{ 45, 45, 45},{ 5,-35, 5},
184 { 5, 45, 5}
187 xyz square[]=
189 {-35,-35,-35},{-35,-15,-35},{-35, 05,-35},{-35, 25,-35},{-35, 45,-35},
190 {-15,-35,-35},{-15,-15,-35},{-15, 05,-35},{-15, 25,-35},{-15, 45,-35},
191 { 05,-35,-35},{ 05,-15,-35},{ 05, 05,-35},{ 05, 25,-35},{ 05, 45,-35},
192 { 25,-35,-35},{ 25,-15,-35},{ 25, 05,-35},{ 25, 25,-35},{ 25, 45,-35},
193 { 45,-35,-35},{ 45,-15,-35},{ 45, 05,-35},{ 45, 25,-35},{ 45, 45,-35}
196 xyz cross[]=
198 {0x00,0x00,0x19}, {0x00,0x05,0x19}, {0x00,0x14,0x01}, {0x00,0x32,0x00},
199 {0x00,0x7D,0x00}, {0x00,0xC9,0x00}, {0x01,0x5F,0x01}, {0x01,0xAB,0x01},
200 {0x01,0xF6,0x01}, {0x02,0x41,0x02}, {0x02,0x8D,0x02}, {0x02,0xD8,0x02},
201 {0x03,0x23,0x03}, {0x03,0x05,0x04}, {0x03,0x6F,0x03}, {0x03,0xBA,0x03},
202 {0x04,0x51,0x04}, {0x04,0x9C,0x04}, {0x04,0xE7,0x04}, {0x05,0x13,0x06},
203 {0x05,0x32,0x05}, {0x05,0x7D,0x05}, {0x05,0xC8,0x05}, {0x06,0x5E,0x06},
204 {0x06,0xA9,0x06}, {0x06,0xF4,0x06}, {0x07,0x3F,0x07}, {0x07,0x8A,0x07},
205 {0x07,0xD5,0x07}, {0x08,0x00,0x09}, {0x08,0x20,0x08}, {0x08,0x6B,0x08},
206 {0x08,0xB5,0x08}, {0x09,0x4B,0x09}, {0x09,0x95,0x09}, {0x09,0xE0,0x09},
207 {0x0A,0x09,0x0B}, {0x0A,0x2A,0x0A}, {0x0A,0x75,0x0A}, {0x0A,0xBF,0x0A},
208 {0x0B,0x54,0x0B}, {0x0D,0x07,0x26}, {0x0F,0x02,0x28}, {0x19,0x09,0x32},
209 {0x1E,0x04,0x37}, {0x22,0x0B,0x3B}, {0x2C,0x06,0x45}, {0x2D,0x01,0x46},
210 {0x39,0x08,0x52}, {0x3D,0x03,0x56}, {0x43,0x0A,0x5C}, {0x4B,0x00,0x64},
211 {0x4B,0x05,0x64}, {0x58,0x07,0x71}, {0x5B,0x02,0x74}, {0x64,0x09,0x7C},
212 {0x84,0x08,0x9C}, {0x88,0x03,0xA1}, {0x8D,0x0A,0xA6}, {0x96,0x00,0xAF},
213 {0x96,0x05,0xAF}, {0xA3,0x07,0xBC}, {0xA6,0x02,0xBF}, {0xAE,0x09,0xC7},
214 {0xB5,0x04,0xCE}, {0xC2,0x06,0xDB}, {0xC4,0x01,0xDD}, {0xCE,0x08,0xE7},
215 {0xD3,0x03,0xEC}, {0xD8,0x0A,0xF1}, {0xE1,0x05,0xFA}, {0xE2,0x00,0xFB},
216 {0xEE,0x07,0x07}, {0xF1,0x02,0x0A}, {0xF9,0x09,0x11}
219 // -----------------------------------------------------------------------
220 // object lists...
222 xyz *obj_list[]= // pointers to each object
224 (xyz *) &cube,
225 (xyz *) &dots,
226 (xyz *) &star,
227 (xyz *) &square,
228 (xyz *) &cross
231 int point_counts[]= // number of points in each object
233 size(cube),
234 size(dots),
235 size(star),
236 size(square),
237 size(cross)
240 #define NUM_OBJECTS size(obj_list)
242 // -----------------------------------------------------------------------
243 // i love global variables :)
245 // I hate 40 page functions with 50 levels if,and and but loop nesting
247 char *ProgName = NULL;
248 char *Version = "0.2 Beta";
250 int x_angle = 0; // angles of rotation in each axis
251 int y_angle = 0;
252 int z_angle = 0;
254 short cos_x = 0; // trig stuff
255 short cos_y = 0;
256 short cos_z = 0;
257 short sin_x = 0;
258 short sin_y = 0;
259 short sin_z = 0;
261 int x_off = 30; // world space position of object
262 int y_off = 30;
263 int z_off = 150;
265 int delta_x = 1; // rotational speed of object
266 int delta_y = 1;
267 int delta_z = 1;
269 int itters = 1; // number of frames till shape change
270 int num_points = 0; // number of points in object
271 int obj_number = 0;
272 xyz *object = NULL; // pointer to current object
274 xy trail_1[125]; // frame histories
275 xy trail_2[125];
276 xy trail_3[125];
278 char *p_buff; // addr of pel buffer ( see draw_point() )
280 // -----------------------------------------------------------------------
283 modifier w1 = // changes x rotation speed
285 30, // count down counter
286 34, // reset value for countdown counter
287 &delta_x, // item to modify on count = 0
288 2, // ammount to add to item
289 8, // upper limit for item
290 0, // lower limit for item
293 modifier w2 = // changes y rotation speed
295 20, 20, &delta_y, -1, 6, 0
298 modifier w3 = // changes z rotation speed
300 30, 30, &delta_z, 1, 7, 0
303 modifier w4 = // zooms object in / out of window
305 4, 4, &z_off, -2, 200, 90
308 // modifier w5 = // these two do some funky things with
309 // { // object space but they tend to make
310 // 10,10,&x_off,-3,30,10 // the objects small and look further
311 // }; // away so im not using them
313 // modifier w6 = // but go ahead and take a look at what
314 // { // they do :)
315 // 10,30,&y_off,-5,30,10
316 // };
318 // -----------------------------------------------------------------------
319 // draw a point at x/y in specified colour
321 void draw_point(int x, int y, int c)
323 char *p;
325 if(x != -1) // is point clipped ?
327 c <<= 1; // adjust c for xpm lookup of colour
328 p = p_buff + (x + (MASK_WIDTH * y));
330 if (*p > c) // if pel at *p is higher its darker so
331 { // its ok to overwrite it
332 *p = c; // remember pel colour at this position
333 copyXPMArea(c, 65, PEL_SIZE, PEL_SIZE, x, y);
338 // -----------------------------------------------------------------------
339 // Erase previously drawn point (draw again in BLACK!!!)
341 void erase_point(int x, int y)
343 if(x != -1) // is point clipped?
345 copyXPMArea(34, 65, PEL_SIZE, PEL_SIZE, x, y);
349 // -----------------------------------------------------------------------
350 // Process pending X events
352 void do_pending(void)
354 XEvent Event;
356 while (XPending(display)) // for all pending events do...
358 XNextEvent(display, &Event); // get event type
360 switch (Event.type) // we are only interested in...
362 case Expose: // expose events and...
363 RedrawWindow();
364 break;
366 case DestroyNotify: // our own "pending" demise :)
367 XCloseDisplay(display);
368 exit(0);
369 break;
374 // -----------------------------------------------------------------------
375 // clear frame history buffers
377 void clear_histories(void)
379 int i = MAX_POINTS;
381 while (i--) // for loops suck
383 trail_1[i].x = trail_1[i].y = -1; // -1 = invalid coordinate
384 trail_2[i].x = trail_2[i].y = -1; // draw_point() ignores -1
385 trail_3[i].x = trail_3[i].y = -1;
389 // -----------------------------------------------------------------------
390 // erase points that are 3 frames old. shift frame histories
392 void do_trails(void)
394 int i = MAX_POINTS;
396 while (i--)
398 erase_point(trail_3[i].x, trail_3[i].y);
400 trail_3[i].x = trail_2[i].x; // shift points within history
401 trail_2[i].x = trail_1[i].x; // buffers
402 trail_1[i].x = -1;
404 trail_3[i].y = trail_2[i].y;
405 trail_2[i].y = trail_1[i].y;
406 trail_1[i].y = -1;
410 // -----------------------------------------------------------------------
411 // pre calculate sin and cosine values for x y and z angles of rotation
413 void wmdots_sincos(void)
415 sin_x = sin_tab[x_angle];
416 sin_y = sin_tab[y_angle];
417 sin_z = sin_tab[z_angle];
419 cos_x = sin_tab[adjust(x_angle)];
420 cos_y = sin_tab[adjust(y_angle)];
421 cos_z = sin_tab[adjust(z_angle)];
424 // -----------------------------------------------------------------------
425 // roatate object about x y and z axis (in object space)
427 void rotate(int *px, int *py, int *pz)
429 int tx, ty, tz; // temp store
431 if (x_angle) // rotate point about x axis...
433 ty = (*py * cos_x) - (*pz * sin_x);
434 tz = (*py * sin_x) + (*pz * cos_x);
436 *py = (ty >> 14); // sin table is scaled up so we
437 *pz = (tz >> 14); // must re scale all results down
440 if (y_angle) // rotate point about y axis
442 tx = (*px * cos_y) - (*pz * sin_y);
443 tz = (*px * sin_y) + (*pz * cos_y);
445 *px = (tx >> 14);
446 *pz = (tz >> 14);
449 if (z_angle) // rotate point about z axis
451 tx = (*px * cos_z) - (*py * sin_z);
452 ty = (*px * sin_z) + (*py * cos_z);
454 *px = (tx >> 14);
455 *py = (ty >> 14);
459 // -----------------------------------------------------------------------
460 // project point in 3d space onto plane in 2d space
462 void project(int px, int py, int pz, int *x, int *y)
464 int tx, ty; // temp store...
466 *x = *y = -1; // assume point is clipped
468 if ((z_off + pz - 5) < 0)
470 return;
473 ty = ((y_off * py) / (z_off + pz)) + 30;
475 if ((ty > 5) && (ty < 59))
477 tx = ((x_off * px) / (z_off + pz)) + 30;
479 if ((tx > 5) && (tx < 59))
481 *x = tx;
482 *y = ty;
487 // -----------------------------------------------------------------------
488 // draw one frame of object...
490 void do_frame(void)
492 int px, py, pz; // 3d coordinates to rotate
493 int x, y, c; // 2d coordiantes of point and colour
494 int i = num_points; // loop counter
495 int j = MASK_SIZE;
496 char pel_buff[MASK_SIZE]; // frame buffer ( see draw_point() )
497 p_buff = &pel_buff[0];
499 while (j--) // erase pel buffer
501 pel_buff[j] = 32;
504 do_trails(); // clear pels that are 3 frames old
505 wmdots_sincos(); // calculate all sin/cos values
507 while(i--)
509 px = object[i].x; // collect point from object
510 py = object[i].y;
511 pz = object[i].z;
513 rotate(&px, &py, &pz); // rotate this point about x/y and z axis
514 project(px, py, pz, &x, &y); // projection = convert xyz to xy
516 trail_1[i].x = x; // store frame history for all pels
517 trail_1[i].y = y; // of this frame
519 c = (((z_off - 90) / 14) & 15) < 1;
520 c -= ((-pz / 5) - 10);
522 draw_point(x, y, c);
526 // -----------------------------------------------------------------------
527 // adjust rotational speeds / distance between min and max for each
529 void modify(modifier *mod)
531 mod->counter--;
533 if (!mod->counter)
535 mod->counter = mod->reset;
537 *mod->ptr += mod->delta;
539 if (*mod->ptr >= mod->upper || *mod->ptr <= mod->lower)
541 mod->delta = -(mod->delta);
546 // -----------------------------------------------------------------------
547 // do the above on each of the 4 modifiers
549 void do_deltas(void)
551 modify(&w1); // modify x rotational speed
552 modify(&w2); // modify y rotational speed
553 modify(&w3); // modify z rotational speed
554 modify(&w4); // zoom object in and out
555 // modify(&w5); // not used because they make objects
556 // modify(&w6); // stay in the distance
559 // -----------------------------------------------------------------------
560 // adjust x y and z angles of ritation for next frame
562 void change_angles(void)
564 x_angle += delta_x;
565 y_angle += delta_y;
566 z_angle += delta_z;
568 x_angle &= 0x1ff;
569 y_angle &= 0x1ff;
570 z_angle &= 0x1ff;
573 // -----------------------------------------------------------------------
575 void do_demo(void)
577 while (1) // only way out is to die
579 while(--itters) // countdown to next shape change...
580 { // shape change FORCED on entry
581 change_angles(); // adjust angles of rotation
582 do_frame(); // draw object
583 do_deltas(); // modify rotation speeds etc
585 RedrawWindow(); // lets see what weve drawn...
586 do_pending(); // quit / expose
587 usleep(50000); // erm... coders never sleep :)
590 itters = 2500; // should randomise this
592 object = obj_list[obj_number];
593 num_points = point_counts[obj_number++];
595 if (obj_number == NUM_OBJECTS)
597 obj_number = 0;
602 // -----------------------------------------------------------------------
603 // display version info and credits
605 void credits(void)
607 printf("\n");
608 printf("WM-Dots DEMO? version %s\n",Version);
609 printf(" by Mark I Manning IV\n\n");
610 printf("greets to follow soon....\n\n");
613 // sgore for helping me get star office :)
615 // -----------------------------------------------------------------------
616 // scan command line args
618 void scan_args(int argc,char **argv)
620 int i;
622 for (i = 0; i < argc; i++)
624 char *arg = argv[i];
626 if (*arg == '-')
628 switch (arg[1])
630 case 'v':
631 credits();
632 exit(0);
633 break;
635 default:
637 break;
643 // -----------------------------------------------------------------------
644 // main at BOTTOM of source so we have no EVIL forward refs!!
646 int main(int argc, char *argv[])
648 char mask[MASK_SIZE];
650 ProgName = argv[0];
651 if (strlen(ProgName) >= 5)
653 ProgName += (strlen(ProgName) - 5);
656 scan_args(argc, argv);
658 createXBMfromXPM(mask, master_xpm, MASK_WIDTH, MASK_HEIGHT);
659 openXwindow(argc, argv, master_xpm, mask, MASK_WIDTH, MASK_HEIGHT);
661 clear_histories(); // clear frame history buffers
662 do_demo(); // main = short and sweet :)
664 return(0); // never gets executed but lets get rid
665 } // of that stupid warning :)
667 // =======================================================================