mev-4.0.01/source/org/tigr/microarray/mev/cluster/gui/impl/terrain/Landscape.java

Code
Comments
Other
Rev Date Author Line
2 26 Feb 07 jari 1 /*
2 26 Feb 07 jari 2 Copyright @ 1999-2003, The Institute for Genomic Research (TIGR).
2 26 Feb 07 jari 3 All rights reserved.
2 26 Feb 07 jari 4 */
2 26 Feb 07 jari 5 /*
2 26 Feb 07 jari 6  * $RCSfile: Landscape.java,v $
2 26 Feb 07 jari 7  * $Revision: 1.3 $
2 26 Feb 07 jari 8  * $Date: 2005/03/10 20:33:21 $
2 26 Feb 07 jari 9  * $Author: braistedj $
2 26 Feb 07 jari 10  * $State: Exp $
2 26 Feb 07 jari 11  */
2 26 Feb 07 jari 12 package org.tigr.microarray.mev.cluster.gui.impl.terrain;
2 26 Feb 07 jari 13
2 26 Feb 07 jari 14 import java.awt.image.BufferedImage;
2 26 Feb 07 jari 15 import java.util.Arrays;
2 26 Feb 07 jari 16
2 26 Feb 07 jari 17 import javax.media.j3d.Appearance;
2 26 Feb 07 jari 18 import javax.media.j3d.Geometry;
2 26 Feb 07 jari 19 import javax.media.j3d.GeometryArray;
2 26 Feb 07 jari 20 import javax.media.j3d.GeometryUpdater;
2 26 Feb 07 jari 21 import javax.media.j3d.Material;
2 26 Feb 07 jari 22 import javax.media.j3d.PolygonAttributes;
2 26 Feb 07 jari 23 import javax.media.j3d.Shape3D;
2 26 Feb 07 jari 24 import javax.media.j3d.TriangleStripArray;
2 26 Feb 07 jari 25 import javax.vecmath.Vector3f;
2 26 Feb 07 jari 26
2 26 Feb 07 jari 27 public class Landscape extends Shape3D implements GeometryUpdater {
2 26 Feb 07 jari 28
2 26 Feb 07 jari 29     private float[][] heights;
2 26 Feb 07 jari 30     private float[] coords;  // reference to this shape geometry coordinaties
2 26 Feb 07 jari 31     private float[] colors;  // reference to this shape vertices colors
2 26 Feb 07 jari 32     private float[] normals; // reference to this shape vertices normals
2 26 Feb 07 jari 33
2 26 Feb 07 jari 34     public Landscape(float[][] heights) {
2 26 Feb 07 jari 35         this.heights = heights;
2 26 Feb 07 jari 36         setCapability(ALLOW_GEOMETRY_READ);
2 26 Feb 07 jari 37         setCapability(ALLOW_GEOMETRY_WRITE);
2 26 Feb 07 jari 38         setCapability(ALLOW_APPEARANCE_READ);
2 26 Feb 07 jari 39         setCapability(ENABLE_PICK_REPORTING);
2 26 Feb 07 jari 40         initBuffers(heights.length);
2 26 Feb 07 jari 41         // create the shape geometry coords
2 26 Feb 07 jari 42         updateCoords(this.coords, this.heights);
2 26 Feb 07 jari 43         updateColors(this.colors, this.heights);
2 26 Feb 07 jari 44         updateNormals(this.normals, this.heights);
2 26 Feb 07 jari 45         // set geometry and appearance
2 26 Feb 07 jari 46         setGeometry(createGeometry(heights.length, this.coords, this.colors, this.normals));
2 26 Feb 07 jari 47         setAppearance(createAppearance());
2 26 Feb 07 jari 48     }
2 26 Feb 07 jari 49
2 26 Feb 07 jari 50     private void initBuffers(int size) {
2 26 Feb 07 jari 51         this.coords  = new float[(size-1)*size*2*3]; 
2 26 Feb 07 jari 52         this.colors  = new float[(size-1)*size*2*3];
2 26 Feb 07 jari 53         this.normals = new float[(size-1)*size*2*3];
2 26 Feb 07 jari 54     }
2 26 Feb 07 jari 55
2 26 Feb 07 jari 56     public void setHeights(float[][] heights) {
2 26 Feb 07 jari 57         if (this.heights.length != heights.length) {
2 26 Feb 07 jari 58             initBuffers(heights.length);
2 26 Feb 07 jari 59             setGeometry(createGeometry(heights.length, this.coords, this.colors, this.normals));
2 26 Feb 07 jari 60         }
2 26 Feb 07 jari 61         this.heights = heights;
2 26 Feb 07 jari 62         ((GeometryArray)getGeometry()).updateData(this);
2 26 Feb 07 jari 63     }
2 26 Feb 07 jari 64
2 26 Feb 07 jari 65     public void setPoligonMode(int mode) {
2 26 Feb 07 jari 66         Appearance appearance = getAppearance();
2 26 Feb 07 jari 67         PolygonAttributes pa = appearance.getPolygonAttributes();
2 26 Feb 07 jari 68         pa.setPolygonMode(mode);
2 26 Feb 07 jari 69     }
2 26 Feb 07 jari 70
2 26 Feb 07 jari 71     private Geometry createGeometry(int size, float[] coords, float[] colors, float[] normals) {
2 26 Feb 07 jari 72         int[] stripVertexCounts = new int[size-1];
2 26 Feb 07 jari 73         Arrays.fill(stripVertexCounts, size*2);
2 26 Feb 07 jari 74
2 26 Feb 07 jari 75         GeometryArray geometry = new TriangleStripArray(coords.length/3,
2 26 Feb 07 jari 76                                                         GeometryArray.COORDINATES |
2 26 Feb 07 jari 77                                                         GeometryArray.COLOR_3     |
2 26 Feb 07 jari 78                                                         GeometryArray.NORMALS     |
2 26 Feb 07 jari 79                                                         GeometryArray.BY_REFERENCE,
2 26 Feb 07 jari 80                                                         stripVertexCounts
2 26 Feb 07 jari 81                                                        );
2 26 Feb 07 jari 82         geometry.setCapability(GeometryArray.ALLOW_COUNT_READ);
2 26 Feb 07 jari 83         geometry.setCapability(GeometryArray.ALLOW_FORMAT_READ);
2 26 Feb 07 jari 84         geometry.setCapability(GeometryArray.ALLOW_REF_DATA_READ);
2 26 Feb 07 jari 85         geometry.setCapability(GeometryArray.ALLOW_REF_DATA_WRITE);
2 26 Feb 07 jari 86         geometry.setCoordRefFloat(coords);
2 26 Feb 07 jari 87         geometry.setColorRefFloat(colors);
2 26 Feb 07 jari 88         geometry.setNormalRefFloat(normals);
2 26 Feb 07 jari 89         return geometry;
2 26 Feb 07 jari 90     }
2 26 Feb 07 jari 91
2 26 Feb 07 jari 92     private Appearance createAppearance() {
2 26 Feb 07 jari 93         PolygonAttributes pa = new PolygonAttributes();
2 26 Feb 07 jari 94         pa.setCapability(PolygonAttributes.ALLOW_MODE_WRITE);
2 26 Feb 07 jari 95         pa.setCullFace(PolygonAttributes.CULL_NONE);
2 26 Feb 07 jari 96
2 26 Feb 07 jari 97         Appearance appearance = new Appearance();
2 26 Feb 07 jari 98         appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_READ);
2 26 Feb 07 jari 99         appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_WRITE);
2 26 Feb 07 jari 100         appearance.setPolygonAttributes(pa);
2 26 Feb 07 jari 101         appearance.setMaterial(new Material());
2 26 Feb 07 jari 102         return appearance;
2 26 Feb 07 jari 103     }
2 26 Feb 07 jari 104
2 26 Feb 07 jari 105     public void updateData(Geometry geometry) {
2 26 Feb 07 jari 106         updateCoords(this.coords, this.heights);
2 26 Feb 07 jari 107         updateColors(this.colors, this.heights);
2 26 Feb 07 jari 108         updateNormals(this.normals, this.heights);
2 26 Feb 07 jari 109     }
2 26 Feb 07 jari 110
2 26 Feb 07 jari 111     /**
2 26 Feb 07 jari 112      * Creates a triangulated surface from the two dimensional array of heights.
2 26 Feb 07 jari 113      */
2 26 Feb 07 jari 114     public static void updateCoords(float[] coords, float[][] heights) {
2 26 Feb 07 jari 115         final int size = heights.length;
2 26 Feb 07 jari 116         final int stride = 2*3;
2 26 Feb 07 jari 117         float step = 1f/size;
2 26 Feb 07 jari 118         float x = step/2;
2 26 Feb 07 jari 119         float y = step/2;
2 26 Feb 07 jari 120         for (int i=0; i<size-1; i++) {
2 26 Feb 07 jari 121             for (int j=0; j<size; j++) {
2 26 Feb 07 jari 122                 int pos = (i*size+j)*stride;
2 26 Feb 07 jari 123                 //0
2 26 Feb 07 jari 124                 coords[pos++] = x;
2 26 Feb 07 jari 125                 coords[pos++] = heights[i][j];
2 26 Feb 07 jari 126                 coords[pos++] = y;
2 26 Feb 07 jari 127                 //1
2 26 Feb 07 jari 128                 coords[pos++] = x;
2 26 Feb 07 jari 129                 coords[pos++] = heights[i+1][j];
2 26 Feb 07 jari 130                 coords[pos++] = y+step;
2 26 Feb 07 jari 131
2 26 Feb 07 jari 132                 x += step;
2 26 Feb 07 jari 133             }
2 26 Feb 07 jari 134             x = step/2;
2 26 Feb 07 jari 135             y += step;
2 26 Feb 07 jari 136         }
2 26 Feb 07 jari 137     }
2 26 Feb 07 jari 138
2 26 Feb 07 jari 139     public static void updateColors(float[] colors, float[][] heights) {
2 26 Feb 07 jari 140         final int size = heights.length;
2 26 Feb 07 jari 141         final int stride = 2*3;
2 26 Feb 07 jari 142         float step = 1f/size;
2 26 Feb 07 jari 143         float x = step/2;
2 26 Feb 07 jari 144         float y = step/2;
2 26 Feb 07 jari 145         float scale = (float)(size-1)/getMaxValue(heights);           
2 26 Feb 07 jari 146         // create gradient image                                      
2 26 Feb 07 jari 147         BufferedImage gradient = DomainUtil.createGradientImage(size);
2 26 Feb 07 jari 148         int rgb1, rgb2;
2 26 Feb 07 jari 149         for (int i=0; i<size-1; i++) {
2 26 Feb 07 jari 150             for (int j=0; j<size; j++) {
2 26 Feb 07 jari 151                 int pos = (i*size+j)*stride;
2 26 Feb 07 jari 152
2 26 Feb 07 jari 153                 rgb1 = gradient.getRGB((int)(heights[i  ][j]*scale), 0);
2 26 Feb 07 jari 154                 rgb2 = gradient.getRGB((int)(heights[i+1][j]*scale), 0);
2 26 Feb 07 jari 155
2 26 Feb 07 jari 156                 colors[pos++] = (float)((rgb1 >> 16) & 0xFF)/255f;
2 26 Feb 07 jari 157                 colors[pos++] = (float)((rgb1 >>  8) & 0xFF)/255f;
2 26 Feb 07 jari 158                 colors[pos++] = (float)((rgb1 >>  0) & 0xFF)/255f;
2 26 Feb 07 jari 159
2 26 Feb 07 jari 160                 colors[pos++] = (float)((rgb2 >> 16) & 0xFF)/255f;
2 26 Feb 07 jari 161                 colors[pos++] = (float)((rgb2 >>  8) & 0xFF)/255f;
2 26 Feb 07 jari 162                 colors[pos++] = (float)((rgb2 >>  0) & 0xFF)/255f;
2 26 Feb 07 jari 163
2 26 Feb 07 jari 164                 x += step;
2 26 Feb 07 jari 165             }
2 26 Feb 07 jari 166             x = step/2;
2 26 Feb 07 jari 167             y += step;
2 26 Feb 07 jari 168         }
2 26 Feb 07 jari 169     }
2 26 Feb 07 jari 170
2 26 Feb 07 jari 171     protected static void updateNormals(float[] normals, float[][] heights) {
2 26 Feb 07 jari 172         final int size = heights.length;
2 26 Feb 07 jari 173         float[][][] buff = new float[size][size][3]; // vertices normals;
2 26 Feb 07 jari 174         float step = 1f/size;
2 26 Feb 07 jari 175         Vector3f v0 = new Vector3f();
2 26 Feb 07 jari 176         Vector3f south = new Vector3f();
2 26 Feb 07 jari 177         Vector3f east  = new Vector3f();
2 26 Feb 07 jari 178         Vector3f normal = new Vector3f();
2 26 Feb 07 jari 179         for (int i=0; i<size; i++) {
2 26 Feb 07 jari 180             for (int j=0; j<size; j++) {
2 26 Feb 07 jari 181                 if (i == size-1) { // last row
2 26 Feb 07 jari 182                     south.set(0f, 0f, step);
2 26 Feb 07 jari 183                 } else {
2 26 Feb 07 jari 184                     south.set(0f, heights[i+1][j], step);
2 26 Feb 07 jari 185                 }
2 26 Feb 07 jari 186                 if (j == size-1) { // last column
2 26 Feb 07 jari 187                     east.set(step, 0f, 0f);
2 26 Feb 07 jari 188                 } else {
2 26 Feb 07 jari 189                     east.set(step, heights[i][j+1], 0f);
2 26 Feb 07 jari 190                 }
2 26 Feb 07 jari 191                 v0.set(0, heights[i][j], 0);
2 26 Feb 07 jari 192                 south.sub(v0);
2 26 Feb 07 jari 193                 east.sub(v0);
2 26 Feb 07 jari 194                 normal.cross(south, east);
2 26 Feb 07 jari 195                 normal.normalize();
2 26 Feb 07 jari 196                 buff[i][j][0] = normal.x;
2 26 Feb 07 jari 197                 buff[i][j][1] = normal.y;
2 26 Feb 07 jari 198                 buff[i][j][2] = normal.z;
2 26 Feb 07 jari 199             }
2 26 Feb 07 jari 200         }
2 26 Feb 07 jari 201         // copying data
2 26 Feb 07 jari 202         for (int i=0; i<size-1; i++) {
2 26 Feb 07 jari 203             for (int j=0; j<size; j++) {
2 26 Feb 07 jari 204                 int pos = (i*size+j)*6;
2 26 Feb 07 jari 205                 normals[pos++] = buff[i][j][0];
2 26 Feb 07 jari 206                 normals[pos++] = buff[i][j][1];
2 26 Feb 07 jari 207                 normals[pos++] = buff[i][j][2];
2 26 Feb 07 jari 208                 normals[pos++] = buff[i+1][j][0];
2 26 Feb 07 jari 209                 normals[pos++] = buff[i+1][j][1];
2 26 Feb 07 jari 210                 normals[pos++] = buff[i+1][j][2];
2 26 Feb 07 jari 211             }
2 26 Feb 07 jari 212         }
2 26 Feb 07 jari 213     }
2 26 Feb 07 jari 214
2 26 Feb 07 jari 215     private static float getMaxValue(float[][] heights) {
2 26 Feb 07 jari 216         final int size = heights.length;
2 26 Feb 07 jari 217         float max = -Float.MAX_VALUE;
2 26 Feb 07 jari 218         for (int i=0; i<size; i++)
2 26 Feb 07 jari 219             for (int j=0; j<size; j++)
2 26 Feb 07 jari 220                 max = Math.max(max, heights[i][j]);
2 26 Feb 07 jari 221         return max;
2 26 Feb 07 jari 222     }
2 26 Feb 07 jari 223 }
2 26 Feb 07 jari 224
2 26 Feb 07 jari 225