class HeightmapGenerator
{
private float _heightmap[][];
private int _size;
private float _noise_scale;
public HeightmapGenerator(String filename)
{;
PImage img=loadImage(filename);
img.loadPixels();
// Generate a perlins noise height field using s as as the size
_heightmap = new float[img.width][img.height];
for(int y = 0 ; y < img.height; y++)
{
for( int x = 0; x < img.width; x++)
{
color col = img.pixels[img.width*y+x];
float v = (red(col)*green(col)*blue(col))/(255*255*255);
_heightmap[x][y] = v;
}
}
}
// Get the size of the heightmaps wiudth ( this is the same as the height - as its square homeboi )
public float[][] GetHeightMap()
{
return _heightmap;
}
// Returns the width of the heightmap, which happens to be the same as its height.. cool huh?
public int[] getSize()
{
int[] ret = new int[2];
ret[0] = _heightmap[0].length;
ret[1] = _heightmap[1].length;
return ret;
}
}
import processing.opengl.*;
int terrain_size = 5000;
float[][] heightmap; // This is a reference to the data from the heightmap generator class
TerrainBlock[][] terrain_map; // Referenmce to the terrain generatged map
TerrainGenerator terrain;
int block_size = 5;
int step = 6;
Boolean light = false;
int TWOD = 0;
int THREED = 1;
int drawmode = TWOD;
void setup()
{
size(1000,500, P3D);
background(0);
directionalLight(126, 126, 126, 0, 0, -1);
ambientLight(102, 102, 102);
lights();
HeightmapGenerator heightgen;
// Generates a super dooper perlins noise greyscale height map
heightgen = new HeightmapGenerator("tree.jpg");
heightmap = heightgen.GetHeightMap();
// Converts the super dooper heightmap into a rogue terrian... yea yea baby
terrain = new TerrainGenerator( heightmap, heightgen.getSize(), block_size);
terrain_map = terrain.GetTerrainMap();
}
void draw()
{
background(0);
if ( light )
lights();
if (terrain != null )
{
if ( drawmode == TWOD)
terrain.draw2D();
else
terrain.draw3Dfast();
}
}
void keyPressed()
{
if ( keyCode == UP )
{
terrain.viewport_up(step);
}
if ( keyCode == DOWN )
{
terrain.viewport_down(step);
}
if ( keyCode == LEFT )
{
terrain.viewport_left(step);
}
if ( keyCode == RIGHT )
{
terrain.viewport_right(step);
}
if ( key == 'v' )
{
terrain._ascii_view = ! terrain._ascii_view;
}
if ( key == 'm' )
{
if ( drawmode == TWOD )
drawmode = THREED;
else
drawmode = TWOD;
}
if ( key == 'w' )
{
terrain._wire_mode = ! terrain._wire_mode;
}
if ( key == 'l' )
light = ! light;
redraw();
}
public final int DEEP_WATER = 0;
public final int SHALLOW_WATER = 1;
public final int SAND = 2;
public final int PLAINS = 3;
public final int GRASS = 4;
public final int HILLS = 5;
public final int TREE = 6;
public final int VERY_DEEP_WATER = 7;
public final int HILL_TIPS = 8;
public color COLOR_DEEP_WATER = #3549A5;
public color COLOR_SHALLOW_WATER = #AAB9FF;
public color COLOR_SAND = #ECF5DA;
public color COLOR_PLAINS = #C1CEA7;
public color COLOR_GRASS = #00CC00;
public color COLOR_HILLS = #E3E3E3;
public color COLOR_TREE = #75815B;
public color COLOR_VERY_DEEP_WATER = #1C2C6F;
public color COLOR_HILL_TIPS = #FFFFFF;
class TerrainBlock
{
public float actual_z; // This is the actual height of the block without the processing
public float z; // This is the height of the block AFTER the processing of the map
public int type; // The type of the block (WATER/GRASS etc )
public String character; // The ASCII character of this block
}
class TerrainGenerator
{
TerrainBlock[][] _terrain;
int _size;
int _viewport_x = 0;
int _viewport_y = 0;
int _viewport_width = 75;
int _viewport_height = 75;
int _camera_x = 200;
int _camera_y = 0;
public boolean _ascii_view = true;
public boolean _wire_mode = false;
PFont font;
// Pass the heightmap that I will go an convert into some sort of coool pixelated terrain
// god I shoudl nopt code while im drunk coz I got no idea how the code will bloody work
public TerrainGenerator( float[][] heghtmap, int[] terrain_size, int block_size )
{
println(terrain_size);
font = loadFont( "Monospaced.plain-20.vlw" );
textFont( font );
// calculate how many times I have to check across thew heightmap
int wx = terrain_size[0] / block_size;
int wy = terrain_size[1] / block_size;
_terrain = new TerrainBlock[ wx ] [ wy ];
for( int x = 0; x < wx; x++)
for( int y = 0; y < wy; y++)
_terrain[x][y] = new TerrainBlock();
_size = wx;
// Run the pixelation routine
pixelate_terrain(wx,wy);
}
public void create_mesh()
{
}
//--------------- Calculates what type of block it is by checking the z value of the TerrainBlock
private void set_type ( TerrainBlock block )
{
if ( block.z < 15 )
{
block.type = VERY_DEEP_WATER;
block.character = "~";
return;
}
if ( block.z < 25 )
{
block.type = DEEP_WATER;
block.character = "~";
return;
}
else if ( block.z < 30 )
{
block.type = SHALLOW_WATER;
block.character = "~";
return;
}
else if ( block.z < 35 )
{
block.type = SAND;
block.character = ".";
return;
}
else if ( block.z < 40 )
{
block.type = PLAINS;
block.character = "-";
return;
}
else if ( block.z < 60 )
{
int r = int(random(100));
if ( r < 20 )
{
block.type = TREE;
block.character = "×";
}
else
{
block.type = GRASS;
block.character = "*";
}
return;
}
else if ( block.z < 75 )
{
block.type = HILLS;
block.character = "^";
}
else
{
block.type = HILL_TIPS;
block.character = "^";
}
}
//--------------- Returns the color the block represents
private color block_color ( TerrainBlock block )
{
switch ( block.type )
{
case VERY_DEEP_WATER:
{
return COLOR_VERY_DEEP_WATER;
}
case DEEP_WATER:
{
return COLOR_DEEP_WATER;
}
case SHALLOW_WATER:
{
return COLOR_SHALLOW_WATER;
}
case SAND:
{
return COLOR_SAND;
}
case PLAINS:
{
return COLOR_PLAINS;
}
case GRASS:
{
return COLOR_GRASS;
}
case HILLS:
{
return COLOR_HILLS;
}
case HILL_TIPS:
{
return COLOR_HILL_TIPS;
}
case TREE:
{
return COLOR_TREE;
}
default:
{
return #000000;
}
}
}
//--------------- Pixelates the terrain (bascially convert it into many 'blocks')
private void pixelate_terrain(int wx, int wy)
{
// ex 50
for ( int iy = 0; iy < wy; iy++)
{
for( int ix = 0; ix < wx; ix++)
{
float sum = 0.0f;
// ex 10
for( int y = 0; y < block_size; y++)
{
for( int x = 0; x < block_size; x++)
{
sum = sum + heightmap[ ix*block_size+x ] [ iy*block_size+y ] ;
}
}
sum = sum / ( block_size*block_size );
_terrain [ ix ] [ iy ].actual_z = sum;
_terrain [ ix ] [ iy ].z = sum * 100;
set_type( _terrain [ ix ] [ iy ] );
}
}
}
public int viewport_up( int step )
{
_viewport_y -= step;
_camera_y -= -step;
if ( _viewport_y < 0) _viewport_y = 0;
return _viewport_y;
}
public int viewport_down( int step )
{
_viewport_y += step;
_camera_y += -step;
if ( (_viewport_y + _viewport_height ) > _size )
{
_viewport_y = _size - _viewport_height;
}
return _viewport_y;
}
public int viewport_left( int step )
{
_viewport_x -= step;
_camera_x -= -step;
if ( _viewport_x < 0) _viewport_x = 0;
return _viewport_x;
}
public int viewport_right( int step )
{
_viewport_x += step;
_camera_x += -step;
if ( (_viewport_x + _viewport_width) > _size )
{
_viewport_x = _size-_viewport_width;
}
return _viewport_x;
}
public void draw2D()
{
for( int y =0; y < _viewport_height; y++)
for(int x = 0 ; x < _viewport_width; x++)
{
if (!_wire_mode )
{
stroke ( block_color( _terrain[_viewport_x+x][_viewport_y+y] ));
}
else
{
stroke(0);
}
fill( block_color( _terrain[_viewport_x+x][_viewport_y+y] ));
if ( ! _ascii_view )
{
rect( x*block_size, y*block_size, block_size, block_size);
}
else
{
text ( _terrain[ _viewport_x + x] [_viewport_y + y].character, x*11, y*11 );
}
}
}
// Very slow - attempts to ignore all objects that are not directly in view
public void draw3D()
{
for( int y =0; y < _size; y++)
for(int x = 0 ; x < _size; x++)
{
stroke ( block_color( _terrain[x][y] ));
fill( block_color( _terrain[x][y] ));
if ( ((_camera_x + ( block_size*x)) > 0) && ((_camera_x + ( block_size*x)) < 600) )
if ( (_camera_y + (block_size * y ) > 0 ) && (_camera_y + (block_size * y ) < 500 ))
{
pushMatrix();
rotateX(45);
translate( _camera_x, _camera_y );
translate( x* block_size, y*block_size, -150 + _terrain[x][y].actual_z * 200 );
// Hide yo kids, Hide yo wife (8)
box(5,5,_terrain[x][y].actual_z * 30);
popMatrix();
}
}
}
// Much faster approach at drawing the map, only draws a set amount of polygons.. sorted
public void draw3Dfast()
{
for( int y =0; y < _viewport_height; y++)
for(int x = 0 ; x < _viewport_width; x++)
{
if (!_wire_mode )
{
stroke ( block_color( _terrain[_viewport_x+x][_viewport_y+y] ));
}
else
{
stroke(0);
}
fill( block_color( _terrain[_viewport_x+x][_viewport_y+y] ));
pushMatrix();
rotateX(45);
translate(200, 100 );
translate( x* block_size, y*block_size, -150 + _terrain[x+_viewport_x][y+_viewport_y].actual_z * 200 );
if ( _terrain[ _viewport_x + x ] [ _viewport_y + y ].type == TREE )
{
box(5,5,_terrain[x+_viewport_x][y+_viewport_y].actual_z * 60);
}
else
{
box(5,5,_terrain[x+_viewport_x][y+_viewport_y].actual_z * 30);
}
popMatrix();
}
}
public TerrainBlock[][] GetTerrainMap()
{
return _terrain;
}
public int GetSize()
{
return _size;
}
}