Java/3D/Text 2D

Материал из Java эксперт
Версия от 06:13, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Render a single, Text2D object

/*
 * @(#)Text2DApp.java 1.1 00/09/22 14:03
 * 
 * Copyright (c) 1996-2000 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.Font;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Text2D;
import com.sun.j3d.utils.universe.SimpleUniverse;
/*
 * Text2DApp renders a single, Text2D object. The Text2D object spins revealing
 * that the backside does not render by default. The code to make the Text2D
 * object double-sided is commented out in this program.
 */
public class Text2DApp extends Applet {
  public BranchGroup createSceneGraph() {
    // Create the root of the branch graph
    BranchGroup objRoot = new BranchGroup();
    // Create the transform group node and initialize it to the
    // identity. Add it to the root of the subgraph.
    TransformGroup objSpin = new TransformGroup();
    objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objRoot.addChild(objSpin);
    // Create a simple Text2D leaf node, add it to the scene graph.
    Text2D text2d = new Text2D("2D text in Java 3D", new Color3f(0.9f,
        1.0f, 1.0f), "Helvetica", 24, Font.ITALIC);
    objSpin.addChild(text2d);
    Appearance textAppear = text2d.getAppearance();
    // The following 4 lines of code (commented out) make the Text2D object
    // 2-sided.
    // This code depends on the line of code above that sets TextAppear.
    //         PolygonAttributes polyAttrib = new PolygonAttributes();
    //         polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
    //         polyAttrib.setBackFaceNormalFlip(true);
    //         textAppear.setPolygonAttributes(polyAttrib);
    // The following 12 lines of code (commented out) use the texture from
    // the previous Text2D object on another object.
    // This code depends on the line of code above that sets TextAppear.
    //         QuadArray qa = new QuadArray(4, QuadArray.COORDINATES |
    //                                         QuadArray.TEXTURE_COORDINATE_2);
    //         qa.setCoordinate(0, new Point3f(-10.0f, 1.0f, -5.0f));
    //         qa.setCoordinate(1, new Point3f(-10.0f, -1.0f, -5.0f));
    //         qa.setCoordinate(2, new Point3f(10.0f, -1.0f, -5.0f));
    //         qa.setCoordinate(3, new Point3f(10.0f, 1.0f, -5.0f));
    //         qa.setTextureCoordinate(0, new Point2f(0.0f, 1.0f));
    //         qa.setTextureCoordinate(1, new Point2f(0.0f, 0.0f));
    //         qa.setTextureCoordinate(2, new Point2f(1.0f, 0.0f));
    //         qa.setTextureCoordinate(3, new Point2f(1.0f, 1.0f));
    //
    //         objRoot.addChild(new Shape3D(qa, textAppear));
    // Create a new Behavior object that will perform the desired
    // operation on the specified transform object and add it into
    // the scene graph.
    Alpha rotationAlpha = new Alpha(-1, 8000);
    RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
        objSpin);
    // a bounding sphere specifies a region a behavior is active
    // create a sphere centered at the origin with radius of 100
    BoundingSphere bounds = new BoundingSphere();
    rotator.setSchedulingBounds(bounds);
    objSpin.addChild(rotator);
    Background backg = new Background();
    backg.setColor(0.4f, 0.4f, 1.0f);
    backg.setApplicationBounds(new BoundingSphere());
    objRoot.addChild(backg);
    return objRoot;
  } // end of CreateSceneGraph method
  public Text2DApp() {
    setLayout(new BorderLayout());
    GraphicsConfiguration config = SimpleUniverse
        .getPreferredConfiguration();
    Canvas3D canvas3D = new Canvas3D(config);
    canvas3D.setStereoEnable(false);
    add("Center", canvas3D);
    BranchGroup scene = createSceneGraph();
    // SimpleUniverse is a Convenience Utility class
    SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
    // This will move the ViewPlatform back a bit so the
    // objects in the scene can be viewed.
    simpleU.getViewingPlatform().setNominalViewingTransform();
    simpleU.addBranchGraph(scene);
  } // end of Text2DApp (constructor)
  //  The following allows this to be run as an application
  //  as well as an applet
  public static void main(String[] args) {
    System.out
        .println("Text2DApp.java - a demonstration of Text2D in Java 3D");
    System.out.println("The scene is of a rotating Text2D object.");
    System.out
        .print("If you don"t have a 3D card, it may take a few seconds ");
    System.out.println("before you see anything.");
    System.out.println("The Java 3D Tutorial is available on the web at:");
    System.out
        .println("http://java.sun.ru/products/java-media/3D/collateral");
    Frame frame = new MainFrame(new Text2DApp(), 256, 32);
  } // end of main (method of Text2DApp)
} // end of class Text2DApp





Renders Java 3D 2D Text objects in a variety of styles

/**********************************************************
 Copyright (C) 2001   Daniel Selman
 First distributed with the book "Java 3D Programming"
 by Daniel Selman and published by Manning Publications.
 http://manning.ru/selman
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation, version 2.
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 The license can be found on the WWW at:
 http://www.fsf.org/copyleft/gpl.html
 Or by writing to:
 Free Software Foundation, Inc.,
 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 Authors can be contacted at:
 Daniel Selman: daniel@selman.org
 If you make changes you think others would like, please 
 contact one of the authors or someone at the 
 www.j3d.org web site.
 **************************************************************/
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GraphicsConfigTemplate;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.net.URL;
import javax.media.j3d.AudioDevice;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Group;
import javax.media.j3d.Locale;
import javax.media.j3d.PhysicalBody;
import javax.media.j3d.PhysicalEnvironment;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.media.j3d.VirtualUniverse;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import com.sun.j3d.audioengines.javasound.JavaSoundMixer;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Text2D;
/**
 * Renders Java 3D 2D Text objects in a variety of styles.
 */
