3D Terrain (Using DrawPerspectiveSprites)

Started by kevin, November 09, 2007, 10:03:09 AM

Previous topic - Next topic

kevin

 3D Terrain (Using Perspective Sprites)

  This example uses one of the new features found in PB1.70 and above called perspective sprites.  In particular the drawing command DrawPerspectiveSprites.  What this allows you to do is render a collection of sprites as 3d geometry from a view point.  In this example it's creating a terrain styled effect from a single sprite.  This is done by creating a entity sprite (a sprite has than more than 1 face) and setting up it's vertex and faces lists in the shape of the terrain.    Each vertex in an terrain entity sprite is given coordinates in 3D space,  and has has it's 3D rotation mode activated.    So when this sprite is drawn from the view point (a camera) perspectively, it'll be translated and rendered to the view port.

  Requires PlayBASIC FX V1.70 or above.    



; Open a 800*600*32 screen in FullScreen with Z buffer support.
OpenScreen 800,600,32,PBscreenmode_FullScreenZ

; Make the Random Grass texture
Grass=MakeGrass(512,56)


; The Size (along edges) of the Terrain Mesh
TerrainSize=96


; Create the a Sprite With a terrain like mesh  
terrain= MakeTerrainSprite(Grass,rnd(0),rnd(0),TerrainSize)


