home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * Fractal.c © John M. Olsen. 9-1-86
- * This is a fractal program which produces random square fractal
- * terrain, with resolution where the size of the sides is
- * 2^n + 1 where n is between 0 and 6.
- * The 3D view uses a light source off to the upper left.
- *
- * This program requires both c.lib and m.lib when linked. It was written for
- * Aztec and I have no idea what it will do when compiled with Lettuce C.
- *
- * This program is freely distributable as long as this notice remains
- * with it. Do not use any part of this program in a commercial application
- * without written consent from the author:
- *
- * John M. Olsen
- * 1547 Jamestown Drive
- * Salt Lake City, UT 84121
- ****************************************************************/
-
- #define MAXFRACT 65 /* This must be 2^something + 1 */
- #define EVEN(a) (!(a & 1))
- #define ODD(a) (a & 1)
-
- #include <exec/types.h>
- #include <graphics/gfx.h>
- #include <graphics/gfxbase.h>
- #include <graphics/gfxmacros.h>
- #include <graphics/rastport.h>
- #include <intuition/intuition.h>
- #include <stdio.h>
- #include <math.h>
-
- void *OpenLibrary(), *ScreenToBack(), *ScreenToFront();
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct Screen *OpenScreen(), *s;
- struct Window *OpenWindow(), *w;
- struct IntuiMessage *GetMsg();
- float myrand();
-
- BYTE *AllocRaster();
- WORD areabuffer[250];
- struct TmpRas tmpras;
- struct AreaInfo myAreaInfo;
-
- struct NewScreen ss =
- { 0, 0, 320, 200, /* Edges & size */
- 5, 0, 1, /* Depth, pens */
- NULL, CUSTOMSCREEN, /* Viewmodes, type */
- NULL, /* *font */
- (UBYTE *) "3D Random Fractal Terrain",
- NULL, NULL /* Gadgets, bit map */
- };
-
- float p[MAXFRACT][MAXFRACT], divisor, scale;
- int shadows, degree, size;
-
- main()
- {
- long sc, mc;
-
- printf("Fractal generator by John M. Olsen ©1986\n\n");
- printf("This program is freely distributable so long as the above\n");
- printf("notice remains in it.\n");
- printf("After a fractal has been computed and drawn, you need to\n");
- printf("push the picture screen back, bringing this screen foreward\n");
- printf("before trying to enter more data.\n");
- if(!(GfxBase = OpenLibrary("graphics.library",0l)))
- die(1);
- if(!(IntuitionBase = OpenLibrary("intuition.library")))
- die(2);
- if(!(s = OpenScreen(&ss)))
- die(3);
- InitArea(&myAreaInfo, areabuffer, 100l);
- s->RastPort.AreaInfo = &myAreaInfo;
- tmpras.RasPtr = AllocRaster(320l, 200l);
- tmpras.Size = (long) RASSIZE(320l, 200l);
- s->RastPort.TmpRas = &tmpras;
- ScreenToBack(s);
- docolors(&(s->RastPort));
- while(1)
- {
- CurrentTime(&sc,&mc); /* Seed the random number by time */
- myrand(-(int)sc);
- getsize(); /* Exits from this routine. */
- compute();
- ScreenToFront(s);
- draw(&(s->RastPort));
- }
- }
-
- /* Compute the array. */
- compute()
- {
- float tempscale, rnum, t1, t2, t3, t4;
- int x, y, n;
-
- /* Zero out the corner of the array. */
- for(x = 0;x < 2; x++)
- for(y = 0; y < 2; y++)
- p[x][y] = 0;
- tempscale = 64.0;
- size = 1;
- for(n = 1; n <= degree; n++)
- {
- size *= 2;
- for(x = size; x >= 0; x--)
- {
- for(y = size; y >= 0; y--)
- {
- t1 = p[x / 2][y / 2];
- t2 = p[(x+1) / 2][(y+1) / 2];
- t3 = p[x / 2][(y + 1) / 2];
- t4 = p[(x + 1) / 2][y / 2];
- rnum = myrand(0) - .5;
- rnum *= tempscale;
- if(ODD(x) && EVEN(y))
- {
- p[x][y] = (t1 + t4) / 2.0 + rnum;
- }
- else if(EVEN(x) && ODD(y))
- {
- p[x][y] = (t1 + t3) / 2.0 + rnum;
- }
- else if(ODD(x) && ODD(y))
- {
- p[x][y] = (t1+t2+t3+t4) / 4.0 + rnum;
- }
- else if(EVEN(x) && EVEN(y))
- {
- p[x][y] = t1;
- }
- else
- printf("Toasted.\n");
- }
- }
- tempscale /= divisor;
- }
- /* now run it through the scaler. */
- for(x = 0; x <= size; x++)
- for(y = 0; y <= size; y++)
- p[x][y] *= scale;
- }
-
- die(kind)
- int kind;
- {
- static char *errortext[] = { "No error.\n",
- "Unable to open graphics.\n",
- "Unable to open Intuition.\n",
- "Unable to open screen.\n",
- "4\n",
- "5\n",
- "6\n"
- };
-
- if(kind)
- puts(errortext[kind]);
- if(tmpras.RasPtr) FreeRaster(tmpras.RasPtr,320l,200l);
- if(s) CloseScreen(s);
- if(GfxBase) CloseLibrary(GfxBase);
- if(IntuitionBase) CloseLibrary(IntuitionBase);
- exit(kind);
- }
-
- float myrand(seed)
- int seed;
- {
- static unsigned int val;
-
- if(seed < 0)
- val = - seed;
- val *= 25173;
- val += 13849;
- val %= 32768;
- return((float) val / 32768.0);
- }
-
- draw(r)
- struct RastPort *r;
- {
- int h, x, y, cl, sz;
- float slopex, slopey;
-
- SetAPen(r, 0l);
- RectFill(r, 0l,10l,320l,200l);
- /* SetRast(r,0l); this line took out the title bar.*/
- h = 150; /* use this many of the 200 lines. */
- for(y = 1; y <= size; y++)
- {
- for(x = 1; x <= size; x++)
- {
- if(shadows)
- {
- slopex = p[x][y-1];
- slopex += p[x][y];
- slopex -= p[x-1][y-1];
- slopex -= p[x-1][y];
-
- slopey = p[x][y];
- slopey -= p[x][y-1];
- slopey -= p[x-1][y-1];
- slopey += p[x-1][y];
- cl = (int) (slopex + slopey) + 15;
- }
- else
- {
- cl = (int) p[x][y];
- cl += (int) p[x-1][y];
- cl += (int) p[x][y-1];
- cl += (int) p[x-1][y-1];
- cl /= 8;
- cl += 16;
- }
- sz = h / (size + 1);
- if(cl > 31)
- cl = 31;
- if(cl < 1)
- cl = 1;
- SetAPen(r, (long)cl);
- AreaMove(r, (long)(50+((x-1)*sz+(size-y+1)*60/size)+1),
- (long)(((y-1)*sz-(int)p[x-1][y-1])+30));
- /*+1extra*/ AreaDraw(r, (long)(50+(x*sz+(size-y+1)*60/size)+1),
- (long)(((y-1)*sz-(int)p[x][y-1])+30));
- /*+1 extra*/ AreaDraw(r, (long)(50+(x*sz+(size-y)*60/size)+1),
- /*+1 extra*/ (long)((y*sz-(int)p[x][y])+30));
- AreaDraw(r, (long)(50+((x-1)*sz+(size-y)*60/size)+1),
- (long)((y*sz-(int)p[x-1][y])+30));
- AreaEnd(r);
- }
- }
- }
-
- /*********************
- Set up the colors to 32 gray shades.
- *********************/
- docolors(r)
- struct RastPort *r;
- {
- long loop;
-
- r = &(s->RastPort);
- for(loop = 1l; loop < 32l; loop++)
- SetRGB4(&s->ViewPort, loop, loop/2l, (loop - 1)/2l, loop/2l);
- }
-
- getsize()
- {
- printf("Enter the degree(1-6 or invalid to quit): ");
- scanf(" %d", °ree);
- if(degree < 1 || degree > 6)
- die(0);
- printf("Enter the scale(0.0 to 3.0, 1.0 is standard): ");
- scanf(" %f", &scale);
- if(scale > 3.0 || scale < 0.0)
- die(0);
- printf("Enter the divisor(1.0 to 4.0, 2.0 is standard): ");
- scanf(" %f", &divisor);
- if(divisor > 4.0 || divisor < 1.0)
- die(0);
- printf("Altitudes (0) or shadows(non-zero)? ");
- scanf(" %d", &shadows);
- }
-