Code archives/3D Graphics - Mesh/Mesh LoadTerrain

This code has been declared by its author to be Public Domain code.

Download source code

Mesh LoadTerrain by Ross C2006
This function is exactly like the LoadTerrain command in blitz, except it uses a blitz mesh instead of a blitz terrain. There's no LOD, but it should be alot faster in many circumstances. Same syntax as the Blitz function. Also centres the mesh, unlike the original function.

EDIT<<< I have redone this routine, as it had many errors and inaccurate workings:

- It will now properly apply the heightmap without a strange seem appearing.
- I have added the functionality to adjust the Y scale.
- You can load three textures, and state flags, and they will be applied.
- The UV mapping has been fixed now.
- The function returns the mesh back, which i don't think it did before?

Global terrain = load_terrain("heightmap.bmp",0.5); load the terrain half scale (since Red pixel colours highest value is 255, the highest value will now be 128.)


To load a texture and apply it to the terrain.

Global terrain = load_terrain("heightmap.bmp",0.5,"terrain_texture.bmp",1+16+32); load the terrain, and apply a texture, with the clamping flags and colour flag. Note, you must clamp the texture if it encompasses the whole mesh, or it's edges will bleed to the other side.
; Y position is calculated by: scale * pixel colour on loaded image.

; PLEASE NOTE: You must clamp the texture your applying if it is spread across the whole mesh.
;              If you don't, it will bleed across to the opposite side. Clamp with flags 16 + 32
Function load_terrain(heightmap$,y_scale#=1,texture1$="",t_flag1 = 1,texture2$="",t_flag2 = 1,texture3$="",t_flag3 = 1)


	temp = LoadImage(heightmap$)
	If temp = 0 Then Return 0
	
	x = ImageWidth(temp)
	DebugLog(" image width = "+x)
	y = ImageHeight(temp)

	mesh = CreateMesh()
	surf = CreateSurface(mesh)

	For ly = 0 To y-1 ; your doing -1 because the image pixels start at 1 and the vertex
					  ; indices start at 0
		For lx = 0 To x-1
			AddVertex surf,lx , 0, -ly, Float(lx)/(x-1), Float(ly)/(y-1)
		Next
	Next
	RenderWorld
	
	AddTriangle surf, 0, 65,64
	AddTriangle surf, 0, 1 ,65
	For ly = 0 To y-2
		For lx = 0 To x-2 ; leave the vertex counting an extra unit short, as the code below reaches
						  ; reaches one unit ahead to create the triangles

			; below is to simply explain the creation process and order of the triangles.
			; Triangles must be created in clockwise order, facing the camera, to be seen.
			current_y = ly*y
			next_y = (ly+1)*y
			current_x = lx
			next_x = lx+1
			;create the quad
			AddTriangle surf, current_y+current_x, next_y+next_x    , next_y + current_x
			AddTriangle surf, current_y+current_x, current_y+next_x , next_y + next_x
		Next
	Next


	PositionMesh mesh, -x/2.0,0,y/2.0 ; centre the mesh on the world axis.

	SetBuffer ImageBuffer(temp)
	For ly = 0 To y-1
		For lx = 0 To x-1
			GetColor lx,ly
			index = (ly*y) + lx
			VertexCoords surf, index , VertexX(surf,index), ColorRed()*y_scale, VertexZ(surf,index)
		Next
	Next
	SetBuffer BackBuffer()
	
	UpdateNormals mesh
	
	If texture1 <> "" Then
		t1 = LoadTexture(texture1,t_flag1)
		If t1 = 0 Then RuntimeError(" Error in load_terrain() function: Texture1 not found from filename given")
		EntityTexture mesh,t1,0,0
	End If
	If texture2 <> "" Then
		t2 = LoadTexture(texture2,t_flag2)
		If t2 = 0 Then RuntimeError(" Error in load_terrain() function: Texture2 not found from filename given")
		EntityTexture mesh,t2,0,1
	End If
	If texture3 <> "" Then
		t3 = LoadTexture(texture3,t_flag3)
		If t3 = 0 Then RuntimeError(" Error in load_terrain() function: Texture3 not found from filename given")
		EntityTexture mesh,t3,0,2
	End If
		
	
	Return mesh
	
End Function

Comments

Hambone2006
Very nice. Very clear. When I have a little time I may extend this further to something like this:

Global terrain = load_terrain("heightmap.bmp, texture.bmp,lightmap.bmp")


ShadowTurtle2006
You mean:

Global terrain = load_terrain("heightmap.bmp", "texture.bmp", "lightmap.bmp")

Function load_terrain(file$, texfile$ = "", lightfile$ = "")
...
End Function


Hambone2006
Yeah,

Exactly like that. Your English is fine. Far better than the gibberish that I type most of the time :)

