Just a clarification...

This bug is fixed in the sense that the geometry primitives have been
optimized in 1.2.1 beta2.  For the Box primitive this means the internal
TransformGroups have been removed and geometry is cached so boxes with
the same parameters can share their geometry.  These optimizations
improved the memory usage a lot, but a program with 20,000 boxes will
still run out of memory because there are 6 Shape3D nodes for each Box.
This is needed because the getShape(int partId) method must return a
separate Shape3D for each face.

For more performance information, please check out the attached
performance guide.

Thanks.

andrea



Kelvin Chung wrote:
>
> Hi,
>
>    This bug
>
>    4346786 - OutOfMemory error when generating 20,000 Box primitives
>
> is fixed in next v1.2.1beta2 release. The Transform3D group in
> the utility Box/Cone/Cylinder primitives is removed.
>
> Thanks.
>
> - Kelvin
> --------------
> Java 3D Team
> Sun Microsystems Inc.
>
> >X-Unix-From: [EMAIL PROTECTED]  Tue Nov 21 22:36:28 2000
> >Date: Tue, 21 Nov 2000 22:07:26 -0800
> >From: R Wang <[EMAIL PROTECTED]>
> >Subject: [JAVA3D] How to handle a large number of objects? (Java3d sucks?)
> >To: [EMAIL PROTECTED]
> >
> >Hello guys,
> >I've been playing around with java3d for 2 weeks and think it's a pretty cool
> thing until today. I was trying to build a scene of 128 x 128 simple boxes. I
> arranged each box with a new TransformGroup like this:
> >
> >Transform3D trans = new Transform3D();
> >TransformGroup tg;
> >for (int i = 0; i < 128; i++)
> >    for (int j = 0; j < 128; j++) {
> >         trans.do_some_translations...
> >         tg = new TransformGroup(trans);
> >         tg.add_a_box_object...
> >    }
> >
> >Was it the way that you guys did to construct such a scene? (I hope I was
> wrong.) but the rendering seemed to last forever until "out of memory" error
> showed up. Even if I used "java -mx256m xxxx" command, no good at all. I finally
> got the scene show up by reducing the number of objects to 30 x 30 ! ..and the
> rendering is way slow. If that was java3d supposed to be, it really SUCKS! By
> openGL on the same PC I can easily make that scene and even animate it. The
> rendering only takes a couple of seconds and I can run lots of other big
> programs at the same time, like Visual c++, matlab...
> >I don't know why java3d makes contructing objects so complicated...why do we
> need that memory-sucking transformgroup for every object?
> >I feel so disappointed tonight because of the poor performance of java3d. I
> spent lots of time during this two weeks learning java3d as I thought java3d can
> make that scene easily. (It's 3D tool, isn't it?). But now I feel desperate
> 'cause I've been working on this for two weeks and looks like I have to move
> back to openGL..I'm running out of time:-(
> >
> >..so my question is; does someone have experience building a scene with large
> number of objects? How did you do that to avoid memory exhaustion
> >
> >===========================================================================
> >To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
> >of the message "signoff JAVA3D-INTEREST".  For general help, send email to
> >[EMAIL PROTECTED] and include in the body of the message "help".
>
> ===========================================================================
> To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
> of the message "signoff JAVA3D-INTEREST".  For general help, send email to
> [EMAIL PROTECTED] and include in the body of the message "help".
                Performance Guide for Java 3D 1.2.1

I - Introduction

    The Java 3D API was designed with high performance 3D graphics
as a primary goal.  Since this is a new API, many of its performance
features are not well known.  This document presents the performance
features of Java 3D in a number of ways.  It describes the specific
APIs that were included for performance.  It describes which
optimizations are currently implemented in Java 3D 1.2.1.  And, it describes
a number of tips and tricks that application writers can use to improve
the performance of their application.


II - Performance in the API

    There are a number of things in the API that were included specifically
