A while back there was some traffic concerning the Background
        node's image component---it doesn't rescale to fit a resized
        canvas.  Attached is some code that provides, as an example,
        a rescalable background image.

          GradientImage - creates a gradient BufferedImage using
                          Java 2D's gradient paint capabilities.

          RescalableCanvas - a subclass of Canvas3D that catches resize
                             events and rescales an attached Background's
                             image to match.

          HelloUniverse - a slightly hacked version of the standard
                          Java 3D demo that uses the above classes to
                          to provide a rescalable gradient background
                          image.

        javac HelloUniverse.java
        java HelloUniverse

        Critical feedback (or otherwise) welcome.

--
Allen McPherson
[EMAIL PROTECTED]
//  Copyright (c) 2000 by Allen Lynn McPherson.  All rights reserved.
//  This example is provided WITHOUT ANY WARRANTY either expressed or implied.

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;

//  Creates a gradient image using the Java 2D API.  Generally used
//  for view backgrounds.
public class  GradientImage  extends BufferedImage {
  public  GradientImage() {
    this(128, 128);
  }

  public  GradientImage(int width, int height) {
    super(width, height, BufferedImage.TYPE_INT_RGB);
    GradientPaint  grad =
      new GradientPaint(0, 0, new Color(0,0,128), 0, height, Color.white);
    Graphics2D  g2d = this.createGraphics();
    g2d.setPaint(grad);
    g2d.fillRect(0, 0, width, height);
  }
}


//  Copyright (c) 2000 by Allen Lynn McPherson.  All rights reserved.
//  This example is provided WITHOUT ANY WARRANTY either expressed or implied.

import java.awt.event.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.AffineTransform;
import javax.media.j3d.*;
import javax.vecmath.*;

//  Subclass of Canvas3D (and hence Canvas) that catches resize events and
//  rescales a Background's image.
//    Associated Background must:
//      - have been inserted into the scene graph
//      - have good application bounds set
//      - have its ALLOW_IMAGE_WRITE capability bit set
public class  RescalableCanvas  extends Canvas3D {
  GradientImage      gImage   = null;   //  Original gradient image to rescale
  Background         bg       = null;   //  Will have it's image set and reset
  Dimension          origDim  = null;   //  Original canvas dimensions
  boolean            beenHere = false;  //  Used to ensure single image create

  //  No Background yet--must be set with setBG()
  public  RescalableCanvas(java.awt.GraphicsConfiguration gc) {
    this(gc, null);
  }

  //  Sets member Background and event listener (component resize)
  public  RescalableCanvas(java.awt.GraphicsConfiguration gc, Background bg) {
    super(gc);
    this.bg = bg;
    addComponentListener(new ComponentAdapter() {
      public void  componentResized(ComponentEvent e) {
        //  First time through, create initial gradient image to match initial
        //  Canvas dimensions (if neither dimension is 0).
        if (!beenHere) {
          beenHere = createOriginalGradient();
          return;
        }
        //  Subsequent times through, just rescale the original image and
        //  reset the Background's image.
        rescaleAndSet((double)(getSize().width)  / (double)origDim.width,
                      (double)(getSize().height) / (double)origDim.height);
      }
    });
  }

  public void  setBG(Background bg) {
    this.bg = bg;
  }

  //  Called to greate initial gradient image.  Once this method returns true
  //  it will not be called again.
  protected boolean  createOriginalGradient() {
    if (bg == null) return true;
    origDim = getSize();
    if (origDim.width==0 || origDim.height==0)
      return false;
    gImage = new GradientImage(origDim.width, origDim.height);
    bg.setImage(new ImageComponent2D(ImageComponent.FORMAT_RGBA, gImage));
    return true;        //  Don't call this method again.
  }

  //  Rescales the initial gradient image to match the canvas' new size and
  //  applies it to Background node.
  protected void  rescaleAndSet(double xScale, double yScale) {
    if (xScale == 1.0 && yScale == 1.0)
      return;
    if (bg == null) return;
    AffineTransformOp  op =
      new AffineTransformOp(AffineTransform.getScaleInstance(xScale, yScale),
                            null);
    BufferedImage  bimg = op.filter(gImage, null);
    bg.setImage(new ImageComponent2D(ImageComponent.FORMAT_RGBA, bimg));
    return;
  }
}


/*
 *      @(#)HelloUniverse.java 1.47 99/09/15 13:36:59
 *
 * Copyright (c) 1996-1999 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 java.awt.GraphicsConfiguration;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class HelloUniverse extends Applet {
    // Changed to accept a RescalableCanvas
    public BranchGroup createSceneGraph(RescalableCanvas canvas) {
        // Create the root of the branch graph
        BranchGroup objRoot = new BranchGroup();

        // 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);
        objRoot.addChild(objTrans);

        // Create a simple shape leaf node, add it to the scene graph.
        objTrans.addChild(new ColorCube(0.4));

        // Create a new Behavior object that will perform the desired
        // operation on the specified transform object and add it into
        // the scene graph.
        Transform3D yAxis = new Transform3D();
        Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
                                        0, 0,
                                        4000, 0, 0,
                                        0, 0, 0);

        RotationInterpolator rotator =
            new RotationInterpolator(rotationAlpha, objTrans, yAxis,
                                     0.0f, (float) Math.PI*2.0f);
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        rotator.setSchedulingBounds(bounds);
        objTrans.addChild(rotator);

        // Changed to add Background node with image that will be
        // rescaled when the canvas is resized.
        Background  bg = new Background();
        bg.setCapability(Background.ALLOW_IMAGE_WRITE);
        bg.setApplicationBounds(new BoundingSphere(new Point3d(0,0,0), 100));
        canvas.setBG(bg);
        objRoot.addChild(bg);


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

        return objRoot;
    }

    public HelloUniverse() {
        setLayout(new BorderLayout());
        GraphicsConfiguration config =
           SimpleUniverse.getPreferredConfiguration();

        RescalableCanvas c = new RescalableCanvas(config);
        add("Center", c);

        // Create a simple scene and attach it to the virtual universe
        BranchGroup scene = createSceneGraph(c);
        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 HelloUniverse to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {
        new MainFrame(new HelloUniverse(), 256, 256);
    }
}


Reply via email to