Channels ▼
RSS

JVM Languages

Heightmap Terrain Rendering

Source Code Accompanies This Article. Download It Now.


Rendering

How do you render the generated quads? The answer to this question is in the render method of the HeightMap class; see Listing Eight. All you need to do is go through the table of quads and render them at their given position in space. The user of the render method may supply a transform to be applied to each quad after the local transform, which is only putting each quad in its own place. Finally, you place the water mesh at the height level defined during heightmap creation.

public void render(Graphics3D g3d, Transform t)
    {
        for(int x = 0; x < map.length - 1; x++)
        {
            for(int y = 0; y < map[x].length - 1; y++)
            {
                localTransform.setIdentity();

                localTransform.postTranslate(x * 5.0f, 0.0f, (mapHeight- y) * -5.0f);
                localTransform.postMultiply(t);
                g3d.render(map[x][y], localTransform);
            }
        }
       
        localTransform.setIdentity();
        localTransform.postScale(255, 255, 255);
        localTransform.postRotate(-90, 1.0f, 0.0f, 0.0f);
        g3d.render(water, localTransform);
    }
Listing Eight

Putting It All Together

Now you are finally ready to use the HeightMap class to load and render a heightmap from an existing grayscale image; see Listing Nine. Nothing out of the ordinary here. You just load the heightmap and do some transforms on it, since the transform is supplied to the HeightMap's render method later on. We want to scale it a lot since terrain is normally huge.

private void createScene()
    {
        try
        {
            // We're using a pretty high resolution. If you want to test this on an actual
            // handheld, try using a lower resolution, such as 0.20 or 0.10
         hm = new HeightMap("/res/heightmap4.png", 0.30f, 40);       
                 
         t.postTranslate(0.0f, -2.0f, -5.0f);
         t.postScale(0.01f, 0.01f, 0.01f);
        
         camTrans.postTranslate(0.0f, 5.0f, 0.0f);
         //camTrans.postTranslate(0.0f, 5.0f, 2.0f);
        }
        catch(Exception e)
        {
            System.out.println("Heightmap error: " + e.getMessage());
            e.printStackTrace();
            TutorialMidlet.die();
        }
    }
Listing Nine

It is also important to note that for clarity, the HeightMap I present here is rendered without culling, something needed with large terrains. Finally, Listing Ten presents the draw method for rendering the HeightMap. While the HeightMap.render(g3d, t) method is straightforward, the controls might be unfamiliar. Move the camera with the joystick—up, down, and rotate left and right. To move the camera forward, use the FIRE key.

// Get the Graphics3D context
            g3d = Graphics3D.getInstance();
           
         // First bind the graphics object. We use our pre-defined rendering hints.
         g3d.bindTarget(g, true, RENDERING_HINTS);
        
         // Clear background
         g3d.clear(back);
        
         // Bind camera at fixed position in origo
         g3d.setCamera(cam, camTrans);
        
         // Render everything
         hm.render(g3d, t);
        

         // Check controls for camera movement
         if(key[UP])
         {
             camTrans.postTranslate(0.0f, 1.0f, 0.0f);
         }
         if(key[DOWN])
         {
             camTrans.postTranslate(0.0f, -1.0f, 0.0f);
         }
         if(key[LEFT])
         {
             camTrans.postRotate(5, 0.0f, 1.0f, 0.0f);
         }
         if(key[RIGHT])
         {
             camTrans.postRotate(-5, 0.0f, 1.0f, 0.0f);
         }
        
         // Fly forward
         if(key[FIRE])
             camTrans.postTranslate(0.0f, 0.0f, -1.0f);
Listing Ten

Conclusion

At this point, why don't you load the other heightmaps supplied in the source code files available electronically? See what kind of terrains come out. Or even better, create your own heightmap image!


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video