to increase performance.  This section examines a few of them.

    - Capability bits
        Capability bits are the applications way of describing its intentions
        to the Java 3D implementation.  The implementation examines the
        capability bits to determine which objects may change at run time.
        Many optimizations are possible with this feature.

    - Compile
        The are two compile methods in Java 3D 1.2.1.  They are in the
        BranchGroup and SharedGroup classes.  Once an application calls
        compile(), only those attributes of objects that have their
        capability bits set may be modified.  The implementation may then
        use this information to "compile" the data into a more efficient
        rendering format.

    - Bounds
        Many Java 3D object require a bounds associated with them.  These
        objects include Lights, Behaviors, Fogs, Clips, Backgrounds,
        BoundingLeafs, Sounds, and Soundscapes.  The purpose of these
        bounds is to limit the spatial scope of the specific object.
        The implementation may quickly disregard the processing
        of any objects that are out of the spatial scope of a target
        object.

    - Unordered Rendering
        All state required to render a specific object in Java 3D is
        completely defined by the direct path from the root node to the
        given leaf.  That means that leaf nodes have no effect on other
        leaf nodes, and therefore may be rendered in any order.  There
        are a few ordering requirements for direct descendents of
        OrderedGroup nodes or Transparent objects.  But, most leaf nodes
        may be reordered to facilitate more efficient rendering

    - Appearance Bundles
        A Shape3D node has a reference to a Geometry and an Appearance.
        An Appearance NodeComponent is simply a collection of other
        NodeComponent references that describe the rendering characteristics
        of the geometry.  Because the Appearance is nothing but a
        collection of references, it is much simpler and more efficient for
        the implementation to check for rendering characteristic changes when
        rendering.  This allows the implementation to minimize state changes
        in the low level rendering API.


III - Current Optimizations in Java 3D 1.2.1

    This section describes a number of optimizations that are currently
implemented in Java 3D 1.2.1.  Other optimizations will be implemented as
the API matures.  The purpose of this section is to help application
programmers focus their optimizations on things that will compliment
the current optimizations in Java 3D.

    - Hardware
        Java 3D uses OpenGL and Direct3D as its low level rendering
        APIs.  It relies on the underlying OpenGL and Direct3D drivers
        for its low level rendering acceleration.  Using a graphics
        display adapter that offers OpenGL or Direct3D acceleration is
        the best way to increase overall rendering performance in Java 3D.

    - Compile
        In the Java 3D 1.2 release, no compile optimizations were
        implemented.  The following compile optimizations are
        implemented in the Java 3D 1.2.1 release:

            .   Scene graph flattening:  TransformGroup nodes that are
                neither readable nor writable are collapsed into a
                single transform node.

            .   Combining Shape3D nodes:  Non-writable Shape3D nodes
                that have the same appearance attributes and are under
                the same TransformGroup (after flattening) are
                combined, internally, into a single Shape3D node that
                can be rendered with less overhead.

    - State Sorted Rendering
        Since Java 3D allows for unordered rendering for most leaf
        nodes, the implementation sorts all objects to be rendered on
        a number of rendering characteristics.  The characteristics
        that are sorted on are, in order, Lights, Texture, Geometry
        Type, Material, and finally localToVworld transform.  The only
        exception to this is any child of an OrderedGroup node.  There
        is no state sorting for those objects.

    - View Frustum Culling

        The Java 3D implementation implements view frustum culling.
        The view frustum cull is done when an object is processed for
        a specific Canvas3D.  This cuts down on the number of objects
        needed to be processed by the low level graphics API.

    - Multithreading
        The Java 3D API was designed with multithreaded environments
        in mind.  The current implementation is a fully multithreaded
        system.  At any point in time, there may be parallel threads
        running performing various tasks such as visibility detection,
        rendering, behavior scheduling, sound scheduling, input
        processing, collision detection, and others.  Java 3D is
        careful to limit the number of threads that can run in
        parallel based on the number of CPUs available.


IV - Tips and Tricks

    This section presents a number of tips and tricks for an application