public class Text2DTest1 extends Java3dApplet {
  private static int m_kWidth = 400;
  private static int m_kHeight = 400;
  public Text2DTest1() {
    initJava3d();
  }
  protected BranchGroup createSceneBranchGroup() {
    BranchGroup objRoot = super.createSceneBranchGroup();
    Color3f color = new Color3f(0.0f, 0.0f, 0.0f);
    objRoot.addChild(createText2D("400 point 1x", color, 400, 1.0f, 6.0f));
    objRoot.addChild(createText2D("150 point 3x", color, 150, 3.0f, 3.0f));
    objRoot.addChild(createText2D("50 point 10x", color, 50, 10.0f, 0.0f));
    objRoot.addChild(createText2D("10 point 50x", color, 10, 50.0f, -3.0f));
    objRoot.addChild(createText2D("5 point 100x", color, 5, 100.0f, -6.0f));
    return objRoot;
  }
  TransformGroup createText2D(String szText, Color3f color, int nSize,
      float scale, float trans) {
    TransformGroup tg = new TransformGroup();
    Transform3D t3d = new Transform3D();
    t3d.setScale(scale);
    t3d.setTranslation(new Vector3d(-8.0, trans, 0));
    tg.setTransform(t3d);
    Text2D text2D = new Text2D(szText, color, "SansSerif", nSize,
        Font.PLAIN);
    tg.addChild(text2D);
    return tg;
  }
  public static void main(String[] args) {
    Text2DTest1 text2DTest = new Text2DTest1();
    text2DTest.saveCommandLineArguments(args);
    new MainFrame(text2DTest, m_kWidth, m_kHeight);
  }
}
/*******************************************************************************
 * Copyright (C) 2001 Daniel Selman
 * 
 * First distributed with the book "Java 3D Programming" by Daniel Selman and
 * published by Manning Publications. http://manning.ru/selman
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, version 2.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * The license can be found on the WWW at: http://www.fsf.org/copyleft/gpl.html
 * 
 * Or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite
 * 330, Boston, MA 02111-1307, USA.
 * 
 * Authors can be contacted at: Daniel Selman: daniel@selman.org
 * 
 * If you make changes you think others would like, please contact one of the
 * authors or someone at the www.j3d.org web site.
 ******************************************************************************/
//*****************************************************************************
/**
 * Java3dApplet
 * 
 * Base class for defining a Java 3D applet. Contains some useful methods for
 * defining views and scenegraphs etc.
 * 
 * @author Daniel Selman
 * @version 1.0
 */