Thanks,

Allan


Ross C2006
Well, the texture co-ords are set, so, it should be a doodle to set up :o)


Chroma2006
Got it working but the texture coords are out of whack. =(


Chroma2006
It also loads the height map inverted...

EDIT: Change this line and it will load the height map correctly.

GetColor lx,y-ly


Also add this to the end of the function:
Return mesh



Chroma2006
Altered it to:
LoadTerrain3( "hmap.bmp","tmap.bmp","lmap.bmp")


Now the heightmap is loaded correctly and also the texture coordinates are set. The function automatically scales the texture to fit the terrain. Next on my list for this function is to have it break the terrain up into manageable segments that can be used with PVS and also define the detail level of the terrains so you can cap each segment at say, 500.

Function LoadTerrain3(hmap$,tmap$=0,lmap$=0)

	; load the heightmap
	temp = LoadImage(hmap$)
	If temp = 0 Then RuntimeError "Heightmap image "+hmap$+" does not exist." : Return 0
	
	; store heightmap dimensions
	x = ImageWidth(temp)
	y = ImageHeight(temp)

	; load texture and lightmaps
	tmap = LoadTexture(tmap$)
	lmap = LoadTexture(lmap$)
	
	; auto scale the textures to the right size
	If tmap ScaleTexture tmap,x,y
	If lmap	ScaleTexture lmap,x,y

	; start building the terrain
	mesh = CreateMesh()
	surf = CreateSurface(mesh)

	; create some verts for the terrain
	For ly = 0 To y
		For lx = 0 To x
			AddVertex surf,lx,0,ly,1.0/lx,1.0/ly
		Next
	Next
	RenderWorld
	
	; connect the verts with faces
	For ly = 0 To y-1
		For lx = 0 To x-1
			AddTriangle surf,lx+((x+1)*ly),lx+((x+1)*ly)+(x+1),(lx+1)+((x+1)*ly)
			AddTriangle surf,(lx+1)+((x+1)*ly),lx+((x+1)*ly)+(x+1),(lx+1)+((x+1)*ly)+(x+1)
		Next
	Next
	
	; position the terrain to center 0,0,0
	PositionMesh mesh, -x/2.0,0,-y/2.0

	; alter vertice height to match the heightmap red channel
	SetBuffer ImageBuffer(temp)
	For lx = 0 To x
		For ly = 0 To y
			GetColor lx,y-ly
			index = lx + ((x+1)*ly)
			VertexCoords surf, index , VertexX(surf,index), ColorRed()/20.0,VertexZ(surf,index)
			; set the terrain texture coordinates
			VertexTexCoords surf,index,lx,-ly 
		Next
	Next
	SetBuffer BackBuffer()
	
	; update the terrain normals so lighting will look correct
	UpdateNormals mesh
	
	; apply texture map to index 0
	If tmap EntityTexture mesh,tmap,0,0
		
	; apply lightmap to index 1 with flag 2
	If lmap EntityTexture mesh,lmap,0,1 : TextureBlend lmap,2
	
	Return Mesh
End Function



Chroma2006
Hmm...new bug.

The far right and bottom vertices aren't effected by the hmap. They stay at 0,0,0 even if the right wall is painted pure white...


ckob2006
not sure why but when I try this it crashes on renderworld.


Stevie G2006
Your heightmap is probably too big .. creating too many poly's or verts per surface. I think the limit is 64k verts and 32k polys - higher on some cards.

Stevie


ckob2006
256 X 256 ?


ShadowTurtle2006
from Chroma:
>> The far right and bottom vertices aren't effected by
>> the hmap. They stay at 0,0,0 even if the right wall
>> is painted pure white...

from ckob:
>> not sure why but when I try this it crashes on
>> renderworld.

In an other situation i am haved the same problem. Any vertice from triangle does not exists. Blitz debugger does it nothin register and so it make bugs.

You must integrate border-checking. As sample this would be set on a vertice in mesh:
; from: AddTriangle surf,lx+((x+1)*ly),lx+((x+1)*ly)+(x+1),(lx+1)+((x+1)*ly)

vertice = lx+((x+1)*ly)


So you must test:
If lx+((x+1)*ly) > CountVertices(surf) then ... End If


... ... or similarly.

On many refers of vertices this would be a long work for(to? sry, my english is bad) testing.


thelizardking2007
128x128, actually...


thelizardking2007
128x128, actually...but the function works AWSOME! thnxs ta big10p 4 finding it 4 me...lol thats how lazy i am

p.s. just add ResizeImage temp,128,128 after If temp = 0 Then RuntimeError "Heightmap image "+hmap$+" does not exist." : Return 0


Krischan2007
The functions works very good. I wrote a complete tech demo which tiles a given heightmap/colormap into smaller pieces and displays it nearly seamless (there is still a bug with the UV coordinates I couldn't locate).

Screenshot


Download with Source and Images

Source:



Nexus62007
Moved comments to programming.


Ross C2008
Need to have another look at this... Thanks for tidying it up though :o)


Ross C2009
UPDATED!


Blitzplotter2009
Hey Ross, this is very interesting. I did some stuff a while back (ermm 10 years or so ago) that used Vista and DEM files to create landscapes.

It is great to see the type of code necessary to produce such fantastic results, thanks for sharing.


Guy Fawkes2009
Did anyone fix the UV Coordinate glitch yet? I cant seem to find it.


Guy Fawkes2009
?


Guy Fawkes2009
I know u guys proally dont have time to fix it, but here's what i mean by uv coordinate glitch. its some bad geometry.




Guy Fawkes2009
Ok, guys. I have tried & tried to fix ur code, but i still end up where i started. here's my code so far. download the zip provided above to try the code.

i added stuff as well. ull need a cloud texture. i will provide it to u. and a sea texture. which i cant provide to you. i say this because my sea texture isnt perfect.




Guy Fawkes2009
Cloud texture: http://www.mediafire.com/download.php?zgmjlieydgl


cyberyoyo2009
Great demo Drkshadowwing,I'll take a lot at the UV problem but there is a possibility that it might not be fixable since it appears on the limit between two different meshes.

As for RossC code, it always gives me a MAV on renderworld()...

It's nice to see that B3d can be so great after all these years :)


cyberyoyo2009
(double post plz delete)


cyberyoyo2009
[EDITED]
Code removed and moved to the appropriate thread there:
http://www.blitzbasic.com/Community/posts.php?topic=83668


Ross C2009
Remember this isn't a help forum. The code works perfectly fine. If you have trouble with code using my code, please don't post it here :o)


