fb:porticula NoPaste
Versuch eines Landschaftsgenerators
Uploader: | Muttonhead |
Datum/Zeit: | 08.03.2009 21:29:42 |
/'
die Darstellungsgrösse/-auflösung: resx,resy
Kamerablickrichtung wird durch das geodätische Horizontsystem definiert
Azimut(a,tmpa) 0=360 Nord
90 Ost
180 Süd
270 West
Höhe(h,tmph) 0 waagerecht (Horizont)
+90 senkrecht nach oben (Zenit)
-90 senkrecht nach unten (Nadir)
die Vektoren(vx,vy,vz) ergeben sich dann aus Azimut und Höhe
vz=sin(2*pi/360*h)
vx=sin(2*pi/360*a)*cos(2*pi/360*h)
vy=cos(2*pi/360*a)*cos(2*pi/360*h)
aktuelle Position des Strahls im Raum: rayposx,rayposy,rayposz
die Kameraposition: cx,cy,cz
der Öffnungswinkel (waagerecht) der Kamera (empfohlen 60-90 grd): cwx
der Öffnungswinkel (senkrecht) der Kamera (in Abhängigkeit von Öffnungswinkel und Auflösung): cwy
Winkelschrittweite in Abhängigkeit von Öffnungswinkel und Auflösung: astp,hstp
Strahlenlänge (eine Abbruchbedingung): rayl
maximale Strahlenlänge: maxrayl
Wasserspiegel: waterlevel
zum Höhenarray:
Grösse :xmin,xmax,ymin,ymax
vertikale Auflösung: bumplevel
Höhenarray: heightfield()
farbarray: colorfield()
Lage des Höhenarrays im Raum: fieldposx,fieldposy,fieldposz
damit lässt sich eine bestimmt Landschaft immer wieder generieren
Saatnummer: seed
'/
declare sub calcbump (xmin as integer ,xmax as integer ,ymin as integer ,ymax as integer,entry as integer)
const as double pi=3.1415926535897932
dim as single a,h,tmpa,tmph,vx,vy,vz,rayposx,rayposy,rayposz,astp,hstp
dim as integer resx,resy,cx,cy,cz,cwx,cwy,rayl,waterlevel,maxrayl,seed
'Auflösung
resx=800
resy=600
'Öffnungswinkel
cwx=60
cwy=cwx * (resy/resx)
'Winkelschrittweite für Azimut und Höhe
'im Bezug zum Öffnungswinkel und der Auflösung
astp=cwx/resx
hstp=cwy/resy
'Kameraposition
cx=300 'px nach ost
cy=-400'px nach süd
cz=300 'px nach oben
'Azimut u. Höhe (Blickrichtung der Kamera)
a=322 'nördlich(leicht westl.)
h=-20 'schräg nach unten
'maximale Strahlenlänge festlegen
'Abbruchbedingung!!!
maxrayl=1500
'Wasserstand
waterlevel=128
'Grösse(Höhe) und Lage des Höhenarrays festlegen
dim as integer xmin,xmax,ymin,ymax,fieldposx,fieldposy,fieldposz
dim shared as integer bumplevel
xmin=0
ymin=0
xmax=800
ymax=800
bumplevel=256
fieldposx=(xmax-xmin)\2*-1
fieldposy=(ymax-ymin)\2*-1
fieldposz=0
dim shared as integer heightfield(xmin to xmax , ymin to ymax)
dim shared as integer colorfield(xmin to xmax , ymin to ymax)
screen 20,32
'erzeugen der Höhenwerte
seed=1470
randomize seed
calcbump (xmin,xmax,ymin,ymax,1)
dim as integer i,k,actposx,actposy,col,exitloop
for k=0 to resy-1
for i=0 to resx-1
'momentanes Azimut und Höhe
tmpa=a-(cwx\2) + i*astp
tmph=h+(cwy\2) - k*hstp
'Vektoren daraus ermitteln
vz=sin(2*pi/360*tmph)
vx=sin(2*pi/360*tmpa)*cos(2*pi/360*tmph)
vy=cos(2*pi/360*tmpa)*cos(2*pi/360*tmph)
'Ausgangsposition des Strahls ist die der Kamera
rayposx=cx
rayposy=cy
rayposz=cz
'Beginn der Strahlenverfolgung
exitloop=0
do
'Vektoren drauf addieren
rayposx +=vx
rayposy +=vy
rayposz +=vz
'nur action wenn Strahl sich überm Höhenarray befindet
if cint(rayposx)>=fieldposx and cint(rayposx)<fieldposx+xmax and _
cint(rayposy)>=fieldposy and cint(rayposy)<fieldposy+ymax then
actposx=cint(rayposx)-fieldposx
actposy=cint(rayposy)-fieldposy
if cint(rayposz)>waterlevel and cint(rayposz)<=heightfield(actposx,actposy) then
col=rgb(heightfield(actposx,actposy),heightfield(actposx,actposy),heightfield(actposx,actposy))
pset (i,k),col
exitloop=1
end if
end if
'Strahlenlänge für Abbruch ermitteln
rayl=sqr(rayposx*rayposx +rayposy*rayposy +rayposz*rayposz)
if rayl>=maxrayl then
if rayposz<= waterlevel then pset (i,k),&H3344AA else pset (i,k),&H33AAFF
exitloop=1
end if
loop until exitloop
next i
next k
beep
sleep
end
'füllt ein Array rekursiv mit Höhenwerte!!!!
sub calcbump (xmin as integer ,xmax as integer ,ymin as integer ,ymax as integer,entry as integer)
static as integer xfullrange,yfullrange
dim as integer i,k,xrange,yrange,randomvalue
dim as integer north,west,south,east,xmid,ymid,middle
xrange=xmax-xmin
yrange=ymax-ymin
if entry=1 then
for k=ymin to ymax
for i=xmin to xmax
heightfield(i,k)=-1
next i
next k
heightfield(xmin,ymin)=rnd*bumplevel
heightfield(xmin,ymax)=rnd*bumplevel
heightfield(xmax,ymax)=rnd*bumplevel
heightfield(xmax,ymin)=rnd*bumplevel
xfullrange=xmax-xmin
yfullrange=ymax-ymin
end if
if xrange>1 and yrange>1 then 'normales Befuellen des Arrays mit 4*Seite und 1*Mitte
randomvalue=xrange / xfullrange * rnd * bumplevel
north=(heightfield(xmin,ymax)+heightfield(xmax,ymax))/2 + (sgn(rnd-.5)*randomvalue)
if north>=bumplevel then north=bumplevel-1
if north<0 then north=0
randomvalue=xrange / xfullrange * rnd * bumplevel
south=(heightfield(xmin,ymin)+heightfield(xmax,ymin))/2 + (sgn(rnd-.5)*randomvalue)
if south>=bumplevel then south=bumplevel-1
if south<0 then south=0
randomvalue=yrange / yfullrange * rnd * bumplevel
west=(heightfield(xmin,ymin)+heightfield(xmin,ymax))/2 + (sgn(rnd-.5)*randomvalue)
if west>=bumplevel then west=bumplevel-1
if west<0 then west=0
randomvalue=yrange / yfullrange * rnd * bumplevel
east=(heightfield(xmax,ymin)+heightfield(xmax,ymax))/2 + (sgn(rnd-.5)*randomvalue)
if east>=bumplevel then east=bumplevel-1
if east<0 then east=0
xmid=xmin+(xrange\2)
ymid=ymin+(yrange\2)
if heightfield(xmid,ymax)=-1 then heightfield(xmid,ymax)=north
if heightfield(xmid,ymin)=-1 then heightfield(xmid,ymin)=south
if heightfield(xmin,ymid)=-1 then heightfield(xmin,ymid)=west
if heightfield(xmax,ymid)=-1 then heightfield(xmax,ymid)=east
'heightfield(xmid,ymax)=north
'heightfield(xmid,ymin)=south
'heightfield(xmin,ymid)=west
'heightfield(xmax,ymid)=east
randomvalue=(xrange+yrange)/2 / (xfullrange+yfullrange)/2 * rnd * bumplevel
middle=(heightfield(xmid,ymax) + heightfield(xmid,ymin) + heightfield(xmin,ymid) + heightfield(xmax,ymid))/4 + (sgn(rnd-.5)*randomvalue)
if middle>=bumplevel then middle=bumplevel-1
if middle<0 then middle=0
heightfield(xmid,ymid)=middle
calcbump(xmin,xmid,ymin,ymid,0)'south-west
calcbump(xmid,xmax,ymin,ymid,0)'south-east
calcbump(xmid,xmax,ymid,ymax,0)'north-east
calcbump(xmin,xmid,ymid,ymax,0)'north-west
end if
if xrange>1 and yrange<2 then' nur noch Befüllen in west-east Richtung möglich
randomvalue=xrange / xfullrange * rnd * bumplevel
north=(heightfield(xmin,ymax)+heightfield(xmax,ymax))/2 + (sgn(rnd-.5)*randomvalue)
if north>=bumplevel then north=bumplevel-1
if north<0 then north=0
randomvalue=xrange / xfullrange * rnd * bumplevel
south=(heightfield(xmin,ymin)+heightfield(xmax,ymin))/2 + (sgn(rnd-.5)*randomvalue)
if south>=bumplevel then south=bumplevel-1
if south<0 then south=0
xmid=xmin+(xrange\2)
if heightfield(xmid,ymax)=-1 then heightfield(xmid,ymax)=north
if heightfield(xmid,ymin)=-1 then heightfield(xmid,ymin)=south
calcbump(xmin,xmid,ymin,ymax,0)'west
calcbump(xmid,xmax,ymin,ymax,0)'east
end if
if yrange>1 and xrange<2 then' nur noch Befüllen in north-south Richtung möglich
randomvalue=yrange / yfullrange * rnd * bumplevel
west=(heightfield(xmin,ymin)+heightfield(xmin,ymax))/2 + (sgn(rnd-.5)*randomvalue)
if west>=bumplevel then west=bumplevel-1
if west<0 then west=0
randomvalue=yrange / yfullrange * rnd * bumplevel
east=(heightfield(xmax,ymin)+heightfield(xmax,ymax))/2 + (sgn(rnd-.5)*randomvalue)
if east>=bumplevel then east=bumplevel-1
if east<0 then east=0
ymid=ymin+(yrange\2)
if heightfield(xmin,ymid)=-1 then heightfield(xmin,ymid)=west
if heightfield(xmax,ymid)=-1 then heightfield(xmax,ymid)=east
calcbump(xmin,xmax,ymin,ymid,0)'south
calcbump(xmin,xmax,ymid,ymax,0)'north
end if
end sub