// // DisplayImplJ3D.java // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and Tommy Jasmin. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* MEMORY LEAK DisplayImplJ3D.destrory() DisplayRendererJ3D.destroy() VisADCanvasJ3D.stop() stopRenderer() DisplayPanelJ3D.destroy() display, renderer = null; universe.destroy() DisplayAppletJ3D.destroy() display, renderer = null; universe.destroy() display, component = null MouseBehaviorJ3D.destroy() helper, display, display_renderer = null root.detach() root, trans, vpTrans, non_direct, view, canvas = null DisplayImpl.destroy() stop() removeThingChangedListener() for all links LinkVector.removeAllElements() pool.queue(this) run_links = null DisplayActivity.destroy() notify listeners remove all listeners clearMaps() check RendererVector empty MapVector.removeAllElements() ConstantMapVector.removeAllElements() RealTypeVector.removeAllElements() AnimationControlJ3D.stop() animationThread = null // causes run() to exit applet, projection, mode = null; */ package visad.java3d; import visad.*; import java.rmi.*; import java.awt.*; import javax.media.j3d.*; import com.sun.j3d.utils.applet.MainFrame; import java.util.Iterator; import java.util.Vector; // import com.sun.j3d.utils.applet.AppletFrame; /** DisplayImplJ3D is the VisAD class for displays that use Java 3D. It is runnable.<P> DisplayImplJ3D is not Serializable and should not be copied between JVMs.<P> */ public class DisplayImplJ3D extends DisplayImpl { /** distance behind for surfaces in 2-D mode */ // WLH 25 March 2003 (at BOM) // public static final float BACK2D = -2.0f; public static final float BACK2D = -0.01f; /** * Use a parallel projection view * @see GraphicsModeControlJ3D#setProjectionPolicy */ public static final int PARALLEL_PROJECTION = javax.media.j3d.View.PARALLEL_PROJECTION; /** * Use a perspective projection view. This is the default. * @see GraphicsModeControlJ3D#setProjectionPolicy */ public static final int PERSPECTIVE_PROJECTION = javax.media.j3d.View.PERSPECTIVE_PROJECTION; /** Render polygonal primitives by filling the interior of the polygon @see GraphicsModeControlJ3D#setPolygonMode */ public static final int POLYGON_FILL = javax.media.j3d.PolygonAttributes.POLYGON_FILL; /** * Render polygonal primitives as lines drawn between consecutive vertices * of the polygon. * @see GraphicsModeControlJ3D#setPolygonMode */ public static final int POLYGON_LINE = javax.media.j3d.PolygonAttributes.POLYGON_LINE; /** * Render polygonal primitives as points drawn at the vertices of * the polygon. * @see GraphicsModeControlJ3D#setPolygonMode */ public static final int POLYGON_POINT = javax.media.j3d.PolygonAttributes.POLYGON_POINT; /** * Use the nicest available method for transparency. * @see GraphicsModeControlJ3D#setTransparencyMode */ public static final int NICEST = javax.media.j3d.TransparencyAttributes.NICEST; /** * Use the fastest available method for transparency. * @see GraphicsModeControlJ3D#setTransparencyMode */ public static final int FASTEST = javax.media.j3d.TransparencyAttributes.FASTEST; /** Field for specifying unknown API type */ public static final int UNKNOWN = 0; /** Field for specifying that the DisplayImpl be created in a JPanel */ public static final int JPANEL = 1; /** Field for specifying that the DisplayImpl does not have a screen Component */ public static final int OFFSCREEN = 2; /** Field for specifying that the DisplayImpl be created in an Applet */ public static final int APPLETFRAME = 3; /** Field for specifying that the DisplayImpl transforms but does not render */ public static final int TRANSFORM_ONLY = 4; /** * Property name for setting whether to use geometry by reference. * @see #GEOMETRY_BY_REF */ public static final String PROP_GEOMETRY_BY_REF = "visad.java3d.geometryByRef"; /** * Indicates whether to use geometry by reference when creating geometry arrays. * @see javax.media.j3d.GeometryArray#BY_REFERENCE */ public static final boolean GEOMETRY_BY_REF; static { GEOMETRY_BY_REF = Boolean.parseBoolean(System.getProperty(PROP_GEOMETRY_BY_REF, "true")); } /** * Property name for enabling the use of non-power of two textures. * @see #TEXTURE_NPOT */ public static final String PROP_TEXTURE_NPOT = "visad.java3d.textureNpot"; /** * Indicates whether to allow non-power of two textures. This has been known * to cause some issues with Apple 32bit Macs eventhough the Canvas3D * properties indicate that NPOT is supported. * @see javax.media.j3d.Canvas3D#queryProperties() */ // FIXME: // This works with the Java3D 1.5.2 example TextureImageNPOT but does not work // with the VisAD library image rednering. On initial testing it behaves as if // there may be threading issues. This requires more investigation before we // can enable this based on the Canvas3D properties. public static final boolean TEXTURE_NPOT; static { TEXTURE_NPOT = Boolean.parseBoolean(System.getProperty(PROP_TEXTURE_NPOT, "false")); //System.err.println("TEXTURE_NPOT:"+TEXTURE_NPOT); } /** * Workaround for Java3D "grey window problem": sometimes Canvas3D is not painted * This problem is rare and often hard to reproduce, so it is disabled by default. */ public static final String NO_ERASE_BACKGROUND = "visad.java3d.noerasebackground"; static { if (Boolean.parseBoolean(System.getProperty(NO_ERASE_BACKGROUND, "false"))) { System.setProperty("sun.awt.noerasebackground", "true"); // If setting the above, suggested by Jogamp to set this to a small non-zero value. (TDR) UniverseBuilderJ3D.setMinimumFrameCycleTime(20); } } /** this is used for APPLETFRAME */ private DisplayAppletJ3D applet = null; private ProjectionControlJ3D projection = null; private GraphicsModeControlJ3D mode = null; private int apiValue = UNKNOWN; private UniverseBuilderJ3D universe = null; /** construct a DisplayImpl for Java3D with the default DisplayRenderer, in a JFC JPanel */ public DisplayImplJ3D(String name) throws VisADException, RemoteException { this(name, null, JPANEL, null); } /** construct a DisplayImpl for Java3D with a non-default DisplayRenderer, in a JFC JPanel */ public DisplayImplJ3D(String name, DisplayRendererJ3D renderer) throws VisADException, RemoteException { this(name, renderer, JPANEL, null); } /** constructor with default DisplayRenderer */ public DisplayImplJ3D(String name, int api) throws VisADException, RemoteException { this(name, null, api, null); } /** construct a DisplayImpl for Java3D with a non-default GraphicsConfiguration, in a JFC JPanel */ public DisplayImplJ3D(String name, GraphicsConfiguration config) throws VisADException, RemoteException { this(name, null, JPANEL, config); } /** construct a DisplayImpl for Java3D with a non-default DisplayRenderer; in a JFC JPanel if api == DisplayImplJ3D.JPANEL and in an AppletFrame if api == DisplayImplJ3D.APPLETFRAME */ public DisplayImplJ3D(String name, DisplayRendererJ3D renderer, int api) throws VisADException, RemoteException { this(name, renderer, api, null); } /** construct a DisplayImpl for Java3D with a non-default DisplayRenderer and GraphicsConfiguration, in a JFC JPanel */ public DisplayImplJ3D(String name, DisplayRendererJ3D renderer, GraphicsConfiguration config) throws VisADException, RemoteException { this(name, renderer, JPANEL, config); } /** constructor with default DisplayRenderer and a non-default GraphicsConfiguration */ public DisplayImplJ3D(String name, int api, GraphicsConfiguration config) throws VisADException, RemoteException { this(name, null, api, config); } public DisplayImplJ3D(String name, DisplayRendererJ3D renderer, int api, GraphicsConfiguration config) throws VisADException, RemoteException { this(name, renderer, api, config, null); } /** the 'c' argument is intended to be an extension class of VisADCanvasJ3D (or null); if it is non-null, then api must be JPANEL and its super() constructor for VisADCanvasJ3D must be 'super(renderer, config)' */ public DisplayImplJ3D(String name, DisplayRendererJ3D renderer, int api, GraphicsConfiguration config, VisADCanvasJ3D c) throws VisADException, RemoteException { super(name, renderer); initialize(api, config, c); } /** constructor for off screen */ public DisplayImplJ3D(String name, int width, int height) throws VisADException, RemoteException { this(name, null, width, height); } /** constructor for off screen */ public DisplayImplJ3D(String name, DisplayRendererJ3D renderer, int width, int height) throws VisADException, RemoteException { this(name, renderer, width, height, null); } /** constructor for off screen; the 'c' argument is intended to be an extension class of VisADCanvasJ3D (or null); if it is non-null, then its super() constructor for VisADCanvasJ3D must be 'super(renderer, width, height)' */ public DisplayImplJ3D(String name, DisplayRendererJ3D renderer, int width, int height, VisADCanvasJ3D c) throws VisADException, RemoteException { super(name, renderer); initialize(OFFSCREEN, null, width, height, c); } public DisplayImplJ3D(RemoteDisplay rmtDpy) throws VisADException, RemoteException { this(rmtDpy, null, rmtDpy.getDisplayAPI(), null); } public DisplayImplJ3D(RemoteDisplay rmtDpy, DisplayRendererJ3D renderer) throws VisADException, RemoteException { this(rmtDpy, renderer, rmtDpy.getDisplayAPI(), null); } public DisplayImplJ3D(RemoteDisplay rmtDpy, int api) throws VisADException, RemoteException { this(rmtDpy, null, api, null); } public DisplayImplJ3D(RemoteDisplay rmtDpy, GraphicsConfiguration config) throws VisADException, RemoteException { this(rmtDpy, null, rmtDpy.getDisplayAPI(), config); } public DisplayImplJ3D(RemoteDisplay rmtDpy, DisplayRendererJ3D renderer, int api) throws VisADException, RemoteException { this(rmtDpy, renderer, api, null); } public DisplayImplJ3D(RemoteDisplay rmtDpy, DisplayRendererJ3D renderer, GraphicsConfiguration config) throws VisADException, RemoteException { this(rmtDpy, renderer, rmtDpy.getDisplayAPI(), config); } public DisplayImplJ3D(RemoteDisplay rmtDpy, int api, GraphicsConfiguration config) throws VisADException, RemoteException { this(rmtDpy, null, api, config); } public DisplayImplJ3D(RemoteDisplay rmtDpy, DisplayRendererJ3D renderer, int api, GraphicsConfiguration config) throws VisADException, RemoteException { this(rmtDpy, renderer, api, config, null); } /** the 'c' argument is intended to be an extension class of VisADCanvasJ3D (or null); if it is non-null, then api must be JPANEL and its super() constructor for VisADCanvasJ3D must be 'super(renderer, config)' */ public DisplayImplJ3D(RemoteDisplay rmtDpy, DisplayRendererJ3D renderer, int api, GraphicsConfiguration config, VisADCanvasJ3D c) throws VisADException, RemoteException { super(rmtDpy, ((renderer == null && api == TRANSFORM_ONLY) ? new TransformOnlyDisplayRendererJ3D() : renderer)); // use this for testing cluster = true in ordinary collab programs // super(rmtDpy, // ((renderer == null && api == TRANSFORM_ONLY) ? // new TransformOnlyDisplayRendererJ3D() : renderer), true); initialize(api, config, c); syncRemoteData(rmtDpy); } private void initialize(int api, GraphicsConfiguration config) throws VisADException, RemoteException { initialize(api, config, -1, -1, null); } private void initialize(int api, GraphicsConfiguration config, VisADCanvasJ3D c) throws VisADException, RemoteException { initialize(api, config, -1, -1, c); } private void initialize(int api, GraphicsConfiguration config, int width, int height) throws VisADException, RemoteException { initialize(api, config, width, height, null); } private void initialize(int api, GraphicsConfiguration config, int width, int height, VisADCanvasJ3D c) throws VisADException, RemoteException { // a ProjectionControl always exists projection = new ProjectionControlJ3D(this); addControl(projection); if (api == APPLETFRAME) { applet = new DisplayAppletJ3D(this, config); Component component = new MainFrame(applet, 256, 256); // Component component = new AppletFrame(applet, 256, 256); setComponent(component); // component.setTitle(name); apiValue = api; } else if (api == JPANEL) { Component component = new DisplayPanelJ3D(this, config, c); setComponent(component); apiValue = api; } else if (api == TRANSFORM_ONLY) { if (!(getDisplayRenderer() instanceof TransformOnlyDisplayRendererJ3D)) { throw new DisplayException("must be TransformOnlyDisplayRendererJ3D " + "for api = TRANSFORM_ONLY"); } setComponent(null); apiValue = api; } else if (api == OFFSCREEN) { DisplayRendererJ3D renderer = (DisplayRendererJ3D) getDisplayRenderer(); VisADCanvasJ3D canvas = (c != null) ? c : new VisADCanvasJ3D(renderer, width, height); universe = new UniverseBuilderJ3D(canvas); BranchGroup scene = renderer.createSceneGraph(universe.view, universe.vpTrans, canvas); universe.addBranchGraph(scene); setComponent(null); apiValue = api; } else { throw new DisplayException("DisplayImplJ3D: bad graphics API " + api); } if (api != TRANSFORM_ONLY) { // initialize projection and set Display in Canvas projection.setAspect(new double[] {1.0, 1.0, 1.0}); ((DisplayRendererJ3D) getDisplayRenderer()).getCanvas().setDisplay(); } // a GraphicsModeControl always exists mode = new GraphicsModeControlJ3D(this); addControl(mode); } /** return a DefaultDisplayRendererJ3D */ protected DisplayRenderer getDefaultDisplayRenderer() { return new DefaultDisplayRendererJ3D(); } public void setScreenAspect(double height, double width) { DisplayRendererJ3D dr = (DisplayRendererJ3D) getDisplayRenderer(); Screen3D screen = dr.getCanvas().getScreen3D(); screen.setPhysicalScreenHeight(height); screen.setPhysicalScreenWidth(width); } /** * Get the projection control associated with this display * @see ProjectionControlJ3D * * @return this display's projection control */ public ProjectionControl getProjectionControl() { return projection; } /** * Get the graphics mode control associated with this display * @see GraphicsModeControlJ3D * * @return this display's graphics mode control */ public GraphicsModeControl getGraphicsModeControl() { return mode; } /** * Return the applet associated with this display * * @return the applet or null if API != APPLETFRAME */ public DisplayAppletJ3D getApplet() { return applet; } /** * Return the API used for this display * * @return the mode being used (UNKNOWN, JPANEL, APPLETFRAME, * OFFSCREEN, TRANSFORM_ONLY) * @throws VisADException */ public int getAPI() throws VisADException { return apiValue; } private void setGeometryCapabilities(GeometryArray array) { array.setCapability(GeometryArray.ALLOW_COLOR_READ); array.setCapability(GeometryArray.ALLOW_COORDINATE_READ); array.setCapability(GeometryArray.ALLOW_COUNT_READ); array.setCapability(GeometryArray.ALLOW_FORMAT_READ); array.setCapability(GeometryArray.ALLOW_NORMAL_READ); array.setCapability(GeometryArray.ALLOW_TEXCOORD_READ); /* TDR (2013-10-12): Should only be used in conjunction with GeometryArray.updateData which is not currently implemented array.setCapability(GeometryArray.ALLOW_REF_DATA_WRITE); */ // only used when using BY_REFERENCE, so just set it anyways //array.setCapability(GeometryArray.ALLOW_REF_DATA_READ); } public GeometryArray makeGeometry(VisADGeometryArray vga) throws VisADException { if (vga == null) return null; boolean mode2d = getDisplayRenderer().getMode2D(); int vertexFormat = makeFormat(vga); if (vga instanceof VisADIndexedTriangleStripArray) { /* this is the 'normal' makeGeometry */ VisADIndexedTriangleStripArray vgb = (VisADIndexedTriangleStripArray) vga; if (vga.vertexCount == 0) return null; IndexedTriangleStripArray array = new IndexedTriangleStripArray(vga.vertexCount, vertexFormat, vgb.indexCount, vgb.stripVertexCounts); setGeometryCapabilities(array); basicGeometry(vga, array, mode2d); if (vga.coordinates != null) { array.setCoordinateIndices(0, vgb.indices); } if (vga.colors != null) { array.setColorIndices(0, vgb.indices); } if (vga.normals != null) { array.setNormalIndices(0, vgb.indices); } if (vga.texCoords != null) { array.setTextureCoordinateIndices(0, vgb.indices); } return array; /* this expands indices if (vga.vertexCount == 0) return null; // // expand vga.coordinates, vga.colors, vga.normals and vga.texCoords // int count = vga.indices.length; int len = 3 * count; int sum = 0; for (int i=0; i<vga.stripVertexCounts.length; i++) sum += vga.stripVertexCounts[i]; System.out.println("vga.indexCount = " + vga.indexCount + " sum = " + sum + " count = " + count + " vga.stripVertexCounts.length = " + vga.stripVertexCounts.length); // int[] strip_counts = new int[1]; // strip_counts[0] = count; // TriangleStripArray array = // new TriangleStripArray(count, makeFormat(vga), strip_counts); TriangleStripArray array = new TriangleStripArray(count, makeFormat(vga), vga.stripVertexCounts); if (vga.coordinates != null) { System.out.println("expand vga.coordinates"); float[] coords = new float[len]; for (int k=0; k<count; k++) { int i = 3 * k; int j = 3 * vga.indices[k]; coords[i] = vga.coordinates[j]; coords[i + 1] = vga.coordinates[j + 1]; coords[i + 2] = vga.coordinates[j + 2]; } array.setCoordinates(0, coords); } if (vga.colors != null) { System.out.println("expand vga.colors"); byte[] cols = new float[len]; for (int k=0; k<count; k++) { int i = 3 * k; int j = 3 * vga.indices[k]; cols[i] = vga.colors[j]; cols[i + 1] = vga.colors[j + 1]; cols[i + 2] = vga.colors[j + 2]; } array.setColors(0, cols); } if (vga.normals != null) { System.out.println("expand vga.normals"); float[] norms = new float[len]; for (int k=0; k<count; k++) { int i = 3 * k; int j = 3 * vga.indices[k]; norms[i] = vga.normals[j]; norms[i + 1] = vga.normals[j + 1]; norms[i + 2] = vga.normals[j + 2]; } array.setNormals(0, norms); } if (vga.texCoords != null) { System.out.println("expand vga.texCoords"); float[] tex = new float[len]; for (int k=0; k<count; k++) { int i = 3 * k; int j = 3 * vga.indices[k]; tex[i] = vga.texCoords[j]; tex[i + 1] = vga.texCoords[j + 1]; tex[i + 2] = vga.texCoords[j + 2]; } array.setTextureCoordinates(0, tex); } return array; */ /* this draws normal vectors if (vga.vertexCount == 0) return null; LineArray array = new LineArray(2 * vga.vertexCount, LineArray.COORDINATES); float[] new_coords = new float[6 * vga.vertexCount]; int i = 0; int j = 0; for (int k=0; k<vga.vertexCount; k++) { new_coords[j] = vga.coordinates[i]; new_coords[j+1] = vga.coordinates[i+1]; new_coords[j+2] = vga.coordinates[i+2]; j += 3; new_coords[j] = vga.coordinates[i] + 0.05f * vga.normals[i]; new_coords[j+1] = vga.coordinates[i+1] + 0.05f * vga.normals[i+1]; new_coords[j+2] = vga.coordinates[i+2] + 0.05f * vga.normals[i+2]; i += 3; j += 3; } array.setCoordinates(0, new_coords); return array; */ /* this draws the 'dots' if (vga.vertexCount == 0) return null; PointArray array = new PointArray(vga.vga.vertexCount, makeFormat(vga)); basicGeometry(vga, array, false); return array; */ } if (vga instanceof VisADTriangleStripArray) { VisADTriangleStripArray vgb = (VisADTriangleStripArray) vga; if (vga.vertexCount == 0) return null; TriangleStripArray array = new TriangleStripArray(vga.vertexCount, vertexFormat, vgb.stripVertexCounts); setGeometryCapabilities(array); basicGeometry(vga, array, mode2d); return array; } else if (vga instanceof VisADLineArray) { if (vga.vertexCount == 0) return null; LineArray array = new LineArray(vga.vertexCount, vertexFormat); setGeometryCapabilities(array); basicGeometry(vga, array, false); return array; } else if (vga instanceof VisADLineStripArray) { if (vga.vertexCount == 0) return null; VisADLineStripArray vgb = (VisADLineStripArray) vga; LineStripArray array = new LineStripArray(vga.vertexCount, vertexFormat, vgb.stripVertexCounts); setGeometryCapabilities(array); basicGeometry(vga, array, false); return array; } else if (vga instanceof VisADPointArray) { if (vga.vertexCount == 0) return null; PointArray array = new PointArray(vga.vertexCount, vertexFormat); setGeometryCapabilities(array); basicGeometry(vga, array, false); return array; } else if (vga instanceof VisADTriangleArray) { if (vga.vertexCount == 0) return null; TriangleArray array = new TriangleArray(vga.vertexCount, vertexFormat); setGeometryCapabilities(array); basicGeometry(vga, array, mode2d); return array; } else if (vga instanceof VisADQuadArray) { if (vga.vertexCount == 0) return null; QuadArray array = new QuadArray(vga.vertexCount, vertexFormat); setGeometryCapabilities(array); basicGeometry(vga, array, mode2d); return array; } else { throw new DisplayException("DisplayImplJ3D.makeGeometry"); } } private void basicGeometry(VisADGeometryArray vga, GeometryArray array, boolean mode2d) { if (mode2d) { if (vga.coordinates != null) { int len = vga.coordinates.length; float[] coords = new float[len]; System.arraycopy(vga.coordinates, 0, coords, 0, len); for (int i=2; i<len; i+=3) coords[i] = BACK2D; if (GEOMETRY_BY_REF) array.setCoordRefFloat(coords); else array.setCoordinates(0, coords); } } else { if (vga.coordinates != null) { if (GEOMETRY_BY_REF) array.setCoordRefFloat(vga.coordinates); else array.setCoordinates(0, vga.coordinates); } } if (vga.colors != null) { if (GEOMETRY_BY_REF) array.setColorRefByte(vga.colors); else array.setColors(0, vga.colors); } if (vga.normals != null) { if (GEOMETRY_BY_REF) array.setNormalRefFloat(vga.normals); else array.setNormals(0, vga.normals); } if (vga.texCoords != null) { if (GEOMETRY_BY_REF) array.setTexCoordRefFloat(0, vga.texCoords); else array.setTextureCoordinates(0, vga.texCoords); } } private static int makeFormat(VisADGeometryArray vga) { int format = 0; if (vga.coordinates != null) format |= GeometryArray.COORDINATES; if (vga.colors != null) { if (vga.colors.length == 3 * vga.vertexCount) { format |= GeometryArray.COLOR_3; } else { format |= GeometryArray.COLOR_4; } } if (vga.normals != null) format |= GeometryArray.NORMALS; if (vga.texCoords != null) { if (vga.texCoords.length == 2 * vga.vertexCount) { format |= GeometryArray.TEXTURE_COORDINATE_2; } else { format |= GeometryArray.TEXTURE_COORDINATE_3; } } if (GEOMETRY_BY_REF) format |= GeometryArray.BY_REFERENCE; return format; } public void destroyUniverse() { if (universe != null) universe.destroy(); universe = null; } public void destroy() throws VisADException, RemoteException { if(isDestroyed())return; ((DisplayRendererJ3D) getDisplayRenderer()).destroy(); if (apiValue == OFFSCREEN) { destroyUniverse(); } MouseBehavior mouse = getMouseBehavior(); if(mouse!=null && mouse instanceof MouseBehaviorJ3D) { ((MouseBehaviorJ3D) mouse).destroy(); } super.destroy(); applet = null; projection = null; mode = null; } float getOffsetDepthMinimum(float depthOffsetMax) { Vector rendVec = getRendererVector(); Iterator<DataRenderer> iter = rendVec.iterator(); float offsetMin = depthOffsetMax; while (iter.hasNext()) { DataRenderer rend = iter.next(); if (rend.hasPolygonOffset()) { if (rend.getPolygonOffset() < offsetMin) { offsetMin = rend.getPolygonOffset(); } } } return offsetMin; } int getNumRenderersWithZoffset() { Vector rendVec = getRendererVector(); Iterator<DataRenderer> iter = rendVec.iterator(); int num = 0; while (iter.hasNext()) { DataRenderer rend = iter.next(); if (rend.hasPolygonOffset()) { num++; } } return num; } /** * Sets the depth buffer offset when autoDepthOffset is enabled for this display. * @param renderer * @param mode */ public void setDepthBufferOffset(DataRenderer renderer, GraphicsModeControl mode) { GraphicsModeControlJ3D mode3d = (GraphicsModeControlJ3D) mode; if (mode3d.getAutoDepthOffsetEnable()) { float depthOffsetInc = mode3d.getDepthOffsetIncrement(); int numLayers = mode3d.getNumRenderersWithDepthOffset(); float maxDepthOffset = numLayers*(-depthOffsetInc); if (!renderer.hasPolygonOffset()) { int cnt = getNumRenderersWithZoffset(); if (cnt < numLayers) { renderer.setPolygonOffset(getOffsetDepthMinimum(maxDepthOffset) + depthOffsetInc); renderer.setPolygonOffsetFactor(0f); renderer.setHasPolygonOffset(true); } else { renderer.setPolygonOffset(0f); renderer.setPolygonOffsetFactor(0f); renderer.setHasPolygonOffset(false); } } mode3d.setPolygonOffset(renderer.getPolygonOffset(), false); mode3d.setPolygonOffsetFactor(renderer.getPolygonOffsetFactor(), false); } } public void resetDepthBufferOffsets() { Vector rendVec = getRendererVector(); Iterator<DataRenderer> iter = rendVec.iterator(); while (iter.hasNext()) { DataRenderer rend = iter.next(); if (rend.hasPolygonOffset()) { rend.setHasPolygonOffset(false); rend.setPolygonOffset(0f); rend.setPolygonOffsetFactor(0f); } } } }