//*****************************************************************************
abstract class Java3dApplet extends Applet {
  public static int m_kWidth = 300;
  public static int m_kHeight = 300;
  protected String[] m_szCommandLineArray = null;
  protected VirtualUniverse m_Universe = null;
  protected BranchGroup m_SceneBranchGroup = null;
  protected Bounds m_ApplicationBounds = null;
  //  protected com.tornadolabs.j3dtree.Java3dTree m_Java3dTree = null;
  public Java3dApplet() {
  }
  public boolean isApplet() {
    try {
      System.getProperty("user.dir");
      System.out.println("Running as Application.");
      return false;
    } catch (Exception e) {
    }
    System.out.println("Running as Applet.");
    return true;
  }
  public URL getWorkingDirectory() throws java.net.MalformedURLException {
    URL url = null;
    try {
      File file = new File(System.getProperty("user.dir"));
      System.out.println("Running as Application:");
      System.out.println("   " + file.toURL());
      return file.toURL();
    } catch (Exception e) {
    }
    System.out.println("Running as Applet:");
    System.out.println("   " + getCodeBase());
    return getCodeBase();
  }
  public VirtualUniverse getVirtualUniverse() {
    return m_Universe;
  }
  //public com.tornadolabs.j3dtree.Java3dTree getJ3dTree() {
  //return m_Java3dTree;
  //  }
  public Locale getFirstLocale() {
    java.util.Enumeration e = m_Universe.getAllLocales();
    if (e.hasMoreElements() != false)
      return (Locale) e.nextElement();
    return null;
  }
  protected Bounds getApplicationBounds() {
    if (m_ApplicationBounds == null)
      m_ApplicationBounds = createApplicationBounds();
    return m_ApplicationBounds;
  }
  protected Bounds createApplicationBounds() {
    m_ApplicationBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
        100.0);
    return m_ApplicationBounds;
  }
  protected Background createBackground() {
    Background back = new Background(new Color3f(0.9f, 0.9f, 0.9f));
    back.setApplicationBounds(createApplicationBounds());
    return back;
  }
  public void initJava3d() {
    //  m_Java3dTree = new com.tornadolabs.j3dtree.Java3dTree();
    m_Universe = createVirtualUniverse();
    Locale locale = createLocale(m_Universe);
    BranchGroup sceneBranchGroup = createSceneBranchGroup();
    ViewPlatform vp = createViewPlatform();
    BranchGroup viewBranchGroup = createViewBranchGroup(
        getViewTransformGroupArray(), vp);
    createView(vp);
    Background background = createBackground();
    if (background != null)
      sceneBranchGroup.addChild(background);
    //    m_Java3dTree.recursiveApplyCapability(sceneBranchGroup);
    //  m_Java3dTree.recursiveApplyCapability(viewBranchGroup);
    locale.addBranchGraph(sceneBranchGroup);
    addViewBranchGroup(locale, viewBranchGroup);
    onDoneInit();
  }
  protected void onDoneInit() {
    //  m_Java3dTree.updateNodes(m_Universe);
  }
  protected double getScale() {
    return 1.0;
  }
  public TransformGroup[] getViewTransformGroupArray() {
    TransformGroup[] tgArray = new TransformGroup[1];
    tgArray[0] = new TransformGroup();
    // move the camera BACK a little...
    // note that we have to invert the matrix as
    // we are moving the viewer
    Transform3D t3d = new Transform3D();
    t3d.setScale(getScale());
    t3d.setTranslation(new Vector3d(0.0, 0.0, -20.0));
    t3d.invert();
    tgArray[0].setTransform(t3d);
    return tgArray;
  }
  protected void addViewBranchGroup(Locale locale, BranchGroup bg) {
    locale.addBranchGraph(bg);
  }
  protected Locale createLocale(VirtualUniverse u) {
    return new Locale(u);
  }
  protected BranchGroup createSceneBranchGroup() {
    m_SceneBranchGroup = new BranchGroup();
    return m_SceneBranchGroup;
  }
  protected View createView(ViewPlatform vp) {
    View view = new View();
    PhysicalBody pb = createPhysicalBody();
    PhysicalEnvironment pe = createPhysicalEnvironment();
    AudioDevice audioDevice = createAudioDevice(pe);
    if (audioDevice != null) {
      pe.setAudioDevice(audioDevice);
      audioDevice.initialize();
    }
    view.setPhysicalEnvironment(pe);
    view.setPhysicalBody(pb);
    if (vp != null)
      view.attachViewPlatform(vp);
    view.setBackClipDistance(getBackClipDistance());
    view.setFrontClipDistance(getFrontClipDistance());
    Canvas3D c3d = createCanvas3D();
    view.addCanvas3D(c3d);
    addCanvas3D(c3d);
    return view;
  }
  protected PhysicalBody createPhysicalBody() {
    return new PhysicalBody();
  }
  protected AudioDevice createAudioDevice(PhysicalEnvironment pe) {
    JavaSoundMixer javaSoundMixer = new JavaSoundMixer(pe);
    if (javaSoundMixer == null)
      System.out.println("create of audiodevice failed");
    return javaSoundMixer;
  }
  protected PhysicalEnvironment createPhysicalEnvironment() {
    return new PhysicalEnvironment();
  }
  protected float getViewPlatformActivationRadius() {
    return 100;
  }
  protected ViewPlatform createViewPlatform() {
    ViewPlatform vp = new ViewPlatform();
    vp.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW);
    vp.setActivationRadius(getViewPlatformActivationRadius());
    return vp;
  }
  protected Canvas3D createCanvas3D() {
    GraphicsConfigTemplate3D gc3D = new GraphicsConfigTemplate3D();
    gc3D.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED);
    GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment()
        .getScreenDevices();
    Canvas3D c3d = new Canvas3D(gd[0].getBestConfiguration(gc3D));
    c3d.setSize(getCanvas3dWidth(c3d), getCanvas3dHeight(c3d));
    return c3d;
  }
  protected int getCanvas3dWidth(Canvas3D c3d) {
    return m_kWidth;
  }
  protected int getCanvas3dHeight(Canvas3D c3d) {
    return m_kHeight;
  }
  protected double getBackClipDistance() {
    return 100.0;
  }
  protected double getFrontClipDistance() {
    return 1.0;
  }
  protected BranchGroup createViewBranchGroup(TransformGroup[] tgArray,
      ViewPlatform vp) {
    BranchGroup vpBranchGroup = new BranchGroup();
    if (tgArray != null && tgArray.length > 0) {
      Group parentGroup = vpBranchGroup;
      TransformGroup curTg = null;
      for (int n = 0; n < tgArray.length; n++) {
        curTg = tgArray[n];
        parentGroup.addChild(curTg);
        parentGroup = curTg;
      }
      tgArray[tgArray.length - 1].addChild(vp);
    } else
      vpBranchGroup.addChild(vp);
    return vpBranchGroup;
  }
  protected void addCanvas3D(Canvas3D c3d) {
    setLayout(new BorderLayout());
    add(c3d, BorderLayout.CENTER);
    doLayout();
  }
  protected VirtualUniverse createVirtualUniverse() {
    return new VirtualUniverse();
  }
  protected void saveCommandLineArguments(String[] szArgs) {
    m_szCommandLineArray = szArgs;
  }
  protected String[] getCommandLineArguments() {
    return m_szCommandLineArray;
  }
}





Text2D Exployer

