📄 heightmap.java
字号:
import java.io.IOException;
import javax.microedition.lcdui.Image;
import javax.microedition.m3g.*;
public class HeightMap
{
// The actual heightmap containing the Y-coords of our indexBuffer
private short[] heightMap;
private int[] data;
// Map dimensions
private int mapWidth;
private int mapHeight;
// Actual quads
private Mesh[][] map;
private static final String TerrainImgFn ="/Terrain0.png" ;
private float resolution = 0.25f;
private int imgw, imgh;
private static VertexArray POSITION_ARRAY;
private static VertexArray COLOR_ARRAY ;
private static VertexArray TEXCOORD_ARRAY;
private static VertexBuffer vertexBuffer;
private static IndexBuffer indexBuffer;
private static Appearance appearance;
private static PolygonMode polygonmode;
private static Texture2D texture;
// Local transform used for internal calculations
private Transform localTransform = new Transform();
/**
* Allocates the internal heightmap and prepares it for rendering.
* @param imageName The path to the actual heightmap BW image
* @param resolution The resolution of the heightmap. A value of 1.0 means that each pixel is one quad.
* @param waterLevel TODO
* @throws IOException if any error occurs while loading the heightmap image or the texture images.
*/
public HeightMap() throws IOException
{
// Check for invalid resolution values
if(resolution <= 0.0001f || resolution > 1.0f)
throw new IllegalArgumentException("Resolution too small or too large");
// Load image and allocate the internal array
loadMapImage();
createTexture();
// Create quads
createQuads();
}
public Mesh[][]getQuads(){
return map;
}
public int getMapWidth(){
return mapWidth;
}
public int getMapHeight(){
return mapHeight;
}
private static void createTexture(){
Image2D waterIm = null;
try {
waterIm = (Image2D)Loader.load("/SAND1.PNG")[0];
}
catch (Exception e)
{ System.out.println("Cannot make image " ); }
texture = new Texture2D(waterIm);
texture.setFiltering(Texture2D.FILTER_NEAREST, Texture2D.FILTER_NEAREST);
texture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
}
/**
* Create all quads (Triangle pairs) that our
*/
private void createQuads()
{
map = new Mesh[mapWidth][mapHeight];
short[] heights = new short[4];
for(int x = 0; x < (mapWidth - 1); x++)
{
for(int y = 0; y < (mapHeight - 1); y++)
{
// Set heights
heights[0] = heightMap[x + y * mapWidth];
heights[1] = heightMap[x + y * mapWidth + 1];
heights[3] = heightMap[x + (y + 1) * mapWidth];
heights[2] = heightMap[x + (y + 1) * mapWidth + 1];
// Create mesh
map[x][y] = createQuad(heights);
}
}
}
private void loadMapImage() throws IOException
{
// Load actual image
Image img = Image.createImage(TerrainImgFn);
// Allocate temporary memory to store pixels
data = new int[img.getWidth() * img.getHeight()];
// Get its rgb values
img.getRGB(data, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());
imgw = img.getWidth();
imgh = img.getHeight();
// Clear image
img = null;
System.gc();
// Calculate new width and height
mapWidth = (int)(resolution * imgw);
mapHeight = (int)(resolution * imgh);
// Allocate heightmap
heightMap = new short[mapWidth * mapHeight];
// Calculate height and width offset into image
int xoff = imgw / mapWidth;
int yoff = imgh / mapHeight;
// Set height values
for(int y = 0; y < mapHeight; y++)
{
for(int x = 0; x < mapWidth; x++)
{
heightMap[x + y * mapWidth] = (short)((data[x * xoff + y * yoff * imgw] & 0x000000ff) * 10);
}
}
// Clear data
data = null;
img = null;
System.gc();
}
/**
* Renders this heightmap using a specified graphics context and a transform.
* @param g3d
* @param t
*/
public void setTransform(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 * 20.4f, 0.0f, (mapHeight - y) * -20.4f);
localTransform.postScale(0.04f, 0.04f, 0.04f);
localTransform.postMultiply(t);
map[x][y].setTransform(localTransform);
}
}
}
/**
* Creates a colored quad consisting of two indexBuffer.
* The heights parameter is an array that holds the heights of the new quad.
* The array must have a length of 4 and goes counter-clockwise starting from the
* northwestern position of the quad (-1, -1)
* @param heights The height array, denoting the heights (y-coords) of the four corners.
* @param cullFlags
* @param texFilename
* @return
*/
public static Mesh createQuad(short[] heights)
{
// The POINTS of the quad
short[] POINTS = {-255, heights[0], -255,
255, heights[1], -255,
255, heights[2], 255,
-255, heights[3], 255};
// The arrays
// Create the model's POINTS
POSITION_ARRAY = new VertexArray(POINTS.length/3, 3, 2);
POSITION_ARRAY.set(0, POINTS.length/3, POINTS);
// Allocate COLORS array
byte[] COLORS = new byte[12];
short[] TEXCOORDS = {
0,0, 1,0,
1,1, 0,1
};
TEXCOORD_ARRAY = new VertexArray(TEXCOORDS.length/2, 2, 2);
TEXCOORD_ARRAY.set(0, TEXCOORDS.length/2, TEXCOORDS);
// Compose a VertexBuffer out of the previous POINTS and texture coordinates
vertexBuffer = new VertexBuffer();
vertexBuffer.setPositions(POSITION_ARRAY, 1.0f, null);
vertexBuffer.setTexCoords(0, TEXCOORD_ARRAY, 1.0f, null);
// Create INDICES and face lengths
int INDICES[] = new int[] {0, 1, 3, 2};
int[] LENGTHS = new int[] {4};
// Create the model's indexBuffer
indexBuffer = new TriangleStripArray(INDICES, LENGTHS);
// Create the appearance
appearance = new Appearance();
polygonmode = new PolygonMode();
polygonmode.setCulling(PolygonMode.CULL_NONE);
polygonmode.setPerspectiveCorrectionEnable(true);
polygonmode.setShading(PolygonMode.SHADE_SMOOTH);
appearance.setPolygonMode(polygonmode);
createTexture();
appearance.setTexture(0, texture);
// Finally create the Mesh
Mesh mesh = new Mesh(vertexBuffer, indexBuffer, appearance);
// All done
return mesh;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -