HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"When Mars Is Too Big to Download"
Vol. 9, Issue 9, p. 57

	



Listing 1

// The height field contains a float value for
// each [row, col] vertex.
float[ ][ ] hf = getHeightField();
BranchGroup objRoot = new BranchGroup();
GeometryInfo gi = new GeometryInfo(GeometryInfo.QUAD_ARRAY);
// The number of vertices (or coordinates) is based on the
// number of squares in the grid (4 by 4) times the number
// of corners (4) for each.
Point3f[ ] coordinates = new Point3f[64];
// For each corner of each square in the grid, convert the
// height field altitude value into instances of Point3f.
// The row is mapped to the minus z-axis, the column to
// the x-axis and the height field altitude value
// to the y-axis. Each iteration adds one square.
int ci = 0; // coordinate index
for (int row = 0; row < 4; row++) {
  for (int col = 0; col < 4; col++) {
    // use compass bearings to id the corners
    float sw = hf[row][col];
    float se = hf[row][col + 1];
    float ne = hf[row + 1][col + 1];
    float nw = hf[row + 1][col];

    coordinates[ci] = new Point3f(col, sw, -row);
    coordinates[ci + 1] = new Point3f(col + 1, se, -row);
    coordinates[ci + 2] =
            new Point3f(col + 1, ne, - (row + 1));
    coordinates[ci + 3] =
	        new Point3f(col, nw, - (row + 1));
    ci = ci + 4;
  }
}
gi.setCoordinates(coordinates);

Listing 2

float[ ][ ] hf = getHeightField();
// The height field
BranchGroup objRoot = new BranchGroup();

GeometryInfo gi =
new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
// The number of vertices (or coordinates) is based on the
// number of triangles in the grid (4 by 4 by 2) times the
// number of corners (3) for each.
Point3f[ ] coordinates = new Point3f[96];
// For each corner of each square in the grid, convert the
// height field altitude value into instances of Point3f.
// The row is mapped to the minus z-axis, the column to
// the x-axis and the height field altitude value
// to the y-axis.  Each iteration adds two triangles.
int ci = 0; // coordinate index
for (int row = 0; row < 4; row++) {
    for (int col = 0; col < 4; col++) {
        // use compass bearings to id the corners
        float sw = hf[row][col];
        float se = hf[row][col + 1];
        float ne = hf[row + 1][col + 1];
        float nw = hf[row + 1][col];

        coordinates[ci] = new Point3f(col, sw, -row);
        coordinates[ci + 1] = new Point3f(col + 1, se, -row);
        coordinates[ci + 2] =
                new Point3f(col, nw, - (row + 1));
        coordinates[ci + 3] = new Point3f(col + 1, se, -row);
        coordinates[ci + 4] =
                new Point3f(col + 1, ne, - (row + 1));
        coordinates[ci + 5] =
                new Point3f(col, nw, - (row + 1));
        ci = ci + 6;
    }
}
gi.setCoordinates(coordinates);

Listing 3

float[ ][ ] hf = getHeightField();
// The height field
BranchGroup objRoot = new BranchGroup();

GeometryInfo gi =
new GeometryInfo(GeometryInfo.TRIANGLE_STRIP_ARRAY);
// The number of vertices (or coordinates) is based on the
// number of horizontal strips (height - 1) times the
// number of vertices per strip (width * 2).
Point3f[] coordinates = new Point3f[40];
// The secret is that the strip vertices must be ordered
// like this: NW, SW, NE, SE for each set of four corners
// of a quad.  A convenient way to accomplish this is to
// organize the landscape in horizontal strips and iterate
// across the columns calculating two vertices at a time.
int ci = 0; // coordinate index
for (int row = 0; row < 4; row++) {
    for (int col = 0; col < 5; col++) {
        // use compass bearings to id the corners
        float sw = hf[row][col];
        float nw = hf[row + 1][col];

        coordinates[ci] = new Point3f(col, nw, - (row + 1));
        coordinates[ci + 1] = new Point3f(col, sw, -row);
        ci = ci + 2;
    }
}
// The strip count handling could be done above
// but is here to make it easier to understand
int[] stripCounts = new int[4];
for (int strip = 0; strip < 4; strip++) {
    stripCounts[strip] = 10;
}
gi.setStripCounts(stripCounts);
gi.setCoordinates(coordinates);

Listing 4

float[ ][ ] hf = getHeightField();
// The height field
BranchGroup objRoot = new BranchGroup();

GeometryInfo gi =
new GeometryInfo(GeometryInfo.TRIANGLE_STRIP_ARRAY);
// The number of vertices (or coordinates) is based on the
// number of rows (5) times the number of columns (5)
// times 3 (one each for x, y, and z values).
float[] coordinates = new float[75]; // No more Point3f!

