1. 3D Landscapes - a closer look
- Posted by "Graeme." <hmi at POWERUP.COM.AU> Feb 16, 1998
- 639 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? ;->
2. Re: 3D Landscapes - a closer look
- Posted by "Graeme." <hmi at POWERUP.COM.AU> Feb 18, 1998
- 672 views
- Last edited Feb 19, 1998
>I'll take a look at your thing. I already do all the perspective >calculations on mine, and I'm drawing back to front, so I don't have to >worry about the hidden line problems. If you are including perspective as against just rotation around each axis, then as soon as you drop below satellite view you must also draw from both edges of the screen inwards as well as from back to front to ensure you are *eventually* displaying the correct polygon. This is the method my 'thing' uses. This is compounded when you are looking at the map from an odd angle as you would have to find the central line of vision and display points, in order, from most distant to this line, to the closest. For example: if you are looking north up a city street, you see the east face of the buildings on the west side of the road and the west face of the buildings on the east side of the road. If you are drawing from back to front and left to right, a building on the west side of the road will be drawn correctly but the east face of a building on the east side of the road (out of view) will be drawn over the top of the building's roof. If you are looking up a street that points south south-west, you have to work out which buildings are on which side of the road. >If you set wire=0 it will draw >wireframe with hidden lines. (actually I draw a black filled poly then a >colored unfilled poly, so whatever was behind the current polygon is >erased. Looks nice and clean, especially in 1024x768. Looks great, but that's not the point, the point is that drawing several hundred polygons, then drawing over the top of them can hardly be called speed optomization. Surely to have any hope of doing any of this in real-time, you'd have to first work out which bits can be seen, before you bother drawing them. I'm assuming that this exercise is eventually leading to more than just pretty fractal distractions. (and they are very pretty - don't get me wrong >In my first few positings I had the perspective D and screen position MY >positive instead of negative, which made the perspectives look wrong. It >was a typo in the book I got the routine from. Ish. Ya get some weird >perspective views by changing these values. If I get around to it, I'll >do a version where you can place the camera and target and it will give >you a perspective view from the surface, which will look much cooler. >I want to get a fast texture mapping thing working first though. Sounds great, I look forward to it. Graeme