home *** CD-ROM | disk | FTP | other *** search
- 10 ' Fracscapes
- 20 ' or
- 30 ' 3-D Fractal landscapes
- 40 '
- 50 ' by Michiel van de Panne
- 60 ' From the july issue of Creative Computing (R.I.P.)
- 70 '
- 80 ' hacked unmercifully and
- 90 ' modified for the Amiga from
- 100 ' the Mac version by
- 110 ' David Milligan, 70707,2521
- 120 ' and Ted Ingalls
- 130 ' 10-19-85
- 140 '
- 150 ' ** This program will construct a realistic
- 160 ' ** 3-D landscape fractal from many random numbers
- 170 ' ** in up to seven levels of detail, simulating
- 180 ' ** mountain ranges, coastlines, sea floor and/or
- 190 ' ** surfaces, lakes, islands, etc.
- 200 ' ** Once the array used to do the drawing is created,
- 210 ' ** it can be saved to disk and reloaded and re-drawn.
- 220 ' ** We saved the array rather than the screen because
- 230 ' ** (1) we couldn't figure out how to find the start
- 240 ' ** of screen memory from ABasiC and couldn't get
- 250 ' ** a 640x200 screen stuffed into an array, and
- 260 ' ** (2) the array can be re-drawn with different scaling
- 270 ' ** factors for perspective changes and with sea level on
- 280 ' ** or off (default is off).
- 290 ' ** The length of time required to draw an array depends
- 300 ' ** on the number of levels selected. For each increase
- 310 ' ** in level the number of triangular subdivisions
- 320 ' ** is quadrupled. A level 7 landscape has the highest
- 330 ' ** 'resolution', but takes over an hour to draw.
- 340 '
- 350 ' ** One of the main things we added to the original
- 360 ' ** program was color. The 12 colors are selected
- 370 ' ** by what we determined was altitude to render
- 380 ' ** forests, water, snow, dirt, etc.
- 390 ' ** Considering we understand vitually nothing
- 400 ' ** of the math involved, it works pretty well.
- 410 ' ** If you've got a better idea, have at it.
- 420 ' ** This program is definately NOT polished,
- 430 ' ** optimized or bug free, but it is fun to
- 440 ' ** play with.
- 450 ' ** While I don't understand them, I find fractal
- 460 ' ** graphics generation fascinating. If you've
- 470 ' ** got a nifty fractal program, upload it here
- 480 ' ** or sing out via E-mail.
- 490 '
- 500 ' David Milligan, 70707,2521
- 510 '
- 520 scnclr
- 530 '
- 540 rem *** Set Screen to 640 x 200 ***
- 550 '
- 560 ask window wid%,hi%
- 570 if wid%<600 then screen 1,4,0
- 580 '
- 590 ' *** Program Initialization ***
- 600 '
- 610 dim d(128,65),name$(40):a%=varptr(d(0,0)):l%=33280:le=0
- 620 gosub 4450:gosub 690:gosub 770:gosub 3300:goto 2760
- 630 '
- 640 rem *** Trap Mouse Button ***
- 650 '
- 660 ask mouse x%,y%,b%:if b%=0 then 660
- 670 return
- 680 '
- 690 rem *** Turn Off Cursor ***
- 700 '
- 710 rgb 15,0,0,0:return
- 720 '
- 730 rem *** Turn Cursor on ***
- 740 '
- 750 rgb 15,11,11,11:return
- 760 '
- 770 rem *** Set Program Colours ***
- 780 '
- 790 rgb 0,0,0,0
- 800 rgb 1,15,15,15
- 810 rgb 3,8,8,8:' light grey
- 820 rgb 4,5,5,5:' dark grey
- 830 rgb 5,7,4,3:' light brown
- 840 rgb 6,6,3,2:' dark brown
- 850 rgb 7,0,4,0:' medium green
- 860 rgb 8,0,0,12:' light blue
- 870 rgb 9,0,0,10:' blue
- 880 rgb 10,0,0,7:' medium blue
- 890 rgb 11,0,0,4:' dark blue
- 900 rgb 12,0,6,0:' green
- 910 rgb 13,0,7,0:' light green
- 920 rgb 14,0,2,0 :' dark green
- 930 return
- 940 '
- 950 ' *** Calculate array data and insert ***
- 960 '
- 970 print at (8,3);"Working on Level "
- 980 ds=2:for n=1 to le:ds=ds+2^(n-1):next n
- 990 mx=ds-1:my=mx/2:rh=pi*30/180:vt=rh*1.2
- 1000 for n=1 to le:l=10000/1.8^n
- 1010 print at (26,3);n
- 1020 ib=mx/2^n:sk=ib*2
- 1030 randomize -1
- 1040 gosub 1120:rem Assign heights along x in array
- 1050 gosub 1210:rem *** Assign heights along Y ***
- 1060 gosub 1300:rem *** Assign heights along Z ***
- 1070 next n
- 1080 scnclr:goto 2680
- 1090 '
- 1100 ' *** Heights along X ***
- 1110 '
- 1120 for ye=0 to mx-1 step sk
- 1130 for xe=ib+ye to mx step sk
- 1140 ax=xe-ib:ay=ye:gosub 1400:d1=d:ax=xe+ib:gosub 1400:d2=d
- 1150 d=(d1+d2)/2+rnd(1)*l/2-l/4:ax=xe:ay=ye:gosub 1470
- 1160 next xe
- 1170 next ye:return
- 1180 '
- 1190 rem *** Heights along Y ***
- 1200 '
- 1210 for xe=mx to 1 step -sk
- 1220 for ye=ib to xe step sk
- 1230 ax=xe:ay=ye+ib:gosub 1400:d1=d:ay=ye-ib:gosub 1400:d2=d
- 1240 d=(d1+d2)/2+rnd(1)*l/2-l/4:ax=xe:ay=ye:gosub 1470
- 1250 next ye
- 1260 next xe:return
- 1270 '
- 1280 rem *** Heights along Z ***
- 1290 '
- 1300 for xe=0 to mx-1 step sk
- 1310 for ye=ib to mx-xe step sk
- 1320 ax=xe+ye-ib:ay=ye-ib:gosub 1400:d1=d
- 1330 ax=xe+ye+ib:ay=ye+ib:gosub 1400:d2=d
- 1340 ax=xe+ye:ay=ye:d=(d1+d2)/2+rnd(1)*l/2-l/4:gosub 1470
- 1350 next ye
- 1360 next xe:return
- 1370 '
- 1380 rem *** Return data from array ***
- 1390 '
- 1400 if ay>my then 1420
- 1410 by=ay:bx=ax:goto 1430
- 1420 by=mx+1-ay:bx=mx-ax
- 1430 d=d(bx,by):return
- 1440 '
- 1450 rem *** Put data into array ***
- 1460 '
- 1470 if ay>my then 1490
- 1480 by=ay:bx=ax:goto 1500
- 1490 by=mx+1-ay:bx=mx-ax
- 1500 d(bx,by)=d:return
- 1510 '
- 1520 rem *** Sea level section ***
- 1530 '
- 1540 if sealevel=0 then gosub 1750:return
- 1550 if xo<>-999 then 1580
- 1560 if zz<0 then gosub 2010:z2=zz:zz=0:goto 1740
- 1570 gosub 2050:goto 1730
- 1580 if z2>0 and zz>0 then gosub 1750:goto 1730
- 1590 if z2<0 and zz<0 then z2=zz:zz=0:goto 1740
- 1600 w3=zz/(zz-z2):x3=(x2-xx)*w3+xx:y3=(y2-yy)*w3+yy:z3=0
- 1610 zt=zz:yt=yy:xt=xx
- 1620 if zz>0 then 1710
- 1630 '
- 1640 rem *** Going into water ***
- 1650 '
- 1660 zz=z3:yy=y3:xx=x3:gosub 2320
- 1670 gosub 2010:zz=0:yy=yt:xx=xt:z2=zt:goto 1740
- 1680 '
- 1690 rem *** Coming out of water ***
- 1700 '
- 1710 zz=z3:yy=y3:xx=x3:gosub 2320
- 1720 gosub 2050:zz=zt:yy=yt:xx=xt
- 1730 z2=zz
- 1740 x2=xx:y2=yy:return
- 1750 '
- 1760 ' *** New Color Subroutine ***
- 1770 '
- 1780 if zz<0 then goto 1890
- 1790 if zz>950 then pena 2:return
- 1800 if zz>850 then pena 3:return
- 1810 if zz>750 then pena 4:return
- 1820 if zz>650 then pena 5:return
- 1830 if zz>550 then pena 6:return
- 1840 if zz>450 then pena 13:return
- 1850 if zz>350 then pena 12:return
- 1860 if zz>100 then pena 7:return
- 1870 gosub 2050
- 1880 return
- 1890 '
- 1900 ' *** below sea level ***
- 1910 '
- 1920 if zz>-200 then gosub 2010:return
- 1930 if zz>-500 then pena 9:return
- 1940 if zz>-800 then pena 10:return
- 1950 if zz>-1200 then pena 11:return
- 1960 pena 11
- 1970 return
- 1980 '
- 1990 rem *** Switch to sea level color ***
- 2000 '
- 2010 pena 8:f1=1:return
- 2020 '
- 2030 rem *** Switch to land color ***
- 2040 '
- 2050 pena 14
- 2060 f1=0:return
- 2070 '
- 2080 ' *** Rotation ***
- 2090 '
- 2100 if xx<>0 then 2130
- 2110 if yy<=0 then ra=-pi/2:goto 2150
- 2120 ra=pi/2:goto 2150
- 2130 ra=atn(yy/xx)
- 2140 if xx<0 then ra=ra+pi
- 2150 r1=ra+rh:rd=sqr(xx*xx+yy*yy)
- 2160 xx=rd*cos(r1):yy=rd*sin(r1)
- 2170 return
- 2180 '
- 2190 rem *** Tilt down ***
- 2200 '
- 2210 rd=sqr(zz*zz+xx*xx)
- 2220 if xx=0 then ra=pi/2:goto 2250
- 2230 ra=atn(zz/xx)
- 2240 if xx<0 then ra=ra+pi
- 2250 r1=ra-vt
- 2260 xx=rd*cos(r1)+xx:zz=rd*sin(r1)
- 2270 return
- 2280 '
- 2290 rem *** Plot to (xp,yp) ***
- 2300 '
- 2310 gosub 1540
- 2320 xx=xx*xs:yy=yy*ys:zz=zz*zs
- 2330 gosub 2100:rem *** Rotate ***
- 2340 gosub 2210:rem *** Tilt up ***
- 2350 if xo=-999 then pr$="M" else pr$="D"
- 2360 xp=int(yy)+cx:yp=int(zz)
- 2370 gosub 2400
- 2380 return
- 2390 '
- 2400 rem *** do plotting here ***
- 2410 '
- 2420 ask mouse x%,y%,b%:if b%<>0 then 2760
- 2430 xp=xp*1.38:yp=48.53-0.663*yp:if pr$="M" then x8=xp:y8=yp
- 2440 draw (x8,y8 to xp,yp):x8=xp:y8=yp:xo=xp
- 2450 return
- 2460 '
- 2470 rem *** Plot X Axis ***
- 2480 '
- 2490 for ax=0 to mx:xo=-999:for ay=0 to ax
- 2500 gosub 1400:zz=d:yy=ay/mx*10000:xx=ax/mx*10000-yy/2
- 2510 gosub 2310:next ay:next ax
- 2520 return
- 2530 '
- 2540 rem *** Plot Y Axis ***
- 2550 '
- 2560 for ay=0 to mx:xo=-999:for ax=ay to mx
- 2570 gosub 1400:zz=d:yy=ay/mx*10000:xx=ax/mx*10000-yy/2
- 2580 gosub 2310:next ax:next ay
- 2590 return
- 2600 '
- 2610 rem *** Plot Z Axis ***
- 2620 '
- 2630 for ex=0 to mx:xo=-999:for ey=0 to mx-ex
- 2640 ax=ex+ey:ay=ey:gosub 1400:zz=d:yy=ay/mx*10000
- 2650 xx=ax/mx*10000-yy/2:gosub 2310:next ey:next ex
- 2660 return
- 2670 '
- 2680 ' *** Setup Screen ***
- 2690 '
- 2700 close 2:cmd 1:graphic(1):gosub 760
- 2710 tax=ax:tay=ay
- 2720 gosub 2630
- 2730 gosub 2560
- 2740 gosub 2490
- 2750 '
- 2760 rem *** Main Menu Section ***
- 2770 '
- 2780 gosub 3370
- 2790 print at(4,2);"-> Use Keyboard to Select <-"
- 2800 print at(6,4);"1 - Start New Landscape"
- 2810 ? at(6,5);"2 - Draw Existing Array"
- 2820 ? at(6,6);"3 - Save Fractal Array"
- 2830 ? at(6,7);"4 - Load Fractal Array"
- 2840 ? at(6,8);"5 - Reset Scaling Factors"
- 2850 ? at(6,9);"6 - Set Sea Level Options"
- 2860 rem ? at(6,10);"7 - Read & Display Mouse x,y"
- 2870 ? at(6,11);"7 - Close This Window !"
- 2880 ? at(10,12);"Click the Left Button"
- 2890 ? at(10,13);"To Restore Menu"
- 2900 ? at(6,14);"0 - Exit to ABasiC"
- 2910 pena 0:gosub 4500
- 2920 print at(10,16);"Selection (0-8) ";:input a$
- 2930 query=val(a$):print at(10,16);spc(20):erase a$
- 2940 on query goto 3120,4140,3650,3760,4240,4010,4000,4000,4000
- 2950 '
- 2960 rem *** Program exit ***
- 2970 '
- 2980 scnclr:close 3
- 2990 cmd 1:scnclr:close 1
- 3000 cmd 0:pena 0
- 3010 '
- 3020 rem *** Restore ABasiC's colours ***
- 3030 '
- 3040 rgb 0,6,9,15
- 3050 rgb 1,0,0,0
- 3060 rgb 2,15,15,15
- 3070 gosub 750
- 3080 clr:end
- 3090 '
- 3100 rem *** Start a new fractal screen ***
- 3110 '
- 3120 scnclr:close 3
- 3130 '
- 3140 rem *** New landscape ***
- 3150 '
- 3160 cmd 1:graphic(1):scnclr
- 3170 gosub 3330
- 3180 '
- 3190 rem *** Prompt to begin drawing ***
- 3200 '
- 3210 print at(2,2);"Click the Left Mouse Button to Start."
- 3220 print at(4,4);"Click While Drawing to Abort."
- 3230 gosub 660:scnclr
- 3240 print at(8,3);"Number of levels ";:input le
- 3250 scnclr:if le<1 or le>7 then 3240
- 3260 goto 950
- 3270 '
- 3280 rem *** Windows ***
- 3290 '
- 3300 window #1,0,0,639,199,"Fracscapes"
- 3310 return
- 3320 '
- 3330 window #2,120,50,340,60,"New Fracscape"
- 3340 cmd #2:graphic(0):scnclr
- 3350 return
- 3360 '
- 3370 window #3,100,20,300,160,"Main Menu"
- 3380 cmd 3:graphic(0):scnclr
- 3390 return
- 3400 '
- 3410 window #4,100,50,400,40,"Save Array"
- 3420 cmd 4:graphic(0):scnclr
- 3430 return
- 3440 '
- 3450 window #5,100,100,400,40,"Load Array"
- 3460 cmd 5:graphic(0):scnclr
- 3470 return
- 3480 '
- 3490 window #6,100,20,340,130,"Array Description"
- 3500 cmd 6:graphic(0):scnclr
- 3510 return
- 3520 '
- 3530 window #7,100,30,340,60,"Sea Level Options"
- 3540 cmd 7:graphic(0):scnclr
- 3550 return
- 3560 '
- 3570 window #8,50,20,340,50,"Draw Array in Memory"
- 3580 cmd 8:graphic(0)
- 3590 return
- 3600 '
- 3610 window #9,150,30,300,130,"Scaling Settings"
- 3620 cmd 9:graphic(0)
- 3630 return
- 3640 '
- 3650 rem *** screen save ***
- 3660 '
- 3670 on error goto 4540
- 3680 gosub 3410:name$=""
- 3690 print at(2,2);"Save Array as -> ";:line input name$
- 3700 d(0,65)=le:d(1,65)=mx:d(2,65)=my:d(3,65)=tax:d(4,65)=tay
- 3710 d(5,65)=xs:d(6,65)=ys:d(7,65)=zs:d(8,65)=sealevel
- 3720 bsave name$,a%,l%
- 3730 scnclr:close 4:cmd 3
- 3740 goto 4110
- 3750 '
- 3760 rem *** Screen Load ***
- 3770 '
- 3780 ' on error goto 5000
- 3790 gosub 3450:name$=""
- 3800 print at(2,2);"Name of Array to Load -> ";:line input name$
- 3810 bload name$,a%
- 3820 le=d(0,65):mx=d(1,65):my=d(2,65):ax=d(3,65):ay=d(4,65)
- 3830 xs=d(5,65):ys=d(6,65):zs=d(7,65):sealevel=d(8,65)
- 3840 scnclr:close 5
- 3850 gosub 3490
- 3860 ? at(7,2);"Array name -> ";name$
- 3870 ? at(7,4);"Number of Levels -> ";le
- 3880 if sealevel=0 then level$="off" else level$="on"
- 3890 ? at(7,6);"Sea Level Display -> ";level$
- 3900 ? at(7,8);"Scaling Values -> X= ";xs
- 3910 ? at(26,9);"Y= ";ys
- 3920 ? at(26,10);"Z= ";zs
- 3930 ? at(5,13);"Click left button to continue"
- 3940 gosub 640
- 3950 scnclr:close #6:cmd 3
- 3960 goto 4110
- 3970 '
- 3980 rem *** Turn off menu window ***
- 3990 '
- 4000 scnclr:close 3:gosub 660:goto 2760
- 4010 '
- 4020 ' **** Set Sea Level Option ****
- 4030 '
- 4040 gosub 3530
- 4050 print at (2,3);"Display sea level surface (Y/N) ";:input a$
- 4060 if a$="y" or a$="Y" then sealevel=1 else sealevel=0:goto 4070
- 4070 scnclr:close 7:cmd 3
- 4080 '
- 4090 ' *** Error Trap ***
- 4100 '
- 4110 on error goto 4540
- 4120 query=0:erase a$
- 4130 goto 2920
- 4140 '
- 4150 ' *** Redraw old Array ***
- 4160 '
- 4170 if le=0 then 2920
- 4180 gosub 3570
- 4190 print at(2,2);"Clear Screen Before Re-Draw (Y/N) ";:input a$
- 4200 scnclr:close 8:cmd 3:scnclr:close 3:cmd 1:graphic(1)
- 4210 if a$="y" or a$="Y" then scnclr
- 4220 erase a$:goto 2700
- 4230 '
- 4240 ' *** Scaling Settings ***
- 4250 '
- 4260 gosub 3610
- 4270 graphic(0)
- 4280 print at(5,2);"Current Scaling Settings :"
- 4290 print at(13,4);"X= ";xs
- 4300 print at(13,5);"Y= ";ys
- 4310 print at(13,6);"Z= ";zs
- 4320 print at(5,8);"Press C to Change Settings"
- 4330 print at(11,9);"D for Default Settings"
- 4340 print at(11,10);"X to Exit"
- 4350 gosub 4500
- 4360 print at(13,12);"Selection ";:input a$
- 4370 if a$="c" or a$="C" then 4420
- 4380 if a$="d" or a$="D" then gosub 4460:goto 4410
- 4390 if a$<>"x" and a$<>"X" then 4410
- 4400 scnclr:close 9:cmd 3:goto 4110
- 4410 scnclr:erase a$:goto 4280
- 4420 print at(13,12);spc(16)
- 4430 print at(4,12);"Input New X,Y,Z ";:input xs,ys,zs
- 4440 goto 4410
- 4450 '
- 4460 ' *** Stock Scaling Factors ***
- 4470 '
- 4480 xs=.04:ys=.04:zs=.05:return
- 4490 '
- 4500 for i=0 to 10
- 4510 get a$:erase a$:next i
- 4520 on error goto 4540
- 4530 return
- 4540 '
- 4550 '
- 4560 ' **** error trap ****
- 4570 '
- 4580 '
- 4590 fmem%=fre
- 4600 window #10,100,100,300,90,"Rats - An Error Occurred"
- 4610 cmd #10:graphic(0):scnclr
- 4620 ?at(2,2);"Error # ";err;" occurred at line ";erl
- 4630 ?at(2,4);err$(err)
- 4640 ?at(2,5);"There are ";fmem%;" bytes of memory showing"
- 4650 ?at(2,7);"Click left button to continue...."
- 4660 gosub 640
- 4670 scnclr:close 10,3,4,5,6
- 4680 goto 2760
-