1 package test0580; 2 3 import ecosim.model.DefaultLocationModel; 4 import ecosim.model.LocationModel; 5 import ecosim.model.MapModel; 6 7 8 /** 9 * @author Ben Hutchison 10 * 11 */ 12 public class DiamondSquareTerrainGenerator implements MapGenerator 13 { 14 //number of halving recursive subdivisons to cover map 15 int _subdivisions; 16 17 //both width and height = 2^_subdivisions + 1 (ie square map) 18 int _width, _height; 19 20 d 21 22 LocationModel[][] _map; 23 24 /* (non-Javadoc) 25 * @see ecosim.model.map.MapGenerator#generateLocation(int, int, ecosim.model.MapModel) 26 */ generateLocation(int i, int j, MapModel mapModel)27 public LocationModel generateLocation(int i, int j, MapModel mapModel) 28 { 29 30 // TODO Auto-generated method stub 31 return null; 32 } 33 /* (non-Javadoc) 34 * @see ecosim.model.map.MapGenerator#setSize(int, int) 35 */ setSize(int width, int height)36 public void setSize(int width, int height) 37 { 38 _subdivisions = Math.max(ceilLogBase2(width), ceilLogBase2(height)); 39 40 //diamond-square alg needs map size == power of 2 plus one; select next suitable size 41 _width = powerOf2(_subdivisions) + 1; 42 _height = powerOf2(_subdivisions) + 1; 43 44 _map = new LocationModel[_width][_height]; 45 46 generateMap(); 47 } 48 generateMap()49 void generateMap() { 50 int lod = _subdivisions; 51 for (int i = 0; i < lod; ++ i) { 52 int q = 1 << i, r = 1 << (lod - i), s = r >> 1; 53 for (int j = 0; j < divisions; j += r) 54 for (int k = 0; k < divisions; k += r) 55 diamond (j, k, r, rough); 56 if (s > 0) 57 for (int j = 0; j <= divisions; j += s) 58 for (int k = (j + s) % r; k <= divisions; k += r) 59 square (j - s, k - s, r, rough); 60 rough *= roughness; 61 } 62 } 63 diamond(int x, int y, int side, double scale)64 void diamond(int x, int y, int side, double scale) { 65 if (side > 1) { 66 int half = side / 2; 67 double avg = (terrain[x][y] + terrain[x + side][y] + 68 terrain[x + side][y + side] + terrain[x][y + side]) * 0.25; 69 terrain[x + half][y + half] = avg + rnd () * scale; 70 } 71 72 } 73 square(int x, int y, int side, double scale)74 void square (int x, int y, int side, double scale) { 75 int half = side / 2; 76 double avg = 0.0, sum = 0.0; 77 if (x >= 0) 78 { avg += terrain[x][y + half]; sum += 1.0; } 79 if (y >= 0) 80 { avg += terrain[x + half][y]; sum += 1.0; } 81 if (x + side <= divisions) 82 { avg += terrain[x + side][y + half]; sum += 1.0; } 83 if (y + side <= divisions) 84 { avg += terrain[x + half][y + side]; sum += 1.0; } 85 terrain[x + half][y + half] = avg / sum + rnd () * scale; 86 } 87 88 ceilLogBase2(int value)89 public static int ceilLogBase2(int value) { 90 if (value <= 1) 91 return 0; 92 int exponent = 1; 93 value--; 94 while ((value = value >> 1) != 0) 95 exponent++; 96 return exponent; 97 } powerOf2(int exponent)98 public static int powerOf2(int exponent) { 99 int value = 1; 100 while (exponent-- > 0) 101 value = value << 1; 102 return value; 103 } 104 105 main(String[] args)106 public static void main(String[] args) 107 { 108 System.out.println("1: "+ceilLogBase2(1)); 109 System.out.println("2: "+ceilLogBase2(2)); 110 System.out.println("3: "+ceilLogBase2(3)); 111 System.out.println("4: "+ceilLogBase2(4)); 112 System.out.println("5: "+ceilLogBase2(5)); 113 System.out.println("-3: "+ceilLogBase2(3)); 114 System.out.println("1024: "+ceilLogBase2(1024)); 115 System.out.println("1023: "+ceilLogBase2(1023)); 116 System.out.println("1025: "+ceilLogBase2(1025)); 117 118 System.out.println("1 "+powerOf2(1)); 119 System.out.println("2 "+powerOf2(2)); 120 System.out.println("3 "+powerOf2(3)); 121 } 122 123 } 124