Java tutorial
package net.voidGameDev.world.surface; import static org.lwjgl.opengl.GL11.GL_COMPILE; import static org.lwjgl.opengl.GL11.GL_LINEAR; import static org.lwjgl.opengl.GL11.GL_RGB; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER; import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER; import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; import static org.lwjgl.opengl.GL11.glBegin; import static org.lwjgl.opengl.GL11.glBindTexture; import static org.lwjgl.opengl.GL11.glEnd; import static org.lwjgl.opengl.GL11.glEndList; import static org.lwjgl.opengl.GL11.glGenLists; import static org.lwjgl.opengl.GL11.glGenTextures; import static org.lwjgl.opengl.GL11.glNewList; import static org.lwjgl.opengl.GL11.glTexImage2D; import static org.lwjgl.opengl.GL11.glTexParameteri; import static org.lwjgl.opengl.GL11.glVertex3f; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import javax.imageio.ImageIO; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; /** * @author lclc98 Lesser GNU Public License v3 * (http://www.gnu.org/licenses/lgpl.html) */ public class WorldSurfaceRender { /** * The display list that will contain the height-map's vertex data. */ public static int heightmapDisplayList; /** * The points of the height. The first dimension represents the * z-coordinate. The second dimension represents the x-coordinate. The float * value represents the height. */ private static float[][] data; public static int loadTexture(String path) { try { BufferedImage image = ImageIO.read(new File(path)); int[] pixels = new int[image.getWidth() * image.getHeight()]; image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth()); ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4); for (int y = 0; y < image.getHeight(); y++) { for (int x = 0; x < image.getWidth(); x++) { int pixel = pixels[y * image.getWidth() + x]; buffer.put((byte) ((pixel >> 16) & 0xFF)); buffer.put((byte) ((pixel >> 8) & 0xFF)); buffer.put((byte) (pixel & 0xFF)); buffer.put((byte) ((pixel >> 24) & 0xFF)); } } buffer.flip(); int textureID = glGenTextures(); // Generate texture ID glBindTexture(GL_TEXTURE_2D, textureID); // Bind texture ID // Setup texture scaling filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Send texel data to OpenGL glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.getWidth(), image.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); // Return the texture ID so we can bind it later again return textureID; } catch (IOException e) { e.printStackTrace(); return 0; } } public void setUpHeightmap(String heightMap, String texture) { try { // Load the heightmap-image from its resource file BufferedImage heightmapImage = ImageIO.read(getClass().getResource(heightMap)); // Initialise the data array, which holds the heights of the // heightmap-vertices, with the correct dimensions data = new float[heightmapImage.getWidth()][heightmapImage.getHeight()]; // Lazily initialise the convenience class for extracting the // separate red, green, blue, or alpha channels // an int in the default RGB color model and default sRGB // colourspace. Color colour; // Iterate over the pixels in the image on the x-axis for (int z = 0; z < data.length; z++) { // Iterate over the pixels in the image on the y-axis for (int x = 0; x < data[z].length; x++) { // Retrieve the colour at the current x-location and // y-location in the image colour = new Color(heightmapImage.getRGB(x, z)); // Store the value of the red channel as the height of a // heightmap-vertex in 'data'. The choice for // the red channel is arbitrary, since the heightmap-image // itself only has white, gray, and black. data[z][x] = colour.getRed(); } } } catch (IOException e) { e.printStackTrace(); } // Generate a display list handle for the display list that will store // the heightmap vertex data heightmapDisplayList = glGenLists(32); // version 3 and higher. GL11.glEnable(GL_TEXTURE_2D); int z = 0; int x = 0; glBindTexture(GL_TEXTURE_2D, loadTexture(texture)); for (int i = 0; i < 32; i++) { glNewList(heightmapDisplayList + i, GL_COMPILE); // Iterate over the 'strips' of heightmap data. outerLoop: for (; z < data.length - 1; z++) { // Render a quad strip for each 'strip'. glBegin(GL11.GL_QUAD_STRIP); for (; x < data[z].length; x++) { // Take a vertex from the current strip GL11.glTexCoord2d(x, z); glVertex3f(x, data[x][z], z); // Take a vertex from the next strip glVertex3f(x, data[x][z + 1], z + 1); if ((x + 1) % 32 == 0 && (z + 1) % 32 == 0) { glEnd(); glEndList(); System.out.println(x + ":" + z); break outerLoop; } else { System.out.println((x + 1) % 32); } } } } System.out.println("DOne"); } public float getHeight(int x, int z) { return data[z][x]; } }