Terrain mesh to height map

Community Forums/General Help/Terrain mesh to height map

Oiduts Studios(Posted 2010) [#1]
Is there any way or program so i can convert a mesh to a height map? I know linepick might do the trick but before i start that, does anyone know of any easier techniques?? Thank you for your help.


Yasha(Posted 2010) [#2]
...VertexY()...?

cf. http://www.blitzbasic.com/codearcs/codearcs.php?code=2443


Oiduts Studios(Posted 2010) [#3]
Thanks for the fast response, i have looked at the code and i still do not understand the vertex index variable. Can you please describe this to me.


Stevie G(Posted 2010) [#4]
Linepick IS the easiest method. You will need to store all points in an array or suchlike initially. Keep a record of the lowest and highest points found and convert all heights so that they are between 0..255. Then draw this color to the heightmap. The Red RGB component is used to store the height information when loading heightmaps for blitz terrains.

The advantage is that it's trivial to create any size of heightmap without the need to interpolate heights between vertices, which are likley may be non-uniformly spaced.

Stevie


Yasha(Posted 2010) [#5]
Stevie's right - I was assuming that a heightmap by necessity must be an evenly-spaced grid, but linepick would work for other meshes too.

However, I just thought of another idea which might be useful if you're doing the conversions in advance (I wouldn't bother with this if you need a real-time solution):

1) Colour your mesh pure white and fullbright.

2) Position your camera a suitable distance above the mesh, set to orthographic projection and zoomed out sufficiently to fit it into the desired render area.

3) Set camera fog colour to black.

4) Set camera fog range to match the highest and lowest points of the mesh.

5) Render it! You should have something resembling a heightmap!

It takes a bit of tweaking and I think would be too fiddly to set up to work with arbitrary meshes, but might be helpful if all you need is a conversion utility.