/*
 * %Z%%M% %I% %E% %U%
 * 
 * ************************************************************** "Copyright (c)
 * 2001 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * -Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 
 * -Redistribution in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * 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.
 * 
 * You acknowledge that Software is not designed,licensed or intended for use in
 * the design, construction, operation or maintenance of any nuclear facility."
 * 
 * ***************************************************************************
 */
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Group;
import javax.media.j3d.Texture;
import javax.media.j3d.Texture2D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.View;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Color4f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class TexBug extends Applet implements ActionListener,
    Java3DExplorerConstants {
  // Scene graph items
  SimpleUniverse u;
  Group scene;
  Appearance appearance;
  // temp image grabber
  boolean isApplication;
  Canvas3D canvas;
  View view;
  // Texture2D
  Texture2D texture;
  TextureLoader texLoader;
  int texWidth;
  int texHeight;
  int texFormat;
  boolean texEnable;
  String texEnableString = "Enable Texture";
  String texMipEnableString = "Enable MipMap";
  JCheckBox texEnableCheckBox;
  int texBoundaryModeS;
  int texBoundaryModeT;
  String wrapString = "WRAP";
  String clampString = "CLAMP";
  String texBoundarySWrapString = "S WRAP";
  String texBoundarySClampString = "S CLAMP";
  String texBoundaryTWrapString = "T WRAP";
  String texBoundaryTClampString = "T CLAMP";
  Color4f texBoundaryColor;
  int texMinFilter;
  int texMagFilter;
  String texFilterBasePointString = "BASE_LEVEL_POINT";
  String texFilterBaseLinearString = "BASE_LEVEL_LINEAR";
  String texFilterMultiPointString = "MULTI_LEVEL_POINT";
  String texFilterMultiLinearString = "MULTI_LEVEL_LINEAR";
  String texMinFilterBasePointString = "min base point";
  String texMinFilterBaseLinearString = "min base linear";
  String texMinFilterMultiPointString = "mag multi point";
  String texMinFilterMultiLinearString = "mag multi linear";
  String texMinFilterFastestString = "min fastest";
  String texMinFilterNicestString = "min nicest";
  String texMagFilterBasePointString = "mag base point";
  String texMagFilterBaseLinearString = "mag base linear";
  String texMagFilterNicestString = "mag nicest";
  String texMagFilterFastestString = "mag fastest";
  int texMipMapMode;
  String texMipMapBaseString = "BASE_LEVEL";
  String texMipMapMultiString = "MULTI_LEVEL_MIPMAP";
  // Temporaries that are reused
  Transform3D tmpTrans = new Transform3D();
  Vector3f tmpVector = new Vector3f();
  AxisAngle4f tmpAxisAngle = new AxisAngle4f();
  // colors
  Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
  Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
  Color3f green = new Color3f(0.0f, 1.0f, 0.0f);
  Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);
  Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f);
  Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f);
  Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f);
  Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
  Color3f darkGrey = new Color3f(0.2f, 0.2f, 0.2f);
  Color3f grey = new Color3f(0.5f, 0.5f, 0.5f);
  // geometric constant
  Point3f origin = new Point3f();
  Vector3f yAxis = new Vector3f(0.0f, 1.0f, 0.0f);
  // NumberFormat to print out floats with only two digits
  NumberFormat nf;
  // Base for URLs, used to handle application/applet split
  String codeBaseString = null;
  // create the appearance and it"s components
  void setupAppearance() {
    appearance = new Appearance();
    // Texture2D
    // set the values to the defaults
    texEnable = false;
    texMipMapMode = Texture.BASE_LEVEL;
    texBoundaryModeS = Texture.WRAP;
    texBoundaryModeT = Texture.WRAP;
    texMinFilter = Texture.BASE_LEVEL_POINT;
    texMagFilter = Texture.BASE_LEVEL_POINT;
    texBoundaryColor = new Color4f(1.0f, 1.0f, 1.0f, 1.0f);
    // set up the appearance to allow the texture to be changed
    appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
    // set the texture
    setTexture();
  }
  int powerOfTwo(int value) {
    int retval = 2;
    while (retval < value) {
      retval *= 2;
    }
    return retval;
  }
  // create a Texture2D using the current values from the GUI
  // and attach it to the appearance
  void setTexture() {
    // set up the image using the TextureLoader
    java.net.URL imageURL = null;
    try {
      imageURL = new java.net.URL(codeBaseString + "earth.jpg");
      //imageURL = new java.net.URL(codeBaseString +
      //  "decal_textures/fish1.gif");
    } catch (Exception e) {
      System.err.println("Exception: " + e);
      System.exit(1);
    }
    int flags;
    if (texMipMapMode == Texture.BASE_LEVEL) {
      flags = 0;
    } else {
      flags = TextureLoader.GENERATE_MIPMAP;
    }
    texLoader = new TextureLoader(imageURL, new String("RGBA"),
    //new String("LUMINANCE"),
        flags, this);
    // We could create texture from image
    //
    // Get the image from the loader. We need an image which
    // has power of two dimensions, so we"ll get the unscaled image,
    // figure out what the scaled size should be and then get a scale
    // image
    //ImageComponent2D unscaledImage = texLoader.getImage();
    //int width = unscaledImage.getWidth();
    //int height = unscaledImage.getWidth();
    //
    // scaled values are next power of two greater than or equal to
    // value
    //texWidth = powerOfTwo(width);
    //texHeight = powerOfTwo(height);
    //
    // rescale the image if necessary
    //ImageComponent2D texImage;
    //if ((texWidth == width) && (texHeight == height)) {
    //    texImage = unscaledImage;
    //} else {
    //    texImage = texLoader.getScaledImage(texWidth, texHeight);
    //}
    //texFormat = Texture.RGB;
    //texture = new Texture2D(texMipMapMode, texFormat, texWidth,
    //  texHeight);
    //texture.setImage(0, texImage);
    // instead we"ll just get get the texture from loader
    texture = (Texture2D) texLoader.getTexture();
    //texture.setBoundaryColor(texBoundaryColor);
    texture.setBoundaryColor(1.0f, 1.0f, 1.0f, 1.0f);
    texture.setBoundaryModeS(texBoundaryModeS);
    texture.setBoundaryModeT(texBoundaryModeT);
    texture.setEnable(texEnable);
    texture.setMinFilter(texMinFilter);
    texture.setMagFilter(texMagFilter);
    // Set the capabilities to enable the changable attrs
    texture.setCapability(Texture.ALLOW_ENABLE_WRITE);
    texture.setCapability(Texture.ALLOW_IMAGE_WRITE);
    // connect the new texture to the appearance
    System.out.println("Appearance.setTexture(" + texture + ")");
    appearance.setTexture(texture);
  }
  // sets up the scene switch
  void setupScene() {
    scene = new Group();
    // create a sphere with the shared appearance
    Sphere sphere = new Sphere(1.0f, Sphere.GENERATE_NORMALS
        | Sphere.GENERATE_TEXTURE_COORDS, appearance);
    scene.addChild(sphere);
  }
  public void actionPerformed(ActionEvent e) {
    String action = e.getActionCommand();
    Object source = e.getSource();
    if (action == texEnableString) {
      texEnable = texEnableCheckBox.isSelected();
      System.out.println("texture.setEnable(" + texEnable + ")");
      texture.setEnable(texEnable);
    } else if (action == texBoundarySWrapString) {
      texBoundaryModeS = Texture.WRAP;
      setTexture();
    } else if (action == texBoundarySClampString) {
      texBoundaryModeS = Texture.CLAMP;
      setTexture();
    } else if (action == texBoundaryTWrapString) {
      texBoundaryModeT = Texture.WRAP;
      setTexture();
    } else if (action == texBoundaryTClampString) {
      texBoundaryModeT = Texture.CLAMP;
      setTexture();
    } else if (action == texMinFilterBasePointString) {
      texMinFilter = Texture.BASE_LEVEL_POINT;
      setTexture();
    } else if (action == texMinFilterBaseLinearString) {
      texMinFilter = Texture.BASE_LEVEL_LINEAR;
      setTexture();
    } else if (action == texMinFilterMultiPointString) {
      texMinFilter = Texture.MULTI_LEVEL_POINT;
      setTexture();
    } else if (action == texMinFilterMultiLinearString) {
      texMinFilter = Texture.MULTI_LEVEL_LINEAR;
      setTexture();
    } else if (action == texMinFilterFastestString) {
      texMinFilter = Texture.FASTEST;
      setTexture();
    } else if (action == texMinFilterNicestString) {
      texMinFilter = Texture.NICEST;
      setTexture();
    } else if (action == texMagFilterBasePointString) {
      texMagFilter = Texture.BASE_LEVEL_POINT;
      setTexture();
    } else if (action == texMagFilterBaseLinearString) {
      texMagFilter = Texture.BASE_LEVEL_LINEAR;
      setTexture();
    } else if (action == texMagFilterNicestString) {
      texMagFilter = Texture.NICEST;
      setTexture();
    } else if (action == texMagFilterFastestString) {
      texMagFilter = Texture.FASTEST;
      setTexture();
    } else if (action == texMipMapBaseString) {
      texMipMapMode = Texture.BASE_LEVEL;
      setTexture();
    } else if (action == texMipMapMultiString) {
      texMipMapMode = Texture.MULTI_LEVEL_MIPMAP;
      setTexture();
    }
  }
  BranchGroup createSceneGraph() {
    // Create the root of the branch graph
    BranchGroup objRoot = new BranchGroup();
    // Add the primitives to the scene
    setupAppearance();
    setupScene();
    objRoot.addChild(scene);
    return objRoot;
  }
  public TexBug() {
    this(false);
  }
  public TexBug(boolean isApplication) {
    this.isApplication = isApplication;
  }
  public void init() {
    // initialize the code base
    try {
      java.net.URL codeBase = getCodeBase();
      codeBaseString = codeBase.toString();
    } catch (Exception e) {
      // probably running as an application, try the application
      // code base
      codeBaseString = "file:./";
    }
    // set up a NumFormat object to print out float with only 3 fraction
    // digits
    nf = NumberFormat.getInstance();
    nf.setMaximumFractionDigits(3);
    setLayout(new BorderLayout());
    GraphicsConfiguration config = SimpleUniverse
        .getPreferredConfiguration();
    canvas = new Canvas3D(config);
    add("Center", canvas);
    // Create a simple scene and attach it to the virtual universe
    BranchGroup scene = createSceneGraph();
    u = new SimpleUniverse(canvas);
    // set up sound
    u.getViewer().createAudioDevice();
    // get the view
    view = u.getViewer().getView();
    // Get the viewing platform
    ViewingPlatform viewingPlatform = u.getViewingPlatform();
    // Move the viewing platform back to enclose the -2 -> 2 range
    double viewRadius = 2.0; // want to be able to see circle
    // of viewRadius size around origin
    // get the field of view
    double fov = u.getViewer().getView().getFieldOfView();
    // calc view distance to make circle view in fov
    float viewDistance = (float) (viewRadius / Math.tan(fov / 2.0));
    tmpVector.set(0.0f, 0.0f, viewDistance);// setup offset
    tmpTrans.set(tmpVector); // set trans to translate
    // move the view platform
    viewingPlatform.getViewPlatformTransform().setTransform(tmpTrans);
    // add an orbit behavior to move the viewing platform
    OrbitBehavior orbit = new OrbitBehavior(canvas);
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
        100.0);
    orbit.setSchedulingBounds(bounds);
    viewingPlatform.setViewPlatformBehavior(orbit);
    u.addBranchGraph(scene);
    add("South", guiPanel());
  }
  public void destroy() {
    u.removeAllLocales();
  }
  // create a panel with a tabbed pane holding each of the edit panels
  JPanel guiPanel() {
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add("Center", texture2DPanel());
    return panel;
  }
  JPanel texture2DPanel() {
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(1, 0)); // horizontal
    JPanel leftPanel = new JPanel();
    leftPanel.setLayout(new GridLayout(0, 1)); // vertical
    panel.add(leftPanel);
    JPanel rightPanel = new JPanel();
    rightPanel.setLayout(new GridLayout(0, 1)); // vertical
    panel.add(rightPanel);
    texEnableCheckBox = new JCheckBox(texEnableString);
    // set up the action commands
    texEnableCheckBox.setActionCommand(texEnableString);
    // register the applet as the listener for the buttons
    texEnableCheckBox.addActionListener(this);
    // set the initial value
    texEnableCheckBox.setSelected(texEnable);
    // add the checkbox to the panel
    leftPanel.add(texEnableCheckBox);
    // texture boundary S
    leftPanel.add(new JLabel("Boundary S Mode:"));
    // create the buttons
    JRadioButton texBoundarySWrapButton = new JRadioButton(wrapString);
    JRadioButton texBoundarySClampButton = new JRadioButton(clampString);
    // set up the action commands
    texBoundarySWrapButton.setActionCommand(texBoundarySWrapString);
    texBoundarySClampButton.setActionCommand(texBoundarySClampString);
    // add the buttons to a group so that only one can be selected
    ButtonGroup boundSButtonGroup = new ButtonGroup();
    boundSButtonGroup.add(texBoundarySWrapButton);
    boundSButtonGroup.add(texBoundarySClampButton);
    // register the applet as the listener for the buttons
    texBoundarySWrapButton.addActionListener(this);
    texBoundarySClampButton.addActionListener(this);
    // add the buttons to the panel
    leftPanel.add(texBoundarySWrapButton);
    leftPanel.add(texBoundarySClampButton);
    // set the default
    texBoundarySWrapButton.setSelected(true);
    // texture boundary T
    leftPanel.add(new JLabel("Boundary T Mode:"));
    // create the buttons
    JRadioButton texBoundaryTWrapButton = new JRadioButton(wrapString);
    JRadioButton texBoundaryTClampButton = new JRadioButton(clampString);
    // set up the action commands
    texBoundaryTWrapButton.setActionCommand(texBoundaryTWrapString);
    texBoundaryTClampButton.setActionCommand(texBoundaryTClampString);
    // add the buttons to a group so that only one can be selected
    ButtonGroup boundTButtonGroup = new ButtonGroup();
    boundTButtonGroup.add(texBoundaryTWrapButton);
    boundTButtonGroup.add(texBoundaryTClampButton);
    // register the applet as the listener for the buttons
    texBoundaryTWrapButton.addActionListener(this);
    texBoundaryTClampButton.addActionListener(this);
    // add the buttons to the panel
    leftPanel.add(texBoundaryTWrapButton);
    leftPanel.add(texBoundaryTClampButton);
    // set the default
    texBoundaryTWrapButton.setSelected(true);
    // texture min filter
    rightPanel.add(new JLabel("Min Filter:"));
    // create the buttons
    JRadioButton texMinFilterBasePointButton = new JRadioButton(
        texFilterBasePointString);
    JRadioButton texMinFilterBaseLinearButton = new JRadioButton(
        texFilterBaseLinearString);
    JRadioButton texMinFilterMultiPointButton = new JRadioButton(
        texFilterMultiPointString);
    JRadioButton texMinFilterMultiLinearButton = new JRadioButton(
        texFilterMultiLinearString);
    JRadioButton texMinFilterNicestButton = new JRadioButton(nicestString);
    JRadioButton texMinFilterFastestButton = new JRadioButton(fastestString);
    // set up the action commands
    texMinFilterBasePointButton
        .setActionCommand(texMinFilterBasePointString);
    texMinFilterBaseLinearButton
        .setActionCommand(texMinFilterBaseLinearString);
    texMinFilterMultiPointButton
        .setActionCommand(texMinFilterMultiPointString);
    texMinFilterMultiLinearButton
        .setActionCommand(texMinFilterMultiLinearString);
    texMinFilterNicestButton.setActionCommand(texMinFilterNicestString);
    texMinFilterFastestButton.setActionCommand(texMinFilterFastestString);
    // add the buttons to a group so that only one can be selected
    ButtonGroup minFilterButtonGroup = new ButtonGroup();
    minFilterButtonGroup.add(texMinFilterBasePointButton);
    minFilterButtonGroup.add(texMinFilterBaseLinearButton);
    minFilterButtonGroup.add(texMinFilterMultiPointButton);
    minFilterButtonGroup.add(texMinFilterMultiLinearButton);
    minFilterButtonGroup.add(texMinFilterNicestButton);
    minFilterButtonGroup.add(texMinFilterFastestButton);
    // register the applet as the listener for the buttons
    texMinFilterBasePointButton.addActionListener(this);
    texMinFilterBaseLinearButton.addActionListener(this);
    texMinFilterMultiPointButton.addActionListener(this);
    texMinFilterMultiLinearButton.addActionListener(this);
    texMinFilterNicestButton.addActionListener(this);
    texMinFilterFastestButton.addActionListener(this);
    // add the buttons to the panel
    rightPanel.add(texMinFilterBasePointButton);
    rightPanel.add(texMinFilterBaseLinearButton);
    rightPanel.add(texMinFilterMultiPointButton);
    rightPanel.add(texMinFilterMultiLinearButton);
    rightPanel.add(texMinFilterNicestButton);
    rightPanel.add(texMinFilterFastestButton);
    // set the default
    texMinFilterBasePointButton.setSelected(true);
    // texture max filter
    rightPanel.add(new JLabel("Mag Filter:"));
    // create the buttons
    JRadioButton texMagFilterBasePointButton = new JRadioButton(
        texFilterBasePointString);
    JRadioButton texMagFilterBaseLinearButton = new JRadioButton(
        texFilterBaseLinearString);
    JRadioButton texMagFilterNicestButton = new JRadioButton(nicestString);
    JRadioButton texMagFilterFastestButton = new JRadioButton(fastestString);
    // set up the action commands
    texMagFilterBasePointButton
        .setActionCommand(texMagFilterBasePointString);
    texMagFilterBaseLinearButton
        .setActionCommand(texMagFilterBaseLinearString);
    texMagFilterNicestButton.setActionCommand(texMagFilterNicestString);
    texMagFilterFastestButton.setActionCommand(texMagFilterFastestString);
    // add the buttons to a group so that only one can be selected
    ButtonGroup magFilterButtonGroup = new ButtonGroup();
    magFilterButtonGroup.add(texMagFilterBasePointButton);
    magFilterButtonGroup.add(texMagFilterBaseLinearButton);
    magFilterButtonGroup.add(texMagFilterNicestButton);
    magFilterButtonGroup.add(texMagFilterFastestButton);
    // register the applet as the listener for the buttons
    texMagFilterBasePointButton.addActionListener(this);
    texMagFilterBaseLinearButton.addActionListener(this);
    texMagFilterNicestButton.addActionListener(this);
    texMagFilterFastestButton.addActionListener(this);
    // add the buttons to the panel
    rightPanel.add(texMagFilterBasePointButton);
    rightPanel.add(texMagFilterBaseLinearButton);
    rightPanel.add(texMagFilterNicestButton);
    rightPanel.add(texMagFilterFastestButton);
    // set the default
    texMagFilterBasePointButton.setSelected(true);
    // MipMap Mode
    leftPanel.add(new JLabel("MipMap Mode:"));
    // create the buttons
    JRadioButton texMipMapBaseButton = new JRadioButton(texMipMapBaseString);
    JRadioButton texMipMapMultiButton = new JRadioButton(
        texMipMapMultiString);
    // set up the action commands
    texMipMapBaseButton.setActionCommand(texMipMapBaseString);
    texMipMapMultiButton.setActionCommand(texMipMapMultiString);
    // add the buttons to a group so that only one can be selected
    ButtonGroup texMipMapButtonGroup = new ButtonGroup();
    texMipMapButtonGroup.add(texMipMapBaseButton);
    texMipMapButtonGroup.add(texMipMapMultiButton);
    // register the applet as the listener for the buttons
    texMipMapBaseButton.addActionListener(this);
    texMipMapMultiButton.addActionListener(this);
    // add the buttons to the panel
    leftPanel.add(texMipMapBaseButton);
    leftPanel.add(texMipMapMultiButton);
    // set the default
    texMipMapBaseButton.setSelected(true);
    return panel;
  }
  // The following allows TexBug to be run as an application
  // as well as an applet
  //
  public static void main(String[] args) {
    new MainFrame(new TexBug(true), 650, 800);
  }
}
interface Java3DExplorerConstants {
  // colors
  static Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
  static Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
  static Color3f green = new Color3f(0.0f, 1.0f, 0.0f);
  static Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);
  static Color3f skyBlue = new Color3f(0.6f, 0.7f, 0.9f);
  static Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f);
  static Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f);
  static Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f);
  static Color3f brightWhite = new Color3f(1.0f, 1.5f, 1.5f);
  static Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
  static Color3f darkGrey = new Color3f(0.15f, 0.15f, 0.15f);
  static Color3f medGrey = new Color3f(0.3f, 0.3f, 0.3f);
  static Color3f grey = new Color3f(0.5f, 0.5f, 0.5f);
  static Color3f lightGrey = new Color3f(0.75f, 0.75f, 0.75f);
  // infinite bounding region, used to make env nodes active everywhere
  BoundingSphere infiniteBounds = new BoundingSphere(new Point3d(),
      Double.MAX_VALUE);
  // common values
  static final String nicestString = "NICEST";
  static final String fastestString = "FASTEST";
  static final String antiAliasString = "Anti-Aliasing";
  static final String noneString = "NONE";
  // light type constants
  static int LIGHT_AMBIENT = 1;
  static int LIGHT_DIRECTIONAL = 2;
  static int LIGHT_POSITIONAL = 3;
  static int LIGHT_SPOT = 4;
  // screen capture constants
  static final int USE_COLOR = 1;
  static final int USE_BLACK_AND_WHITE = 2;
  // number formatter
  NumberFormat nf = NumberFormat.getInstance();
}





