adjust to match the uname changes.
[AROS-Contrib.git] / Demo / Galaxy / galaxy.c
blob6b1b3465b4dc2c16acc73734f2fb8ce4f7caa818
2 #include <dos/dos.h>
3 #include <intuition/intuition.h>
4 #include <graphics/gfx.h>
5 #include <cybergraphx/cybergraphics.h>
6 #include <proto/exec.h>
7 #include <proto/dos.h>
8 #include <proto/graphics.h>
9 #include <proto/cybergraphics.h>
10 #include <proto/intuition.h>
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <memory.h>
18 #include "schedul_fx.h"
20 /***********************************************************************************/
22 #define ARG_TEMPLATE "WINPOSX=X/N/K,WINPOSY=Y/N/K,NOBLUR/S,FORCESCREEN=SCR/S,FORCEWINDOW=WIN/S"
24 #define ARG_X 0
25 #define ARG_Y 1
26 #define ARG_NOBLUR 2
27 #define ARG_SCR 3
28 #define ARG_WIN 4
29 #define NUM_ARGS 5
31 struct IntuitionBase *IntuitionBase;
32 struct GfxBase *GfxBase;
33 struct Library *CyberGfxBase;
34 struct Screen *scr;
35 struct Window *win;
36 struct RastPort *rp;
37 struct RDArgs *myargs;
38 ULONG cgfx_coltab[256];
39 UBYTE remaptable[256];
40 UBYTE Keys[128];
41 char s[256];
42 WORD winx = -1, winy = -1;
43 IPTR args[NUM_ARGS];
44 BOOL forcescreen, forcewindow;
45 BOOL mustremap, truecolor, remapped, wbscreen = TRUE;
47 static void cleanup(char *msg);
49 /***********************************************************************************/
51 #ifndef M_PI
52 #define M_PI 3.14159265358979323846 /* pi */
53 #endif
55 #define W 320 /* if you change it: dont forget to also change the W
56 in memshd.S ... */
57 #define H 240
59 int motion_blur;
60 char *b8; /* working 8bits buffer */
61 char *b8_remapped;
63 typedef struct
65 int x,y,z,r;
66 } p3;
68 typedef float matrix[3][3];
70 #define GMAX 5000
71 p3 gal[GMAX];
72 float precos[512];
73 float presin[512];
75 typedef unsigned short word;
77 void memshset (char *dst, int center_shade,int fixed_shade, int length_2);
79 void init_plouf();
80 void drawgalaxy();
82 static inline float ocos(float a){
83 return (precos[(int)(a*256/M_PI)&511]);
86 static inline float osin(float a){
87 return (presin[(int)(a*256/M_PI)&511]);
90 /*#undef ocos
91 #undef osin
93 #define ocos cos
94 #define osin sin
98 void mulmat(matrix *a, matrix *b, matrix *c){
99 int i,j;
101 for (i=0; i<3; i++)
102 for (j=0; j<3; j++)
103 (*c)[i][j] = (*a)[i][0] * (*b)[0][j]
104 +(*a)[i][1] * (*b)[1][j]
105 +(*a)[i][2] * (*b)[2][j];
108 static inline void mulvec(matrix *a, float *x, float *y, float *z){
109 float nx=*x,ny=*y,nz=*z;
111 *x = nx*(*a)[0][0] + ny*(*a)[0][1] + nz*(*a)[0][2];
112 *y = nx*(*a)[1][0] + ny*(*a)[1][1] + nz*(*a)[1][2];
113 *z = nx*(*a)[2][0] + ny*(*a)[2][1] + nz*(*a)[2][2];
118 void setrmat(float a, float b, float c, matrix *m){
119 int i,j;
120 for (i=0; i<3; i++) for (j=0; j<3; j++) (*m)[i][j]=(float)(i==j);
122 if (a!=0){
123 (*m)[0][0] = cos(a); (*m)[0][1] = sin(a);
124 (*m)[1][0] = sin(a); (*m)[1][1] = -cos(a);
125 return;
127 if (b!=0){
128 (*m)[0][0] = cos(b); (*m)[0][2] = sin(b);
129 (*m)[2][0] = sin(b); (*m)[2][2] = -cos(b);
130 return;
133 (*m)[1][1] = cos(c); (*m)[1][2] = sin(c);
134 (*m)[2][1] = sin(c); (*m)[2][2] = -cos(c);
138 void rotate3d(float *xr, float *yr, float *zr, /* point to rotate */
139 float ax, float ay, float az) /* the 3 angles (order ?..) */
141 float xr2,yr2,zr2;
144 xr2= (*xr*ocos(az) + *yr*osin(az));
145 yr2= (*xr*osin(az) - *yr*ocos(az));
146 *xr=xr2;
147 *yr=yr2;
149 xr2= (*xr*ocos(ay) + *zr*osin(ay));
150 zr2= (*xr*osin(ay) - *zr*ocos(ay));
151 *xr=xr2;
152 *zr=zr2;
154 zr2= (*zr*ocos(ax) + *yr*osin(ax));
155 yr2= (*zr*osin(ax) - *yr*ocos(ax));
156 *zr=zr2;
157 *yr=yr2;
160 void aff () {
162 if (truecolor)
164 WriteLUTPixelArray(b8,
169 cgfx_coltab,
170 win->BorderLeft,
171 win->BorderTop,
174 CTABFMT_XRGB8);
176 else if (mustremap)
178 LONG i;
179 UBYTE *src = b8;
180 UBYTE *dest = b8_remapped;
182 for(i = 0; i < W * H; i++)
184 *dest++ = remaptable[*src++];
186 WriteChunkyPixels(rp,
187 win->BorderLeft,
188 win->BorderTop,
189 win->BorderLeft + W - 1,
190 win->BorderTop + H - 1,
191 b8_remapped,
195 else
197 WriteChunkyPixels(rp,
198 win->BorderLeft,
199 win->BorderTop,
200 win->BorderLeft + W - 1,
201 win->BorderTop + H - 1,
208 void init_plouf(){
209 int i;
211 b8 = (unsigned char *)malloc(W*(H+1)); /* +1 : I dont trust my range checkings... */
212 if (!b8) cleanup("Out of memory!");
214 if (mustremap)
216 b8_remapped = (unsigned char *)malloc(W*H);
217 if (!b8_remapped) cleanup("Out of memory!");
220 for (i=0; i<256; i++){
221 unsigned int r,g,b;
222 r = (int)(i*0.7);
223 g = (int)(i*0.8);
224 b = i;
226 if (truecolor)
228 cgfx_coltab[i]=((r<<16)|(g<<8)|(b));
230 else if (mustremap)
232 ULONG red = r * 0x01010101;
233 ULONG green = g * 0x01010101;
234 ULONG blue = b * 0x01010101;
236 remaptable[i] = ObtainBestPen(scr->ViewPort.ColorMap,
237 red,
238 green,
239 blue,
240 OBP_Precision, PRECISION_IMAGE,
241 OBP_FailIfBad, FALSE,
242 TAG_DONE);
243 remapped = TRUE;
245 else
248 ULONG red = r * 0x01010101;
249 ULONG green = g * 0x01010101;
250 ULONG blue = b * 0x01010101;
252 SetRGB32(&scr->ViewPort, i, red, green, blue);
257 for (i=0; i<512; i++){
258 precos[i]=cos(i*M_PI/256);
259 presin[i]=sin(i*M_PI/256);
264 uniforme cubique
265 for (i=0; i<GMAX; i++){
266 gal[i].x = 1*((rand()&1023) - 512);
267 gal[i].y = 1*((rand()&1023) - 512);
268 gal[i].z = 1*((rand()&1023) - 512);
269 gal[i].r = rand()&63;
273 for (i=0; i<GMAX; i++){
274 float r,th,h,dth;
275 r = rand()*1.0 / RAND_MAX;
276 r = (1-r)*(1-r)+0.05;
277 if (r<0.12)
278 th = rand()*M_PI*2/RAND_MAX;
279 else {
280 th = (rand()&3)*M_PI / 2+ r*r*2;
281 dth = rand()*1.0/RAND_MAX;
282 dth = dth*dth*2;
283 th+=dth;
287 gal[i].x = 512*r*cos(th);
288 gal[i].z = 512*r*sin(th);
289 h = (1+cos(r*M_PI))*150;
290 dth = rand()*1.0/RAND_MAX;
291 gal[i].y =h*(dth-0.5);
292 gal[i].r = (2-r)*60+31;
294 gal[0].x = gal[0].y = gal[0].z = 0;
295 gal[0].r = 320;
300 void starsh(char *, char);
302 void drawshdisk(int x0, int y0, int r){
303 int x=0;
304 int y;
305 int ly; /* last y */
306 int delta;
307 int c; /* color at center */
308 int d; /* delta */
310 #define SLIMIT 17
311 #define SRANGE 15
312 if (r<=SLIMIT)
314 /* range checking is already (more or less) done... */
315 starsh(&b8[x0 + W*y0],10+r*5);
316 return;
319 if (r < SLIMIT+SRANGE)
320 r = ((r-SLIMIT)*SLIMIT)/SRANGE+1;
322 y=ly=r; /* AAaargh */
324 delta = 3-2*r;
325 do{
327 if (y!=ly){ /* dont overlap these lines */
328 c = ((r-y+1)<<13)/r;
329 d = -c/(x+1);
332 if (y==x+1) /* this would overlap with the next x lines */
333 goto TOTO; /* WHY NOT */
335 /* note : for "normal" numbers (not too big) :
336 (unsigned int)(x) < M <=> 0<=x<H
337 (because if x<0, then (unsigned)(x) = 2**32-|x| which is
338 BIG and thus >H )
340 This is clearly a stupid, unmaintanable, unreadable "optimization".
341 But i like it :)
343 if ((unsigned int)(y0-y-1)<H-3)
344 memshset(&b8[x0 + W*(y0-y+1)] ,c,d, x);
345 if ((unsigned int)(y0+y-1)<H-3)
346 memshset(&b8[x0 + W*(y0+y)] ,c,d, x);
348 TOTO:
349 c = ((r-x+1)<<13)/r;
350 d = -c/(y);
352 if ((unsigned int)(y0-x-1)<H-3)
353 memshset(&b8[x0 + W*(y0-x)] ,c,d, y);
354 if ((unsigned int)(y0+x-1)<H-3)
355 memshset(&b8[x0 + W*(y0+x+1)] ,c,d, y);
357 ly=y;
358 if (delta<0)
359 delta += 4*x+6;
360 else {
361 delta += 4*(x-y)+10;
362 y--;
365 x++;
366 } while (x<y);
371 void mblur (char *src, int nbpixels);
374 void drawgalaxy(){
375 int r;
376 int x,y;
377 float rx,ry,rz;
378 int i;
379 float oa,ob,oc;
380 float t;
382 float a, b, c;
383 matrix ma,mb,mc,mr;
385 /* t is the parametric coordinate for the animation;
386 change the scale value to change the speed of anim
387 (independant of processor speed)
389 t=opti_scale_time(0.418, &demo_elapsed_time);
391 a= 0.9*t;
392 b= t;
393 c= 1.1*t;
397 setrmat(a,0,0,&ma);
398 setrmat(0,b,0,&mb);
399 mulmat(&ma,&mb,&mc);
400 setrmat(0,0,c,&ma);
401 mulmat(&ma,&mc,&mr);
403 oa=140*osin(a);
404 ob=140*ocos(b);
405 oc=240*osin(c);
407 if (motion_blur){
409 mblur does something like that:
410 (or did, perhaps it's another version!..)
412 for (i=0; i<W*H; i++)
413 b8[i]= (b8[i]>>3) + (b8[i]>>1) ;
415 mblur (b8, W*H);
417 else
418 memset(b8,0,W*H);
421 for (i=0; i<GMAX; i++){
423 rx=gal[i].x;
424 ry=gal[i].y;
425 rz=gal[i].z;
427 mulvec(&mr, &rx, &ry, &rz);
429 rx+=oa;
430 ry+=ob;
431 rz+=oc;
432 rz+=300;
434 if (rz>5){
435 x = (int)(15*rx/(rz/5+1))+W/2; /* tain jcomprend plus rien */
436 y = (int)(15*ry/(rz/5+1))+H/2; /* a ces formules de daube !! */
437 r = (int)(3*gal[i].r / (rz/4+3))+2;
440 if ((unsigned int)x<W-1
442 (unsigned int)y<H-1)
444 drawshdisk(x,y, r);
451 /***********************************************************************************/
453 static void cleanup(char *msg)
456 if (msg)
458 printf("Galaxy: %s\n",msg);
461 if (win) CloseWindow(win);
463 if (remapped)
465 WORD i;
467 for(i = 0; i < 256; i++)
469 ReleasePen(scr->ViewPort.ColorMap, remaptable[i]);
473 if (scr)
475 if (wbscreen)
476 UnlockPubScreen(0, scr);
477 else
478 CloseScreen(scr);
481 if (myargs) FreeArgs(myargs);
483 if (CyberGfxBase) CloseLibrary(CyberGfxBase);
484 if (GfxBase) CloseLibrary((struct Library *)GfxBase);
485 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
487 exit(0);
490 /***********************************************************************************/
492 static void openlibs(void)
494 if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)))
496 cleanup("Can't open intuition.library V39!");
499 if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)))
501 cleanup("Can't open graphics.library V39!");
504 if (!(CyberGfxBase = OpenLibrary("cybergraphics.library",0)))
506 cleanup("Can't open cybergraphics.library!");
510 /***********************************************************************************/
512 static void getargs(void)
514 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, 0)))
516 Fault(IoErr(), 0, s, 255);
517 cleanup(s);
520 if (args[ARG_NOBLUR])
522 motion_blur = 0;
523 } else {
524 motion_blur = 1;
527 if (args[ARG_SCR])
528 forcescreen = TRUE;
529 else if (args[ARG_WIN])
530 forcewindow = TRUE;
532 if (args[ARG_X]) winx = *(IPTR *)args[ARG_X];
533 if (args[ARG_Y]) winy = *(IPTR *)args[ARG_Y];
537 /***********************************************************************************/
539 static void getvisual(void)
541 if (!(scr = LockPubScreen(NULL)))
543 cleanup("Can't lock pub screen!");
546 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
548 if (!forcewindow)
550 wbscreen = FALSE;
552 else
554 mustremap = TRUE;
558 if (forcescreen) wbscreen = FALSE;
560 if (!wbscreen)
562 UnlockPubScreen(NULL, scr);
563 wbscreen = FALSE;
565 scr = OpenScreenTags(NULL, SA_Width , W ,
566 SA_Height , H ,
567 SA_Depth , 8 ,
568 TAG_DONE);
569 if (!scr) cleanup("Can't open screen!");
572 truecolor = (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) >= 15) ? TRUE : FALSE;
575 /***********************************************************************************/
577 static void makewin(void)
579 struct TagItem winonwbtags[] =
581 {WA_DragBar , TRUE },
582 {WA_DepthGadget , TRUE },
583 {WA_CloseGadget , TRUE },
584 {WA_Title , (IPTR)"Galaxy" },
585 {TAG_DONE }
588 struct TagItem winonscrtags[] =
590 {WA_Borderless, TRUE },
591 {TAG_DONE }
594 if (winx == -1) winx = (scr->Width - W - scr->WBorLeft - scr->WBorRight) / 2;
595 if (winy == -1) winy = (scr->Height - H - scr->WBorTop - scr->WBorTop - scr->Font->ta_YSize - 1) / 2;
597 win = OpenWindowTags(NULL, WA_CustomScreen , (IPTR)scr,
598 WA_Left , winx,
599 WA_Top , winy,
600 WA_InnerWidth , W,
601 WA_InnerHeight , H,
602 WA_AutoAdjust , TRUE,
603 WA_Activate , TRUE,
604 WA_IDCMP , IDCMP_CLOSEWINDOW |
605 IDCMP_RAWKEY,
606 TAG_MORE , wbscreen ? winonwbtags : winonscrtags);
609 if (!win) cleanup("Can't open window");
611 rp = win->RPort;
614 /***********************************************************************************/
616 #define KC_LEFT 0x4F
617 #define KC_RIGHT 0x4E
618 #define KC_UP 0x4C
619 #define KC_DOWN 0x4D
620 #define KC_ESC 0x45
622 /***********************************************************************************/
624 static void getevents(void)
626 struct IntuiMessage *msg;
628 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
630 switch(msg->Class)
632 case IDCMP_CLOSEWINDOW:
633 Keys[KC_ESC] = 1;
634 break;
636 case IDCMP_RAWKEY:
638 WORD code = msg->Code & ~IECODE_UP_PREFIX;
640 Keys[code] = (code == msg->Code) ? 1 : 0;
643 break;
646 ReplyMsg((struct Message *)msg);
651 /***********************************************************************************/
653 static void action(void)
655 //init_fps();
656 init_plouf();
657 opti_sched_init();
659 while (!Keys[KC_ESC])
661 getevents();
663 drawgalaxy();
665 aff();
666 WaitTOF();
667 opti_sched_nextframe();
668 opti_sched_update();
672 //aff_fps(NAME);
676 /***********************************************************************************/
678 int main(void)
680 getargs();
681 openlibs();
682 getvisual();
683 makewin();
684 action();
685 cleanup(0);
687 return 0;
690 /***********************************************************************************/