home *** CD-ROM | disk | FTP | other *** search
- /* FastGro 1.0 - a simulation of Diffusion-Limited Aggregation
-
- Copyright (c) 1989 Doug Houck (03-Feb-89)
-
- This program has been placed in the PUBLIC DOMAIN, so anyone,
- anywhere can do anything they want with it.
-
- This was compiled with the Aztec C compiler, version 3.6a, using
- the large data, large code, small integer model. "cc +d +d ..."
- and linked with "ln FastGro.o Wander.o -lml -lcl"
- */
-
- #include <exec/types.h>
- #include <intuition/intuition.h>
- #include <functions.h> /* learn about system */
-
- #define RANDOMS 50437 /* how many random #s to generate */
- #define STARTING_POINTS 200 /* points around circle for starting */
-
- #define ffp long /* Motorola Fast Floating Point */
- extern ffp
- ran(), /* use manx random # generator */
- SPFlt(), SPFix(), SPMul(), SPDiv(),
- SPSin(), SPCos(), SPAdd(), SPSub();
-
- struct Screen *hires_screen = NULL;
- struct Window *hires_window = NULL;
- struct RastPort *hires_rp = NULL;
- struct MsgPort *window_port = NULL;
-
- long MathBase = NULL, /* library bases */
- MathTransBase = NULL,
- IntuitionBase = NULL,
- GfxBase = NULL;
-
- int rows, columns, /* size of screen in pixels */
- maxrow, maxcolumn,
- columnsdiv8; /* in bytes */
-
- long radius, color_iterations,
- points, points_to_go; /* parameters for drawing */
-
-
- char *row[550]; /* pointers to rows */
- char *row_memory = NULL; /* in row memory */
- char *border[550]; /* pointers to rows */
- char *border_memory = NULL; /* in border memory */
- long optimizer_memory; /* how much space used */
-
- char *randoms = NULL; /* pointer to random array */
- char *next_random; /* index into randoms */
-
- struct start_t /* cache starting points */
- { int x, y;
- };
- struct start_t start[STARTING_POINTS];
-
- struct NewScreen new_hires_screen =
- { 0,0,
- 640, STDSCREENHEIGHT, /* size from Workbench screen */
- 4, /* 16 colors */
- 2,1, /* pens */
- HIRES | LACE,
- CUSTOMSCREEN | SHOWTITLE | SCREENQUIET | SCREENBEHIND,
- NULL,
- NULL,
- NULL,
- NULL
- };
-
-
- struct NewWindow new_hires_window =
- { 0,0, /* coords */
- 640,400,
- 0,1, /* pens */
- MOUSEBUTTONS,
- BACKDROP | BORDERLESS,
- NULL,
- NULL,
- NULL, /* title */
- NULL, /* screen */
- NULL, /* bitmap */
- 0,0,0,0, /* min, max */
- CUSTOMSCREEN
- };
-
-
- initialize(argc, argv) /* open libraries, allocate memory... */
- int argc;
- char **argv;
- {
- IntuitionBase = (long)OpenLibrary( "intuition.library",33L);
- if (!IntuitionBase)
- { ReportProblem("I Really Needed Kickstart/Workbench 1.2");
- return(0);
- }
-
- GfxBase = (long)OpenLibrary( "graphics.library",33L);
- if (!GfxBase)
- { ReportProblem("can't open graphics.library");
- return(FALSE);
- }
-
- MathBase = (long)OpenLibrary( "mathffp.library",33L);
- if (!MathBase)
- { ReportProblem("can't open mathffp.library");
- return(FALSE);
- }
-
- MathTransBase = (long)OpenLibrary( "mathtrans.library",33L);
- if (!MathTransBase)
- { ReportProblem("Would kinda liketa have 'mathtrans.library' 1.2, mebbee?");
- return(FALSE);
- }
-
- rows = DisplayRows()<<1; /* get # of rows in WB screen */
- maxrow = rows-1;
- columns = DisplayColumns()<<1; /* get # of columns in WB screen */
- columnsdiv8 = (columns+7)>>3;
- maxcolumn = columns-1;
- optimizer_memory = rows * columnsdiv8; /* space arrays will use */
-
- /* ------------------------------- display screen ---------------------- */
- new_hires_screen.Height = rows;
- new_hires_screen.Width = columns;
-
- hires_screen = OpenScreen( &new_hires_screen );
- if (!hires_screen)
- { ReportProblem("No Memory for HiRes Screen. Sorry!");
- return(0);
- }
-
- new_hires_window.Screen = hires_screen;
- new_hires_window.Width = hires_screen->Width;
- new_hires_window.Height = hires_screen->Height;
- hires_window = OpenWindow( &new_hires_window );
- if (!hires_window )
- { ReportProblem("Can't open hires window");
- return(0);
- }
- hires_rp = hires_window->RPort;
- window_port = hires_window->UserPort;
-
- { long red, green, blue; /* set up colors */
- green = 12;
- for( red = 0, blue = 15;
- red <= 15;
- red++, blue--
- )
- SetRGB4( &hires_screen->ViewPort, red, red, green, blue );
- SetRGB4( &hires_screen->ViewPort, 0L, 0L, 0L, 0L );
- }
-
- /* ---------------------- allocate optimizing arrays --------------------- */
-
- row_memory = (char*)AllocMem( optimizer_memory, 0L );
- border_memory = (char*)AllocMem( optimizer_memory, 0L );
- if (!row_memory || !border_memory)
- { ReportProblem("No Memory For Auxiliary Arrays");
- return(FALSE);
- }
-
- { int i = 0; /* init row pointers into arrays */
- char *row_ptr = row_memory;
- char *border_ptr = border_memory;
-
- for( i=0; i < rows; i++ )
- { row[i] = row_ptr;
- border[i] = border_ptr;
- row_ptr += columnsdiv8;
- border_ptr += columnsdiv8;
- }
- }
-
- randoms = (char*)AllocMem( (long)RANDOMS, 0L );
- if (!randoms)
- { ReportProblem( "no random array");
- return(0);
- }
- { long counter = RANDOMS-1; /* init random array */
- register char *ptr = randoms;
- long scaler;
- scaler = SPFlt( 254L );
- while(--counter)
- *ptr++ = SPFix( SPMul(ran(), scaler ) )+ 1;
- *ptr = 0; /* 0 marks the end */
- next_random = randoms;
- }
-
- radius = 70;
- color_iterations = 100;
- points = 5000;
-
- return( TRUE );
- }
-
- wrapup() /* clean up, close libraries, deallocate, wipe nose, etc */
- {
- if (randoms) FreeMem ( randoms, (long)RANDOMS );
- if (row_memory) FreeMem ( row_memory, optimizer_memory );
- if (border_memory) FreeMem ( border_memory, optimizer_memory );
- if (hires_window) CloseWindow ( hires_window );
- if (hires_screen) CloseScreen ( hires_screen );
- if (IntuitionBase) CloseLibrary ( IntuitionBase );
- if (GfxBase) CloseLibrary ( GfxBase );
- if (MathTransBase) CloseLibrary ( MathTransBase );
- if (MathBase) CloseLibrary ( MathBase );
-
- exit( 0 );
- }
-
- ReportProblem( text )
- char *text;
- { char answer[64];
- printf("Had a slight problem...\n\n");
- printf(" %s\n\n", text);
- printf("Press <RETURN> to abort. ");
- gets( answer );
- }
-
- mark_perimeter( x, y ) /* mark perimeter around a pixel */
- int x, y;
- { setbit( row, x, y );
-
- if (y>0) setbit( row, x , y-1 ); /* careful of edges... */
- if (y<maxrow) setbit( row, x , y+1 );
-
- if (x>0)
- { if (y>0) setbit( row, x-1, y-1 );
- setbit( row, x-1, y );
- if (y<maxrow) setbit( row, x-1, y+1 );
- }
- if (x<maxcolumn)
- { if (y>0) setbit( row, x+1, y-1 );
- setbit( row, x+1, y );
- if (y<maxrow) setbit( row, x+1, y+1 );
- }
- }
-
- set_up_optimizing( radius )
- long radius;
- { int x, y;
- long midx, midy;
- int steps, s, thick;
- ffp theta, stepsize, radi;
-
- midx = columns / 2;
- midy = rows / 2;
-
- for(y = 0; y<rows; y++) /* clear everything first */
- for(x=0; x<columnsdiv8; x++)
- { row[y][x] = 0;
- border[y][x] = 0;
- }
-
- steps = radius * 12; /* mark border of circle */
- stepsize = SPDiv( SPFlt((long)steps), /* 2 pi / steps */
- SPDiv( SPFlt(1000L), SPFlt( 6283L) ) );
- radi = SPFlt( radius );
-
- for(thick = 0; thick<4; thick++ ) /* make sure no leaks */
- { for( theta = 0, s = steps;
- s;
- s--, theta = SPAdd(theta, stepsize ) )
- { x = midx + SPFix(SPMul( SPCos(theta), radi ));
- y = midy + SPFix(SPMul( SPSin(theta), radi ));
- setbit( row, x, y );
- setbit( border, x, y );
- }
- radi = SPSub( SPDiv( SPFlt(3L),SPFlt(1L)), radi );
- }
- /* set up starting points */
-
- steps = STARTING_POINTS;
- stepsize = SPDiv( SPFlt((long)steps),SPDiv( SPFlt(1000L), SPFlt( 6283L) ) );
- radi = SPFlt( radius - 3L );
-
- for( theta = 0, steps = 0;
- steps < STARTING_POINTS;
- steps++, theta = SPAdd(theta, stepsize )
- )
- { start[steps].x = midx + SPFix(SPMul( SPCos(theta), radi ));
- start[steps].y = midy + SPFix(SPMul( SPSin(theta), radi ));
- }
- }
-
- draw_fractal()
- { long max_radius, color_counter, color;
- int x,y;
- ffp start_scale;
- int start_location;
- struct IntuiMessage *im;
- char answer[64];
-
- max_radius = rows/2 - 2;
- start_scale = SPFlt( (long)STARTING_POINTS );
-
- printf("\n\nRadius (10..%ld) [%ld] ",max_radius, radius); /* get parms */
- gets( answer );
- if (answer[0])
- { sscanf(answer, "%ld", &radius );
- if (radius < 10) radius = 10;
- if (radius > max_radius) radius = max_radius;
- }
-
- printf("Particles (1..1000000) [%ld] ",points);
- gets( answer );
- if (answer[0])
- sscanf(answer, "%ld", &points );
- points_to_go = points;
-
- printf("Change Color After (1..1000000) [%ld] ",color_iterations);
- gets( answer );
- if (answer[0])
- sscanf( answer, "%ld", &color_iterations );
- color = 1;
- color_counter = color_iterations;
-
- printf("To abort drawing, click anywhere on drawing.\n");
- printf("Setting up...\n");
-
- set_up_optimizing( radius);
-
- x = columns / 2; /* seed the center */
- y = rows / 2;
- mark_perimeter(x,y);
- WritePixel( hires_rp, (long)x, (long)y );
-
- SetAPen( hires_rp, 1L ); /* erase window */
- SetDrMd( hires_rp, JAM2 );
- SetRast( hires_rp, 0L );
-
- ScreenToFront( hires_screen );
-
- /* clean out port */
- while( im = (struct IntuiMessage*)GetMsg( window_port) )
- ReplyMsg( im );
-
- while(!IsMessageWaiting(window_port) && (points_to_go> 0 ))
- { start_location = SPFix(SPMul( ran(), start_scale ));
- x = start[start_location].x;
- y = start[start_location].y;
-
- wander_asm( &x, &y ); /* do the time-consuming stuff */
-
- if (!checkbit( border, x, y ) ) /* not a border hit? OK! */
- { mark_perimeter(x,y);
- WritePixel( hires_rp, (long)x, (long)y );
- points_to_go--;
- if( !(--color_counter) )
- { color_counter = color_iterations;
- color++;
- if (color > 15) color = 1;
- SetAPen( hires_rp, color );
- }
- }
- }
-
- ScreenToBack( hires_screen);
- }
-
- main( argc, argv )
- int argc;
- char **argv;
- { char answer[32];
-
- printf("Welcome to FastGro, a fractal program by Doug Houck,\n");
- printf("simulating Diffusion-Limited Aggregation. The purpose\n");
- printf("of this program is to demonstrate how selected\n");
- printf("optimizations can improve the speed of a program by\n");
- printf("an order of magnitude. Meanwhile, I'm setting up...\n");
-
- if (!initialize( argc, argv ))
- wrapup();
-
- do
- { draw_fractal();
- printf("More? (Y/N) [Yes] ");
- gets( answer );
- }
- while ( ! ((answer[0]=='N') || (answer[0]=='n')) );
-
- wrapup();
- }
-
-