3D Landscapes - a closer look
Hi Michael,
Great looking demo.
I've been playing around with 3D projections, and thought
a couple of bits might interest you.
When viewing objects a bit closer, introducing perspective gives a
good effect. The severity of the effect is regulated by the distance
between the view point and the projection plane ( integer d, in this
instance ).
The perspective looks OK, but it still needs a hidden line checking
routine. Try playing around with the 'd' variable.
I wrote a simple landscape generator to demonstrate it. I don't understand
all that fractal stuff, it just picks a bunch of random numbers.
BTW: To slightly reduce your polygon drawing overhead, you could call the
machine_proc() directly (see graphics.e), but obviously you really want
an asm routine that draws lists of triangles to a vscreen.
Hope this helps.
Graeme.
--- snip ---
-- 3D perspective demo. G.Burke 2/97
include get.e
include graphics.e
include machine.e
constant p2= 3.141592653589/2
sequence map,sine,cosine,ang,points,os,pal
integer d,k,zsize,size,s2,z2,zoom
size=power(2,7)+1
s2=floor(size/2)
os={512,200} -- screen offset for origin
zoom=4 -- simple dimension multiplier
ang={.001,0.7,3.2} -- initail angles in radians
d=80 -- "perspective factor" (dist vp->pp)
zsize=25 -- mountain height
z2=floor(zsize/2)
procedure border_color(integer color)
sequence regs
regs=repeat(0,10)
regs[REG_AX]=#0B00
regs[REG_BX]=color
regs=dos_interrupt(#10,regs)
end procedure
if graphics_mode(261) then
end if
-- INSERT YOUR FAVOURITE LANDSCAPE PALETTE HERE
-- pal=
-- all_palette(pal)
border_color(0)
function num()
return (rand(2000)-1000)/1000
end function
procedure genmap()
sequence temp,r
position(1,1)
puts(1,"Generating map ")
r={}
for y=1 to 16 do
temp={}
for x=1 to 16 do
temp=temp&num()*zsize
end for
r=append(r,temp)
end for
map=r
for l= 1 to 4 do
r={}
for y=1 to length(map) do
temp={}
for x=1 to length(map[1])-1 do
temp=temp&map[y][x]&(map[y][x]+map[y][x+1])/2+num()
end for
r=append(r,temp&map[y][length(map[1])])
end for
map=r r={}
for y=1 to length(map)-1 do
temp={}
for x=1 to length(map[1]) do
temp=temp&(map[y][x]+map[y+1][x])/2+num()
end for
r=append(append(r,map[y]),temp)
end for
map=append(r,map[length(map)])
end for
position(1,1)
puts(1,"Leveling sea ")
for y=1 to length(map) do
for x=1 to length(map[1]) do
if map[y][x]<0.5 then
map[y][x]=1/zsize+0.1
end if
end for
end for
end procedure
function transform(sequence point)
atom a,b,c
a=point[1]*cosine[1]+point[2]*sine[1]
b=point[2]*cosine[1]-point[1]*sine[1]
c=point[3]*cosine[2]-a*sine[2]
a=d-(a*cosine[2]+point[3]*sine[2])
return floor({((b*cosine[3]+c*sine[3])*d)/a,((c*cosine[3]-b*sine[3])*d)/a})
end function
procedure dotrans()
position(1,1)
puts(1,"Calculating screen points. ")
points=repeat(repeat({0,0},size),size)
sine=sin(ang)
cosine=cos(ang)
for y=1 to size do
for x=1 to size do
points[y][x]=zoom*transform({(x-s2),(y-s2),map[y][x]-z2})+os
if points[y][x][1]>1023
or points[y][x][2]>767
or points[y][x][2]<0
or points[y][x][1]<0 then
points[y][x]={0,0}
end if
end for
end for
end procedure
function sgn(atom sn)
if sn>0 then
return 1
elsif sn=0 then
return 0
else
return-1
end if
end function
procedure draw()
integer n,y1,y2,x1,x2
position(1,1)
puts(1," ")
n=bits_to_int((transform({-1,-1,0})>=transform({1,1,0}))&0&0)
if n=3 then
x1=1 x2=s2 y2=1 y1=size-1
elsif n=2 then
x2=1 x1=size-1 y1=1 y2=s2
elsif n=1 then
x1=1 x2=size-1 y1=1 y2=s2
else
x1=1 x2=s2 y1=1 y2=size-1
end if
clear_screen()
puts(1,"<ESC> exit <SPACE> rotate 90 <N> new map")
if n=0 or n=3 then
for x=x1 to x2 by sgn(x2-x1) do
for y=y1 to y2 by sgn(y2-y1) do
if compare(points[y][x],{0,0})!=0
and compare(points[y+1][x],{0,0})!=0
and compare(points[y][x+1],{0,0})!=0
and compare(points[y+1][x+1],{0,0})!=0 then
n=floor((map[y][x]/zsize)*220)
polygon(n,1,{points[y][x],points[y][x+1],points[y+1][x+1]})
polygon(n,1,{points[y][x],points[y+1][x],points[y+1][x+1]})
end if
if compare(points[y][size-x],{0,0})!=0
and compare(points[y+1][size-x],{0,0})!=0
and compare(points[y][size-x+1],{0,0})!=0
and compare(points[y+1][size-x+1],{0,0})!=0 then
n=floor((map[y][size-x]/zsize)*220)
end if
end for
end for
else
for y=y1 to y2 by sgn(y2-y1) do
for x=x1 to x2 by sgn(x2-x1) do
if compare(points[y][x],{0,0})!=0
and compare(points[y+1][x],{0,0})!=0
and compare(points[y][x+1],{0,0})!=0
and compare(points[y+1][x+1],{0,0})!=0 then
n=floor((map[y][x]/zsize)*220)
polygon(n,1,{points[y][x],points[y][x+1],points[y+1][x+1]})
polygon(n,1,{points[y][x],points[y+1][x],points[y+1][x+1]})
end if
if compare(points[size-y][x],{0,0})!=0
and compare(points[size-y+1][x],{0,0})!=0
and compare(points[size-y][x+1],{0,0})!=0
and compare(points[size-y+1][x+1],{0,0})!=0 then
n=floor((map[size-y][x]/zsize)*220)
end if
end for
end for
end if
end procedure
genmap()
dotrans()
draw()
while 1 do
k=wait_key()
if k=27 then
exit
elsif k=32 then
ang[1]=ang[1]+p2
dotrans()
draw()
elsif k='n' or k='N' then
genmap()
dotrans()
draw()
end if
end while
--- snip ---
Pass this on to Bill Oney next time you see him, will you? ;->
|
Not Categorized, Please Help
|
|