/* Experimental fractal landscape. 27.11.1991 VNP (SWAP inc.) (812)1001590 */ #include #include #include #include #include #include #include #include int pageno, maxx, maxy, xasp, yasp, gmode; void StartGraphics (void) { int gdriver = EGA, errorcode; /* initialize graphics mode */ pageno = 0; detectgraph (&gdriver, &gmode); if (gmode == VGAHI) gmode = VGAMED; initgraph(&gdriver, &gmode, ""); /* read result of initialization */ errorcode = graphresult(); if (errorcode != grOk) /* an error occurred */ { printf("Graphics error: %s\n", grapherrormsg(errorcode)); printf("Press any key to halt:"); getch(); exit (1); } maxx = getmaxx(); maxy = getmaxy(); getaspectratio (&xasp, &yasp); if (gdriver == HERCMONO) xasp = 6000; } void swappage (void) { setvisualpage (pageno); pageno = 1-pageno; setactivepage (pageno); } /********************************************************* * * * GenFractSurf generates fractal surface of given size * * * *********************************************************/ void GenFractSurf (int width, int length, int maxstep, int* _scape, int* zmin, int* zmax) /* Synopsis: width - number of cells from left to right; length - number of cells from front to background; maxstep - maximum height step across a cell; scape - width*length array to store the table; zmin - the table's minimal value; zmax - the table's maximal value. how we calculate: scape[i,j]=(scape[i-1,j]+scape[i,j-1])/2+(random(2*maxstep+2)-maxstep) */ { #define scape(i,j) *(_scape + (i) * length + (j)) int lat, lng, prev, number; int delta; *zmin = maxstep; *zmax = -maxstep; for (lat = 0; lat < width; lat++) for (lng = 0; lng < length; lng++) { prev = number = 0; if (lat > 0) { prev = scape(lat-1, lng); number++; } if (lng > 0) { prev += scape(lat, lng-1); number++; } if (number > 1) prev /= number; delta = random(2 * maxstep + 1) - maxstep; scape(lat, lng) = prev + delta; *zmin = min (*zmin, scape (lat, lng)); *zmax = max (*zmax, scape (lat, lng)); } #undef scape } /**************************************************************** * * * ProjectSurf project fractal surface onto background plane * * * ****************************************************************/ void ProjectSurf (int width, int length, int* _scape, int xstep, int ystep, float lambda, float fi, int *_xscape, int *_yscape, int *xmin, int *xmax, int *ymin, int *ymax) /* Synopsis: width - number of cells from left to right; length - number of cells from front to background; scape - width*length array containing tha table; xstep, ystep - scape's step sizes; lambda, fi - view rotation and altitude; xscape - X coords for scape projection; yscape - Y coords for scape projection; xmin, xmax - xscape's minimal and maximal values; ymin, ymax - yscape's minimal and maximal values. how we calculate: x' = x * cos(lambda) + y * sin(lambda); y' = -x * sin(lambda) + y * cos(lambda); z' = z; x" = x' * cos(fi) + z' * sin(fi); y" = y'; z" = -x' * sin(fi) + z' * cos(fi); xp = -y"; yp = z"; */ { #define scape(i,j) *( _scape + (i) * length + (j)) #define xscape(i,j) *(_xscape + (i) * length + (j)) #define yscape(i,j) *(_yscape + (i) * length + (j)) int lat, lng, x, y, z; float rlam = M_PI/180*lambda; float rfi = M_PI/180*fi; float cosl = cos(rlam); float sinl = sin(rlam); float cosf = cos(rfi); float sinf = sin(rfi); *xmin = *ymin = MAXINT; *xmax = *ymax = 1 - MAXINT; for (lat = 0; lat < width; lat++) for (lng = 0; lng < length; lng++) { x = lat * xstep - width * xstep / 2; y = lng * ystep - length * ystep / 2; z = scape(lat, lng); xscape (lat, lng) = x * sinl - y * cosl; yscape (lat, lng) = -(x * cosl + y * sinl) * sinf + z * cosf; *xmin = min (*xmin, xscape (lat, lng)); *xmax = max (*xmax, xscape (lat, lng)); *ymin = min (*ymin, yscape (lat, lng)); *ymax = max (*ymax, yscape (lat, lng)); } #undef scape #undef xscape #undef yscape } /************************************************** * * * DrawSurf draws a skeleton of fractal surface * * * **************************************************/ void DrawSurf (int width, int length, int *_xscape, int *_yscape, float x0, float x1, float y0, float y1) /* Synopsis: width - number of cells from left to right; length - number of cells from front to background; xscape - X coords for scape projection; yscape - Y coords for scape projection; x0, x1 - x to screen conversion coeffs; y0, y1 - y to screen conversion coeffs. */ { #define xscape(i,j) *(_xscape + (i) * length + (j)) #define yscape(i,j) *(_yscape + (i) * length + (j)) int lat, lng; cleardevice(); for (lat = 0; lat < width; lat++) { moveto (x0 + x1 * xscape (lat, 0), y0 + y1 * yscape (lat, 0)); for (lng = 1; lng < length; lng++) { lineto (x0 + x1 * xscape (lat, lng), y0 + y1 * yscape (lat, lng)); } } for (lng = 0; lng < length; lng++) { moveto (x0 + x1 * xscape (0, lng), y0 + y1 * yscape (0, lng)); for (lat = 1; lat < width; lat++) { lineto (x0 + x1 * xscape (lat, lng), y0 + y1 * yscape (lat, lng)); } } #undef scape #undef xscape #undef yscape } void main (void) { int scape[5000], xscape[5000], yscape[5000]; int wid = 20, len = 20, xs = 10, ys = 10; int z0, z1; float x0, x1, y0, y1; int xma, xmi, yma, ymi; int key; float fi = 0, lam = 0; char buf[81]; FILE* file; int scrmaxx; int scrmaxy; clrscr(); cputs ("\r\n\n\n\n\n\n\n\n\n\n\n" " Fractal surface demo. VNP 27.11.91.\n"); GenFractSurf (len, wid, 30, scape, &z0, &z1); StartGraphics(); scrmaxx = getmaxx(); scrmaxy = getmaxy(); xmi = min (z0, min (-len * xs/2, -wid * ys/2)); xma = max (z1, max ( len * xs/2, wid * ys/2)); x1 = (float)scrmaxx / (xma - xmi); x0 = -x1 * xmi; y1 = (float)scrmaxy / (xma - xmi); y0 = -y1 * xmi; while (1) { ProjectSurf (len, wid, scape, xs, ys, lam, fi, xscape, yscape, &xmi, &xma, &ymi, &yma); DrawSurf (len, wid, xscape, yscape, x0, x1, y0, y1); if ((key = getch()) == 0x1b) break; if (!key) { key = getch(); switch (key) { case 80: /* dn */ fi += 5; break; case 72: /* up */ fi -= 5; break; case 77: /* rt */ lam += 10; break; case 75: /* lt */ lam -= 10; break; } } } closegraph(); }