Away3D HeightMapModifierOne of the things that I love about Away3D is that doing simple things is simple. You don’t have to jump through a bunch of hoops and write a bunch of code just to display an irregular mesh – like the one on the right.

The mesh to the right is created very simply by placing a Plane in the scene.

// Plane
var plane : Plane = new Plane();
plane.width 		= 4000;
plane.height 		= 4000;
plane.segmentsW 		= 50;
plane.segmentsH 		= 50;
_view3D.scene.addChild( plane );

This plane here has a WireframeMaterial applied to it to give it that early 1980s video game look. Although that isn’t absolutely essential because one of the things that Away3D is great at is doing things for you if you don’t explicitly tell it to. For instance to see a Plane, or any other shape, it must have some material applied to it otherwise there’s nothing to see. So if you don’t give your object a material it will be assigned one with a random color. That way you can at least see it.

var material : WireframeMaterial = new WireframeMaterial( 0xFFFFFF );
material.wireAlpha 		= 0.5;
plane.material 		= material;

With just this much you would have a Plane that looks like this image below.

Away3D Plane

To give it that bumpy look you need to add a HeightMapModifier. Here’s what The Essential Guide to 3D in Flash – book review – has to say about Height Maps.

A height map is generally considered to be a bitmap image that contains data relating to the relief of a 3D mesh’s surface. The pixel values are interpreted as height values, and the resulting image describes a continuous contour in 3D. This can be applied to a mesh using the UV coordinates on each face to map the height map as a texture map. A position offset is then applied to the vertices of the mesh by taking the average of the offset values for the height map around the UV positions of each vertex point. ( Chapter 7, pg. 163 )

What that means is that the brightness values from a bitmap are translated into offsets for the vertices of the mesh.

The bitmapData that I’m using here is created dynamically using Perlin noise.

var bmp : BitmapData = new BitmapData( 4000, 4000, false );
bmp.perlinNoise( 200, 200, 2, 0, true, true, 7, true );

var heightMap :  HeightMapModifier = new HeightMapModifier( plane, bmp );
heightMap.scale 	= 1.2 // arbitrary value
heightMap.offset 	= -heightMap.scale * 127; // re-center the mesh
heightMap.execute();

That produces the the effect below:

view source

There are two ultra important aspects of using the HeightMapModifier that are easy to miss. First, after you set or change your heightMap you have to call the .execute() method on it. That's a common aspect of things in Away3D where you can set things all you like but at the end you have to tell it to actually render. That's a good thing because it lets you do lots of modifications as you wish which isn't all that processor intensive and then tell Away3D to render the display - which is processor intensive - when your ready and only when you're ready.

The other aspect to pay close attention to is the heightMap.offset. The Essential Guide to 3D in Flash - book review -  has this to say about using offset:

Because the vertices in the plane primitive all belong to faces pointing in the same direction, they all have the same vertex normal. This means that any perturbation applied by the HeightMapModifier object will move all vertices in the same direction—in this case, either up or down.

To keep the mesh centered in the scene while this movement occurs, we counterbalance the effect of the height map by adjusting the offset property of the HeightMapModifier object in the opposite direction. The height map values taken from the supplied Perlin noise bitmap range from 0 to 255, so to center these offsets, we need adjust the base offset property by an appropriately scaled –127 units. This is done in the final line of code of the preceding _onKeyDown() method by multiplying –127 by _scale to match the scaling applied to our height map values, which results in an overall vertex offset applied equally in both up and down directions from the starting position of the vertices in the plane. ( Chapter 7, pg 166 )

The automatic scaling up and down motion has nothing really to do with Away3D. I'm just using the timer.currentCount to adjust the value of the slider which in turn changes the scale on the heightMap.

scaleSlider.value = Math.sin( _tic.currentCount / 10 );

What do you think?