Text 2D Test

/*
 * @(#)Text2DTest.java 1.11 02/10/21 13:55:56
 * 
 * Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met: -
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer. - Redistribution in binary
 * form must reproduce the above copyright notice, this list of conditions and
 * the following disclaimer in the documentation and/or other materials provided
 * with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * 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.
 * 
 * You acknowledge that Software is not designed,licensed or intended for use in
 * the design, construction, operation or maintenance of any nuclear facility.
 */
import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.event.KeyEvent;
import java.util.Enumeration;
import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCondition;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Text2D;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class Text2DTest extends Applet {
  private SimpleUniverse u = null;
  public BranchGroup createSceneGraph() {
    // Create the root of the branch graph
    BranchGroup objRoot = new BranchGroup();
    // Create a Transformgroup to scale all objects so they
    // appear in the scene.
    TransformGroup objScale = new TransformGroup();
    Transform3D t3d = new Transform3D();
    t3d.setScale(0.4);
    objScale.setTransform(t3d);
    objRoot.addChild(objScale);
    // 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);
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
        100.0);
    TransformGroup textTranslationGroup;
    Transform3D textTranslation;
    float yPos = -.5f;
    Shape3D textObject = new Text2D("Rotating Yellow Text", new Color3f(1f,
        1f, 0f), "Serif", 60, Font.BOLD);
    Appearance app = textObject.getAppearance();
    PolygonAttributes pa = app.getPolygonAttributes();
    if (pa == null)
      pa = new PolygonAttributes();
    pa.setCullFace(PolygonAttributes.CULL_NONE);
    if (app.getPolygonAttributes() == null)
      app.setPolygonAttributes(pa);
    objTrans.addChild(textObject);
    textTranslation = new Transform3D();
    textTranslation.setTranslation(new Vector3f(0f, yPos, 0f));
    textTranslationGroup = new TransformGroup(textTranslation);
    textTranslationGroup.addChild(objTrans);
    objScale.addChild(textTranslationGroup);
    yPos += .5f;
    /* Blue 40point text */
    textObject = new Text2D("Blue 40point Text", new Color3f(0f, 0f, 1f),
        "Serif", 40, Font.BOLD);
    textTranslation = new Transform3D();
    textTranslation.setTranslation(new Vector3f(0f, yPos, 0f));
    textTranslationGroup = new TransformGroup(textTranslation);
    textTranslationGroup.addChild(textObject);
    objScale.addChild(textTranslationGroup);
    yPos += .5f;
    /* Green italic text */
    textObject = new Text2D("Green Italic Text", new Color3f(0f, 1f, 0f),
        "Serif", 70, Font.ITALIC);
    textTranslation = new Transform3D();
    textTranslation.setTranslation(new Vector3f(0f, yPos, 0f));
    textTranslationGroup = new TransformGroup(textTranslation);
    textTranslationGroup.addChild(textObject);
    objScale.addChild(textTranslationGroup);
    yPos += .5f;
    // 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);
    rotator.setSchedulingBounds(bounds);
    objTrans.addChild(rotator);
    return objRoot;
  }
  public Text2DTest() {
  }
  public void init() {
    setLayout(new BorderLayout());
    GraphicsConfiguration config = SimpleUniverse
        .getPreferredConfiguration();
    Canvas3D c = new Canvas3D(config);
    add("Center", c);
    // Create a simple scene and attach it to the virtual universe
    BranchGroup scene = createSceneGraph();
    u = new SimpleUniverse(c);
    MoverBehavior navigator = new MoverBehavior(u.getViewingPlatform()
        .getViewPlatformTransform());
    scene.addChild(navigator);
    // Have Java 3D perform optimizations on this scene graph.
    scene.rupile();
    // This will move the ViewPlatform back a bit so the
    // objects in the scene can be viewed.
    u.getViewingPlatform().setNominalViewingTransform();
    u.addBranchGraph(scene);
  }
  public void destroy() {
    u.cleanup();
  }
  //
  // The following allows HelloUniverse to be run as an application
  // as well as an applet
  //
  public static void main(String[] args) {
    new MainFrame(new Text2DTest(), 256, 256);
  }
}
// Mover behavior class - used to allow viewer to move using arrow keys
class MoverBehavior extends Behavior {
  WakeupOnAWTEvent w1 = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
  WakeupCriterion[] w2 = { w1 };
  WakeupCondition w = new WakeupOr(w2);
  TransformGroup viewTransformGroup;
  double rotation = 0.0; // holds current rotation radians
  public void initialize() {
    // Establish initial wakeup criteria
    wakeupOn(w);
  }
  /**
   * Override Behavior"s stimulus method to handle the event.
   */
  public void processStimulus(Enumeration criteria) {
    WakeupOnAWTEvent ev;
    WakeupCriterion genericEvt;
    AWTEvent[] events;
    while (criteria.hasMoreElements()) {
      genericEvt = (WakeupCriterion) criteria.nextElement();
      if (genericEvt instanceof WakeupOnAWTEvent) {
        ev = (WakeupOnAWTEvent) genericEvt;
        events = ev.getAWTEvent();
        processManualEvent(events);
      }
    }
    // Set wakeup criteria for next time
    wakeupOn(w);
  }
  /**
   * Process a keyboard event to move or rotate the viewer.
   */
  void processManualEvent(AWTEvent[] events) {
    for (int i = 0; i < events.length; ++i) {
      if (events[i] instanceof KeyEvent) {
        KeyEvent event = (KeyEvent) events[i];
        if (event.getKeyCode() == KeyEvent.VK_EQUALS) {
          continue;
        }
        Transform3D t = new Transform3D();
        viewTransformGroup.getTransform(t);
        Vector3f viewDir = new Vector3f(0f, 0f, -1f);
        Vector3f translation = new Vector3f();
        t.get(translation);
        t.transform(viewDir);
        if (event.getKeyCode() == KeyEvent.VK_UP) {
          translation.x += viewDir.x;
          translation.y += viewDir.y;
          translation.z += viewDir.z;
        } else if (event.getKeyCode() == KeyEvent.VK_DOWN) {
          translation.x -= viewDir.x;
          translation.y -= viewDir.y;
          translation.z -= viewDir.z;
        } else if (event.getKeyCode() == KeyEvent.VK_RIGHT) {
          rotation += -.1;
        } else if (event.getKeyCode() == KeyEvent.VK_LEFT) {
          rotation += .1;
        }
        t.rotY(rotation);
        t.setTranslation(translation);
        viewTransformGroup.setTransform(t);
      }
    }
  }
  /**
   * Constructor
   */
  public MoverBehavior(TransformGroup trans) {
    viewTransformGroup = trans;
    Bounds bound = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 10000.0);
    this.setSchedulingBounds(bound);
  }
}