ETS : Eole Terrain System

Miscellaneous Forums/Blitz Showcase/ETS : Eole Terrain System

Hi all !

I decide ti give my terrain system without occulusion system in a speciale License Agreement version.

The heightmap must be in n^2+1 width 129,257,513,1025 ..

Look at the code to use it

; ------------------------------------------------------------------------------------
; Project Title	: QTS : Quadtree Terrain System
;
; Author		: Poursin Nicolas
; Email			: Nicolas.poursin@...
;
; Version		: 1.0.0          
; Date			: 05.04.2004
; ------------------------------------------------------------------------------------


; ------------------------------------------------------------------------------------
; Terms of Use License
;
; This is a legal agreement ("License Agreement") between you And Poursin Nicolas.

;	You are permitted To:

;   - Create For free or commercial games 
;   - Free Tool
;	 
;	You are Not permitted To: 
;
;	1) Sell, resell it
;	2) Use it, in commercial tool 
;	3) Modify the products And sell it                   
; ------------------------------------------------------------------------------------


; The global who contain the terrain mesh
Global QTS_Terrain 


; Set collission state for the terrain
Const QTS_TerrainCollision = 800	


; Type that contain the patch of the terrain
Type QTS_TPatch

	Field mesh
	Field x#
	Field y#
	Field z#
	Field inView
	
End Type



; Bank used to create the terrain
Global QTS_QuadTree
Global QTS_HeightMap
Global QTS_Vertex
Global QTS_Tile

; Global information  on the terrain
Global QTS_BlockSize		; Size of Terrain Patch = 16 * QTS_BlockSize
Global QTS_HeightMapSize	; Size of the heightmap must = 2^n+1 ( 129,257,513,1025 etc ...)


;********************************************** PUBLIC FONCTION **************************************************************



;------------------------------------------------------------------------------------
; Name: 				QTS_CreateTerrain
;
; Description: Create the terrain m
;
; Arguments:	- filename$ : path to the heightmap
;				- Blocksize	: Size of the terrain patch = 16 * QTS_BlockSize
;				- EdgeError	: The Error lenght to set the number of polygons
; -----------------------------------------------------------------------------------
Function QTS_CreateTerrain( filename$ , BlockSize , EdgeError   )

	QTS_Terrain = CreateMesh()
	QTS_LoadHeightMap( filename$  )

	QTS_BlockSize = BlockSize
	QTS_NbPatch = QTS_HeightMapSize/( QTS_BlockSize*16)
	QTS_Tile = CreateBank( 64*64*4 )
	
	QTS_Roughness(EdgeError)
	QTS_CreatePatch( QTS_BlockSize )

	QTS_Texture()
	
	FreeBank QTS_QuadTree
	FreeBank QTS_HeightMap
	FreeBank QTS_Vertex

End Function

;------------------------------------------------------------------------------------
; Name: 				QTS_FreeTerrain
;
; Description: Free the terrain and all attach object
; -----------------------------------------------------------------------------------
Function QTS_FreeTerrain()

	FreeEntity QTS_Terrain
	For tt.QTS_TPatch = Each QTS_TPatch
		Delete tt
	Next
	
End Function

