Author Topic: 3D Visualization of a Height Map  (Read 5437 times)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10656
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
3D Visualization of a Height Map
« on: 2007-Feb-15 »
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 Data
FOR x=0 TO 14
FOR y=0 TO 9
        world[x][y]=RND(15)/10
NEXT
NEXT

        // 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
        WEND



FUNCTION 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-8
LOCAL 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)

ENDFUNCTION


FUNCTION 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 GLBasic
LOCAL 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_OBJNEWGROUP
ENDFUNCTION
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.

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2510
    • View Profile
3D Visualization of a Height Map
« Reply #1 on: 2007-Feb-17 »
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)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10656
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
3D Visualization of a Height Map
« Reply #2 on: 2007-Feb-17 »
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".

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2510
    • View Profile
3D Visualization of a Height Map
« Reply #3 on: 2007-Feb-18 »
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)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10656
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
3D Visualization of a Height Map
« Reply #4 on: 2007-Feb-18 »
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.

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2510
    • View Profile
3D Visualization of a Height Map
« Reply #5 on: 2007-Feb-18 »
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)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10656
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
3D Visualization of a Height Map
« Reply #6 on: 2007-Feb-19 »
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".

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2510
    • View Profile
3D Visualization of a Height Map
« Reply #7 on: 2007-Feb-19 »
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)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10656
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
3D Visualization of a Height Map
« Reply #8 on: 2007-Feb-19 »

The red lines ;)