3D Landscapes - a closer look
- Posted by "Graeme." <hmi at POWERUP.COM.AU> Feb 16, 1998
- 638 views
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? ;->