Hi Paul,

    Bug 4733554 -
    OrientedShape3D scale not work when set before live

is filed for this. To workaround ,please set the scale
after shape live.

Thanks for your bug report.

- Kelvin
--------------
Java 3D Team
Sun Microsystems Inc.


Paul Pantera wrote:

>
> OK, I've found a bug and an RFE in OrientedShape 3D with
> constantScaleEnable:
>
> 1)  The contructor for OrientedShape3D that takes a "scale" doesn't work
>     correctly - it always sets the scale to 1.0.  In the example program
>     I'm setting the scale to 10, but it's getting 1 (zoom into the sphere
>     and you can see the label very small).  You have to use the view menu
>     to set it to 1 and then back to 10 to get it to work right.
>
>     Also, it's not clear to me why I need to set the scale to 10 in order
>     to see the label.  The documentation says that the default scale is
>     1.0 meters.  It's coming out of Text2D with a size of 20/256 =
>     0.078 meters, but I have to set the scale to about 5 to make it
>     seem that big.
>
> 2)  Setting constantScale makes OrientedShape3D useless for labels (which
>     is one of its major purposes).  When you move in and out the label
>     appears to move in and out with respect to the sphere it's labelling.
>     This is because the label is remaining at a constant position in Z.
>     So when the user moves in, the sphere appears to move closer, but
>     the label remains at the same distance.  This is not the desired
> effect.
>     Believe it or not, what we need is constant scale in X and Y and *not*
>     constant scale in Z.
>
> -Paul
>
>
> ------------------------------------------------------------------------
>
> 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 OS3DBugs 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 static final Point3f F_ORIGIN = new Point3f(0, 0, 0);
>
>   private Canvas3D c3d;
>
>   private boolean constantScale = true;
>   private boolean scaleOne = false;
>
>   private OrientedShape3D os3d;
>
>   private boolean parallel = false;
>
>   private static final float SPHERE_RADIUS = 0.2f;
>
>   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 constantScaleItem = new JMenuItem("not constantScale");
>     viewMenu.add(constantScaleItem);
>     constantScaleItem.addActionListener(
>       new ActionListener() {
>       public void actionPerformed(ActionEvent e) {
>         JMenuItem constantScaleItem = (JMenuItem)e.getSource();
>         constantScale = !constantScale;
>         os3d.setConstantScaleEnable(constantScale);
>         if (constantScale) {
>           constantScaleItem.setText("not constantScale");
>         } else {
>           constantScaleItem.setText("constantScale");
>         }
>       }
>       }
>     );
>     JMenuItem scaleOneItem = new JMenuItem("scale = 1");
>     viewMenu.add(scaleOneItem);
>     scaleOneItem.addActionListener(
>       new ActionListener() {
>       public void actionPerformed(ActionEvent e) {
>         JMenuItem scaleOneItem = (JMenuItem)e.getSource();
>         scaleOne = !scaleOne;
>         if (scaleOne) {
>           scaleOneItem.setText("scale = 10");
>           os3d.setScale(1.0);
>         } else {
>           scaleOneItem.setText("scale = 1");
>           os3d.setScale(10.0);
>         }
>       }
>       }
>     );
>     JMenuItem projectionItem = new JMenuItem("Parallel Projection");
>     viewMenu.add(projectionItem);
>     projectionItem.addActionListener(
>       new ActionListener() {
>       public void actionPerformed(ActionEvent e) {
>         JMenuItem projectionItem = (JMenuItem)e.getSource();
>         parallel = !parallel;
>         if (parallel) {
>           c3d.getView().setProjectionPolicy(View.PARALLEL_PROJECTION);
>         } else {
>           c3d.getView().setProjectionPolicy(View.PERSPECTIVE_PROJECTION);
>         }
>       }
>       }
>     );
>
>
>     // 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(SPHERE_RADIUS);
>     scaleTg.setTransform(scale);
>     posTg.addChild(scaleTg);
>
>     // Set appearance of node
>     RenderingAttributes 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();
>
>     MyText2D t2d = new MyText2D("OrientedShape3D constantScaleEnable",
>       WHITE, null, 20, 0);
>     QuadArray qa = (QuadArray)t2d.getGeometry();
>     float[] ar = new float[12];
>     qa.getCoordinates(0, ar);
>     float width = t2d.getImageWidth();
>     float height = t2d.getImageHeight();
>     for (int i = 0 ; i < 4 ; i++) {
>       // Center
>       ar[0 + i * 3] -= width / 2;
>       ar[1 + i * 3] -= height / 2;
>       // Move forward in front of sphere
>       ar[2 + i * 3] = SPHERE_RADIUS;
>     }
>     qa.setCoordinates(0, ar);
>     Appearance labelApp = t2d.getAppearance();
>     os3d = new OrientedShape3D(qa, labelApp,
>       OrientedShape3D.ROTATE_ABOUT_POINT, F_ORIGIN, true, 10.0);
>     os3d.setCapability(OrientedShape3D.ALLOW_SCALE_WRITE);
>     posTg.addChild(os3d);
>
>     root.compile();
>
>     objRoot.addChild(root);
>   } // End of addNode
>
>
>   public static void main(String[] args) {
>     new JMainFrame(new OS3DBugs(args), 500, 500);
>   }
>
>   public OS3DBugs(String[] args)
>   {
>   }
>
>   public OS3DBugs()
>   {
>   }
> } // End of file RenderEngine.java
>
>
> ------------------------------------------------------------------------
>
> import java.awt.image.BufferedImage;
> import java.awt.image.WritableRaster;
> import java.awt.image.DataBufferInt;
> import java.awt.Color;
> import java.awt.Font;
> import java.awt.FontMetrics;
> import java.awt.Graphics;
> import java.awt.Toolkit;
> import java.util.Hashtable;
>
> import javax.media.j3d.*;
> import javax.vecmath.Color3f;
>
>
> /**
>  * A Text2D object is a representation of a string as a texture mapped
>  * rectangle.  The texture for the rectangle shows the string as rendered in
>  * the specified color with a transparent background.  The appearance of the
>  * characters is specified using the font indicated by the font name, size
>  * and style (see java.awt.Font).  The approximate height of the rendered
>  * string will be the font size times the rectangle scale factor, which has a
>  * default value of 1/256.  For example, a 12 point font will produce
>  * characters that are about 12/256 = 0.047 meters tall. The lower left
>  * corner of the rectangle is located at (0,0,0) with the height
>  * extending along the positive y-axis and the width extending along the
>  * positive x-axis.<p>
>  * Java 3D texture maps must be a power of two.  Therefore,
>  * the texture mapped onto the quad by Text2D (and the quad)
>  * may be much bigger than they need to be.  The only way to
>  * get the actual size of the text is withing Text2D, so we'd
>  * have to import the utility into our code.
>  */
> public class MyText2D extends Shape3D {
>
>     // This table caches FontMetrics objects to avoid the huge cost
>     // of re-retrieving metrics for a font we've already seen.
>     private static Hashtable metricsTable = new Hashtable();
>     float rectangleScaleFactor = 1f/256;
>
>     Color3f   color = new Color3f();
>     String    fontName;
>     int       fontSize, fontStyle;
>
>     String text;
>
>     float imageWidth, imageHeight;
>
>
>     /**
>      * Creates a Shape3D object which holds a
>      * rectangle that is texture-mapped with an image that has
>      * the specified text written with the specified font
>      * parameters.
>      *
>      * @param text The string to be written into the texture map.
>      * @param color The color of the text string.
>      * @param fontName The name of the Java font to be used for
>      *  the text string.
>      * @param fontSize The size of the Java font to be used.
>      * @param fontStyle The style of the Java font to be used.
>      */
>     public MyText2D(String text, Color3f color, String fontName,
>                 int fontSize, int fontStyle) {
>
>         this.color.set(color);
>         this.fontName = fontName;
>         this.fontSize = fontSize;
>         this.fontStyle = fontStyle;
>       this.text = text;
>
>         updateText2D(text, color, fontName, fontSize, fontStyle);
>     }
>
>     /*
>      * Changes text of this Text2D to 'text'. All other
>      * parameters (color, fontName, fontSize, fontStyle
>      * remain the same.
>      * @param text The string to be set.
>      */
>     public void setString(String text){
>       this.text = text;
>         ImageComponent imageComponent = setupImage(text, color, fontName,
>                                           fontSize, fontStyle);
>       getAppearance().getTexture().setImage(0, imageComponent);
>     }
>
>     private void updateText2D(String text, Color3f color, String fontName,
>                   int fontSize, int fontStyle) {
>         ImageComponent imageComponent = setupImage(text, color, fontName,
>                                           fontSize, fontStyle);
>
>         Texture2D t2d = setupTexture(imageComponent);
>
>       QuadArray rect = setupGeometry(imageComponent.getWidth(),
>               imageComponent.getHeight());
>       setGeometry(rect);
>
>       Appearance appearance = setupAppearance(t2d);
>       setAppearance(appearance);
>     }
>
>
>     /**
>      * Sets the scale factor used in converting the image width/height
>      * to width/height values in 3D.
>      *
>      * @param newScaleFactor The new scale factor.
>      */
>     public void setRectangleScaleFactor(float newScaleFactor) {
>       rectangleScaleFactor = newScaleFactor;
>     }
>
>     /**
>      * Gets the current scale factor being used in converting the image
>      * width/height to width/height values in 3D.
>      *
>      * @return The current scale factor.
>      */
>     public float getRectangleScaleFactor() {
>       return rectangleScaleFactor;
>     }
>
>     /**
>      * Create the ImageComponent and Texture object.
>      */
>     private Texture2D setupTexture(ImageComponent imageComponent) {
>       Texture2D t2d = new Texture2D(Texture2D.BASE_LEVEL,
>                                     Texture.RGBA,
>                                     imageComponent.getWidth(),
>                                     imageComponent.getHeight());
>       t2d.setMinFilter(t2d.BASE_LEVEL_LINEAR);
>       t2d.setMagFilter(t2d.BASE_LEVEL_LINEAR);
>       t2d.setImage(0, imageComponent);
>       t2d.setEnable(true);
>
>       return t2d;
>     }
>
>     /**
>      * Creates a ImageComponent2D of the correct dimensions for the
>      * given font attributes.  Draw the given text into the image in
>      * the given color.  The background of the image is transparent
>      * (alpha = 0).
>      */
>     private ImageComponent setupImage(String text, Color3f color,
>                                    String fontName,
>                                    int fontSize, int fontStyle) {
>       Toolkit toolkit = Toolkit.getDefaultToolkit();
>       Font font = new java.awt.Font(fontName, fontStyle, fontSize);
>
>       FontMetrics metrics;
>       if ((metrics = (FontMetrics)metricsTable.get(font)) == null) {
>           metrics = toolkit.getFontMetrics(font); // deprecated
>           metricsTable.put(font, metrics);
>       }
>       int width = metrics.stringWidth(text);
>       int descent = metrics.getMaxDescent();
>       int ascent = metrics.getMaxAscent();
>       int leading = metrics.getLeading();
>       int height = descent + ascent;
>
>       imageWidth = (float)width * rectangleScaleFactor;
>       imageHeight = (float)height * rectangleScaleFactor;
>
>       // Need to make width/height powers of 2 because of Java3d texture
>       // size restrictions
>       int pow = 1;
>       for (int i = 1; i < 32; ++i) {
>           pow *= 2;
>           if (width <= pow)
>               break;
>       }
>       width = Math.max (width, pow);
>       pow = 1;
>       for (int i = 1; i < 32; ++i) {
>           pow *= 2;
>           if (height <= pow)
>               break;
>       }
>       height = Math.max (height, pow);
>
>       // For now, jdk 1.2 only handles ARGB format, not the RGBA we want
>       BufferedImage bImage = new BufferedImage(width, height,
>                                                BufferedImage.TYPE_INT_ARGB);
>       Graphics offscreenGraphics = bImage.createGraphics();
>
>       // First, erase the background to the text panel - set alpha to 0
>       Color myFill = new Color(0f, 0f, 0f, 0f);
>       offscreenGraphics.setColor(myFill);
>       offscreenGraphics.fillRect(0, 0, width, height);
>
>       // Next, set desired text properties (font, color) and draw String
>       offscreenGraphics.setFont(font);
>       Color myTextColor = new Color(color.x, color.y, color.z, 1f);
>       offscreenGraphics.setColor(myTextColor);
>       offscreenGraphics.drawString(text, 0, height - descent);
>
>       ImageComponent imageComponent =
>           new ImageComponent2D(ImageComponent.FORMAT_RGBA,
>                                bImage);
>       return imageComponent;
>     }
>
>     /**
>      * Creates a rectangle of the given width and height and sets up
>      * texture coordinates to map the text image onto the whole surface
>      * of the rectangle (the rectangle is the same size as the text image)
>      */
>     private QuadArray setupGeometry(int width, int height) {
>       float zPosition = 0f;
>       float rectWidth = (float)width * rectangleScaleFactor;
>       float rectHeight = (float)height * rectangleScaleFactor;
>       float[] verts1 = {
>           rectWidth, 0f, zPosition,
>           rectWidth, rectHeight, zPosition,
>           0f, rectHeight, zPosition,
>           0f, 0f, zPosition
>       };
>       float[] texCoords = {
>           0f, -1f,
>           0f, 0f,
>           (-1f), 0f,
>           (-1f), -1f
>       };
>
>       QuadArray rect = new QuadArray(4, QuadArray.COORDINATES |
>                                      QuadArray.TEXTURE_COORDINATE_2);
>       rect.setCoordinates(0, verts1);
>       rect.setTextureCoordinates(0, 0, texCoords);
>
>       return rect;
>     }
>
>     /**
>      * Creates Appearance for this Shape3D.  This sets transparency
>      * for the object (we want the text to be "floating" in space,
>      * so only the text itself should be non-transparent.  Also, the
>      * appearance disables lighting for the object; the text will
>      * simply be colored, not lit.
>      */
>     private Appearance setupAppearance(Texture2D t2d) {
>       TransparencyAttributes transp = new TransparencyAttributes();
>       transp.setTransparencyMode(TransparencyAttributes.BLENDED);
>       transp.setTransparency(0f);
>       Appearance appearance = new Appearance();
>       appearance.setTransparencyAttributes(transp);
>       appearance.setTexture(t2d);
>
>       Material m = new Material();
>       m.setLightingEnable(false);
>       appearance.setMaterial(m);
>
>       return appearance;
>     }
>
>     /**
>      * Returns the text string
>      *
>      */
>     public String getString() {
>       return text;
>     }
>
>     /**
>      * Returns the color of the text
>      *
>      */
>     public Color3f getColor() {
>       return color;
>     }
>
>     /**
>      * Returns the font
>      *
>      */
>     public String getFontName() {
>       return fontName;
>     }
>
>     /**
>      * Returns the font size
>      *
>      */
>     public int getFontSize() {
>       return fontSize;
>     }
>
>     /**
>      * Returns the font style
>      *
>      */
>     public int getFontStyle() {
>       return fontStyle;
>     }
>
>     public float getImageWidth() {
>       return imageWidth;
>     }
>
>     public float getImageHeight() {
>       return imageHeight;
>     }
>
> }
>
>
>
>
>
>

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