Terrain mesh to height map
Community Forums/General Help/Terrain mesh to height map
| ||
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. |
| ||
...VertexY()...? cf. http://www.blitzbasic.com/codearcs/codearcs.php?code=2443 |
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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 |
| ||
I never got it working properly so i will have to remake the island, oh well, there were some problems with it anyway. |
| ||
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 |
| ||
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 |
| ||
@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. |
| ||
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. |