package test0580; | |
import ecosim.model.DefaultLocationModel; | |
import ecosim.model.LocationModel; | |
import ecosim.model.MapModel; | |
/** | |
* @author Ben Hutchison | |
* | |
*/ | |
public class DiamondSquareTerrainGenerator implements MapGenerator | |
{ | |
//number of halving recursive subdivisons to cover map | |
int _subdivisions; | |
//both width and height = 2^_subdivisions + 1 (ie square map) | |
int _width, _height; | |
d | |
LocationModel[][] _map; | |
/* (non-Javadoc) | |
* @see ecosim.model.map.MapGenerator#generateLocation(int, int, ecosim.model.MapModel) | |
*/ | |
public LocationModel generateLocation(int i, int j, MapModel mapModel) | |
{ | |
// TODO Auto-generated method stub | |
return null; | |
} | |
/* (non-Javadoc) | |
* @see ecosim.model.map.MapGenerator#setSize(int, int) | |
*/ | |
public void setSize(int width, int height) | |
{ | |
_subdivisions = Math.max(ceilLogBase2(width), ceilLogBase2(height)); | |
//diamond-square alg needs map size == power of 2 plus one; select next suitable size | |
_width = powerOf2(_subdivisions) + 1; | |
_height = powerOf2(_subdivisions) + 1; | |
_map = new LocationModel[_width][_height]; | |
generateMap(); | |
} | |
void generateMap() { | |
int lod = _subdivisions; | |
for (int i = 0; i < lod; ++ i) { | |
int q = 1 << i, r = 1 << (lod - i), s = r >> 1; | |
for (int j = 0; j < divisions; j += r) | |
for (int k = 0; k < divisions; k += r) | |
diamond (j, k, r, rough); | |
if (s > 0) | |
for (int j = 0; j <= divisions; j += s) | |
for (int k = (j + s) % r; k <= divisions; k += r) | |
square (j - s, k - s, r, rough); | |
rough *= roughness; | |
} | |
} | |
void diamond(int x, int y, int side, double scale) { | |
if (side > 1) { | |
int half = side / 2; | |
double avg = (terrain[x][y] + terrain[x + side][y] + | |
terrain[x + side][y + side] + terrain[x][y + side]) * 0.25; | |
terrain[x + half][y + half] = avg + rnd () * scale; | |
} | |
} | |
void square (int x, int y, int side, double scale) { | |
int half = side / 2; | |
double avg = 0.0, sum = 0.0; | |
if (x >= 0) | |
{ avg += terrain[x][y + half]; sum += 1.0; } | |
if (y >= 0) | |
{ avg += terrain[x + half][y]; sum += 1.0; } | |
if (x + side <= divisions) | |
{ avg += terrain[x + side][y + half]; sum += 1.0; } | |
if (y + side <= divisions) | |
{ avg += terrain[x + half][y + side]; sum += 1.0; } | |
terrain[x + half][y + half] = avg / sum + rnd () * scale; | |
} | |
public static int ceilLogBase2(int value) { | |
if (value <= 1) | |
return 0; | |
int exponent = 1; | |
value--; | |
while ((value = value >> 1) != 0) | |
exponent++; | |
return exponent; | |
} | |
public static int powerOf2(int exponent) { | |
int value = 1; | |
while (exponent-- > 0) | |
value = value << 1; | |
return value; | |
} | |
public static void main(String[] args) | |
{ | |
System.out.println("1: "+ceilLogBase2(1)); | |
System.out.println("2: "+ceilLogBase2(2)); | |
System.out.println("3: "+ceilLogBase2(3)); | |
System.out.println("4: "+ceilLogBase2(4)); | |
System.out.println("5: "+ceilLogBase2(5)); | |
System.out.println("-3: "+ceilLogBase2(3)); | |
System.out.println("1024: "+ceilLogBase2(1024)); | |
System.out.println("1023: "+ceilLogBase2(1023)); | |
System.out.println("1025: "+ceilLogBase2(1025)); | |
System.out.println("1 "+powerOf2(1)); | |
System.out.println("2 "+powerOf2(2)); | |
System.out.println("3 "+powerOf2(3)); | |
} | |
} |