programmer to try when optimizing their application.  These tips focus on
improving rendering frame rates, but some may also help overall application
performance.  A number of these optimization will eventually be handled
directly by the Java 3D implementation.

    - Move Object vs. Move ViewPlatform
        If the application simply needs to transform the entire scene,
        transform the ViewPlatform instead.  This changes the problem
        from transforming every object in the scene into only
        transforming the ViewPlatform.

    - Capability bits
        Only set them when needed.  Many optimizations can be done
        when they are not set.  So, plan out application requirements
        and only set the capability bits that are needed.

    - Bounds and Activation Radius
        Consider the spatial extent of various leaf nodes in the scene
        and assign bounds accordingly.  This allows the implementation
        to prune processing on objects that are not in close
        proximity.  Note, this does not apply to Geometric bounds.
        Automatic bounds calculations for geometric objects is fine.

    - Change Number of Shape3D Nodes
        In the current implementation there is a certain amount of
        fixed overhead associated with the use of the Shape3D node.
        In general, the fewer Shape3D nodes that an application uses,
        the better.  However, combining Shape3D nodes without
        factoring in the spatial locality of the nodes to be combined
        can adversely effect performance by effectively disabling view
        frustum culling.  An application programmer will need to
        experiment to find the right balance of combining Shape3D
        nodes while leveraging view frustum culling.  The .compile
        optimization that combines shape node will do this
        automatically, when possible.

    - Geometry Type and Format
        Most rendering hardware reaches peak performance when
        rendering long triangle strips.  Unfortunately, most geometry
        data stored in files is organized as independent triangles or
        small triangle fans (polygons).  The Java 3D utility package
        includes a stripifier utility that will try to convert a given
        geometry type into long triangle strips.  Application
        programmers should experiment with the stripifier to see if it
        helps with their specific data.  If not, any stripification
        that the application can do will help.  Another option is that
        most rendering hardware can process a long list of independent
        triangles faster than a long list of single triangle triangle
        fans.  The stripifier in the Java 3D utility package will be
        continually updated to provided better stripification.

    - Sharing Appearance/Texture/Material NodeComponents
        To assist the implementation in efficient state sorting, and
        allow more shape nodes to be combined during compilation,
        applications can help by sharing Appearance/Texture/Material
        NodeComponent objects when possible.

    - Geometry by reference
        Using geometry by reference reduces the memory needed to store
        a scene graph, since Java 3D avoids creating a copy in some
        cases.  However, using this features prevents Java 3D from
        creating display lists (unless the scene graph is compiled),
        so rendering performance can suffer in some cases.  It is
        appropriate if memory is a concern or if the geometry is
        writable and may change frequently.  The interleaved format
        will perform better than the non-interleaved formats, and
        should be used where possible.  In by-reference mode, an
        application should use arrays of native data types; referring
        to TupleXX[] arrays should be avoided.

    - Texture by reference and Y-up

        Using texture by reference and Y-up format may reduce the
        memory needed to store a texture object, since Java 3D avoids
        creating a copy in some cases.  Currently, Java3D will not
        make a copy of texture image for the following combinations of
        BufferedImage format and ImageComponent format (byReference
        and Yup should both be set to true):

                On both Solaris and Win32 OpenGL:

        BufferedImage.TYPE_CUSTOM       ImageComponent.FORMAT_RGB8 or
        of form 3BYTE_RGB               ImageComponent.FORMAT_RGB

        BufferedImage.TYPE_CUSTOM       ImageComponent.FORMAT_RGBA8 or
        of form 4BYTE_RGBA              ImageComponent.FORMAT_RGBA

        BufferedImage.TYPE_BYTE_GRAY    ImageComponent.FORMAT_CHANNEL8

                On Win32/OpenGL:

        BufferedImage format            ImageComponentFormat
        ----------------------          ----------------------
        BufferedImage.TYPE_3BYTE_BGR    ImageComponent.FORMAT_RGB8 or
                                        ImageComponent.FORMAT_RGB

                On Solaris/OpenGL:

        BufferedImage format            ImageComponentFormat
        ----------------------          ----------------------
        BufferedImage.TYPE_4BYTE_ABGR   ImageComponent.FORMAT_RGBA8 or
                                        ImageComponent.FORMAT_RGBA

    - Application Threads
        The built in threads support in the Java language is very
        powerful, but can be deadly to performance if it is not
        controlled.  Applications need to be very careful in their
        threads usage.  There are a few things to be careful of when
        using Java threads.  First, try to use them in a demand driven
        fashion.  Only let the thread run when it has a task to do.
        Free running threads can take a lot of cpu cycles from the
        rest of the threads in the system - including Java 3D threads.
        Next, be sure the priority of the threads are appropriate.
        Most Java Virtual Machines will enforce priorities
        aggressively.  Too low a priority will starve the thread and
        too high a priority will starve the rest of the system.  If in
        doubt, use the default thread priority.  Finally, see if the
        application thread really needs to be a thread.  Would the
        task that the thread performs be all right if it only ran once
        per frame?  If so, consider changing the task to a Behavior
        that wakes up each frame.

    - Java 3D Threads
        Java 3D uses many threads in its implementation, so it also
        needs to implement the precautions listed above.  In almost
        all cases, Java 3D manages its threads efficiently.  They are
        demand driven with default priorities.  There are a few cases
        that don't follow these guidelines completely.

        - Behaviors
            One of these cases is the Behavior scheduler when there
            are pending WakeupOnElapsedTime criteria.  In this case,
            it needs to wakeup when the minimum WakeupOnElapsedTime
            criteria is about to expire.  So, application use of
            WakeupOnElapsedTime can cause the Behavior scheduler to
            run more often than might be necessary.

        - Sounds
            The final special case for Java 3D threads is the Sound
            subsystem.  Due to some limitations in the current sound
            rendering engine, enabling sounds cause the sound engine
            to potentially run at a higher priority than other
            threads.  This may adversely effect performance.

    - Threads in General
        There is one last comment to make on threads is general.
        Since Java 3D is a fully multithreaded system, applications
        may see significant performance improvements by increasing the
        number of CPUs in the system.  For an application that does
        strictly animation, then two CPUs should be sufficient.  As
        more features are added to the application (Sound, Collision,
        etc.), more CPUs could be utilized.

        Note: When running in the Solaris environment, be sure that
              native threads are enabled.  Green threads will not take
              advantage of multiple CPUs.

    - Switch Nodes for Occlusion Culling
        If the application is a first person point of view
        application, and the environment is well known, Switch nodes
        may be used to implement simple occlusion culling.  The
        children of the switch node that are not currently visible may
        be turned off.  If the application has this kind of knowledge,
        this can be a very useful technique.

    - Switch Nodes for Animation
        Most animation is accomplished by changing the transformations
        that effect an object.  If the animation is fairly simple and
        repeatable, the flip-book trick can be used to display the
        animation.  Simply put all the animation frames under one
        switch node and use a SwitchValueInterpolator on the switch
        node.  This increases memory consumption in favor of smooth
        animations.

    - Switch nodes under Writable Transforms
        Switch nodes that are descendants of writable TransformGroup
        nodes can incur extra cost associate with updating the vworld
        bounds and localToVworld transforms of all children (not just
        those that are switched on).  This is one more reason why it
        is better to rotate the viewer than the entire scene graph
        (see "Move Object vs. Move ViewPlatform")

    - Link/SharedGroup versus cloneTree
        Using multiple Link nodes pointing to a shared subgraph
        (SharedGroup) can have a performance penalty over a shallow
        clone of the scene graph.  To create a shallow clone of the
        scene graph, use cloneTree without duplication the node
        components.  Restrict the use of Link/SharedGroup to those
        cases where you really need the kind of sharing that it
        provides.

    - OrderedGroup Nodes
        OrderedGroup and its subclasses are not as high performing as
        the unordered group nodes.  They disable any state sorting
        optimizations that are possible.  If the application can find
        alternative solutions, performance will improve.

    - LOD Behaviors
        For complex scenes, using LOD Behaviors can improve
        performance by reducing geometry needed to render objects that
        don't need high level of detail.  This is another option that
        increases memory consumption for faster render rates.

    - Picking
        If the application doesn't need the accuracy of geometry based
        picking, use bounds based picking.  For more accurate picking
        and better picking performance, use PickRay instead of
        PickCone/PickCylnder unless you need to pick line/point.
        PickCanvas with a tolerance of 0 will use PickRay for picking.

Reply via email to