Here is a terrain height map class I put together that uses an RGB index of 1537 colors instead of the usual 256 B&W range. It produces nice, smooth terrains when scaled down a little. I used blender to make the map. Here is an example blend file: http://www.irishgrin.com/progs/heightmodelRGB.zip
The code is in two classes.
Here is the first one.
package (YOUR PACKAGE HERE)
import com.jmex.terrain.util.AbstractHeightMap;
import java.awt.Image;
import java.awt.Color;
import java.awt.image.PixelGrabber;
/**
* RGBHeightMap creates a height map from an RGB image created with a specific heightmap gradient.
* It requires a square image. Height values are read as follows:<br>
* Black is the lowest value. Then, the values ascend starting from black to
* red, red to yellow, yellow to green, green to cyan, cyan to blue, blue to
* white. These values are indexed in the RGBIndexer. There isn't much error
* checking for the time being (bad programmer, no cookie).
*/
public class RGBHeightMap extends AbstractHeightMap
{
public RGBHeightMap(Image RGBImage)
{
super();
int width = 0, height = 0;
int[] pixels;
/* Don't mess with media tracker, just kep looking for the width and
height until thry are > 0. Not good if the image doesn't exist, but
this is what I felt like to doing just to get it working. */
while(width < 1 || height < 1)
{
width = RGBImage.getWidth(null);
height = RGBImage.getHeight(null);
}
PixelGrabber pg = new PixelGrabber(RGBImage, 0, 0, -1, -1, true);
try
{
pg.grabPixels();
}
catch (InterruptedException e) {}
size = width;
pixels = (int[])pg.getPixels();
heightData = new int[pixels.length];
for(int i = 0; i < heightData.length; i++)
{
heightData[i] = RGBIndexer.getIndexer().getIndex(pixels[i]);
}
}
public boolean load()
{
return true;
}
}
and put this in the same package
package (YOUR PACKAGE HERE)
import java.awt.Color;
import java.awt.image.PixelGrabber;
import java.util.HashMap;
public class RGBIndexer
{
private static final RGBIndexer indexer = new RGBIndexer();
private HashMap colorIndexes = new HashMap();
public static RGBIndexer getIndexer()
{
return indexer;
}
private RGBIndexer()
{
initHashMap();
}
private void initHashMap()
{
int r = 0, g = 0, b = 0;
int iteration = 0;
int index = 0;
do
{
switch(iteration)
{
case 0: // Increase red values (black to red)
if(r <= 255)
{
setColorIndex(r, g, b, index);
r++;
}
else
{
iteration++;
r = 255;
}
break;
case 1: // Increase green values
if(g < 255)
{
g++;
setColorIndex(r, g, b, index);
}
else
{
iteration++;
}
break;
case 2: // Decrease red values
if(r > 0)
{
r--;
setColorIndex(r, g, b, index);
}
else
{
iteration++;
}
break;
case 3: // Increase blue values
if(b < 255)
{
b++;
setColorIndex(r, g, b, index);
}
else
{
iteration++;
}
break;
case 4: // Decrease green values
if(g > 0)
{
g--;
setColorIndex(r, g, b, index);
}
else
{
iteration++;
}
break;
case 5: // Increase red and green values
if((r < 255) && (g < 255))
{
r++; g++;
setColorIndex(r, g, b, index);
}
else
{
iteration++;
}
break;
}
index++;
}
while(iteration < 6);
System.out.println(index);
}
private void setColorIndex(int r, int g, int b, int index)
{
Color c = new Color(r, g, b);
colorIndexes.put(c.getRGB(),index);
}
public int getIndex(int rgb)
{
if(colorIndexes.containsKey(rgb))
{
Integer val = (Integer)colorIndexes.get(rgb);
return val.intValue();
}
return -1;
}
}
It may not be the most efficient right now, but it gets the job done.
I might make a blender tutorial if anyone is interested in how to make terrains for use with these classes (for those who can't figure it out from the example file).