I'd like to believe that its a Java problem, but the behavior is rather consistant and I don't observe this behavior in other, somewhat similar applets. Any chance I'm just doing something wrong in my destroy() method? Ir maybe the scene graph is mangled in some way.
Check out the attached code...
Kelvin Chung wrote:
[EMAIL PROTECTED]">But I have a lingering question concerning termination and cleanup of Java
3d applets. Everything is stable while running my little applet. But
when I close out the Java window that contains the applet, my web browser
freezes (this is under IE6 and Windows 98).
Do I need to remove any objects in finalize or otherwise clean up after
myself when the applet exits? How, since Java usually handles garbage
collection for me?
This sounds like bug 4466966
- IE/Netscape crash and exit sometimes when applet reload
which is fixed in the next v1.3 beta release.
Thanks.
- Kelvin
--------------
Java 3D Team
Sun Microsystems Inc.
/* * @(#)VisDemo.java 1.32 01/09/27 12:27:00 * * Copyright (c) 1996-2001 Computation.com, Inc. All Rights Reserved. * */
package stand; import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.io.*; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.Sphere; import com.sun.j3d.utils.geometry.Cylinder; import com.sun.j3d.utils.universe.*; import com.sun.j3d.utils.behaviors.mouse.*; import javax.media.j3d.*; import javax.vecmath.*; import stand.MouseRotateY; import java.util.Random; public class VisDemo extends Applet { // Constants for type of light to use private static final int DIRECTIONAL_LIGHT = 0; private static final int POINT_LIGHT = 1; private static final int SPOT_LIGHT = 2; private static final float LATTICE_QUANT = 1.0f; private static final int lightType = POINT_LIGHT; Color3f eColor; Color3f sColor; Color3f lColor1; Color3f alColor; Color3f bgColor; Color3f hColor; Color3f pColor; Color3f gColor; private SimpleUniverse u = null; BranchGroup scene; TransformGroup objScale; BoundingSphere bounds; Random random; MouseRotate rotate; MouseZoom zoom; MouseTranslate translate; private int randomInt(int range) { int rint; rint = random.nextInt() % range; if ( rint < 0 ) rint = rint * -1; return rint; } public BranchGroup createSceneGraph(SimpleUniverse u) { BranchGroup objRoot = new BranchGroup(); // Global transform group... objScale = new TransformGroup(); objScale.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objScale.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); Transform3D t3d = new Transform3D(); t3d.setScale(0.2); objScale.setTransform(t3d); // Set up the background bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); Background bg = new Background(bgColor); bg.setApplicationBounds(bounds); objScale.addChild(bg); objRoot.addChild(objScale); return objRoot; } private void createLights() { Transform3D t; // Create a transformation for the light t = new Transform3D(); Vector3d lPos1 = new Vector3d(10.0, 10.0, 10.0); t.set(lPos1); TransformGroup l1Trans = new TransformGroup(t); objScale.addChild(l1Trans); // Create a Geometry for the light ColoringAttributes caL1 = new ColoringAttributes(); caL1.setColor(lColor1); Appearance appL1 = new Appearance(); appL1.setColoringAttributes(caL1); l1Trans.addChild(new Sphere(0.05f, appL1)); // Create light AmbientLight aLgt = new AmbientLight(alColor); Light lgt1 = null; Point3f lPoint = new Point3f(0.0f, 0.0f, 0.0f); Point3f atten = new Point3f(10.0f, 0.0f, 0.0f); Vector3f lDirect1 = new Vector3f(lPos1); lDirect1.negate(); lgt1 = new DirectionalLight(lColor1, lDirect1); aLgt.setInfluencingBounds(bounds); lgt1.setInfluencingBounds(bounds); // Add the lights into the scene graph objScale.addChild(aLgt); objScale.addChild(lgt1); } private void makeAmino(double x, double y, double z, Color3f color) { Transform3D t; t = new Transform3D(); Vector3d pos = new Vector3d(x, y, z); t.set(pos); TransformGroup transGroup1 = new TransformGroup(t); transGroup1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); transGroup1.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); Material m = new Material(color, eColor, color, sColor, 100.0f); m.setLightingEnable(true); Appearance a = new Appearance(); a.setMaterial(m); Sphere sph = new Sphere(0.25f, a); transGroup1.addChild(sph); objScale.addChild(transGroup1); } double testx[]; double testy[]; double testz[]; private static final int LATTICE_SIZE = 40; private static final int H_FREQUENCY = 3; private static final double SCALER = 8.0; private void buildTests(int n) { testx = new double[n]; testy = new double[n]; testz = new double[n]; for ( int i = 0; i < n; i++ ) { testx[i] = this.randomInt(LATTICE_SIZE) - ( LATTICE_SIZE / 2); testy[i] = this.randomInt(LATTICE_SIZE) - ( LATTICE_SIZE / 2); testz[i] = this.randomInt(LATTICE_SIZE) - ( LATTICE_SIZE / 2); testx[i] /= SCALER; testy[i] /= SCALER; testz[i] /= SCALER; } } private void molecules(int length) { this.buildTests(length); for ( int i = 0; i < length; i++) { double x = testx[i]; double y = testy[i]; double z = testz[i]; if ( this.randomInt(H_FREQUENCY) == 0 ) this.makeAmino(x, y, z, hColor); else this.makeAmino(x, y, z, pColor); if ( i < length - 1 ) makeConnector( x, y, z, testx[ i + 1 ], testy[ i + 1 ], testz[ i + 1 ] ); } } public void connectCylinder(Point3f startAtom, Point3f endAtom, float r, Appearance appear) { float radius = r ; float height = (float) startAtom.distance( endAtom ) ; float xCoor = (startAtom.x + endAtom.x) / 2f ; float yCoor = (startAtom.y + endAtom.y) / 2f ; float zCoor = (startAtom.z + endAtom.z) / 2f ; Vector3f rel = new Vector3f( (float) (endAtom.x-startAtom.x), (float) (endAtom.y-startAtom.y), (float) (endAtom.z-startAtom.z)); double xrot = calcAngle( new Vector3f(0.0f, 1.0f, 0.0f), rel); Vector3f proj = new Vector3f(rel.x, 0.0f, rel.z); float yrot = calcSign(new Vector3f(1.0f, 0.0f, 0.0f), proj)* calcAngle(new Vector3f(0.0f, 0.0f, 1.0f ), proj); Transform3D rot = new Transform3D(); rot.rotX(xrot); Transform3D bond_position = new Transform3D() ; bond_position.rotY(yrot); bond_position.mul(rot); bond_position.setTranslation( new Vector3f( xCoor, yCoor, zCoor ) ); TransformGroup transformGroup = new TransformGroup(bond_position); transformGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_READ); transformGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE); Cylinder bond_cyl = new Cylinder( radius, height ) ; bond_cyl.setAppearance( appear ) ; transformGroup.addChild( bond_cyl ) ; objScale.addChild( transformGroup ) ; } protected static float calcAngle(Vector3f coor, Vector3f other) { double scalarProduct = (double)coor.dot(other); if (scalarProduct == 0.0f) { return (float)Math.PI/2.0f; } scalarProduct = scalarProduct/(coor.length()*other.length()); return (float)Math.acos(scalarProduct); } protected static float calcSign(Vector3f coor, Vector3f other) { double sp = (double)coor.dot(other); if (sp == 0.0f) return 0.0f; return (float)(sp/Math.abs(sp)); } private void makeConnector(double lastx, double lasty, double lastz, double x, double y, double z) { Transform3D t; Vector3d pos; float radius = 0.05f; Point3f startAtom; Point3f endAtom; // Appearance and materials... Material m = new Material(gColor, eColor, gColor, sColor, 100.0f); m.setLightingEnable(true); Appearance a = new Appearance(); a.setMaterial(m); // Now build the cylinder... startAtom = new Point3f((float) lastx, (float) lasty, (float) lastz); endAtom = new Point3f((float) x, (float) y, (float) z); connectCylinder(startAtom, endAtom, radius, a); } public VisDemo() { } public void init() { random = new Random(); eColor = new Color3f(0.0f, 0.0f, 0.0f); sColor = new Color3f(1.0f, 1.0f, 1.0f); lColor1 = new Color3f(1.0f, 1.0f, 1.0f); alColor = new Color3f(0.1f, 0.1f, 0.4f); bgColor = new Color3f(0.01f, 0.01f, 0.05f); hColor = new Color3f(0.6f, 0.1f, 0.1f); // Hydrophobes pColor = new Color3f(0.1f, 0.1f, 0.6f); // Polars gColor = new Color3f(0.6f, 0.6f, 0.6f); // End setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); Canvas3D c = new Canvas3D(config); add("Center", c); u = new SimpleUniverse(c); scene = this.createSceneGraph(u); this.molecules( this.randomInt(LATTICE_SIZE) ); this.createLights(); scene.compile(); // Add mouse behavior... ViewingPlatform v = u.getViewingPlatform(); // Use objScale to center the rotation... MouseRotate rotate = new MouseRotate(); rotate.setTransformGroup(objScale); BranchGroup rotateBG = new BranchGroup(); rotateBG.addChild(rotate); v.addChild(rotateBG); rotate.setSchedulingBounds(bounds); MouseZoom zoom = new MouseZoom(c, MouseZoom.INVERT_INPUT); zoom.setTransformGroup(v.getMultiTransformGroup().getTransformGroup(0)); zoom.setSchedulingBounds(bounds); BranchGroup zoomBG = new BranchGroup(); zoomBG.addChild(zoom); v.addChild(zoomBG); MouseTranslate translate = new MouseTranslate(c, MouseTranslate.INVERT_INPUT); translate.setTransformGroup(v.getMultiTransformGroup().getTransformGroup(0)); translate.setSchedulingBounds(bounds); BranchGroup translateBG = new BranchGroup(); translateBG.addChild(translate); v.addChild(translateBG); // End mouse behavior // This will move the ViewPlatform back a bit so the // objects in the scene can be viewed. u.getViewingPlatform().setNominalViewingTransform(); u.addBranchGraph(scene); } public void destroy() { u.removeAllLocales(); /* eColor = null; sColor = null; lColor1 = null; alColor = null; bgColor = null; hColor = null; pColor = null; gColor = null; u = null; scene = null; objScale = null; bounds = null; random = null; // Do I need to do anything special with behaviors? rotate = null; translate = null; zoom = null; testx = null; testy = null; testz = null; */ } public String getAppletInfo() { return "VisDemo v. 1.0, Written by John T. Nelson"; } // The following allows VisDemo to be run as an application // as well as an applet. public static void main() { new MainFrame(new VisDemo(), 400, 400); } }