Oiduts Studios(Posted 2010) [#6]
I thought this would be east but i guess not. I decided to go old fashioned and check the height dynamically. But for some reason the picked value come out as 0. I have tried multiple value under linepick and none worked.

Graphics3D 800,600,32,2

readx#=-4
readz#=4

Global godown,wentdown,goup,wentup,gorightup,wentrightup,gorightdown,wentrightdown

Global t=LoadMesh("crescent.3ds")
PositionEntity t,0,0,0
EntityPickMode t,2

Global cam=CreateCamera()
PositionEntity cam,0,5,5
PointEntity cam,t

light=CreateLight(2)

beam=CreateCylinder()
ScaleEntity beam,.02,.5,.02
EntityColor beam,255,0,0

godown = 1

Repeat
	
	PositionEntity beam,readx#,.5,readz#
	LinePick ( readx#,5,readz#,1,10,1)
	
	If godown=1 Then readz#=readz#-.1 : wentdown=wentdown+1
	If goup=1 Then readz#=readz#+.1 : wentup=wentup+1
	If gorightup=1 Then readx#=readx#+.1 : wentrightup=wentrightup+1
	If gorightdown=1 Then readx#=readx#+.1 : wentrightdown=wentrightdown+1
	
	If godown=1 And wentdown=80 Then godown=0 : gorightup=1 : wentdown=0
	If goup=1 And  wentup=80 Then goup=0 : gorightdown=1 : wentup=0
	
	If  gorightup=1 And wentrightup=1 Then gorightup=0 : goup=1 : wentrightup=0
	If  gorightdown=1 And wentrightdown=1 Then gorightdown=0 : godown=1 : wentrightdown=0
	
	RenderWorld
	Text 0,0,PickedX()+" "+PickedY()+" "+PickedZ()
	Flip 0
	
Until KeyHit(1)
End



Oiduts Studios(Posted 2010) [#7]
I never got it working properly so i will have to remake the island, oh well, there were some problems with it anyway.


Stevie G(Posted 2010) [#8]
LinePick ( readx#,5,readz#,1,10,1)


^^^
This is the reason you're picking nothing.

The linepick should look something like:

LinePick readx#, 1000, readz#, 0,-2000,0

Where you start at a high point and pick downwards until you hit something.

Also, use loops to iterate through the x and z directions, all this goup , go right etc.. looks overcomplex.

Stevie


D4NM4N(Posted 2010) [#9]
Here is some code from my ted program which might be helpful. It doesnt use picks, it simply cycles through the vertices of the mesh, gets their Y value and does whatever with it depending on what type of heightmap you are using.

This simplified part of the code below is the bit you will find the most useful i think as it gives you each vert index (you can then use vertexY to get the height:
			msurf=GetSurface(terrainmesh,1)
			For y=0 To trn_size  - 1
				For x=0 To trn_size  - 1
					v=x+(y*trn_size)
                                          






Anyway,
Here is the Loader and Saver in their entirety to perhaps give you some more ideas :) Vars A% & B% are the "terrain block array" indexes (useful if there is many terrain patches) and C% & D% are the terrain blocks resolution.


The saver:
		;----------------------------------------------------------------------
		;create output image
		;----------------------------------------------------------------------
		imout=CreateImage((trn_size*trn_quadnumberX)-(trn_quadnumberX-1),(trn_size*trn_quadnumberY)-(trn_quadnumberY-1))
		dgui_messagebox(-1,"Processing.","Creating map please wait...")
		SetBuffer(ImageBuffer(imout))
		
		;----------------------------------------------------------------------
		;transfer appropriate verts 2 pixels
		;----------------------------------------------------------------------		
		;find ranges For scaled 8bit exports
		For b=1 To trn_quadnumberY
			 For a=1 To trn_quadnumberX
				 msurf=GetSurface(trn_modifier(a,b),1) 
				 For y=0 To trn_size  - 1
					 For x=0 To trn_size  - 1
						v=x+y*(trn_size) 
						TFormPoint 0,VertexY(msurf,v),0,trn_modifier(a,b),0
						vy#=TFormedY()
						If vy>highest# highest=vy
						If vy<lowest# lowest=vy
					Next 
				 Next 
			 Next 
		 Next
		range=highest-lowest
		multiplier24=100;eliminate decimals on VY
		
		;write maps
		If trn_quadnumberY>trn_quadnumberX Then trn_quadnumber=trn_quadnumberY Else trn_quadnumber=trn_quadnumberX


		DebugLog "Maps:"+e_use
		For b=1 To  trn_quadnumberY 
		For a=1 To  trn_quadnumberX  
			msurf=GetSurface(trn_modifier(a,b),1)
			For y=0 To trn_size  - 1
				For x=0 To trn_size  - 1
					v=x+y*(trn_size)
					Select e_use
						Case"HEIGHT8"	
							TFormPoint 0,VertexY(msurf,v),0,trn_modifier(a,b),0
							vy=TFormedY()-lowest
							If range>255 
								bpc#=(vy/range)*100
								col#=(bpc/100)*255
							Else
								col=vy
							EndIf
							col=argb(col,col,col)
							add2fname$="_HM8"
						Case"HEIGHT24"	
							TFormPoint 0,VertexY(msurf,v),0,trn_modifier(a,b),0
							vy=TFormedY()-lowest
							col=vy*multiplier24
							add2fname="_HM24"
						Case "COLOR1"
							red=VertexRed(trn_layer1(a,b),v)
							gre=VertexGreen(trn_layer1(a,b),v)
							blu=VertexBlue(trn_layer1(a,b),v)
							col=argb(red,gre,blu)
							add2fname="_CM"
						Case "ALPHA2"
							alp#=VertexAlpha(trn_layer2(a,b),v)
							byt=alp*512:red=byt:gre=byt:blu=byt						
							col=argb(red,gre,blu)
							add2fname="_AM2"
						Case "ALPHA3" 
							alp#=VertexAlpha(trn_layer3(a,b),v)
							byt=alp*512:red=byt:gre=byt:blu=byt						
							col=argb(red,gre,blu)					
							add2fname="_AM3"
						Case "ALPHA4" 
							alp#=VertexAlpha(trn_layer4(a,b),v)
							byt=alp*512:red=byt:gre=byt:blu=byt						
							col=argb(red,gre,blu)					
							add2fname="_AM4"
						Case "ALPHA5" 
							alp#=VertexAlpha(trn_layer5(a,b),v)
							byt=alp*512:red=byt:gre=byt:blu=byt						
							col=argb(red,gre,blu)					
							add2fname="_AM5"
						Case "ALPHA6" 
							alp#=VertexAlpha(trn_layer6(a,b),v)
							byt=alp*512:red=byt:gre=byt:blu=byt	
							col=argb(red,gre,blu)					
							add2fname="_AM6"
					End Select
								
					WritePixel (((a-1)*(trn_size-1))+x), (((b-1)*(trn_size-1))+y),col
				Next
			Next
		Next
		Next
		SetBuffer BackBuffer()

		;----------------------------------------------------------------------
		;transfer bitmap and flip it vertically
		;----------------------------------------------------------------------
		temp=imout
		imout=CreateImage (ImageWidth(temp),ImageHeight(temp))
		b=0
		For a=ImageHeight(temp)-1 To 0 Step -1
			CopyRect 0,a,ImageWidth(imout),1,0,b,ImageBuffer(temp),ImageBuffer(imout)
			b=b+1
		Next

		;----------------------------------------------------------------------
		;force a little blur
		;----------------------------------------------------------------------

		osx=ImageWidth(imout)
		osy=ImageHeight(imout)
		LEV_SHAD_LMBlurImage(radius = 1,osx,osy)

		
		;----------------------------------------------------------------------
		;lsave bmp
		;----------------------------------------------------------------------
		SaveBuffer  (ImageBuffer(imout),filename+add2fname+".bmp")
		If Instr (use,"HEIGHT") dgui_messagebox(0,"Offset","Note: Zero offset is "+lowest)
		;DrawImage imout,0,64:Flip
		filenameout=filename
		;----------------------------------------------------------------------
		;cleanup 
		;----------------------------------------------------------------------
		FreeImage temp
		FreeImage imout
		


The loader:
If use$="HEIGHT"
multiplier24=inputbox("Color Value Division","What was the multiplier when heightmap was saved? Ted's save default is 100","100")
offset=inputbox("Offset - This moves the terrain mesh down by a set amount.","-what is the lowest point of the terrain to be?:","0")
EndIf
For b=1 To trn_quadnumberY
    For a=1 To trn_quadnumberX
            dgui_messagebox(-1,"Importing",">>Processing Line:"+Str(b)+ " of "+Str( trn_quadnumbery),">>Please Wait.")
            segs(a,b)=CreateImage (trn_size,trn_size)

            CopyRect(a-1)*(trn_size-1),(b-1)*(trn_size-1),trn_size,trn_size,0,0,ImageBuffer(map),ImageBuffer(segs(a,b))
            
            surf=GetSurface(trn_modifier(a,b),1)
            
            SetBuffer ImageBuffer(segs(a,b))
            For d=0 To trn_size-1
                    For c=0 To trn_size-1
                            ;get col for heightmaps
                            rgb%=ReadPixel(c,d)
                            ;getcol for alpha and colormaps
                            GetColor c,d
                            red=ColorRed()
                            gre=ColorGreen()
                            blu=ColorBlue()
                            If use="HEIGHT"
                                    ; Get each 8bit component color
                                    bloo%=((rgb%)Shr 16) And $FF
                                    gren%=((rgb% ) Shr 8) And $FF
                                    redd%=(rgb% And $FF)
                                    ; Height map resolution
                                    If res=0 res=8
                                    Select res
										Case 8
											;Calc 8bit height Grayscale (rgb all equal)
											hgt#=(gren)+offset  
										Case 12
											;Calc 12bit height (g and r channels, g most significant)
											hgt#=(gren% Shl 4 + (redd% And $0F))+offset
										Case 16
											;Calc 16bit height (full g and r channels, g most significant)
											hgt#=((gren% Shl 8 + redd%)+offset)
										Case 24
											;Calc 24bit Luminance =  0.3 x R + 0.59 x G + 0.11 x B
											hgt#=(0.3 * redd%)+(0.59 * gren%)+(0.11 * bloo%) + offset
										Case 25
											;Calc 24bit logical
											;hgt=argb(red,gre,blu) + offset
											hgt#=((Float(blu+(256*gre)+(65536*red))/multiplier24))+offset
										Case 26
											;Calc 24bit logical
											;hgt=argb(red,gre,blu) + offset
											hgt#=((Float(red+(256*gre)+(65536*blu))/multiplier24))+offset
                                    End Select
                                    ;average = (((red+gre+blu)/3)-128)
                                    v=c+(d*trn_size)
                                    vx#=VertexX(surf,v)
                                    vz#=VertexZ(surf,v)
                                    ;VertexCoords surf,v,vx,average,vz
									TFormPoint 0,hgt#,0,0,trn_modifier(a,b)
                                    VertexCoords surf,v,vx,TFormedY(),vz
                                    trn_updateflags(a,b)=1
                                    editlatch=1
                            EndIf
                            If use="COLOR1" 
                                    v=c+(d*trn_size)
                                                                            
                                    VertexColor trn_layer1(a,b),v,red,gre,blu,1
                                    VertexColor trn_layer2(a,b),v,red,gre,blu,VertexAlpha(trn_layer2(a,b),v)
                                    VertexColor trn_layer3(a,b),v,red,gre,blu,VertexAlpha(trn_layer3(a,b),v)
                                    VertexColor trn_layer4(a,b),v,red,gre,blu,VertexAlpha(trn_layer4(a,b),v)
                                    VertexColor trn_layer5(a,b),v,red,gre,blu,VertexAlpha(trn_layer5(a,b),v)
                                    VertexColor trn_layer6(a,b),v,red,gre,blu,VertexAlpha(trn_layer6(a,b),v)
                                    editlatch=2
                            EndIf
                            If Instr(use,"ALPHA")
                                    If use="ALPHA2" psurf=trn_layer2(a,b)
                                    If use="ALPHA3" psurf=trn_layer3(a,b)
                                    If use="ALPHA4" psurf=trn_layer4(a,b)
                                    If use="ALPHA5" psurf=trn_layer5(a,b)
                                    If use="ALPHA6" psurf=trn_layer6(a,b)
                                    v=c+(d*trn_size)
                                    vr#=VertexRed(trn_layer1(a,b),v)
                                    vg#=VertexGreen(trn_layer1(a,b),v)
                                    vb#=VertexBlue(trn_layer1(a,b),v)
                                    raw=(red+gre+blu)/3
                                    If raw<1 va#=0.000
                                    If raw>0 va#=0.000
                                    If raw>42 va#=setup_alphalimit*.2
                                    If raw> 85 va#=setup_alphalimit*.4
                                    If raw>127 va#=setup_alphalimit*.6
                                    If raw>170 va#=setup_alphalimit*.8
                                    If raw>213 va#=setup_alphalimit
                                    VertexColor psurf,v,vr,vg,vb,va
                                    editlatch=2
                            EndIf
                    Next
            Next
            SetBuffer BackBuffer()
            FreeImage segs(a,b)
    Next
Next



Oiduts Studios(Posted 2010) [#10]
@StevieG Thanks but I did try multiple variable under linepick, and I also tried a set of coordinates instead of go up, go down, go left, and go right.

@D4NM4N Thank you so much for this, sorry i didn't answer back, i had exams, but i will look through this today. This is VERY helpful.


D4NM4N(Posted 2010) [#11]
Np,

Most of the code you dont need at all as it also handles 24bit height, vertex color and vertex alpha maps as well, but the 8 bit greyscale bits would be the best place to start.