News:

*NEW* Current Version on STEAM16.793

Webchat:
Visit the chat

3D Visualization of a Height Map

Kitty Hello

If you have a heightmap like: height
• [y] and want to draw it in 3D, here's some code (complete project) to create smooth interpolation between each of the center points of the height map.
Code (glbasic) Select
`DIM world[15][10]// Dummy DataFOR x=0 TO 14FOR y=0 TO 9 world[x][y]=RND(15)/10NEXTNEXT // Create World Object X_OBJSTART 0 X_AUTONORMALS 2 FOR x=0 TO 14 FOR y=0 TO 9 MakeTile(world[], x,y, -15/2, -10/2) NEXT NEXT X_OBJEND // some dummy texture: FILLRECT 0,0,128,128, RGB(0,0,255) FILLRECT 4,4,124,124, RGB(255,255,255) FILLRECT 5,62,123,66, RGB(0,255,0) FILLRECT 62,5,66,123, RGB(0,255,0) FILLRECT 62,62,66,66, RGB(255,0,0) PRINT "GLBasic", 8,8 GRABSPRITE 0, 0,0,128,128 BLACKSCREEN WHILE TRUE X_MAKE3D 1,100, 45 X_CAMERA 1,12,10, 0,0,0 X_SETTEXTURE 0,-1 X_ROTATION GETTIMERALL()/100, 0,1,0 X_DRAWOBJ 0,0 SHOWSCREEN WENDFUNCTION MakeTile: heights[], x,y, offsetx, offsety// Triangle Strip is:// 0--2--4-.// | /| /| .// |/ |/ |/// 1--3--5-.// We need:// 0-1-2// |\|/|// 3-4-5// |/|\|// 6-7-8LOCAL pts[]LOCAL i, px, py, mx, my DIM pts[9][3] // 9 points[x,y,z] pts[0][0]=-1; pts[0][1]=-1 pts[1][0]=.0; pts[1][1]=-1 pts[2][0]= 1; pts[2][1]=-1 pts[3][0]=-1; pts[3][1]=.0 pts[4][0]=.0; pts[4][1]=.0 pts[5][0]= 1; pts[5][1]=.0 pts[6][0]=-1; pts[6][1]= 1 pts[7][0]=.0; pts[7][1]= 1 pts[8][0]= 1; pts[8][1]= 1 // now calculate Z for each point mx = BOUNDS(heights[], 0)-1 my = BOUNDS(heights[], 1)-1 FOR i=0 TO 8 // Get neighbour point // but stop at array border px = MIN(mx, MAX(0, x+pts[i][0])) py = MIN(my, MAX(0, y+pts[i][1])) pts[i][2] = ( heights[px][py]+ _ heights[ x][ y]+ _ heights[px][ y]+ _ heights[ x][py])/4 NEXT // Next a function to create 2 triangles: INC x, offsetx INC y, offsety AddQuad(pts[], x,y,1,0,4,3) AddQuad(pts[], x,y,1,4,2,5) AddQuad(pts[], x,y,3,6,4,7) AddQuad(pts[], x,y,5,4,8,7)ENDFUNCTIONFUNCTION AddQuad: pts[], x,y,a,b,c,d // here we build a triangle stipped quad // for the points a,b,c,d // we divide coordinates by 2, so we get a // rectangle of size 1x1 (-0.5 -> 0.5) // for the texture we divide by 2 and add 0.5 // (0.0 -> 1.0) // last: we swap y and z, since y is vertical in GLBasicLOCAL cl cl =RGB(255,255,255) X_OBJADDVERTEX x+pts[a][0]/2,pts[a][2],y+pts[a][1]/2, pts[a][0]/2+.5, pts[a][1]/2+.5,cl X_OBJADDVERTEX x+pts[b][0]/2,pts[b][2],y+pts[b][1]/2, pts[b][0]/2+.5, pts[b][1]/2+.5,cl X_OBJADDVERTEX x+pts[c][0]/2,pts[c][2],y+pts[c][1]/2, pts[c][0]/2+.5, pts[c][1]/2+.5,cl X_OBJADDVERTEX x+pts[d][0]/2,pts[d][2],y+pts[d][1]/2, pts[d][0]/2+.5, pts[d][1]/2+.5,cl X_OBJNEWGROUPENDFUNCTION`And this is what it looks like:

The red dots are the height coordinates, the blue rects are the tiles and the green lines are where I split the tiles for smooth interpolation.

bigsofty

Excellent.

How could this be optimised?... triangle strips along the whole height map or GL vertrex arrays, or even a vertex shader for example?
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Kitty Hello

strips are converted to triangles internally, anyway. I don't see much optimization space here. Well, shaders could be used to make the thing look "rounder".

bigsofty

Cool, how could I get the height of a point, say, if I give it an X & Y co-ordinate to place an object on it?
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Kitty Hello

The easiest method is to use X_COLLISIONRAY. You can do it (for simple MxN meshes with numerical solution, too). No time right now. I can post some code later.

bigsofty

CollisionRay probably will do a scan of all the triangles on a mesh, then do a normal check, once the correct triangle is found etc... Ill give a custom solution a go... Ill cache the grid coordinates, find the right quad with a division and the use interpolation to find the correct hight... I think that would be quicker?
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Kitty Hello

Yes, sure. Get the INTEGER(x_pos / scale) and INTEGER(y_pos / scale) and you have the upper-left index of the map
• [y] array. Check for out-of-bounds and then interpolate. You have to take care, since the "anticline?" of the 2 triangles flips by 90Â° for each "quad".

bigsofty

Almost... "decline"
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

The red lines