;------------------------------------------------------------------------------------
; Name: 				QTS_UpdateTerrain
;
; Description: Free the terrain and all attach object
;
; Arguments:	- Cam : Camera handle
;				- ViewDistance# : Distance in front of camera that terrain pathc is still visible 
; -----------------------------------------------------------------------------------
Function QTS_UpdateTerrain( cam , ViewDistance# )


	For tile.QTS_TPatch = Each QTS_TPatch

			If EntityDistance( cam, tile\mesh ) < ViewDistance# Then

				If  EntityInView( tile\mesh ,cam) Then

					ShowEntity 	tile\mesh
		
				Else
					HideEntity tile\mesh

				EndIf
			Else
				HideEntity tile\mesh
		EndIf
		
	Next
	
End Function

; This fonction return the patch mesh at one position
Function QTS_GetMesh( x,z , scalevalue# )

	patchsize# = (QTS_BlockSize * 16/2 ) * scalevalue#
 	
	For tile.QTS_TPatch = Each QTS_TPatch
		xx = EntityX( tile\mesh,True)
		zz= EntityZ( tile\mesh,True)
	
		If x>= xx - patchsize# And x < xx+ patchsize# And z>= zz - patchsize# And z < zz+ patchsize# Then
			Return tile\mesh
		EndIf
		
	Next

	Return False
	
	
End Function


; REturn the height of the terrain
Function QTS_TerrainY#(x#,z#)

	pick=LinePick(x#,200000,z#,0,-2000000,0)

	Return (PickedY())

End Function

; TExture the terrain
Function QTS_TextureTerrain( hTexture,scale#=1,level=0,BlendMode=2)

	TextureBlend hTexture,BlendMode
	ScaleTexture hTexture,scale#,scale#
	
	For tile.QTS_TPatch = Each QTS_TPatch
		EntityTexture tile\mesh,hTexture,0,level
	Next
	
End Function






;********************************************** PRIVATE FONCTION **************************************************************

Function QTS_Roughness( Error )

	
	EdgeLength = 3
	
	While EdgeLength <=17

		EdgeOffset = (EdgeLength-1)/2
		ChildOffset = (Edgelength-1)/4

		z= EdgeOffset
		While z < QTS_HeightMapSize 

			x= EdgeOffset
			While x < QTS_HeightMapSize 

				node = 0
				kill=0


				If EdgeLength>3 Then
					; top edge
					Node = QTS_GetMatrixValue( x-ChildOffset , z-ChildOffset)
					Node = QTS_MAX( Node , QTS_GetMatrixValue( x+ChildOffset , z-ChildOffset))
					Node = QTS_MAX( Node , QTS_GetMatrixValue( x+ChildOffset , z+ChildOffset))
					Node = QTS_MAX( Node , QTS_GetMatrixValue( x-ChildOffset , z+ChildOffset))
				EndIf
				

				
				If EdgeLength = 3 Or node=0 Then

					QTS_SetMatrixValue( x-EdgeOffset , z-EdgeOffset , 1)
					QTS_SetMatrixValue( x+EdgeOffset , z-EdgeOffset , 1)
					QTS_SetMatrixValue( x+EdgeOffset , z+EdgeOffset , 1)
					QTS_SetMatrixValue( x-EdgeOffset , z+EdgeOffset , 1)
				
					; top edge
					morph# = Abs(QTS_TrueHeightAtPoint#(x,z-EdgeOffset) - ((QTS_TrueHeightAtPoint#(x-EdgeOffset,z-EdgeOffset) + QTS_TrueHeightAtPoint#( x+EdgeOffset,z-EdgeOffset) ) /2))
					If morph#> Error Then
						QTS_SetMatrixValue(  x,z-EdgeOffset, 1 )
					Else
						
						If EdgeLength>3 Then


								QTS_SetMatrixValue( x,z-EdgeOffset ,  0)

						EndIf

						
						kill = kill +1
					EndIf


					; right edge
					morph# = Abs(QTS_TrueHeightAtPoint#(x+EdgeOffset,z) - ((QTS_TrueHeightAtPoint#(x+EdgeOffset,z-EdgeOffset) + QTS_TrueHeightAtPoint#( x+EdgeOffset,z+EdgeOffset) ) /2))
					If morph#> Error Then
						QTS_SetMatrixValue( x+EdgeOffset,z , 1 )
					Else
						If EdgeLength>3 Then	
							QTS_SetMatrixValue( x+EdgeOffset,z , 0 )
						EndIf
						
						
						kill = kill +1
					EndIf

	
					; bottom edge
					morph# = Abs(QTS_TrueHeightAtPoint#(x,z+EdgeOffset) - ((QTS_TrueHeightAtPoint#(x+EdgeOffset,z+EdgeOffset) + QTS_TrueHeightAtPoint#( x-EdgeOffset,z+EdgeOffset) ) /2))
					If morph#> Error Then
						QTS_SetMatrixValue( x,z+EdgeOffset, 1 )
					Else
						If EdgeLength>3 Then

								QTS_SetMatrixValue( x,z+EdgeOffset , 0 )
							
						EndIf
						kill = kill +1
					EndIf					


					; left Edge
					morph# = Abs(QTS_TrueHeightAtPoint#(x-EdgeOffset,z) - ((QTS_TrueHeightAtPoint#(x-EdgeOffset,z+EdgeOffset) + QTS_TrueHeightAtPoint#( x-EdgeOffset,z-EdgeOffset) ) /2))
					If morph#> Error Then
						QTS_SetMatrixValue( x-EdgeOffset,z, 1)
					Else
						If EdgeLength>3 Then
							QTS_SetMatrixValue( x-EdgeOffset,z , 0)
						EndIf
						kill = kill +1
					EndIf

					QTS_SetMatrixValue( x,z, 1)
					
					If kill=4 Then	
				  		; top Left To bottom Right
						morph# = Abs(QTS_TrueHeightAtPoint#(x,z) - ((QTS_TrueHeightAtPoint#(x-EdgeOffset,z-EdgeOffset) + QTS_TrueHeightAtPoint#( x+EdgeOffset,z+EdgeOffset) ) /2))
						If morph#<= Error Then
							morph# = Abs(QTS_TrueHeightAtPoint#(x,z) - ((QTS_TrueHeightAtPoint#(x+EdgeOffset,z-EdgeOffset) + QTS_TrueHeightAtPoint#( x-EdgeOffset,z+EdgeOffset) ) /2))
							If morph#<= Error Then
								QTS_SetMatrixValue( x,z , 0 )
							EndIf
						EndIf
					EndIf
						
				Else If EdgeLength>3
				
					QTS_SetMatrixValue( x , z-EdgeOffset , 1 )
					QTS_SetMatrixValue( x+EdgeOffset , z , 1 )
					QTS_SetMatrixValue( x , z+EdgeOffset , 1 )
					QTS_SetMatrixValue( x-EdgeOffset , z , 1 )	

				EndIf

				x = x + EdgeLength-1
				
			Wend

			
			z = z + EdgeLength-1
		Wend

		EdgeLength = (EdgeLength Shl 1 ) - 1

		
	Wend

	; Propagation
	For z=16 To 513-1 Step 32
		For x=16 To 513-1 Step 32
			QTS_ProcessNode( x,z, 33, False , False )
		Next
	Next
			
End Function

; Create a node of a terrain patch
Function QTS_RenderNode( x,z,EdgeLength , EdgeOffset ,surf , bRender )

	 
	; top
	If bRender Then	VC = QTS_AddVertex( x,z,surf)

	
	If bRender Then  V1 = QTS_AddVertex( x-EdgeOffset , z-EdgeOffset ,surf)
	If bRender=False Then QTS_SetMatrixValue( x-EdgeOffset , z-EdgeOffset)

	If bRender Then VE = QTS_Addvertex( x+EdgeOffset , z-EdgeOffset , surf)
	If bRender=False Then QTS_SetMatrixValue( x+EdgeOffset , z-EdgeOffset )
	
	
	zz = z-EdgeOffset
	xstart = x-EdgeOffset+1
	xend = x-EdgeOffset+EdgeLength -1 - 1
	
	For xx=xstart To xend

		If QTS_GetMatrixValue(xx,zz)>0 Then
		
			If bRender Then V2 = QTS_AddVertex( xx , zz ,surf)
			If bRender=False Then QTS_SetMatrixValue( xx , zz )
			
			If bRender Then AddTriangle surf,V1,V2,VC
			V1=V2
		EndIf
		
	Next

	If bRender Then AddTriangle surf,v1,ve,vc

	
	; bottom
	If bRender Then VC = QTS_AddVertex( x,z,surf)

	If bRender Then V1 = QTS_AddVertex( x-EdgeOffset , z+EdgeOffset ,surf)
	If bRender=False Then QTS_SetMatrixValue( x-EdgeOffset , z+EdgeOffset)

	If bRender Then VE = QTS_Addvertex( x+EdgeOffset , z+EdgeOffset , surf)
	If bRender=False Then QTS_SetMatrixValue( x+EdgeOffset , z+EdgeOffset )
	
	
	zz = z+EdgeOffset
	xstart = x-EdgeOffset+1
	xend = x-EdgeOffset+EdgeLength -1 - 1
	
	For xx=xstart To xend

		If QTS_GetMatrixValue(xx,zz)>0 Then
		
			If bRender Then V2 = QTS_AddVertex( xx , zz ,surf)
			If bRender=False Then QTS_SetMatrixValue( xx , zz )
			
			If bRender Then AddTriangle surf,V2,V1,VC
			V1=V2
		EndIf
	Next

	If bRender Then AddTriangle surf,ve,v1,vc


	; right
	If bRender Then VC = QTS_AddVertex( x,z,surf)

	If bRender Then V1 = QTS_AddVertex( x+EdgeOffset , z-EdgeOffset ,surf)
	If bRender=False Then QTS_SetMatrixValue( x+EdgeOffset , z-EdgeOffset)

	If bRender Then VE = QTS_Addvertex( x+EdgeOffset , z+EdgeOffset , surf)
	If bRender=False Then QTS_SetMatrixValue( x+EdgeOffset , z+EdgeOffset )
	
	
	xx = x+EdgeOffset
	zstart = z-EdgeOffset+1
	zend = z-EdgeOffset+EdgeLength -1 - 1
	
	For zz=zstart To zend

		If QTS_GetMatrixValue(xx,zz)>0 Then
			If bRender Then V2 = QTS_AddVertex( xx , zz ,surf)
			If bRender=False Then QTS_SetMatrixValue( xx , zz )
			
			If bRender Then AddTriangle surf,V1,V2,VC
			V1=V2
		EndIf
	Next

	If bRender Then AddTriangle surf,v1,ve,vc

	; left
	If bRender Then VC = QTS_AddVertex( x,z,surf)

	If bRender Then V1 = QTS_AddVertex( x-EdgeOffset , z-EdgeOffset ,surf)
	If bRender=False Then QTS_SetMatrixValue( x-EdgeOffset , z-EdgeOffset)

	If bRender Then VE = QTS_Addvertex( x-EdgeOffset , z+EdgeOffset , surf)
	If bRender=False Then QTS_SetMatrixValue( x-EdgeOffset , z+EdgeOffset )
	
	xx = x-EdgeOffset
	zstart = z-EdgeOffset+1
	zend = z-EdgeOffset+EdgeLength -1 - 1
	
	For zz=zstart To zend

		If QTS_GetMatrixValue(xx,zz)>0 Then
			If bRender Then V2 = QTS_AddVertex( xx , zz ,surf)
			If bRender=False Then QTS_SetMatrixValue( xx , zz )
			
			If bRender Then AddTriangle surf,V2,V1,VC
			V1=V2
		EndIf
	Next

	If bRender Then AddTriangle surf,ve,v1,vc

	
End Function

; Create a terrain patch
Function QTS_CreatePatch( BlockSize )

	QTS_NbPatch=0
	
	qts=CreateBank( 64*64*4)
	
	z=0
	ztab=0
	While z <=  QTS_HeightMapSize

		x=0
		xtab=0
		While x <= QTS_HeightMapSize

			PatchNumer = PatchNumer + 1
			
			xx# = x  + (BlockSize * 16/2 )
			zz# = z  + (BlockSize * 16/2 )

				
			TerrainPatch = CreateMesh()

			
			TerrainPatchSurface = CreateSurface( TerrainPatch )

			QTS_Vertex = CreateBank( (QTS_HeightMapSize) * (QTS_HeightMapSize) * 4)
			
			For bz=8 To Blocksize*16 Step 16
				For bx=8 To Blocksize*16 Step 16
					cx = x+bx
					cz = z+bz
					If cx<QTS_HeightMapSize And cz<QTS_HeightMapSize Then		
						QTS_ProcessNode( cx,cz, 17 , TerrainPatchSurface ,True )
					EndIf
				Next
			Next

			QTS_NbPatch = QTS_NbPatch +1
			
			FreeBank QTS_Vertex
			UpdateNormals TerrainPatch

			
			
			PositionMesh terrainpatch,-xx#,-MeshHeight(terrainpatch)/2,zz#

			
			
			EntityParent TerrainPatch,QTS_Terrain
			EntityType TerrainPatch,QTS_TerrainCollision

			
			tile.QTS_TPatch = New QTS_TPatch
			
			tile\mesh = TerrainPatch
			tile\x# = xtab * (BlockSize * 16/2 ) *2
			tile\y# = MeshHeight(terrainpatch)/2
			tile\z# = -ztab *(BlockSize * 16/2 ) *2 
 			tile\inView = False
			
			PositionEntity tile\mesh,tile\x#,tile\y#,tile\z#
			EntityPickMode tile\mesh,2

			EntityColor tile\mesh,250,250,250
			
			PokeInt QTS_Tile, ((ztab*64 + xtab)*4),Handle( tile )
			
			x = x + (BlockSize * 16)
			xtab=xtab+1
		Wend
		z = z + (BlockSize * 16)
		ztab=ztab+1
	Wend
	
End Function


; Check a Node of a terrain patch
Function QTS_ProcessNode( x,z, EdgeLength, surf , bRender )

	EdgeOffset = (EdgeLength-1)/2
	ChildOffset = (Edgelength-1)/4
		
	node = QTS_GetMatrixValue( x,z )
	
	If node=1   Then
		
		If  EdgeLength=3 Then
			QTS_RenderNode( x,z,EdgeLength , EdgeOffset ,surf ,bRender)
		Else
			; top left child
			If QTS_GetMatrixValue( x-ChildOffset,z-ChildOffset ) > 0 Then
				QTS_ProcessNode( x-ChildOffset,z-ChildOffset, EdgeLength-(Edgelength/2), surf ,bRender)
			Else
				 QTS_RenderNode(  x-ChildOffset,z-ChildOffset, EdgeLength-(Edgelength/2) , EdgeOffset-(EdgeOffset/2) ,surf,bRender)
			EndIf

			; top right child
			If QTS_GetMatrixValue( x+ChildOffset,z-ChildOffset ) > 0 Then
				QTS_ProcessNode( x+ChildOffset,z-ChildOffset, EdgeLength-(Edgelength/2), surf ,bRender)
			Else
		
			 QTS_RenderNode(  x+ChildOffset,z-ChildOffset, EdgeLength-(Edgelength/2) , EdgeOffset-(EdgeOffset/2) ,surf,bRender)

			EndIf

			; bottom left child
			If QTS_GetMatrixValue( x-ChildOffset,z+ChildOffset ) > 0 Then
				QTS_ProcessNode( x-ChildOffset,z+ChildOffset, EdgeLength-(Edgelength/2), surf,bRender)
			Else
		
			 QTS_RenderNode(  x-ChildOffset,z+ChildOffset, EdgeLength-(Edgelength/2) , EdgeOffset-(EdgeOffset/2) ,surf,bRender)
			EndIf

			; bottom right child
			If QTS_GetMatrixValue( x+ChildOffset,z+ChildOffset ) > 0 Then
				QTS_ProcessNode( x+ChildOffset,z+ChildOffset, EdgeLength-(Edgelength/2), surf,bRender)
			Else
			
				 QTS_RenderNode(  x+ChildOffset,z+ChildOffset, EdgeLength-(Edgelength/2) , EdgeOffset-(EdgeOffset/2) ,surf,bRender)
			EndIf

		EndIf
	
	Else
		
		QTS_RenderNode( x,z,EdgeLength , EdgeOffset ,surf,bRender)
		
	EndIf


	
End Function

Function QTS_AddVertex( x,z,surf)


	If PeekInt( QTS_Vertex, QTS_MatrixIndex( x,z)*4)=0 Then
		y# = QTS_TrueHeightAtPoint(x,z) *0.1
		vertex = AddVertex( surf,x,y#,-z,0,0)
		PokeInt QTS_Vertex, QTS_MatrixIndex( x,z)*4 , vertex+1

	Else
		vertex = PeekInt( QTS_Vertex, QTS_MatrixIndex( x,z)*4)-1
	EndIf
	

	
	Return Vertex
	
End Function


Function QTS_LoadHeightMap(filename$ ,shadow=False)

	
	heightmap = LoadImage( filename$ )
	
	QTS_HeightMapSize = ImageWidth( heightmap )

	QTS_HeightMap = CreateBank( (QTS_HeightMapSize) * (QTS_HeightMapSize) )
	If Not shadow Then
		QTS_QuadTree = CreateBank( (QTS_HeightMapSize) * (QTS_HeightMapSize) )
	EndIf
	

	LockBuffer ImageBuffer( heightmap)

	For z=0 To QTS_HeightMapSize-1
		For x=0 To QTS_HeightMapSize-1
			pixel = ReadPixelFast( x,z, ImageBuffer(heightmap) ) And 255
			offset = z * QTS_HeightMapSize + x
			PokeByte QTS_HeightMap, offset , pixel
			If Not shadow Then	
				PokeByte QTS_QuadTree, offset , 0
			EndIf
		Next
		
	Next

	UnlockBuffer ImageBuffer( heightmap)
	FreeImage heightmap
		
End Function

Function QTS_Texture()


	size = QTS_HeightMapSize 

	For z=0 To 63
		For x=0 To 63
			obj = PeekInt( QTS_Tile, (z*64+x)*4)
			If obj>0
				tile.QTS_TPatch = Object.QTS_TPatch( obj)
				If tile\mesh <>-1 Then

					Surface = GetSurface(tile\mesh, 1)
					Vertices = CountVertices(Surface)

					For Vertex = 0 To Vertices-1

						VX# = EntityX#(tile\mesh) +  (VertexX#(Surface, Vertex) + (4 * 16 )/2)
						VZ# = EntityZ#(tile\mesh) +  (VertexZ#(Surface, Vertex) -  (4 * 16 )/2)
						VertexTexCoords Surface, Vertex, VX#/size, -VZ#/size, 0,0
						
					Next
			
				EndIf					
			EndIf
		Next
	Next
	
	
End Function

Function QTS_GetMatrixValue( x,z )

	value=PeekByte(QTS_QuadTree, QTS_MatrixIndex( x,z))
	
	Return value
	
End Function

Function QTS_SetMatrixValue( x,z , value=1 )

		
	PokeByte QTS_QuadTree , QTS_MatrixIndex( x , z) , value


End Function

Function QTS_MatrixIndex( x,z)

	Return (( z * QTS_HeightMapSize) + x)
	
End Function

Function QTS_Max#(v1#,v2#)

	If v1#>V2# Then
		Return v1#
	Else
		Return v2#
	EndIf
	
End Function

Function QTS_TrueHeightAtPoint#( x, z)

	value#=PeekByte(QTS_HeightMap, (z * QTS_HeightMapSize) + x)
	
	Return value#
	
End Function






Great !

It's not really finish, maybe some bugs could exist

Have downloaded it -- looking forward to trying it out!

ok, look int he Bitz3D Forum I put an example