OK, Kelvin has filed two bugs on my behalf:

> Hi Paul,
>
>    I've filed bug 4732956
> - Raster z value set incorrectly when setDstOffset() or CLIP_IMAGE mode is used
>
> for problem (1).
> Culling works fine if setDstOffset() and CLIP_IMAGE mode is not used.


> For (5) bug 4732965
> - Raster CLIP_IMAGE mode cause flickering when part of it is clipped


Kelvin is right.  If you don't use CLIP_IMAGE or setDstOffset, everything

seems to work fine.

Anyone have a workaround for the setDstOffset problem?  I need the
raster to be centered at its location, so this means I need to move
it up and to the left by half its height and width.  The width and
height are measured in pixels.  Since one pixel is a greater distance
when further from the eye this will need to be a behavior that sets
the offset in a transform depending on the current Z value.  How do
I compute that transform to convert pixels into object coordinates?
My guess:  (getLocalToVworld.mul(getVworldToImagePlate)).inverse.
This should give me an image plate to local transform.  I'll try
that and see if it works.

-Paul




Paul Pantera wrote:

>
> OK, I've composed a small program demonstrating the problems I'm
> seeing.  It has a sphere and a label both at the same position.
>
>> 1)  Rasters ignoring front and back clipping planes.
>
>
>
> Zoom way in, zoom way out.  The sphere disappears, the label
> never does.
>
>
>> 2)  Rasters ignoring setDepthBufferEnable and always doing depth
>>      buffer compare.
>
>
>
> This demo isn't showing this.  Justin suggested that maybe it's a
> rendering order issue. When alwaysOnTop is true (depth buffering
> is disabled) the raster is always either entirely in front of
> the sphere or entirely behind it.  Justin suggested I use
> OrderedGroup to make sure my rasters are rendered last.
>
> OrderedGroup may be the only way to do what I need to do.
> Since I can't control the depth of my rasters, I can use
> OrderedGroup to render my objects in a specific order so
> that objects in front of the scene obscure labels behind
> them.  Any comments on this?  Is the use of OrderedGroup
> going to slow me down?  I guess I'll find out soon enough. . .
>
>> 3)  A raster and another Shape transformed by the same transforms
>>      end up at different depths.
>
>
> Use the menu to turn off alwaysOnTop.  Zoom in and notice how the
> sphere comes right through the label.  The label and the sphere
> are at the same position, so the label should always be in the
> center of the sphere.  Depending on the position of the sphere,
> the label moves relative to it in Z.
>
>> 4)  Documentation unclear about the meaning of a Raster's position.
>>     (Perhaps more bugs here too, depending on the meaning.)
>
>
> I'm not setting the raster's position in this example program, for
> simplicity.
>
>> 5)  CLIP_IMAGE causes flickering
>
>
> Move the sphere over to the left so the left side of the raster is
> clipped. Now spin the sphere and watch the label flicker.
>
>> 6)  Sign problem with setDstOffset
>
>
> This may not be a bug, but you may want to document it because it's
> not clear to me why positive X and Y offsets move the raster up and
> to the left.
>
> -Paul
>
>
> ------------------------------------------------------------------------
>
> /*****************************************************************************
>  *                      J3D.org Copyright (c) 2000
>  *                              Java Source
>  *
>  * This source is licensed under the GNU LGPL v2.1
>  * Please read http://www.gnu.org/copyleft/lgpl.html for more information
>  *
>  ****************************************************************************/
>
> package org.j3d.geom;
>
> // Standard imports
> import javax.media.j3d.*;
>
> import java.awt.AlphaComposite;
> import java.awt.Color;
> import java.awt.Font;
> import java.awt.FontMetrics;
> import java.awt.Graphics;
> import java.awt.Graphics2D;
> import java.awt.geom.Rectangle2D;
> import java.awt.image.BufferedImage;
>
> import javax.vecmath.Point3f;
>
> // Application specific imports
>
> /**
>  * A text label for labelling objects on screen that uses a Java 3D Raster
>  * to produce the overlay effect.
>  * <p>
>  *
>  * If the label text is null, then no label will be displayed. All of the
>  * setup will be done, but no raster will be created.
>  * <p>
>  *
>  * The text label can come in a number of flavours depending on how you
>  * configure it through the constructors. You may build a label that is
>  * only static, always fixed size regardless of text length, and/or may
>  * be hidden from other objects v always on the top. Once configured to one
>  * of these versions, it cannot be changed.
>  * <p>
>  *
>  * If running dynamic text, the internal images will only resize to a
>  * larger size. That is, if a new string comes in that is smaller than
>  * the original string, the image will stay the larger length than the
>  * original. The idea is to reduce the amount of garbage generated. However,
>  * in some instances this may not produce acceptable visual behaviour,
>  * so the crop() method is introduced that will force the image size to
>  * be reduced to the smallest possible size for the next time a string
>  * is set. There are also variants on the setText() methods to do this
>  * as well with a flag. Cropping is independent of the fixedSize flag but is
>  * still subject to the dynamic flag on the constructor.
>  *
>  * @author Justin Couch
>  * @version $Revision: 2.0 $
>  */
> public class RasterTextLabel extends Shape3D
> {
>     /** Message when the text label is not setup for dynamic changes */
>     private static final String CANT_CHANGE_MSG =
>         "Attempting to make a change to a label that was not originally " +
>         "configured to be dynamic";
>
>     /** The clear colour used to clear the background of the image */
>     private static final Color CLEAR_COLOR = new Color(0, 0, 0, 0);
>
>     /** The inset between the text and the border if one is required. */
>     private static final int BORDER_INSETS = 2;
>
>     /** The current color of the text */
>     private Color textColor;
>
>     /** The current color of the border. Null if not in use */
>     private Color borderColor;
>
>     /** The background color of the image */
>     private Color backgroundColor;
>
>     /** The font of the label. Null if using system default */
>     private Font labelFont;
>
>     /** The raster object that we put the information in */
>     private Raster raster;
>
>     /** The image component that holds the image used by the raster */
>     private ImageComponent2D component;
>
>     /**
>      * Flag to say if the implementation should resize the underlying label
>      * for each text update or not.
>      */
>     private boolean adjustImageSize;
>
>     /** Flag indicating if this is a dynamic label */
>     private boolean isDynamic;
>
>     /** Underlying image used. Only set if this is a dynamic label */
>     private BufferedImage textImage;
>
>     /** The current image width */
>     private int imageWidth;
>
>     /** The current image height */
>     private int imageHeight;
>
>     /**
>      * Create a new blank label with no text. It is located at the origin. It
>      * is assumed to be dynamic and always on top.
>      */
>     public RasterTextLabel()
>     {
>         this(null, null, true, true, 0, 0, 0, null, null);
>     }
>
>     /**
>      * Create a new blank label with the given text located at the origin.
>      * If the text color is not specified, white is used and the code assumes
>      * static text, it will always be on top.
>      *
>      * @param label The string to use on the label
>      * @param col The text color to be drawn in
>      */
>     public RasterTextLabel(String label, Color col)
>     {
>         this(label, col, false, true, 0, 0, 0, null, null);
>     }
>
>     /**
>      * Create a new blank label with the given text located at the origin.
>      * If the text color is not specified, white is used and the code assumes
>      * static text, it will always be on top.
>      *
>      * @param label The string to use on the label
>      * @param col The text color to be drawn in
>      * @param alwaysOnTop true if this should never be obscured by content
>      */
>     public RasterTextLabel(String label, Color col, boolean alwaysOnTop)
>     {
>         this(label, col, alwaysOnTop, false, 0, 0, 0, null, null);
>     }
>
>     /**
>      * Create a new blank label with the given text located at the origin.
>      * If the text color is not specified, white is used.
>      *
>      * @param label The string to use on the label
>      * @param col The text color to be drawn in
>      * @param dynamic True if this will change text over time
>      * @param alwaysOnTop true if this should never be obscured by content
>      */
>     public RasterTextLabel(String label,
>                            Color col,
>                            boolean alwaysOnTop,
>                            boolean dynamic)
>     {
>         this(label, col, alwaysOnTop, dynamic, 0, 0, 0, null, null);
>     }
>
>     /**
>      * Create a new blank label with the given text located at a specific
>      * point in 3D world coordinates. The code assumes a static label.
>      *
>      * @param label The string to use on the label
>      * @param col The text color to be drawn in
>      * @param alwaysOnTop true if this should never be obscured by content
>      * @param x The x world coordinate to place the label
>      * @param y The y world coordinate to place the label
>      * @param z The z world coordinate to place the label
>      */
>     public RasterTextLabel(String label,
>                            Color col,
>                            boolean alwaysOnTop,
>                            float x,
>                            float y,
>                            float z)
>     {
>         this(label, col, alwaysOnTop, false, x, y, z, null, null);
>     }
>
>     /**
>      * Create a new blank label with the given text located at a specific
>      * point in 3D world coordinates.
>      *
>      * @param label The string to use on the label
>      * @param col The text color to be drawn in
>      * @param x The x world coordinate to place the label
>      * @param y The y world coordinate to place the label
>      * @param z The z world coordinate to place the label
>      * @param alwaysOnTop true if this should never be obscured by content
>      * @param dynamic True if this will change text over time
>      */
>     public RasterTextLabel(String label,
>                            Color col,
>                            boolean alwaysOnTop,
>                            boolean dynamic,
>                            float x,
>                            float y,
>                            float z)
>     {
>         this(label, col, alwaysOnTop, dynamic, x, y, z, null, null);
>     }
>
>     /**
>      * Create a new blank label with the given text located at a specific
>      * point in 3D world coordinates and an option to show a border and
>      * selected font. If the border color is specified, it will show a 1
>      * pixel wide border in that color. If no font is defined, the system
>      * default font will be used.
>      *
>      * @param label The string to use on the label
>      * @param col The text color to be drawn in
>      * @param x The x world coordinate to place the label
>      * @param y The y world coordinate to place the label
>      * @param z The z world coordinate to place the label
>      * @param border The color to use for the border or null for none
>      * @param font The font to draw the string in or null for default
>      * @param dynamic True if this will change text over time
>      */
>     public RasterTextLabel(String label,
>                            Color col,
>                            boolean alwaysOnTop,
>                            boolean dynamic,
>                            float x,
>                            float y,
>                            float z,
>                            Color border,
>                            Font font)
>     {
>         adjustImageSize = false;
>
>         textColor = (col != null) ? col : Color.white;
>         borderColor = border;
>         labelFont = font;
>         isDynamic = dynamic;
>
>         Appearance app = new Appearance();
>         RenderingAttributes ra = new RenderingAttributes();
>         ra.setAlphaTestFunction(RenderingAttributes.GREATER);
>
>         if(alwaysOnTop)
>         {
>             ra.setDepthBufferEnable(false);
>             ra.setDepthBufferWriteEnable(false);
>         }
>
>         app.setRenderingAttributes(ra);
>         setAppearance(app);
>
>         // create a disposable 1x1 image so that we can fetch the font
>         // metrics associated with the font and text label. This will allow
>         // us to determine the real image size. This is kludgy, but I can't
>         // think of a better way of doing it!
>         BufferedImage tmp_img =
>             new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
>
>         Graphics graphics = tmp_img.getGraphics();
>         FontMetrics fm;
>
>         if(labelFont == null)
>             fm = graphics.getFontMetrics();
>         else
>             fm = graphics.getFontMetrics(labelFont);
>
>         int width = 0;
>         int height = 0;
>
>         if(label == null)
>         {
>             // No label? Create an empty (default) raster object then. This
>             // should result in nothing being rendered on screen, but leaves
>             // us a placeholder for later.
>             raster = new Raster();
>             raster.setPosition(new Point3f(x, y, z));
>         }
>         else
>         {
>             // now we have the metrics, let's work out how big the label is!
>             Rectangle2D dimensions = fm.getStringBounds(label, graphics);
>
>             graphics.dispose();
>             tmp_img.flush();
>             tmp_img = null;
>
>             width = (int)dimensions.getWidth();
>             height = (int)dimensions.getHeight();
>             int ascent = fm.getMaxAscent();
>
>             if(border != null)
>             {
>                 width += BORDER_INSETS * 2 + 2; // one pixel border * 2
>                 height += BORDER_INSETS * 2 + 2;
>             }
>
>             textImage = new BufferedImage(width,
>                                           height,
>                                           BufferedImage.TYPE_INT_ARGB);
>
>             graphics = textImage.getGraphics();
>
>             renderImage(graphics, label, width, height, ascent);
>
>             graphics.dispose();
>
>             component = new ImageComponent2D(ImageComponent2D.FORMAT_RGBA,
>                                              textImage);
>
>             raster = new Raster(new Point3f(x, y, z),
>                                 Raster.RASTER_COLOR,
>                                 0,
>                                 0,
>                                 width,
>                                 height,
>                                 component,
>                                 null);
>
>             // clear the reference if not dynamic
>             if(!dynamic)
>             {
>                 component = null;
>                 textImage = null;
>             }
>         }
>
>         if(dynamic)
>         {
>             component.setCapability(ImageComponent2D.ALLOW_IMAGE_WRITE);
>             raster.setCapability(Raster.ALLOW_SIZE_WRITE);
>             raster.setCapability(Raster.ALLOW_IMAGE_WRITE);
>             raster.clearCapabilityIsFrequent(Raster.ALLOW_IMAGE_WRITE);
>         }
>
>         setGeometry(raster);
>     }
>
>     /**
>      * Set the label string that is to be rendered. This maintains the
>      * current text color. If this was not set up to be a dynamic image, an
>      * exception is thrown.
>      *
>      * @param text The string to be rendered
>      * @throws IllegalStateException The label was not set up to be dynamic
>      *    in the constructor
>      */
>     public void setText(String text) throws IllegalStateException
>     {
>         if(!isDynamic)
>             throw new IllegalStateException(CANT_CHANGE_MSG);
>
>         updateText(text);
>     }
>
>     /**
>      * Set the label string that is to be rendered with the option of croping
>      * it to the length of the string. This maintains the current text color.
>      * If this was not set up to be a dynamic image, an exception is thrown.
>      *
>      * @param text The string to be rendered
>      * @param crop true to crop the underlying raster
>      * @throws IllegalStateException The label was not set up to be dynamic
>      *    in the constructor
>      */
>     public void setText(String text, boolean crop) throws IllegalStateException
>     {
>         if(!isDynamic)
>             throw new IllegalStateException(CANT_CHANGE_MSG);
>
>         if(crop)
>             textImage = null;
>
>         updateText(text);
>     }
>
>     /**
>      * Set the label string that is to be rendered and changes the color
>      * to the new value. If this was not set up to be a dynamic image, an
>      * exception is thrown.
>      *
>      * @param text The string to be rendered
>      * @param col The new color to be used or null for the default (white)
>      * @throws IllegalStateException The label was not set up to be dynamic
>      *    in the constructor
>      */
>     public void setText(String text, Color col) throws IllegalStateException
>     {
>         if(!isDynamic)
>             throw new IllegalStateException(CANT_CHANGE_MSG);
>
>         textColor = (col != null) ? col : Color.white;
>
>         updateText(text);
>     }
>
>     /**
>      * Set the label string that is to be rendered and changes the color
>      * to the new value. If this was not set up to be a dynamic image, an
>      * exception is thrown.
>      *
>      * @param text The string to be rendered
>      * @param col The new color to be used or null for the default (white)
>      * @param crop true to crop the underlying raster
>      * @throws IllegalStateException The label was not set up to be dynamic
>      *    in the constructor
>      */
>     public void setText(String text, Color col, boolean crop)
>         throws IllegalStateException
>     {
>         if(!isDynamic)
>             throw new IllegalStateException(CANT_CHANGE_MSG);
>
>         if(crop)
>             textImage = null;
>
>         textColor = (col != null) ? col : Color.white;
>
>         updateText(text);
>     }
>
>
>     /**
>      * Set the condition of whether the implementation should resize the
>      * canvas after each new label is set or just stick to a fixed size
>      * canvas. A fixed size label is useful when you are making fast updates
>      * such as a counter. When this is called, the label will not be resized
>      * from it's current dimensions. This may be changed dynamically and will
>      * only take effect next time a text string is set and the size is based
>      * on the biggest image used to date, not on the next string that is
>      * set.
>      *
>      * @param fixed true if the label size should remain fixed
>      * @throws IllegalStateException The label was not set up to be dynamic
>      *    in the constructor
>      */
>     public void fixSize(boolean fixed)
>         throws IllegalStateException
>     {
>         if(!isDynamic)
>             throw new IllegalStateException(CANT_CHANGE_MSG);
>
>         adjustImageSize = fixed;
>     }
>
>     /**
>      * Crop the image used for the raster to the length of the string the next
>      * time a string is set. This will not crop the current string, only the
>      * next one.
>      *
>      * @throws IllegalStateException The label was not set up to be dynamic
>      *    in the constructor
>      */
>     public void crop()
>         throws IllegalStateException
>     {
>         if(!isDynamic)
>             throw new IllegalStateException(CANT_CHANGE_MSG);
>
>         // easiest way to force a rebuild is to remove the textImage reference
>         // completely and treat it like a new image with no text set.
>         textImage = null;
>     }
>
>     /**
>      * Update the raster to display the new text.
>      *
>      * @param label The new text string to draw
>      * @param fontChanged true if the font changed
>      */
>     private void updateText(String label)
>     {
>         // If we have no text to display, just set the size to display
>         // nothing and leave immediately.
>         if(label == null)
>         {
>             raster.setSize(0, 0);
>             return;
>         }
>
>         int width = 0;
>         int height = 0;
>         FontMetrics metrics = null;
>         Graphics graphics = null;
>
>         // Work on the null image first because adjustSize may also be set
>         // but would crash with a null source image.
>         if(textImage == null)
>         {
>             BufferedImage tmp_img =
>                 new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
>
>             graphics = tmp_img.getGraphics();
>
>             if(labelFont == null)
>                 metrics = graphics.getFontMetrics();
>             else
>                 metrics = graphics.getFontMetrics(labelFont);
>
>             Rectangle2D dimensions = metrics.getStringBounds(label, graphics);
>
>             graphics.dispose();
>             tmp_img.flush();
>
>             width = (int)dimensions.getWidth();
>             height = (int)dimensions.getHeight();
>
>             if(borderColor != null)
>             {
>                 width += BORDER_INSETS * 2 + 2; // one pixel border * 2
>                 height += BORDER_INSETS * 2 + 2;
>             }
>
>             textImage = new BufferedImage(width,
>                                           height,
>                                           BufferedImage.TYPE_INT_ARGB);
>
>             graphics = textImage.createGraphics();
>             renderImage(graphics, label, width, height, metrics.getAscent());
>
>             component = new ImageComponent2D(ImageComponent2D.FORMAT_RGBA,
>                                              textImage);
>             component.setCapability(ImageComponent2D.ALLOW_IMAGE_WRITE);
>
>             raster.setSize(width, height);
>             raster.setImage(component);
>         }
>         else if(adjustImageSize)
>         {
>             // recalc size and compare against current.
>             graphics = textImage.getGraphics();
>
>             if(labelFont == null)
>                 metrics = graphics.getFontMetrics();
>             else
>                 metrics = graphics.getFontMetrics(labelFont);
>
>             Rectangle2D dimensions = metrics.getStringBounds(label, graphics);
>
>             width = (int)dimensions.getWidth();
>             height = (int)dimensions.getHeight();
>
>             if(borderColor != null)
>             {
>                 width += BORDER_INSETS * 2 + 2; // one pixel border * 2
>                 height += BORDER_INSETS * 2 + 2;
>             }
>
>             // So now we know the required size. Is it bigger than the current
>             // image size? Resize if new size if bigger than the old.
>             if((width > textImage.getWidth(null)) ||
>                (height > textImage.getHeight(null)))
>             {
>                 textImage.flush();
>                 textImage = new BufferedImage(width,
>                                               height,
>                                               BufferedImage.TYPE_INT_ARGB);
>
>                 graphics = textImage.createGraphics();
>
>                 // Probably superfluous, but in for correctness.
>                 if(labelFont == null)
>                     metrics = graphics.getFontMetrics();
>                 else
>                     metrics = graphics.getFontMetrics(labelFont);
>
>                 renderImage(graphics, label, width, height, metrics.getAscent());
>
>                 component = new ImageComponent2D(ImageComponent2D.FORMAT_RGBA,
>                                                  textImage);
>                 component.setCapability(ImageComponent2D.ALLOW_IMAGE_WRITE);
>
>                 raster.setSize(width, height);
>                 raster.setImage(component);
>             }
>             else
>             {
>                 renderImage(graphics, label, width, height, metrics.getAscent());
>
>                 component.set(textImage);
>                 raster.setSize(width, height);
>             }
>         }
>         else
>         {
>             // fixed size
>             graphics = textImage.createGraphics();
>
>             if(labelFont == null)
>                 metrics = graphics.getFontMetrics();
>             else
>                 metrics = graphics.getFontMetrics(labelFont);
>
>             Rectangle2D dimensions = metrics.getStringBounds(label, graphics);
>
>             width = (int)dimensions.getWidth();
>             height = (int)dimensions.getHeight();
>
>             if(borderColor != null)
>             {
>                 width += BORDER_INSETS * 2 + 2; // one pixel border * 2
>                 height += BORDER_INSETS * 2 + 2;
>             }
>
>             renderImage(graphics, label, width, height, metrics.getAscent());
>
>             component.set(textImage);
>             raster.setSize(width, height);
>         }
>
>         graphics.dispose();
>     }
>
>     /**
>      * Convenience method to render the image given the font information. When
>      * this method exits, it will have changed the global imageWidth and
>      * imageHeight variables to the given width and height values.
>      *
>      * @param graphics The graphics context for textImage
>      * @param label The string to render
>      * @param width The width of the image drawn to
>      * @param height The height of the image drawn to
>      * @param ascent The ascent of the font in use
>      */
>     private void renderImage(Graphics graphics,
>                              String label,
>                              int width,
>                              int height,
>                              int ascent)
>     {
>         Graphics2D g = (Graphics2D)graphics;
>         g.setComposite(AlphaComposite.Src);
>
>         g.setColor(CLEAR_COLOR);
>         g.fillRect(0, 0, imageWidth, imageHeight);
>
>         if(borderColor != null)
>         {
>             g.setColor(borderColor);
>             g.drawRect(0, 0, width - 1, height - 1);
>
>             g.setColor(textColor);
>             g.setFont(labelFont);
>             g.drawString(label,
>                          BORDER_INSETS + 1,
>                          ascent + BORDER_INSETS + 1);
>         }
>         else
>         {
>             g.setColor(textColor);
>             g.setFont(labelFont);
>             g.drawString(label, 0, ascent);
>         }
>
>         imageWidth = width;
>         imageHeight = height;
>     }
> }
>
>
> ------------------------------------------------------------------------
>
> import java.awt.*;
> import java.awt.event.*;
> import java.awt.Rectangle;
> import java.util.AbstractList;
> import java.util.ArrayList;
> import java.util.Enumeration;
> import java.util.Iterator;
>
> import javax.media.j3d.*;
> import javax.vecmath.*;
> import javax.swing.*;
>
> import com.sun.j3d.utils.geometry.Sphere;
> import com.sun.j3d.utils.universe.PlatformGeometry;
> import com.sun.j3d.utils.universe.SimpleUniverse;
> import com.sun.j3d.utils.universe.ViewingPlatform;
> import com.sun.j3d.utils.image.TextureLoader;
> import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
> import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
> import com.sun.j3d.utils.applet.JMainFrame;
> import org.j3d.geom.RasterTextLabel;
>
>
> import org.j3d.geom.*;
>
> public final class RasterBugs extends JApplet {
>
>   private static final Geometry sphereGeometry;
>
>   private KeyNavigatorBehavior keyBehavior;
>
>   private TransformGroup vptg;
>
>   private static final float MOVE_BACK = 2.0f;
>
>   private BranchGroup objRoot = null;
>
>   private static final Color3f BLACK = new Color3f(0f, 0f, 0f);
>   private static final Color3f WHITE = new Color3f(1f, 1f, 1f);
>   private static final Color3f GREEN = new Color3f(0.5f, 1f, 0.5f);
>
>   private SimpleUniverse u;
>
>   private PlatformGeometry pg;
>
>   private BoundingSphere bounds;
>
>   private static final Point3d D_ORIGIN = new Point3d(0, 0, 0);
>
>   private Canvas3D c3d;
>
>   private boolean alwaysOnTop = true;
>
>   private RenderingAttributes ra;
>
>   static {
>       final int SPHERE_TESSELATION = 20;
>
>       Sphere s =
>       new Sphere(1.0f, Sphere.GENERATE_NORMALS, SPHERE_TESSELATION, null);
>       sphereGeometry = s.getShape().getGeometry();
>   } // End of static initializer
>
>
>
>   /**
>    * Set up keyboard navigation.
>    */
>   private void addKeyBehavior(BranchGroup b) {
>     // Set up keyboard navigation
>     keyBehavior = new KeyNavigatorBehavior(
>       u.getViewingPlatform().getViewPlatformTransform());
>     keyBehavior.setSchedulingBounds(bounds);
>     // Add behavior to scenegraph
>     b.addChild(keyBehavior);
>   } // End of addKeyBehavior
>
>
>   /**
>    * Initialize and return the Canvas3D we'll be using for rendering.
>    */
>   public void init() {
>
>     bounds = new BoundingSphere(D_ORIGIN, Double.POSITIVE_INFINITY);
>
>     // Use utility to get the right graphics destination
>     GraphicsConfiguration config =
>       SimpleUniverse.getPreferredConfiguration();
>
>     // Create a canvas on the device
>     c3d = new Canvas3D(config);
>
>     Container contentPane = getContentPane();
>     contentPane.setLayout(new BorderLayout());
>     contentPane.add(c3d, "Center");
>     JPopupMenu.setDefaultLightWeightPopupEnabled(false);
>     JMenuBar menuBar = new JMenuBar();
>     setJMenuBar(menuBar);
>     JMenu viewMenu = new JMenu("View");
>     menuBar.add(viewMenu);
>     JMenuItem inFrontItem = new JMenuItem("not alwaysOnTop");
>     viewMenu.add(inFrontItem);
>     inFrontItem.addActionListener(
>       new ActionListener() {
>       public void actionPerformed(ActionEvent e) {
>         JMenuItem inFrontItem = (JMenuItem)e.getSource();
>         alwaysOnTop = !alwaysOnTop;
>         if (alwaysOnTop) {
>           inFrontItem.setText("not alwaysOnTop");
>           ra.setDepthBufferEnable(false);
>           ra.setDepthBufferWriteEnable(false);
>         } else {
>           inFrontItem.setText("alwaysOnTop");
>           ra.setDepthBufferEnable(true);
>           ra.setDepthBufferWriteEnable(true);
>         }
>       }
>       }
>     );
>
>
>     // Use utility to create default universe
>     u = new SimpleUniverse(c3d);
>
>     // Set the viewpoint back from the origin and point toward the origin
>     ViewingPlatform vp = u.getViewingPlatform();
>
>
>     vp.setNominalViewingTransform();
>     vptg = vp.getViewPlatformTransform();
>     Transform3D vpt = new Transform3D();
>     vptg.getTransform(vpt);
>     Transform3D translate = new Transform3D();
>     translate.setTranslation(new Vector3f(0f,0f,MOVE_BACK));
>     vpt.mul(translate);
>     vptg.setTransform(vpt);
>
>     // Allow mouse manipulation
>     OrbitBehavior orbit = new OrbitBehavior(c3d, OrbitBehavior.REVERSE_ALL);
>
>     // Behavior is only enabled within its bounds
>     bounds = new BoundingSphere(D_ORIGIN, 100.0);
>     orbit.setSchedulingBounds(bounds);
>
>     // Attach behavior to ViewingPlatform
>     vp.setViewPlatformBehavior(orbit);
>
>     // Will add lights here so they are "headlights"
>     // that move with the viewer
>     pg = new PlatformGeometry();
>
>     // Set up the ambient light
>     Color3f ambientColor = new Color3f(0.1f, 0.1f, 0.1f);
>     AmbientLight ambientLightNode = new AmbientLight(ambientColor);
>     ambientLightNode.setInfluencingBounds(bounds);
>     pg.addChild(ambientLightNode);
>
>     // Set up the directional lights
>     Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
>     Vector3f light1Direction  = new Vector3f(1.0f, 1.0f, 1.0f);
>     Color3f light2Color = new Color3f(1.0f, 1.0f, 1.0f);
>     Vector3f light2Direction  = new Vector3f(-1.0f, -1.0f, -1.0f);
>
>     DirectionalLight light1
>       = new DirectionalLight(light1Color, light1Direction);
>     light1.setInfluencingBounds(bounds);
>     pg.addChild(light1);
>
>     DirectionalLight light2
>       = new DirectionalLight(light2Color, light2Direction);
>     light2.setInfluencingBounds(bounds);
>     pg.addChild(light2);
>
>     vp.setPlatformGeometry(pg);
>
>     objRoot = new BranchGroup();
>     objRoot.setCapability(objRoot.ALLOW_DETACH);
>     objRoot.setCapability(objRoot.ALLOW_CHILDREN_EXTEND);
>     objRoot.setCapability(objRoot.ALLOW_CHILDREN_WRITE);
>
>     addKeyBehavior(objRoot);
>
>     objRoot.compile();
>
>     u.addBranchGraph(objRoot);
>
>     addNode();
>
>   } // End of init
>
>
>   /**
>    * Add a node to the graph.
>    */
>   public void addNode()
>   {
>     // Each node is connected by a BranchGroup (to allow it to
>     // be removed)
>     BranchGroup root = new BranchGroup();
>
>     // Transform Group to hold position transform
>     TransformGroup posTg = new TransformGroup();
>     Transform3D pos = new Transform3D();
>     Vector3f translate = new Vector3f(0.2f,0f,0f);
>     pos.setTranslation(translate);
>     posTg.setTransform(pos);
>     root.addChild(posTg);
>
>     // TransformGroup to hold scale transform
>     TransformGroup scaleTg = new TransformGroup();
>     Transform3D scale = new Transform3D();
>     scale.setScale(0.2);
>     scaleTg.setTransform(scale);
>     posTg.addChild(scaleTg);
>
>     // Set appearance of node
>     ra = new RenderingAttributes();
>     Material mat = new Material(BLACK, BLACK, GREEN, WHITE, 128.0f);
>     Appearance a = new Appearance();
>     a.setMaterial(mat);
>     a.setRenderingAttributes(ra);
>
>     Shape3D shape = new Shape3D(sphereGeometry, a);
>
>     scaleTg.addChild(shape);
>
>     BranchGroup bg = new BranchGroup();
>
>     RasterTextLabel rtl = new RasterTextLabel(
>       "RasterTextLabel", Color.WHITE, alwaysOnTop, false, 0f, 0f, 0f);
>
>     Raster labelText = (Raster)rtl.getGeometry();
>     labelText.setClipMode(Raster.CLIP_IMAGE);
>
>     Appearance ap = rtl.getAppearance();
>     ra = ap.getRenderingAttributes();
>     ra.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE);
>
>     Dimension dim = new Dimension();
>     labelText.getSize(dim);
>     labelText.setDstOffset(dim.width / 2, dim.height / 2);
>     posTg.addChild(rtl);
>
>     root.compile();
>
>     objRoot.addChild(root);
>   } // End of addNode
>
>
>   public static void main(String[] args) {
>     new JMainFrame(new RasterBugs(args), 500, 500);
>   }
>
>   public RasterBugs(String[] args)
>   {
>   }
>
>   public RasterBugs()
>   {
>   }
> } // End of file RenderEngine.java
>

===========================================================================
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".

Reply via email to