// Convert the height field to x, y, z values
for (int row = 0; row < 5; row++) {
    for (int col = 0; col < 5; col++) {
        // coordinate index is the column plus
        // the row times the width of a row times
        // the 3 (one for each x, y, and z).
        int ci = (col + row * 5) * 3;
        coordinates[ci + 0] = col; // x
        coordinates[ci + 1] = hf[row][col]; // y
        coordinates[ci + 2] = -row; // z
    }
}
// The number of indices is based on the
// number of horizontal strips (height - 1) times the
// number of vertices per strip (width * 2).
int[ ] indices = new int[40];
// The secret is that the strip vertices must be ordered
// like this: NW, SW, NE, SE for each set of four corners
// of a quad.  A convenient way to accomplish this is to
// organize the landscape in horizontal strips and iterate
// across the columns calculating two vertices at a time.
int pi = 0; // points index
for (int row = 0; row < 4; row++) {
    int width = row * 5;
    for (int col = 0; col < 5; col++) {
        int coordinateIndex = width + col;
        indices[pi + 0] = coordinateIndex + 5; //NW
        indices[pi + 1] = coordinateIndex; //SW
        pi = pi + 2;
    }
}
int[] stripCounts = new int[4];
for (int strip = 0; strip < 4; strip++) {
    stripCounts[strip] = 10;
}
gi.setStripCounts(stripCounts);
gi.setCoordinates(coordinates);
gi.setCoordinateIndices(indices);

Listing 5

float[][] hf = new float[divisions + 1][divisions + 1];
// Initialize the corners of the height field. You
// could use random() for these values.
hf[0][0] = 0f;
hf[0][divisions] = 0f;
hf[divisions][divisions] = 0f;
hf[divisions][0] = 0f;
float rough = roughness;
// Evaluate the fractal for each of the
// requested levels of detail.
for (int detail = lod; detail > 0; detail--) {
    // The length of the side for
    // this level of detail iteration.
    int side = 1 << detail;
    int half = side >> 1;
    // Evaluate each square to create the diamond
    // pattern by finding a corner of each square.
    for (int x = 0; x < divisions; x += side) {
        for (int y = 0; y < divisions; y += side) {
            // x,y is the lower left corner of
            // the square to evaluate...
            diamond(hf, x, y, side, rough);
        }
    }
    if (half > 0) {
        // Evaluate each diamond to create the square
        // pattern by finding the center of each
        // diamond.
        for (int x = 0; x <= divisions; x += half) {
            for (int y = (x + half) % side;
                y <= divisions;
                y += side) {
                // x, y is the center of the
                // diamond to evaluate ...
                square(hf, x, y, side, rough);
            }
        }
    }
    // Adjust the roughness factor
    // to gradually scale it down.
    rough *= roughness;
    // Fractal purists would divide the roughness
    // by 2 for each iteration.  This creates a
    // scene that is (subjectively) too rough.
    // rough = rough/2.0f;
}

Listing 6

private void square(
    float[][] terrain,
    int x,
    int y,
    int side,
    float roughness) {
    // Because x, y is the center of the diamond,
    // it is possible that corners of the diamond
    // are outside the bounds of the landscape, so
    // this method has a few boundary conditions
    // to check for this possibility.
    int half = side / 2;
    float sum = 0.0f, number = 0.0f;

    if (x - half >= 0) {
        // West corner
        sum += terrain[x - half][y];
        number += 1.0;
    }
    if (y - half >= 0) {
        // South corner
        sum += terrain[x][y - half];
        number += 1.0;
    }
    if (x + half <= divisions) {
        // East corner
        sum += terrain[x + half][y];
        number += 1.0;
    }
    if (y + half <= divisions) {
        // North corner
        sum += terrain[x][y + half];
        number += 1.0;
    }
    float elevation = sum / number;
    terrain[x][y] = elevation + random() * roughness;
}

Listing 7

GeometryInfo gi =
new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
// The number of vertices (or coordinates) is just for
// one triangle.
Point3f[] coordinates = new Point3f[3];
coordinates[0] = new Point3f(0,0,0);
coordinates[1] = new Point3f(5,0,0);
coordinates[2] = new Point3f(5,0,-5);

Color3f[] colors = new Color3f[3];
colors[0] = new Color3f(1,0,0);
colors[1] = new Color3f(0,1,0);
colors[2] = new Color3f(0,0,1);

gi.setCoordinates(coordinates);
gi.setColors(colors);

Listing 8

private int[] getElevationColorIndices(float[][] hf) {
 int[] indices = new int[divisions * (divisions + 1) * 2];
    int i = 0;
    for (int row = 0; row < divisions; row++) {
        for (int col = 0; col < (divisions + 1); col++) {
            // Normalize the height value to a
            // color index between 0 and NUMBER_OF_COLORS - 1
            int nw =
                Math.round(
                    (NUMBER_OF_COLORS - 1)
                    * ((100f - hf[row + 1][col]) / 100f));
            indices[i] = nw;
            int sw =
                Math.round(
	             (NUMBER_OF_COLORS - 1)
	              * ((100f - hf[row][col]) / 100f));
            indices[i + 1] = sw;
            i = i + 2;
        }
    }
    return indices;
}

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.