NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.
To learn about what's going on, see About the Archive Site.
Hi Randy, > > > ... if I want to display the underlying grid itself, it's going > > > to take quite a bit of effort? > > > > It will take some. It depends on how you want to see it. > > > > Do you want to see the edges of your cells? That may not be > > too difficult. For a large number of cells those edges may > > look pretty complex. > > As a first pass, I would like to display *all* polygonal faces of the > cells, color-coded according to the scalar values at the vertices (actually, > my field is cell-centered, but that's another problem). If I display the cell > faces as opaque polygons, then I'll see only the exterior faces of my > domain... > with semi-transparency, I could peer into the interior a bit. I'm going to post my description of how to write a custom dataRenderer to the mailing list, in case others are interested and so that it will be on Unidata's VisAD mailing list archive. You need to extend two classes, DefaultRendererJ3D and ShadowFunctionTypeJ3D, in the visad.java3d package (you should extend ShadowFunctionTypeJ3D rather than ShadowSetTypeJ3D since your data object is actually a Field rather than just a Set - the Irregular3DSet you construct from your cells is the domain Set of the Field). You could put your new classes in a new package (visad.heiland?) or you could put them right back in visad.java3d. Here is the code for CellFaceRendererJ3D.java: package visad.java3d; import visad.*; import java.rmi.*; import javax.media.j3d.*; public class CellFaceRendererJ3D extends DefaultRendererJ3D { public CellFaceRendererJ3D() { super(); } // override makeShadowFunctionType to use CellFaceShadowFunctionTypeJ3D public ShadowType makeShadowFunctionType( FunctionType type, DataDisplayLink link, ShadowType parent) throws VisADException, RemoteException { return new CellFaceShadowFunctionTypeJ3D(type, link, parent); } } Here is the code for CellFaceShadowFunctionTypeJ3D.java (which needs to be edited): package visad.java3d; import visad.*; import javax.media.j3d.*; import java.util.Vector; import java.util.Enumeration; import java.rmi.*; public class CellFaceShadowFunctionTypeJ3D extends ShadowFunctionTypeJ3D { public CellFaceShadowFunctionTypeJ3D(MathType t, DataDisplayLink link, ShadowType parent) throws VisADException, RemoteException { super(t, link, parent); } // // override doTransform to do the actual work // // the easiest way to way to do this is to copy the entire doTransform // method from ShadowFunctionOrSetTypeJ3D.java, and then edit it // public boolean doTransform(Group group, Data data, float[] value_array, float[] default_values, DataRenderer renderer) throws VisADException, RemoteException { if (data.isMissing()) { ensureNotEmpty(group); return false; } . . . code omitted for brevity . . . // edit the following code (at about line 1418 in // ShadowFunctionOrSetTypeJ3D.java) else if (spatialManifoldDimension == 3) { array = makePointGeometry(spatial_values, color_values); // System.out.println("makePointGeometry for 3D"); // // when make3DGeometry is implemented: // array = spatial_set.make3DGeometry(color_values); // } . . . code omitted for brevity . . . ensureNotEmpty(group); return post; /* throw new UnimplementedException("ShadowFunctionOrSetType.doTransform: " + "not terminal"); */ } // end if (!isTerminal) } } All the real work is in the code to replace the call to makePointGeometry that constructs and returns a VisADGeometryArray. The spatial_values array, organized as float[3][number_of_vertices], contains the locations of all your cell vertices transformed to graphics coordinates (determined from values of RealTypes mapped to spatial DisplayRealTypes such as Display.XAxis, Display.YAXis, etc). The color_values array, organized as float[3 or 4][number_of_vertices], contains the color componments of all your cell vertices scaled to the range (0.0f, 1.0f) (determined from values of RealTypes mapped to color DisplayRealTypes such as Display.Red, Display.RGB, etc). The color_values array contains the (R, G, B) or the (R, G, B, A) components, depending on whether its length is 3 or 4 (which in turn depends on whether the application creates a ScalarMap to Display.Alpha). Your code can get the cell topology from spatial_set, which will be an Irregular3DSet if the domain Set of your Field is and if all its RealType components are mapped to spatial DisplayRealTypes (Display.XAxis, Display.YAxis, etc). Get the topology as follows: if (!(spatial_set instanceof Irregular3DSet)) { throw new DisplayException("CellFaceShadowFunctionTypeJ3D " + "requires Irregular3DSet"); } Delaunay delan = ((Irregular3DSet) spatial_set).Delaunay; int[][] tri = delan.Tri; Now tri is organized int[number_of_tetrahedra][4] and the faces you want to render are each triple of vertices in each tetrahedron. It will be simplest to construct a VisADTriangleArray (extends VisADGeometryArray and is much simpler than VisADIndexedTriangleStripArray). Use the values in the tri array as indices into spatial_values and color_values to get the values for the coordinates and colors arrays in the VisADTriangleArray. You will also need to compute values for the normals array (vector cross product of two edges of the triangle). Note that these arrays are all organized float[number_of_triangles * 3 * 3] (except colors may be organized float[number_of_triangles * 3 * 4] if there are alpha transparency values). That is, the coordinates array is organized: coordinates[0] = x coordinate for 1st vertex of 1st triangle coordinates[1] = y coordinate for 1st vertex of 1st triangle coordinates[2] = z coordinate for 1st vertex of 1st triangle coordinates[3] = x coordinate for 2nd vertex of 1st triangle coordinates[4] = y coordinate for 2nd vertex of 1st triangle coordinates[5] = z coordinate for 2nd vertex of 1st triangle coordinates[6] = x coordinate for 3rd vertex of 1st triangle coordinates[7] = y coordinate for 3rd vertex of 1st triangle coordinates[8] = z coordinate for 3rd vertex of 1st triangle coordinates[9] = x coordinate for 1st vertex of 2st triangle coordinates[10] = y coordinate for 1st vertex of 2st triangle etc You also need to set vertexCount = 3 * number_of_triangles in your VisADTriangleArray, but can ignore vertexFormat. Note that the Delan variable in IrregularSet (inherited by Irregular3DSet) was not public but I just made it so. You can either re-download VisAD, or simply change: Delaunay Delan = null; to: public Delaunay Delan = null; in visad/IrregularSet.java. Also note that transparency rendering will be full of errors unless the triangles in your VisADTriangleArray are sorted in depth order, but that depth order changes depending on rotation angle and it is completely computationally infeasible to re-sort triangles as the scene is interactively rotated. Hence, transparency may not look very good with your data. If you go ahead with this work, it would be great if you would make your new classes available on a web page for others to use (I am sure lots of people will find them useful). We will make a link to your page. If this is a problem for you, we would be happy to serve your classes - but I assume that web serving is no problem at NCSA ;) I hope you do go ahead with this and please let me know if you have any questions or problems. Cheers, Bill ---------------------------------------------------------- Bill Hibbard, SSEC, 1225 W. Dayton St., Madison, WI 53706 whibbard@xxxxxxxxxxxxx 608-263-4427 fax: 608-263-6738 http://www.ssec.wisc.edu/~billh/vis.html
visad
archives: