1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| import java.util.Random;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class FractalTerrain implements Terrain {
private double[][] terrain;
private double roughness, min, max;
private int divisions;
private Random rng;
public FractalTerrain (int lod, double roughness) {
this.roughness = roughness;
this.divisions = 1 << lod;
terrain = new double[divisions + 1][divisions + 1];
rng = new Random ();
terrain[0][0] = rnd ();
terrain[0][divisions] = rnd ();
terrain[divisions][divisions] = rnd ();
terrain[divisions][0] = rnd ();
double rough = roughness;
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;
}
min = max = terrain[0][0];
for (int i = 0; i <= divisions; ++ i)
for (int j = 0; j <= divisions; ++ j)
if (terrain[i][j] < min) min = terrain[i][j];
else if (terrain[i][j] > max) max = terrain[i][j];
}
private 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;
}
}
private 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;
}
private double rnd () {
return 2. * rng.nextDouble () - 1.0;
}
public double getAltitude (double i, double j) {
double alt = terrain[(int) (i * divisions)][(int) (j * divisions)];
return (alt - min) / (max - min);
}
private RGB blue = new RGB (0.0, 0.0, 1.0);
private RGB green = new RGB (0.0, 1.0, 0.0);
private RGB white = new RGB (1.0, 1.0, 1.0);
public RGB getColor (double i, double j) {
double a = getAltitude (i, j);
if (a < .5)
return blue.add (green.subtract (blue).scale ((a - 0.0) / 0.5));
else
return green.add (white.subtract (green).scale ((a - 0.5) / 0.5));
}
public static void main(String args[]) {
double exaggeration = .7;
int lod = 5;
int steps = 1 << lod;
Triple[] []map = new Triple[steps + 1][steps + 1];
RGB[][]colors = new RGB[steps + 1][steps + 1];
Terrain terrain1 = new FractalTerrain (lod, .5);
SimpleUniverse universe = new SimpleUniverse();
BranchGroup group = new BranchGroup();
group.addChild((Node) terrain1);
for (int i1 = 0; i1 <= steps; ++ i1) {
for (int j1 = 0; j1 <= steps; ++ j1) {
double x = 1.0 * i1 / steps, z = 1.0 * j1 / steps;
double altitude = terrain1.getAltitude (x, z);
map[i1][j1] = new Triple (x, altitude * exaggeration, z);
colors[i1][j1] = terrain1.getColor (x, z);
group.addChild((Node) terrain1);
}
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(group);
}
} |
Partager