Hi Scott,

It sounds like you might have found a bug, but we need a test case.  

The exception is being raised on a line which is transforming the bounds for a 
light, with the traverser stack showing the scene graph above the light as:

BranchGroup->
 TransformGroup->
  BranchGroup->
   Switch->
    TransformGroup->
     BranchGroup->
      Link->
       SharedGroup->
        BranchGroup->
         Link->
          SharedGrop->
           Light
     


I tried modifying the LOD example to use shared groups, but that doesn't show 
the problem.  I think we need to build up a more complex scene graph like your 
application.  In particular, it looks like we need to have a light with an 
influencing bounds.  It may be important for the light to appear more than once.

Can you try modifiying LOD.java (attached below) to show the problem?   Start by 
putting a light into each SharedGroup under the switch, if that doesn't show the 
probelm keep adding more elements to match your scene graph until the example 
fails.

It might help if you print out your application's J3D tree. Try calling the 
attched TreePrinter.java with your scene graph.  If you need more detail about 
nodes in the graph, add more inquiries to the TreePrinter (and send your mods 
back my way, thanks).

Hope this helps,
  
Doug

> From: Scott Gross <[EMAIL PROTECTED]>
>  
> I have an application in which a scene graph is built from many many
> imported VRML models.  The models are loaded and the returned
> BranchGroups are wrapped by some application-specific code -- basically
> another BranchGroup and then added to the scene graph.  The world itself
> is built at runtime via the execution of a script that determines which
> VRML models to load and directs the building of the application-specific
> wrappers.  Anyway, once the script got too big I started getting out of
> memory errors and decided I had to optimize.  Many of the imported models
> are the same (many foo.wrls for instance) so I figured I'd use a
> SharedGroup node and instead of having the application-specific wrapper
> BranchGroups add the loader-returned BGs directly, they'd add a link to
> the SharedBranch.  Well it looks like it works in the beginning, and I see
> the first few models, but when it has to load models that initially are
> not visible (their wrappers are in a big switch that is controlled by a
> Distance LOD that puts them far away from the Viewpoint) I get a
> NullPointerException in the Traverser.  Here's the exception:
> 
> java.lang.NullPointerException: 
>       at javax.media.j3d.Traverser.traverse(Traverser.java:1779)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:978)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:1713)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:721)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:807)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:978)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:1713)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:807)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:721)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:904)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:721)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:807)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:721)
>       at javax.media.j3d.Traverser.traverse(Traverser.java:807)
>       at javax.media.j3d.Traverser.run(Traverser.java:2069)
>  
>  
>  Needless to say, I'm between a rock and a hard place here.  If I don't
>  use the shared groups I run out of memory (In my particular app it really
>  makes sense to load the entire scene all in the beginning instead of
>  inrementally -- but there are no textures), but when I do, I get this
>  error. 
>  
> 
>  Heeeelp.
>  
>  thanks,
>  
>                                       -Scott
>  
>  
> 
>    Scott Gross
>    Columbia University CC '98
>    549 Manhattan Avenue #2
>    New York, NY 10025
>    _________________________________________________________________________
>                                                      (212) 939-7100
>                                                      [EMAIL PROTECTED]
>                                                    [EMAIL PROTECTED]
>                                                      
www.cs.columbia.edu/~sbg23
> 
> 
> 
> =====================================================================
> To subscribe/unsubscribe, send mail to [EMAIL PROTECTED]
> Java 3D Home Page: http://java.sun.com/products/java-media/3D/
/*
 *      @(#)LOD.java 1.2 98/09/16 09:09:23
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class LOD extends Applet {
    public BranchGroup createSceneGraph() {
        // Create the root of the branch graph
        BranchGroup objRoot = new BranchGroup();

        createLights(objRoot);

        // Create the transform group node and initialize it to the
        // identity.  Enable the TRANSFORM_WRITE capability so that
        // our behavior code can modify it at runtime.  Add it to the
        // root of the subgraph.
        TransformGroup objTrans = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        objRoot.addChild(objTrans);

        // Create a switch to hold the different levels of detail
        Switch sw = new Switch(0);
        sw.setCapability(javax.media.j3d.Switch.ALLOW_SWITCH_READ);
        sw.setCapability(javax.media.j3d.Switch.ALLOW_SWITCH_WRITE);


        // Create several levels for the switch, with less detailed
        // spheres for the ones which will be used when the sphere is
        // further away
        SharedGroup sphere40 = new SharedGroup();
        sphere40.addChild(new Sphere(0.4f, Sphere.GENERATE_NORMALS, 40));
        SharedGroup sphere20 = new SharedGroup();
        sphere20.addChild(new Sphere(0.4f, Sphere.GENERATE_NORMALS, 20));
        SharedGroup sphere10 = new SharedGroup();
        sphere10.addChild(new Sphere(0.4f, Sphere.GENERATE_NORMALS, 10));
        SharedGroup sphere3 = new SharedGroup();
        sphere3.addChild(new Sphere(0.4f, Sphere.GENERATE_NORMALS, 3));

        sw.addChild(new Link(sphere40));
        sw.addChild(new Link(sphere20));
        sw.addChild(new Link(sphere10));
        sw.addChild(new Link(sphere3));

        // Add the switch to the main group
        objTrans.addChild(sw);

        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

        // set up the DistanceLOD behavior
        float[] distances = new float[3];
        distances[0] = 5.0f;
        distances[1] = 10.0f;
        distances[2] = 25.0f;
        DistanceLOD lod = new DistanceLOD(distances);
        lod.addSwitch(sw);
        lod.setSchedulingBounds(bounds);
        objTrans.addChild(lod);

        // set up a behavior to let the object be moved closer and further
        // away
        MouseZoom mz = new MouseZoom();
        mz.setTransformGroup(objTrans);
        mz.setSchedulingBounds(bounds);
        objTrans.addChild(mz);


        // Have Java 3D perform optimizations on this scene graph.
        objRoot.compile();

        return objRoot;
    }

    private void createLights(BranchGroup graphRoot) {

        // Create a bounds for the light source influence
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

        // Set up the global, ambient light
        Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f);
        AmbientLight aLgt = new AmbientLight(alColor);
        aLgt.setInfluencingBounds(bounds);
        graphRoot.addChild(aLgt);

        // Set up the directional (infinite) light source
        Color3f lColor1 = new Color3f(0.9f, 0.9f, 0.9f);
        Vector3f lDir1  = new Vector3f(1.0f, 1.0f, -1.0f);
        DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
        lgt1.setInfluencingBounds(bounds);
        graphRoot.addChild(lgt1);
    }


    public LOD() {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(null);
        add("Center", c);

        // Create a simple scene and attach it to the virtual universe
        BranchGroup scene = createSceneGraph();
        SimpleUniverse u = new SimpleUniverse(c);

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        u.getViewingPlatform().setNominalViewingTransform();

        u.addBranchGraph(scene);
    }

    //
    // The following allows LOD to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {
        new MainFrame(new LOD(), 512, 512);
    }
}
/*
 *      @(#)TreePrinter.java 1.15 98/11/05 20:35:29
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

/*
 * @Author: Doug Gehringer
 * @Author: Rick Goldberg
 *
 */