Krischan2009
Additional here is my own solution, a little bit more code than a single function, its a complete demo (but still based on Ross C's original code). I managed to fix the UV coordinates and use the Terragen File Format as a heightmap base which gives more precision. You can even use Vertex Shadows now because I fixed the chunk normals, too. The Terragen size is irrelevant, the demo will calculate how many tiles are needed and fixes the seams automatically. The colormap texture is stretched across the whole terrain so it should be huge, otherwise you can activate the "vertexcolors" flag but this is not as nice as a colormap.

Screenshot:


Use Mouse for movement (LMB/RMB = up/down) and these keys:

Arrows = Move (5 times fast while holding right SHIFT)
C = show/hide chunk seams (otherwise you won't notice any seam)
F = fog on/off
Q/E = increase/decrease light angle
1...9 = light angle preset between 0° and 180° in 22.5° steps
SPACE = wireframe on/off

The code is well commented but if you have any questions feel free to ask me.

Complete Demo with media (830KB): http://www.christianhart.de/bb/terratiles/terratiles.zip
(otherwise you need a custom terragen file, ex. 257x257 size and a matching colormap ex. 1024x1024 pixels)



As some of you might have noticed, it is the same island like in this screenshot, yes it could look that nice (i use a quadtree function there but I couldn't manage the Vertex Shadows with it):

http://www.blitzbasic.com/gallery/view_pic.php?id=1910


Guy Fawkes2009
I have a slight fix.

Well. I cant get it to work..

But I added it..

Its a few lines that allow for when the sun = 10 degrees (aka 6 am), it adds a day on to the day variable.

I know, not useful, but maybe you guys can fix it:




Ross C2009
Excuse me. NOT a help forum. Stick this somewhere else. Talk about confusing an issue.

That's real impressive code, but it's not the right place to post this... I reupdated the code, fixing the UV glitch (which someone isn't seeming to understand...)


Krischan2009
And I just added my code because it is based and related to Ross' code. The next one will get its own code archive entry. And yes - Darkshadowwing - if you need assistance this is the wrong subforum, post it into "Blitz 3D Programming". This forum here is some kind of showcase where you can improve the code or comment it.


Ross C2009
Thank you :o) (I really like your extended code btw!)


Krischan2009
Just wait for the next version. You will LOVE it :-) Here ist a small candy snapshot preview:




Guy Fawkes2009
*Drools*


Code Archives Forum