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....
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 // -----------------------------------------------------------------------
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
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
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....
80 // -----------------------------------------------------------------------
88 #include <libdockapp/wmgeneral.h>
90 #include "sintab.c" // sin() and cos() are crap!
92 // -----------------------------------------------------------------------
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 // -----------------------------------------------------------------------
112 typedef struct // a point in 3d space
117 typedef struct // a point in 2d space
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
132 // -----------------------------------------------------------------------
133 // object structures...
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}
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}
183 {-35,-35,-35},{-35,-35, 45},{ 45, 45,-35},{ 45, 45, 45},{ 5,-35, 5},
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}
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 // -----------------------------------------------------------------------
222 xyz
*obj_list
[]= // pointers to each object
231 int point_counts
[]= // number of points in each object
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
254 short cos_x
= 0; // trig stuff
261 int x_off
= 30; // world space position of object
265 int delta_x
= 1; // rotational speed of object
269 int itters
= 1; // number of frames till shape change
270 int num_points
= 0; // number of points in object
272 xyz
*object
= NULL
; // pointer to current object
274 xy trail_1
[125]; // frame histories
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
315 // 10,30,&y_off,-5,30,10
318 // -----------------------------------------------------------------------
319 // draw a point at x/y in specified colour
321 void draw_point(int x
, int y
, int c
)
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)
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...
366 case DestroyNotify
: // our own "pending" demise :)
367 XCloseDisplay(display
);
374 // -----------------------------------------------------------------------
375 // clear frame history buffers
377 void clear_histories(void)
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
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
404 trail_3
[i
].y
= trail_2
[i
].y
;
405 trail_2
[i
].y
= trail_1
[i
].y
;
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
);
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
);
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)
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))
487 // -----------------------------------------------------------------------
488 // draw one frame of object...
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
496 char pel_buff
[MASK_SIZE
]; // frame buffer ( see draw_point() )
497 p_buff
= &pel_buff
[0];
499 while (j
--) // erase pel buffer
504 do_trails(); // clear pels that are 3 frames old
505 wmdots_sincos(); // calculate all sin/cos values
509 px
= object
[i
].x
; // collect point from object
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);
526 // -----------------------------------------------------------------------
527 // adjust rotational speeds / distance between min and max for each
529 void modify(modifier
*mod
)
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
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)
573 // -----------------------------------------------------------------------
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
)
602 // -----------------------------------------------------------------------
603 // display version info and credits
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
)
622 for (i
= 0; i
< argc
; i
++)
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
];
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 // =======================================================================