import javax.media.j3d.*;
import java.io.PrintStream;
import java.util.Set;
import java.util.HashSet;
import java.util.Enumeration;
import java.util.Iterator;

public class TreePrinter {
    PrintStream printStream;
    String j3dPkg = new String("javax.media.j3d.");
    String v97Pkg = new String("com.sun.j3d.loaders.vrml97.impl.");

    public void print(PrintStream s, Locale l) {
        printStream = s;
        HashSet sharedGroups = new HashSet();
        printTree(l, 0, sharedGroups);
        Iterator iterator = sharedGroups.iterator(); 
        while (iterator.hasNext()) {
            SharedGroup sg = (SharedGroup) iterator.next();
            print(s, sg);
        }
    }

    public void print(Locale l) {
        print(System.out, l);
    }

    private void printTree(Locale l, int graphDepth, Set sharedGroups) {
        printNode(l,0,sharedGroups);
        try {
            Enumeration e = l.getAllBranchGraphs();
            while (e.hasMoreElements()) {
                Object o = e.nextElement();     
                if ( o instanceof Locale ) 
                    printTree((Locale)o, graphDepth+1, sharedGroups);
                else if ( o instanceof SceneGraphObject )
                    printTree((SceneGraphObject)o, graphDepth+1, sharedGroups);
                else 
                    printStream.println(o+ " unknown and in tree");
            }
        } catch (CapabilityNotSetException e) {
            printStream.println("No capability to read children");
        }
    }