; Set the Sprite Rotation Mode to 3D (XYZ mode()
SpriteRotationMode terrain,1

; Position the Sprite in 3D space
positionspritexyz terrain,0,-10000,-50500

; Enable Back faces culling so Polygons facing away from the camera won't be drawn
Spritebackface Terrain,On




;  Dim PB Camera type
 Dim Camera as PBCamera Pointer
 Camera = new PBCamera

; Camera Position
Camera.pos.X=0.0  
Camera.pos.y=0.0  
Camera.pos.z=-10000.0


; RotationMode 0= 2d With Perspective down Z axis (z rotation supported Camera.Angle.Z)
; RotationMode 1= 3D ZYX rotation
Camera.RotationMode=1


// Set Camera Projection t
Camera.Projection.x=((GetScreenWidth()/2.0)*1000)/(400)
Camera.Projection.y=((GetScreenHeight()/2.0)*1000)/(400)

// Middle of Camera
Camera.ViewPoint.X=GetScreenWidth()/2.0  
Camera.ViewPoint.y=GetScreenHeight()/2.0  



// Start of Program Main Loop
Do

; Clear the Screen
Cls rgb(30,40,140)


ix=mod(ix+1,getimagewidth(1))

; DRaw the Sprite List from the Camera Viewer Perspectively
DrawPerspectiveSprites Camera


MouseLookCamera(camera,100)

setcursor 0,0

print fps()
print "Camera Position"
print Camera.pos.x
print Camera.pos.y
print Camera.pos.z

print "Camera Projection"
print Camera.Projection.x
print Camera.Projection.y

print "Camera Rotation"
print Camera.Angle.x
print Camera.Angle.y
print Camera.Angle.z
print Camera.RotationMode

Sync
loop  



;*=---------------------------------------------------------------------------=*
;                >> Make A Terrain Sprite<<
;*=---------------------------------------------------------------------------=*





Function MakeTerrainSprite(ThisIMage,Xpos#,Ypos#,points)


; Create the sprite
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2

SpriteTransparent ThisSprite,on
turnspritexyz thissprite,00,00,00

Points2=(points+1)


; Dim an Array to Hold the terraion height map
Dim Matrix#(POints2,points2)

; randomize the heights of each point in the height map
RadomizeHeightMap(Matrix#(),35000)

; smooth out the height map be averageing the points
SmoothHeightMap(Matrix#(),3)

; Set Terrain Sprites number of Vertex and Faces
SpriteVertexQuantity thisSprite,(Points2*POints2)
SpriteFaceQuantity thisSprite,(Points2*Points2)*2


Size=1000
HandleX#=-(((points+1.0)/2.0)*size)
HandleZ#=-(((points+1.0)/2.0)*size)

; init vertex
for Ylp=0 to Points
Zpos#=ylp*Size
for Xlp=0 to Points
Xpos#=Xlp*Size
ThisVertex=(Ylp*(points+1))+xlp
ypos#=Matrix#(xlp,ylp)
PokeSpriteVertex ThisSprite,ThisVertex,Xpos#+HandleX#,Ypos#-10000,Zpos#+HandleZ#
next
next

ThisColour2=rgb(0,255,255)
ThisColour=rgb(255,255,255)

; init faces  (UV points U=X in texture space,  V = Y in texture space)
TUstep#=1.0/(points+1)
Tvstep#=1.0/(points+1)

For Ylp=0 to points-1
For Xlp=0 to points-1

CurrentVertexRow =(Ylp*(points+1))+Xlp
NextVertexRow =CurrentVertexRow+(points+1)

PokeSpriteFaceVerts ThisSprite,ThisFace,3

u1#=Xlp*TUstep#
v1#=Ylp*TVstep#

u2#=(Xlp+1)*TUstep#
v2#=Ylp*TVstep#

u3#=(Xlp+1)*TUstep#
v3#=(Ylp+1)*TVstep#

u4#=(Xlp+0)*TUstep#
v4#=(Ylp+1)*TVstep#

PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,CurrentVertexRow+1 ,u2#,v2#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow+1 ,u3#,v3#,ThisColour
inc ThisFace

PokeSpriteFaceVerts ThisSprite,ThisFace,3
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour2
PokeSpriteface ThisSprite,ThisFace,1,NextVertexRow+1 ,u3#,v3#,ThisColour2
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow ,u4#,v4#,ThisColour2
inc ThisFace

Next
Next


;Set the numbner of faces this sprite has
SpriteFaceQuantity thisSprite,ThisFace+1

EndFUnction ThisSPrite




` *=----------------------------------------------------------------=*
`                        >> Randomize HeightMap Array <<
` *=----------------------------------------------------------------=*


Function RadomizeHeightMap(Matrix#(),Height)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
For Zlp=1 to Depth-2
For Xlp=1 to Width-2
Matrix#(xlp,zlp)=rnd#(Height)
next xlp
next zlp
Endfunction


` *=----------------------------------------------------------------=*
`                    >> Average Matrix Height <<
` *=----------------------------------------------------------------=*





Function SmoothHeightMap(Matrix#(),passes)

Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)

Dim Temp_HeightMap_Yvalues#(Width,Depth)

For ThisPass=0 To Passes

CopyArray Matrix#(),Temp_HeightMap_Yvalues#()
For Zlp=1 to Depth-1

ZlpF=zlp-1
ZlpB=zlp+1
Width2=Width-1

For Xlp=1 to Width2
xlpL=Xlp-1
xlpR=Xlp+1

yb#=Temp_HeightMap_Yvalues#(xlp,zlp)
yt#=Temp_HeightMap_Yvalues#(xlp,zlpF)
yb#=Temp_HeightMap_Yvalues#(xlp,zlpB)
yl#=Temp_HeightMap_Yvalues#(xlpL,zlp)
yr#=Temp_HeightMap_Yvalues#(xlpR,zlp)

ytl#=Temp_HeightMap_Yvalues#(xlpL,zlpF)
ytr#=Temp_HeightMap_Yvalues#(xlpR,zlpF)
ybl#=Temp_HeightMap_Yvalues#(xlpL,zlpB)
ybr#=Temp_HeightMap_Yvalues#(xlpR,zlpB)

matrix#(xlp,zlp)=(yb#+yt#+yb#+yL#+yr#+ytl#+ytr#+ybl#+ybr#)/9

next xlp
next zlp

next ThisPass
unDim Temp_HeightMap_Yvalues#()

endfunction






Function MouseLookCamera(camera as PBcamera pointer,camspeed#)
static acamx#,acamy#

W=GetScreenWidth()
H=GetScreenHeight()

x1=GetScreenXpos()
  Y1=GetScreenYpos()
x2=x1+w
y2=y1+h


MMX#=MouseMoveX()
MMY#=MouseMoveY()

x#=x1+MouseX()
y#=y1+MouseY()


flag=0
If x#=<(x1+75) Then x#=x1+(w/2): flag=1
If x#=>(x2-75) And flag=0 Then x#=x1+(w/2): flag=1

If y#=<(y1+75) Then y#=y1+(h/2): flag=1
If y#=>(y2-75) Then y#=y1+(h/2): flag=1


If flag=1
SetMouse x#,y#
MMX2#=MouseMoveX()
MMY2#=MouseMoveY()
SetMouse x#,y#
EndIf


camf#=0
acamx#=WrapAngle(acamx#,mmy#*0.7)
acamy#=WrapAngle(acamy#,mmx#*0.7)

Camera.Angle.x#=CurveAngle(acamx#,Camera.Angle.x#,6.2)
Camera.Angle.y#=CurveAngle(acamy#,Camera.Angle.y#,6.2)

If KeyState(200 ) Then camf#=camf#+camspeed#
If KeyState(208) Then camf#=camf#-camspeed#

If camf#<>0
movementx#,movementy#,movementz#=CalcMovement(acamx#,acamy#,0.0,Camf#)

x#=Camera.pos.x#+movementx#
y#=Camera.pos.y#+movementy#
z#=Camera.pos.z#+movementz#

; clip the camera to 20 on y axis
; If y#<100 Then y#=100
Camera.pos.x=x#
Camera.pos.y=y#
Camera.pos.z=z#

EndIf
EndFunction






Function CalcMovement(Anglex#,angley#,anglez#,Speed#)
` invert angles
anglex#=WrapAngle(360,-anglex#)
angley#=WrapAngle(90,-angley#)
anglez#=WrapAngle(360,-anglez#)

` precalc cos+sin for rotation
 cx#=Cos(anglex#)
 sx#=Sin(anglex#)

 cy#=Cos(angley#)
 sy#=Sin(angley#)

Zpos#=Speed#

z#=(cx#*Zpos#)
y#=(sx#*zpos#)

` Around Y axis
x2#=(cY#*Z#)-(sy#*X#)
z#=((cy#*X#)+(sy#*Z#))

EndFunction x2#,y#,z#






Function MakeGrass(Size,Seed)
Randomize Seed

Me=New3DImage(Size,Size)
if Me
oldsurface=getsurface()

rendertoimage me
lockbuffer

GrassColour=$30a000
For ylp=0 to size-1
For xlp=0 to size-1
IntensityColour=rnd(255)
C=(IntensityColour+OLDIntensityColour)/2
c=rgbalphamult(GrassColour,Rgb(c,c,c))
dotc xlp,ylp,c
OldIntensityColour= IntensityColour
next
next
unlockbuffer
rendertoimage oldsurface
blurimage me,8.1
endif

EndFunction me




XpMe_v1.2

...XpMe v1.2

http://tilemusic.com/