home *** CD-ROM | disk | FTP | other *** search
-
- /*
- ' 3-Dimensional Fractal surface generating program
- ' From July '85 Creative Computing.
- */
-
- #include <quickdraw.h>
- #include <toolutil.h>
- #define watchCursor 4 /* Should be in TOOLUTIL.H but isn't. JEC */
- double ran(); /* Should be in MATH.H but isn't. JEC */
-
- #include "fractal.h"
-
- #define TRUE (-1)
- #define FALSE 0
-
- int linestart; /* True at the first of the line. */
- int color; /* True when plotting land, else false. */
-
- calcsurf(level)
- int level;
- {
- int i, j, length, incrby, sk;
- float power;
- CursHandle ticktock;
-
- if (!points)
- return;
- ticktock = GetCursor(watchCursor);
- if (ticktock)
- SetCursor(*ticktock); /* Show watch (wait) */
-
- xmax = 1 << level;
- ymax = xmax/2;
- for (i=0; i<=xmax; i++) /* Clear the Array. Use i & incrby as temps. */
- for (incrby=0; incrby<=ymax; incrby++)
- (*points)[i][incrby] = 0;
-
- for (i=1; i<= level; i++) {
- for (power=1.0, j=0; j<i; j++)
- power *= 1.8;
- length = 10000/power; /* = 10000/(1.8^i) */
- incrby = xmax/(1 << i); /* # of line segments in a side of the triangle. */
- sk = incrby * 2;
- calcxs(length, incrby, sk);
- calcys(length, incrby, sk);
- calcdiags(length, incrby, sk);
- }
- InitCursor(); /* Put back the arrow. */
- }
-
- calcxs(len, incr, sk) /* Assign heights along x in array. */
- int len;
- register int incr, sk;
- {
- register int y, x;
- int d1, d2;
-
- for (y=0; y < xmax; y += sk) {
- for (x = incr+y; x <= xmax; x += sk) {
- d1 = getdata(x-incr, y);
- d2 = getdata(x+incr, y);
- stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
- }
- }
- }
-
- calcys(len, incr, sk) /* Assign heights along y in array. */
- int len;
- register int incr, sk;
- {
- register int y, x;
- int d1, d2;
-
- for (x=xmax; x >= 1; x -= sk)
- for (y = incr; y <= x; y += sk) {
- d1 = getdata(x, y+incr);
- d2 = getdata(x, y-incr);
- stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
- }
- }
-
- calcdiags(len, incr, sk) /* Assign heights along diagonal in array. */
- int len;
- register int incr, sk;
- {
- register int y, x;
- int d1, d2;
-
- for (x=0; x < xmax; x += sk)
- for (y = incr; y <= xmax-x; y += sk) {
- d1 = getdata(x+y-incr, y-incr);
- d2 = getdata(x+y+incr, y+incr);
- stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x+y, y);
- }
- }
-
- getdata(x, y)
- register int x, y;
- {
- if (y <= ymax)
- return (*points)[x][y];
- else
- return (*points)[xmax-x][xmax+1-y];
- }
-
- stuffdata(d, x, y)
- register int d, x, y;
- {
- if (y <= ymax)
- (*points)[x][y] = d;
- else
- (*points)[xmax-x][xmax+1-y] = d;
- }
-
-
- /*
- ** Our window is already open at this point, and it is cleared,
- ** all we have to do now is fill it.
- ** Draw the 2D projection of the triangular database on the screen.
- */
-
- plotdata()
- {
- register int xindex, yindex;
-
- if (!points)
- return;
- color = TRUE; /* On land to start. */
-
- for (xindex=0; xindex<=xmax; xindex++) { /* Plot along X axis. */
- linestart = TRUE;
- for (yindex=0; yindex<=xindex; yindex++)
- doplot(xindex, yindex);
- }
- for (yindex=0; yindex<=xmax; yindex++) { /* Plot along Y axis. */
- linestart = TRUE;
- for (xindex=yindex; xindex<=xmax; xindex++)
- doplot(xindex, yindex);
- }
- for (xindex=0; xindex<=xmax; xindex++) { /* Plot along the diagonal. */
- linestart = TRUE;
- for (yindex=0; yindex<=xmax-xindex; yindex++)
- doplot(xindex+yindex, yindex);
- }
- }
-
- doplot(xindex, yindex)
- int xindex, yindex;
- {
- int xcoord, ycoord, zcoord;
- zcoord = getdata(xindex, yindex);
- ycoord = scaler(yindex, 10000, xmax);
- xcoord = scaler(xindex, 10000, xmax) - ycoord/2;
- if (conttype == SETUPWATR)
- sealevel(&xcoord, &ycoord, &zcoord);
- plotto(xcoord, ycoord, zcoord);
- }
-
- sealevel(newx, newy, newz)
- int *newx, *newy, *newz;
- {
- static int oldx, oldy, oldz; /* The starting point for the next call. */
- int waterx, watery, waterz; /* Where the vector hits the waterline. */
- float scratch;
-
- if (linestart) { /* If at the beginning of the line */
- if ((oldz = *newz) < 0) { /* and if we're underwater. */
- color = FALSE;
- *newz = 0; /* Clip to the waterline. */
- }
- else
- color = TRUE; /* Otherwise we're on land from the start. */
- }
- else { /* Else we're in the middle of a line and ... */
- if (oldz > 0 && *newz > 0) { /* start & end points both above water.. */
- oldz = *newz;
- }
- else if (oldz < 0 && *newz < 0) { /* start & end points both under water... */
- oldz = *newz;
- *newz = 0; /* Clip at the waterline */
- }
- else { /* We're now crossing the waterline, */
- /* so calculate the exact point where it dives under. */
- scratch = (float) (*newz)/(*newz-oldz); /* Proportion of the line that's */
- waterx = (int) ((oldx - *newx)*scratch) + *newx; /* below the water. */
- watery = (int) ((oldy - *newy)*scratch) + *newy;
- waterz = 0;
-
- plotto(waterx, watery, waterz); /* Draw to the waterline first. */
- /* The plot from the waterline to the endpoint in the new color
- is done elsewhere. */
- if (*newz > 0) { /* Emerging from the water. */
- color = TRUE; /* Set new color to 'land'. */
- oldz = *newz;
- }
- else { /* Diving into the water. */
- color = FALSE; /* Set new color to 'sea'. */
- oldz = *newz;
- *newz = 0;
- }
- }
- }
- oldx = *newx; /* Save the real endpoint of the vector */
- oldy = *newy; /* to use as the start of the next call. */
- /* (Z taken care of individually above). */
- }
-
- scaler(base, numer, denom) /* Computes base*numer/denom with long intermediate.
- */
- register int base, numer, denom;
- {
- register long temp;
- temp = (long) base * (long) numer;
- temp /= (long) denom;
- return (int) temp;
- }
-
- plotto(x, y, z) /* Convert 3-D line to a 2-D line and plot it. */
- int x, y, z;
- {
- rotate(&x, &y); /* Rotate 30 deg. towards Y in the XY plane */
- tiltdown(&x, &z); /* Tip 36 deg. down in the ZX plane */
- x /= 25; /* Scale 10K to 400. */
- y /= 25;
- z /= 25;
- drawline(y, z); /* Show the YZ planar projection. */
- }
-
- rotate(x, y) /* Rotate XY plane 30 deg positive. */
- int *x, *y;
- {
- cordic(x, y, 5, 17);
- }
-
- tiltdown(x, z) /* Rotate XZ plane 36 deg negative (+?). */
- int *x, *z;
- {
- cordic(x, z, 5, (conttype == SETUPMTN) ? 20 : -20);
- }
-
- drawline(x, y) /* Draw either a line from the last endpoint */
- int x, y; /* to the given point, or only a point at x,y. */
- {
- static int lastx, lasty;
- x += x/10 + 10; /* Quick x1.1 + tiny offset. */
- if (conttype == SETUPMTN)
- y = 220 - y; /* Move the baseline for mountains. */
- else
- y = 80 - y;
- if (linestart || !color) /* Only a point then. */
- MoveTo(x, y);
- LineTo(x, y);
- lastx = x;
- lasty = y;
- linestart = FALSE; /* Stuck in the middle with you... */
- }
-
- cordic(x, y, scale, count) /* Spin XY vector 'count' steps to the left using */
- int *x, *y; /* CORDIC algorithm with a shift factor of 'scale'. */
- register int scale, count; /* Rotates atan(1/(2^scale)) degrees/step. */
- /* (Scale of 5 is 1.79 deg/step; 4 = 3.57 d/s...) */
- /* *x & *y should be large for accuracy. */
- {
- register int tempx, tempy;
- tempx = *x;
- tempy = *y;
- if (count>0) /* Positive count is CCW (left) */
- for (; count; count--) {
- tempx -= (tempy>>scale);
- tempy += (tempx>>scale);
- }
- else /* Negative is CW (right) */
- for (; count; count++) {
- tempx += (tempy>>scale);
- tempy -= (tempx>>scale);
- }
- *x = tempx;
- *y = tempy;
- }
-
-