    public void print(PrintStream s, SceneGraphObject sgo) {
        printStream = s;
        HashSet sharedGroups = new HashSet();
        printTree(sgo, 0, sharedGroups);
        Iterator iterator = sharedGroups.iterator(); 
        while (iterator.hasNext()) {
            SharedGroup sg = (SharedGroup) iterator.next();
            print(s, sg);
        }
    }

    public void print(SceneGraphObject sgo) {
        print(System.out, sgo);
    }

    private void printTree(SceneGraphObject sgo, 
                int graphDepth, Set sharedGroups) {
        
        printNode(sgo, graphDepth, sharedGroups);
        if(sgo instanceof javax.media.j3d.Group) {
            try {
                Enumeration e = ((javax.media.j3d.Group)sgo).getAllChildren();
                while (e.hasMoreElements())  {
                    printTree((SceneGraphObject)(e.nextElement()),graphDepth+1,
                        sharedGroups);
                }
           } catch (CapabilityNotSetException e) {
                // Can't read handled below
           }
        } 
    }

    private String nodeString(Object o) {
        String objString = o.toString();
        if (objString.startsWith(j3dPkg)) {
            objString = objString.substring(j3dPkg.length());
        }
        if (objString.startsWith(v97Pkg)) {
            objString = objString.substring(v97Pkg.length());
        }
        return objString;
    }

    private void printNode(Object o, int indent, Set sharedGroups) {
        for(int i = 0; i<indent; i++) printStream.print(">");
        printStream.print(nodeString(o) + ": ");
        if (o instanceof SceneGraphObject) {
            SceneGraphObject sgo = (SceneGraphObject) o;
            int capBits = 0;
            // TODO: how to make sure we always check all the valid bits?
            for (int i = 0; i < 64; i++) {
                if (sgo.getCapability(i)) {
                    capBits |= 1 << i;
                }
            }
            printStream.print("capBits:Ox" + Integer.toHexString(capBits)); 
            if (o instanceof javax.media.j3d.Group) {
                javax.media.j3d.Group g = (javax.media.j3d.Group)o;
                int numChildren = 0;
                try {
                    numChildren = g.numChildren();
                } catch (CapabilityNotSetException e) {
                    //anyone who is using treePrinter, is debugging, so it is
                    //alright to blindly allow read. you should first detach
                    //browser.curScene, print the tree, then add it back to 
                    //browser.locale when finished.
                    g.setCapability(javax.media.j3d.Group.ALLOW_CHILDREN_READ);
                    numChildren = g.numChildren();
                    //System.out.println("Can't read children on group");
                    //return;
                }
                printStream.print(" children:" + numChildren);
                if (o instanceof TransformGroup) {
                    Transform3D transform = new Transform3D();
                    Transform3D identity = new Transform3D();
                    TransformGroup t = (TransformGroup) o;
                    t.getTransform(transform);
                    // TODO: use getBestType() when implemented
                    if (transform.equals(identity)) {
                        printStream.print(" xform:IDENTITY ");
                    } else {
                        printStream.print(" xform:NON-IDENTITY ");
                    }
                }
            } else if (o instanceof Link) {
                Link l = (Link)o;
                SharedGroup sg = l.getSharedGroup();
                printStream.print(" sg:"+ nodeString(sg));
                sharedGroups.add(sg);
            } else {
                printStream.print(": leaf");
            }
        }
        printStream.println();
    }
}

Reply via email to