3D Landscapes - a closer look

new topic     » topic index » view thread      » older message » newer message

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?  ;->

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu