import java.applet.*;
import java.awt.BorderLayout;
import java.awt.Font;
import java.lang.String;
import java.net.MalformedURLException;
import java.net.URL;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.image.TextureLoader;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.util.Enumeration;

/**-------------------------------------------------------------------
   Credits:
   Planets program by Kirk Brown.
   Orbit/Rotate Behaviors provided by Dan Petersen.

   Planets is a solar system theme to be used as a navigational
   map or menu for the top level of a Web site. It could also
   represent an organization of multiple business units. There
   is at the core, a Sun which is orbited by planets and moons.
   Each object can have a label and URL associated with it.

--------------------------------------------------------------------*/

public class Planets extends Applet {

        // Class variables.  The default values can be overridden
  // by using the PARAMS tag when invoking the applet.
  //
  // The following is the defined HTML interface to this program:
  //
  //    <PARAM NAME="Planets" VALUE=2>
        //                       Value Options: 0 to n
  //    <PARAM NAME ="BackgroundColor" VALUE="black">
  //           Value Options: red,blue,green,yellow,purple,
  //                 gold,orange,black
        //                                       white,medblue,medgreen
  //    <PARAM NAME ="PlanetColor1" VALUE="blue">
  //           Value Options: red,blue,green,yellow,
  //                 purple,gold,orange,black
  //                                     white,medblue,medgreen
  //    <PARAM NAME ="PlanetSpeed1" VALUE="slow">
  //           Value Options: PlanetSpeed[n]
  //           VALUE="[slow, medium, fast, xfast]"
  //    <PARAM NAME ="PlanetOrbit" VALUE="2.0">
  //           Value Options: ( a floating point number to
  //                 increase the orbit's radius incrementally.)
  //    <PARAM NAME="PlanetSize1" VALUE="large">
  //           Value Options: PlanetSize
  //           VALUE="[small, medium, large, xlarge]"
        //        <PARAM NAME="PlanetImage1" VALUE="earth.jpg">
        //                     Value Options: Image[n] VALUE="[image file]"
        //        <PARAM NAME="PlanetURL1" VALUE="http://www.sun.com/">
        //                     Value Options: PlanetURL[n] VALUE="[url reference]"
  //    <PARAM NAME="PlanetText1" VALUE="Engineering">
  //                   Value Options: PlanetText[n] VALUE="[text string]"
        //    <PARAM NAME="PlanetTextColor1" VALUE="red">
        //                     Value Options: PlanetTextColor[n]
  //           Value=[red,blue,green,yellow,
  //             purple,gold,orange,black,
        //                                   white,medblue,medgreen]
        //        <PARAM NAME="PlanetTextFont1" VALUE="Times">
        //                     Value Options: PlanetTextFont[n]
  //           VALUE="[system font name]"
  //      <PARAM NAME="PlanetTextSize1" VALUE="60">
  //                   Value Options: PlanetTextSize[n] VALUE="[font size]"
  //      <PARAM NAME="PlanetTextStyle1" VALUE="bold">
  //                   Value Options: PlanetTextStyle[n]
  //           VALUE="[bold, italic, plain]"
        //        <PARAM NAME="Moon3" VALUE="true">
        //                     Value Options: Moon[n]
  //            VALUE="[true creates a moon around Planets[n]"]
        //        <PARAM NAME="MoonImage1" VALUE="ito.jpg">
        //                     Value Options: MoonImage[n] VALUE="[image file]"
  //      <PARAM NAME="MoonURL1" VALUE="http://www.sun.com/">
        //                     Value Options: MoonURL[n] VALUE="[url reference]"
  //    <PARAM NAME="MoonColor1" VALUE="green">
  //                   Value Options: MoonColor[n]
  //            Value=[red,blue,green,yellow,purple,gold,orange,black,
        //                                         white,medblue,medgreen]
  //    <PARAM NAME ="MoonSpeed1" VALUE="slow">
  //           Value Options: MoonSpeed[n]
  //           VALUE="[slow, medium, fast, xfast]"
  //    <PARAM NAME="MoonSize1" VALUE="large">
  //           Value Options: MoonSize
  //           VALUE="[small, medium, large, xlarge]"
  //    <PARAM NAME="MoonText1" VALUE="Engineering">
  //                   Value Options: MoonText[n] VALUE="[text string]"
        //    <PARAM NAME="MoonTextColor1" VALUE="red">
        //                     Value Options: MoonTextColor[n]
  //           Value=[red,blue,green,yellow,
  //                  purple,gold,orange,black,
        //                                        white,medblue,medgreen]
        //        <PARAM NAME="MoonTextFont1" VALUE="Times">
        //                     Value Options: MoonTextFont[n]
  //           VALUE="[system font name]"
  //      <PARAM NAME="PlanetTextSize1" VALUE="60">
  //                   Value Options: MoonTextSize[n] VALUE="[font size]"
  //      <PARAM NAME="PlanetTextStyle1" VALUE="bold">
  //                   Value Options: MoonTextStyle[n]
  //           VALUE="[bold, italic, plain]"

   // Pre-defined colors
  Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
  Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
        Color3f gray = new Color3f(0.6f, 0.6f, 0.6f);
        Color3f red   = new Color3f(1.0f, 0.0f, 0.0f);
  Color3f ambientred = new Color3f(0.4f, 0.1f, 0.0f);
        Color3f medred = new Color3f(0.80f, 0.4f, 0.3f);
        Color3f green   = new Color3f(0.0f, 0.80f, 0.2f);
  Color3f ambientgreen = new Color3f(0.0f, 0.3f, 0.1f);
        Color3f medgreen = new Color3f(0.0f, 0.5f, 0.1f);
  Color3f orange   = new Color3f(0.7f, 0.4f, 0.0f);
  Color3f ambientorange = new Color3f(0.5f, 0.02f, 0.0f);
        Color3f medorange = new Color3f(0.5f, 0.2f, 0.1f);
        Color3f blue   = new Color3f(0.1f, 0.3f, 0.9f);
  Color3f ambientblue = new Color3f(0.0f, 0.1f, 0.4f);
        Color3f medblue = new Color3f(0.0f, 0.1f, 0.4f);
        Color3f gold = new Color3f(1.0f, 0.8f, 0.0f);
        Color3f yellow = new Color3f(1.0f, 1.0f, 0.6f);
        Color3f purple = new Color3f(0.5f, 0.2f, 0.8f);
        Color3f medpurple = new Color3f(0.5f, 0.2f, 0.5f);
  Color3f ambient = new Color3f(0.2f, 0.2f, 0.2f);
  Color3f diffuse = new Color3f(0.7f, 0.7f, 0.7f);
  Color3f specular = new Color3f(0.7f, 0.7f, 0.7f);

  // Background color
  private Color3f bgcolor = black;

  // Planet "-demo" mode default attributes
  private float position = 0.0f;
        private int numPlanets = 3;       // number of planets
  private float porbit = 1.75f;     // orbit radius
  private float scale = 0.22f;       // scene scale factor
  private int[] pspeed =            // orbit speed
        {OrbitBehavior.SLOW,15000,28000};
  private float[] psize =           // planet size
        {1.5f, 0.3f, 0.45f};
  private Color3f[] pcolor =        // planet color (if no image)
        {white, medpurple, white};
  private String[] pimage =         // planet texturemap
        {"sun.jpg", null, "earth.jpg"};
        private URL[] purl =              // planet URL link
        {null, null, null};
  private String[] ptext =          // planet text label
        {"CORPORATE", "PRODUCTS", "SUPPORT"};
  Point3d ppoint1 = new Point3d(0.1, 0.7, 0.0);
  Point3d ppoint2 = new Point3d(0.65, -0.75, 0.0);
  Point3d ppoint3 = new Point3d(0.4, -0.51, 0.0);
  private Point3d[] ptextpos =      // planet text position
        {ppoint1, ppoint2, ppoint3};
        private Color3f[] ptcolor =       // planet text color
        {yellow, yellow, yellow};
  private String[] ptfont =         // planet text font type
        {"Helvetica", "Helvetica", "Helvetica"};
  private int[] ptstyle =           // planet text font style
        {Font.BOLD, Font.BOLD, Font.BOLD};
  private int[] ptsize =            // planet text label size
         {60, 60, 60};

        // Default "-demo" mode Moon attributes
  private int numMoons = 3;         // number of moons
  private boolean[] moons =         // associate moon with planet
          {false, false, true};
  private int[] mspeed =            // orbit speed
          {0, 0, 10000};
  private float[] msize =           // moon size
          {0.0f, 0.0f, 0.2f};
  private float morbit = 1.0f;      // orbit radius around planet
  private String[] mimage =         // moon texturemap
          {null, null, null};
        private URL[] murl =              // moon URL link
          {null, null, null};
        private Color3f[] mcolor =        // moon color (if no image)
          {null, null, blue};
  private String[] mtext =          // moon text label
          {null, null, "Eng"};
  Point3d mpoint1 = new Point3d();
  Point3d mpoint2 = new Point3d();
  Point3d mpoint3 = new Point3d(0.2,-0.5,0.0);
  private Point3d[] mtextpos =      // moon text position
          {mpoint1, mpoint2, mpoint3};
        private Color3f[] mtcolor =       // moon text color
          {null, null, yellow};
  private String[] mtfont =         // moon text font type
          {null, null, "Helvetica"};
  private int[] mtstyle =           // moon text style
          {Font.BOLD, Font.BOLD, Font.BOLD};
  private int[] mtsize =            // moon text label size
          {0, 0, 48};

  // Pre-defined Text Positions
  private Point3d smallTPOS = new Point3d(0.2, -0.6, 0.0);
  private Point3d mediumTPOS = new Point3d(0.2, -0.5, 0.0);
  private Point3d largeTPOS = new Point3d(0.2, -0.1, 0.0);
  private Point3d xlargeTPOS = new Point3d(0.2, 0.6, 0.0);

  URL[] pimageURL;
  URL[] mimageURL;
  boolean applet = false;

  // Examines all parameters that can be passed in to this
  // applet and updates the global state to reflect any
  // non-default settings.
  private void lookForParameters() {

                // Used to read in the parameters for the applet.
                String paramValue;

    // Reset
    numMoons = 0;
    float morbit = 1.0f;

    // Running as an applet.
    applet = true;

                // Find out the total number of planets.
                //
                paramValue = getParameter("Planets");
                if (paramValue != null)
                    numPlanets = Integer.parseInt(paramValue);
                else
                    numPlanets = 2;

                // Allocate the needed array space based on
    // the number of planets.
                //
    pspeed = new int[numPlanets];
    psize = new float[numPlanets];
                pimageURL = new URL[numPlanets];
                purl = new URL[numPlanets];
    ptext = new String[numPlanets];
    ptextpos = new Point3d[numPlanets];
    pcolor = new Color3f[numPlanets];
    ptcolor = new Color3f[numPlanets];
    ptfont = new String[numPlanets];
    ptstyle = new int[numPlanets];
    ptsize = new int[numPlanets];
    moons = new boolean[numPlanets];
    msize = new float[numPlanets];
    mspeed = new int[numPlanets];
                mimage = new String[numPlanets];
                murl = new URL[numPlanets];
    mtext = new String[numPlanets];
    mtextpos = new Point3d[numPlanets];
    mtcolor = new Color3f[numPlanets];
    mtfont = new String[numPlanets];
    mtstyle = new int[numPlanets];
    mimageURL = new URL[numPlanets];
    mcolor = new Color3f[numPlanets];

        // Look for Background Color
        paramValue = getParameter("BackgroundColor");
                    if (paramValue.equalsIgnoreCase("red") == true)
                                      bgcolor = red;
                    else if (paramValue.equalsIgnoreCase("green") == true)
                                      bgcolor = green;
                    else if (paramValue.equalsIgnoreCase("blue") == true)
                                      bgcolor = blue;
                    else if (paramValue.equalsIgnoreCase("medred") == true)
                                      bgcolor = medred;
                    else if (paramValue.equalsIgnoreCase("medgreen") == true)
                                      bgcolor = medgreen;
                    else if (paramValue.equalsIgnoreCase("medblue") == true)
                                      bgcolor = medblue;
                    else if (paramValue.equalsIgnoreCase("black") == true)
                                      bgcolor = black;
                    else if (paramValue.equalsIgnoreCase("gray") == true)
                                      bgcolor = gray;
                    else if (paramValue.equalsIgnoreCase("white") == true)
                                      bgcolor = white;
                    else if (paramValue.equalsIgnoreCase("yellow") == true)
                                      bgcolor = yellow;
                    else if (paramValue.equalsIgnoreCase("gold") == true)
                                      bgcolor = gold;
                    else if (paramValue.equalsIgnoreCase("purple") == true)
                                      bgcolor = purple;
                    else if (paramValue.equalsIgnoreCase("medpurple") == true)
                                      bgcolor = medpurple;
                    else if (paramValue.equalsIgnoreCase("orange") == true)
                                      bgcolor = orange;
                    else if (paramValue.equalsIgnoreCase("medorange") == true)
                                      bgcolor = medorange;
                    else
                                bgcolor = black;

    // Planet Orbit radius factor
    //
    paramValue = getParameter("PlanetOrbit");
    if (paramValue != null) {
           Float f = new Float(paramValue);
           porbit = f.floatValue();
    }
    else
           porbit = 1.75f;

       // Look for the scaling factor to fit the objects to the
       // window. Factor zoomout1 is large to zoomout10 is scaled
       // way down.
                         //
                         paramValue = getParameter("Scale");
                         if (paramValue != null) {
           if (paramValue.equalsIgnoreCase("zoomout1") == true)
                                             scale = (float) 1.0;
           else if (paramValue.equalsIgnoreCase("zoomout2") == true)
                                             scale = (float) 0.9;
           else if (paramValue.equalsIgnoreCase("zoomout3") == true)
                                             scale = (float) 0.8;
           else if (paramValue.equalsIgnoreCase("zoomout4") == true)
                                             scale = (float) 0.7;
           else if (paramValue.equalsIgnoreCase("zoomout5") == true)
                                             scale = (float) 0.6;
           else if (paramValue.equalsIgnoreCase("zoomout6") == true)
                                             scale = (float) 0.5;
           else if (paramValue.equalsIgnoreCase("zoomout7") == true)
                                             scale = (float) 0.4;
           else if (paramValue.equalsIgnoreCase("zoomout8") == true)
                                             scale = (float) 0.3;
           else if (paramValue.equalsIgnoreCase("zoomout9") == true)
                                             scale = (float) 0.2;
           else if (paramValue.equalsIgnoreCase("zoomout10") == true)
                                             scale = (float) 0.1;
           else
                                             scale = (float) 0.5;
                        } else {
                                    scale = (float) 0.2;
      }

                for (int i=0; i < numPlanets; i++) {

        // Look for the Planet Speed
        paramValue = getParameter("PlanetSpeed" + (i + 1));
        if (paramValue.equalsIgnoreCase("slow") == true)
                                      pspeed[i] = 32000;
        else if (paramValue.equalsIgnoreCase("medium") == true)
              pspeed[i] = 20000;
        else if (paramValue.equalsIgnoreCase("fast") == true)
              pspeed[i] = 10000;
        else if (paramValue.equalsIgnoreCase("xfast") == true)
              pspeed[i] = 1000;
        else
              pspeed[i] = Integer.parseInt(paramValue, 10);

        // Look for Planet's Size
        paramValue = getParameter("PlanetSize" + (i + 1));
        if (paramValue.equalsIgnoreCase("small") == true) {
                                      psize[i] = 0.2f;
              ptextpos[i] = smallTPOS;
        }
        else if (paramValue.equalsIgnoreCase("medium") == true) {
              psize[i] = 0.45f;
              ptextpos[i] = mediumTPOS;
        }
        else if (paramValue.equalsIgnoreCase("large") == true) {
              psize[i] = 0.80f;
              ptextpos[i] = largeTPOS;
        }
        else if (paramValue.equalsIgnoreCase("xlarge") == true) {
              psize[i] = 1.25f;
              ptextpos[i] = xlargeTPOS;
        }
        else {
          psize[i] = 0.80f;
          ptextpos[i] = largeTPOS;
        }

                          // Look for Planet images files to create. They need
        // to be fully qualified URLs to avoid generating a
        // security voilation from the browser.
                          //
                          paramValue = getParameter("PlanetImage" + (i + 1));
                          if (paramValue != null) {

           try {
                                      pimageURL[i] = new URL(paramValue);
           }
           catch (MalformedURLException e) {
                                     System.out.println("ERROR: reading image URL: " +
                                    paramValue);
           }
                          }

                          // Look for URLs to associate with each object. We
        // will stuff this value into a UserData class that
        // will associate the URl with our 3D object. The
        // getURL is called in our mouse behavior (PickURL)
        // and the document is loaded. If the HTML file does
        // not contain a URL for a planet, we need to hack
        // some temp value as place holder and we'll test
        // for a valid URL in the behavior later.
                          //
                          paramValue = getParameter("PlanetURL" + (i + 1));
                          if (paramValue != null) {
                                   try {
                                      purl[i] = new URL(paramValue);
                                   }
                                   catch(MalformedURLException e) {
                                     System.out.println("ERROR: reading value for URL: " +
                                    paramValue);
                                   }
        }
        else {
           try {
             purl[i] = new URL("http://stub");
           }
                                   catch(MalformedURLException e) {
                                     System.out.println("ERROR: reading value for URL: " +
                                    paramValue);
                                   }
        }

                    // Look for a new Planet color
                    paramValue = getParameter("PlanetColor" + (i + 1));
                    if (paramValue != null)
                        if (paramValue.equalsIgnoreCase("red") == true)
                                         pcolor[i] = red;
                        else if (paramValue.equalsIgnoreCase("green") == true)
                                         pcolor[i] = green;
                        else if (paramValue.equalsIgnoreCase("blue") == true)
                                         pcolor[i] = blue;
                        else if (paramValue.equalsIgnoreCase("medred") == true)
                                         pcolor[i] = medred;
                        else if (paramValue.equalsIgnoreCase("medgreen") == true)
                                         pcolor[i] = medgreen;
                        else if (paramValue.equalsIgnoreCase("medblue") == true)
                                         pcolor[i] = medblue;
                        else if (paramValue.equalsIgnoreCase("black") == true)
                                         pcolor[i] = black;
                        else if (paramValue.equalsIgnoreCase("gray") == true)
                                         pcolor[i] = gray;
                        else if (paramValue.equalsIgnoreCase("white") == true)
                                         pcolor[i] = white;
                        else if (paramValue.equalsIgnoreCase("yellow") == true)
                                         pcolor[i] = yellow;
                        else if (paramValue.equalsIgnoreCase("gold") == true)
                                         pcolor[i] = gold;
                        else if (paramValue.equalsIgnoreCase("purple") == true)
                                         pcolor[i] = purple;
                        else if (paramValue.equalsIgnoreCase("medpurple") == true)
                                         pcolor[i] = medpurple;
                        else if (paramValue.equalsIgnoreCase("orange") == true)
                                         pcolor[i] = orange;
                        else if (paramValue.equalsIgnoreCase("medorange") == true)
                                         pcolor[i] = medorange;
                        else
                                   pcolor[i] = blue;
        else
            pcolor[i] = blue;

        // Look for the Planet's text label
        paramValue = getParameter("PlanetText" + (i + 1));
        if (paramValue != null)
                ptext[i] = new String(paramValue);
        else
                                     ptext[i] = null;

        // Look for the Planet's text Font
        paramValue = getParameter("PlanetTextFont" + (i + 1));
        if (paramValue != null)
            if (paramValue.equalsIgnoreCase("TimesRoman") == true)
                ptfont[i] = new String(paramValue);
                        else if (paramValue.equalsIgnoreCase("Helvetica") == true)
                ptfont[i] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Serif") == true)
                ptfont[i] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Monospaced") == true)
                ptfont[i] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Courier") == true)
                ptfont[i] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Dialog") == true)
                ptfont[i] = new String(paramValue);
            else
                // Let's see if we can get other system loaded fonts
                ptfont[i] = new String(paramValue);
                if (ptfont[i] == null)
                    ptfont[i] = new String("Serif");
        else
                                     ptfont[i] = new String("Helvetica");

        // Look for the Planet's text Style
        paramValue = getParameter("PlanetTextStyle" + (i + 1));
        if (paramValue != null)
             if (paramValue.equalsIgnoreCase("bold") == true)
                 ptstyle[i] = Font.BOLD;
             else if (paramValue.equalsIgnoreCase("italic") == true)
                 ptstyle[i] = Font.ITALIC;
             else if (paramValue.equalsIgnoreCase("plain") == true)
                 ptstyle[i] = Font.PLAIN;
             else
                 ptstyle[i] = Font.PLAIN;
        else
                                     ptstyle[i] = Font.BOLD;

         // Look for the Planet's text Size
        paramValue = getParameter("PlanetTextSize" + (i + 1));
        if (paramValue != null)
             ptsize[i] = Integer.parseInt(paramValue);
        else
                                     ptsize[i] = 60;

                    // Look for Text color
                    paramValue = getParameter("PlanetTextColor" + (i + 1));
        if (paramValue != null)
             if (paramValue.equalsIgnoreCase("red") == true)
                    ptcolor[i] = red;
             else if (paramValue.equalsIgnoreCase("green") == true)
                    ptcolor[i] = green;
             else if (paramValue.equalsIgnoreCase("blue") == true)
                    ptcolor[i] = blue;
             else if (paramValue.equalsIgnoreCase("medred") == true)
                    ptcolor[i] = medred;
             else if (paramValue.equalsIgnoreCase("medgreen") == true)
                    ptcolor[i] = medgreen;
             else if (paramValue.equalsIgnoreCase("medblue") == true)
                    ptcolor[i] = medblue;
             else if (paramValue.equalsIgnoreCase("black") == true)
                    ptcolor[i] = black;
             else if (paramValue.equalsIgnoreCase("gray") == true)
                    ptcolor[i] = gray;
             else if (paramValue.equalsIgnoreCase("white") == true)
                    ptcolor[i] = white;
             else if (paramValue.equalsIgnoreCase("yellow") == true)
                    ptcolor[i] = yellow;
             else if (paramValue.equalsIgnoreCase("gold") == true)
                    ptcolor[i] = gold;
             else if (paramValue.equalsIgnoreCase("purple") == true)
                    ptcolor[i] = purple;
             else if (paramValue.equalsIgnoreCase("medpurple") == true)
                    ptcolor[i] = medpurple;
             else if (paramValue.equalsIgnoreCase("orange") == true)
                    ptcolor[i] = orange;
             else if (paramValue.equalsIgnoreCase("medorange") == true)
                    ptcolor[i] = medorange;
             else
                    ptcolor[i] = red;
        else
             ptcolor[i] = red;

     } // END of Planet Loop

     for (int x=0; x < numPlanets; x++) {
        // Look for Moons associated with planets and flag the index.
        // For example, if the user specifies Moon3==true, then we'll
        // need to create a moon that orbits the 3rd planet. Does not
        // support multiple moons per planet.
                          //
                          paramValue = getParameter("Moon" + (x + 1));
                          if (paramValue != null) {
                                      moons[x] = true;
              // Keep track of the number of moons
              numMoons = numMoons + 1;
        }
                          else {
                                      moons[x] = false;
        }

        // Look for Moon URL image files to create
                          //
        paramValue = getParameter("MoonImage" + (x + 1));
                          if (paramValue != null) {
           try {
                                      mimageURL[x] = new URL(paramValue);
           }
           catch (MalformedURLException e) {
                                     System.out.println("ERROR: reading image URL: " +
                                    paramValue);
                                   }
                          }

                          // Look for URLs to associate with each Moon.
        // (See PlanetURL for what does this mean?)
                          //
                          paramValue = getParameter("MoonURL" + (x + 1));
                          if (paramValue != null) {
                                   try {
                                      murl[x] = new URL(paramValue);
                                   }
                                   catch(MalformedURLException e) {
                                     System.out.println("ERROR: reading value for URL: " +
                                    paramValue);
                                   }
        }
        else {
           try {
             murl[x] = new URL("http://stub");
           }
                                   catch(MalformedURLException e) {
                                     System.out.println("ERROR: reading value for URL: " +
                                    paramValue);
                                   }
        }

        // Look for the Moon Speed
        paramValue = getParameter("MoonSpeed" + (x + 1));
        if (paramValue != null)
          if (paramValue.equalsIgnoreCase("slow") == true)
                                      mspeed[x] = 32000;
          else if (paramValue.equalsIgnoreCase("medium") == true)
              mspeed[x] = 20000;
          else if (paramValue.equalsIgnoreCase("fast") == true)
              mspeed[x] = 10000;
          else if (paramValue.equalsIgnoreCase("xfast") == true)
              mspeed[x] = 1000;
          else
              mspeed[x] = Integer.parseInt(paramValue, 10);
        else
              mspeed[x] = 15000;

        // Look for Moon's Size
        paramValue = getParameter("MoonSize" + (x + 1));
        if (paramValue != null) {
          if (paramValue.equalsIgnoreCase("small") == true) {
                                      msize[x] = 0.2f;
              mtextpos[x] = smallTPOS;
          }
          else if (paramValue.equalsIgnoreCase("medium") == true) {
              msize[x] = 0.45f;
              mtextpos[x] = mediumTPOS;
          }
          else if (paramValue.equalsIgnoreCase("large") == true) {
              msize[x] = 0.80f;
              mtextpos[x] = largeTPOS;
          }
          else if (paramValue.equalsIgnoreCase("xlarge") == true) {
              msize[x] = 1.25f;
              mtextpos[x] = xlargeTPOS;
          }
          else {
              msize[x] = 0.2f;
              mtextpos[x] = smallTPOS;
          }
        }
        else {
          msize[x] = 0.2f;
          mtextpos[x] = smallTPOS;
        }

        // Look for a new Moon color
                    paramValue = getParameter("MoonColor" + (x + 1));
                    if (paramValue != null)
                       if (paramValue.equalsIgnoreCase("red") == true)
                                      mcolor[x] = red;
                       else if (paramValue.equalsIgnoreCase("green") == true)
                                      mcolor[x] = green;
                       else if (paramValue.equalsIgnoreCase("blue") == true)
                                      mcolor[x] = blue;
                       else if (paramValue.equalsIgnoreCase("medred") == true)
                                      mcolor[x] = medred;
                       else if (paramValue.equalsIgnoreCase("medgreen") == true)
                                      mcolor[x] = medgreen;
                       else if (paramValue.equalsIgnoreCase("medblue") == true)
                                      mcolor[x] = medblue;
                       else if (paramValue.equalsIgnoreCase("black") == true)
                                      mcolor[x] = black;
                       else if (paramValue.equalsIgnoreCase("gray") == true)
                                      mcolor[x] = gray;
                       else if (paramValue.equalsIgnoreCase("white") == true)
                                      mcolor[x] = white;
                       else if (paramValue.equalsIgnoreCase("yellow") == true)
                                      mcolor[x] = yellow;
                       else if (paramValue.equalsIgnoreCase("gold") == true)
                                      mcolor[x] = gold;
                       else if (paramValue.equalsIgnoreCase("purple") == true)
                                      mcolor[x] = purple;
                       else if (paramValue.equalsIgnoreCase("medpurple") == true)
                                      mcolor[x] = medpurple;
                       else if (paramValue.equalsIgnoreCase("orange") == true)
                                      mcolor[x] = orange;
                       else if (paramValue.equalsIgnoreCase("medorange") == true)
                                      mcolor[x] = medorange;
                       else
                                mcolor[x] = gray;
        else
              mcolor[x] = gray;

                // Look for the Moon's text label
        paramValue = getParameter("MoonText" + (x + 1));
        if (paramValue != null)
                mtext[x] = new String(paramValue);
        else
                mtext[x] = null;

        // Look for the Moon's text Font
        paramValue = getParameter("MoonTextFont" + (x + 1));
        if (paramValue != null)
            if (paramValue.equalsIgnoreCase("TimesRoman") == true)
                mtfont[x] = new String(paramValue);
                        else if (paramValue.equalsIgnoreCase("Helvetica") == true)
                mtfont[x] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Serif") == true)
                ptfont[x] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Monospaced") == true)
                mtfont[x] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Courier") == true)
                mtfont[x] = new String(paramValue);
            else if (paramValue.equalsIgnoreCase("Dialog") == true)
                mtfont[x] = new String(paramValue);
            else
                // Let's see if we can get other system loaded fonts
                mtfont[x] = new String(paramValue);
        else
                                     mtfont[x] = new String("Helvetica");

        // Look for the Moon's text Style
        paramValue = getParameter("PlanetTextStyle" + (x + 1));
        if (paramValue != null)
             if (paramValue.equalsIgnoreCase("bold") == true)
                 mtstyle[x] = Font.BOLD;
             else if (paramValue.equalsIgnoreCase("italic") == true)
                 mtstyle[x] = Font.ITALIC;
             else if (paramValue.equalsIgnoreCase("plain") == true)
                 mtstyle[x] = Font.PLAIN;
             else
                 mtstyle[x] = Font.PLAIN;
        else
                                     mtstyle[x] = Font.PLAIN;

         // Look for the Moon's text Size
        paramValue = getParameter("MoonTextSize" + (x + 1));
        if (paramValue != null)
             mtsize[x] = Integer.parseInt(paramValue);
        else
                                     mtsize[x] = 36;

                    // Look for Moon Text color
                    paramValue = getParameter("MoonTextColor" + (x + 1));
        if (paramValue != null)
            if (paramValue.equalsIgnoreCase("red") == true)
                mtcolor[x] = red;
            else if (paramValue.equalsIgnoreCase("green") == true)
                mtcolor[x] = green;
            else if (paramValue.equalsIgnoreCase("blue") == true)
                mtcolor[x] = blue;
            else if (paramValue.equalsIgnoreCase("medred") == true)
                mtcolor[x] = medred;
            else if (paramValue.equalsIgnoreCase("medgreen") == true)
                mtcolor[x] = medgreen;
            else if (paramValue.equalsIgnoreCase("medblue") == true)
                mtcolor[x] = medblue;
            else if (paramValue.equalsIgnoreCase("black") == true)
                mtcolor[x] = black;
            else if (paramValue.equalsIgnoreCase("gray") == true)
                mtcolor[x] = gray;
            else if (paramValue.equalsIgnoreCase("white") == true)
                mtcolor[x] = white;
            else if (paramValue.equalsIgnoreCase("yellow") == true)
                mtcolor[x] = yellow;
            else if (paramValue.equalsIgnoreCase("gold") == true)
                 mtcolor[x] = gold;
            else if (paramValue.equalsIgnoreCase("purple") == true)
                 mtcolor[x] = purple;
            else if (paramValue.equalsIgnoreCase("medpurple") == true)
                 mtcolor[x] = medpurple;
            else if (paramValue.equalsIgnoreCase("orange") == true)
                 mtcolor[x] = orange;
            else if (paramValue.equalsIgnoreCase("medorange") == true)
                 mtcolor[x] = medorange;
            else
                 mtcolor[x] = yellow;
        else
              mtcolor[x] = white;

      } // END for Moon loop
   } // END LookForParameters


    public BranchGroup createSceneGraph(Canvas3D c,
                                        AppletContext context) {

        Color3f sunlight = new Color3f(1.0f, 1.0f, 1.0f);
        Vector3f Vsun  = new Vector3f(0.0f, 0.0f, -1.0f);

        // Transform array for Planet rotations
        TransformGroup[] planetRot;

        // Transform array for Planet orbits
        TransformGroup[] planetOrb;

        // Planet appearance objects
        Appearance[] papp;

        // Planet objects
        Sphere[] planet;

        // Transform array for Planet text labels
        TransformGroup[] ptextOrb;

        // Text label array for Planet
        Shape3D[] plabel;

        // Transform array for Moon rotations
        TransformGroup[] moonRot;

        //Transforms for Moon orbits
        TransformGroup[] moonOrb;

        // Moon appearance objects
        Appearance[] mapp;

        // Moon objects
        Sphere[] moon;

        // Transform array for Moon text labels
        TransformGroup[] mtextOrb;

        // 2D Text label array for Moon
        Shape3D[] mlabel;

        // Initialize Object arrays
        planetRot = new Rotator[numPlanets];
        planetOrb = new XZorbit[numPlanets];
        papp = new Appearance[numPlanets];
        planet = new Sphere[numPlanets];
        ptextOrb = new XZorbit[numPlanets];
        plabel = new Shape3D[numPlanets];
        moonRot = new Rotator[numPlanets];
        moonOrb = new XZorbit[numPlanets];
        mapp = new Appearance[numPlanets];
        moon = new Sphere[numPlanets];
        mtextOrb = new XZorbit[numPlanets];
        mlabel = new Shape3D[numPlanets];

              // Create the root of the branch graph
              BranchGroup objRoot = new BranchGroup();

              // Create a bounds for the background, behavior and lights
              BoundingSphere bounds =
                  new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

              // This Transform Group scales the objects so
        // they fit the scene
              TransformGroup objScale = new TransformGroup();
        Transform3D t3d = new Transform3D();
        t3d.setScale(scale);
        objScale.setTransform(t3d);
        objRoot.addChild(objScale);

              // Set up the background color
        Background bg = new Background(bgcolor);
              bg.setApplicationBounds(bounds);
              objRoot.addChild(bg);

        // Needed by the texture loader utility.
        String rgb = new String("RGB");

              //  Create the Solar System with Planets, Moons and Text
              //
        for (int i=0; i < numPlanets; i++) {

           // These transforms will ROTATE objects around the Y-axis.
           planetRot[i] = new Rotator(new Transform3D(),
                                            Rotator.MEDIUM);

           // These transforms will ORBIT planet objects around
           // the Z-axis.All Planets orbit around the same origin
           // point, 1, -1, 0 position is really the radius from
           // the origin point. Speed is how fast the object swings
           // around and around.
           //
           planetOrb[i] =  new XZorbit(pspeed[i],
                                   position,
                                   new Point3d(1.0,-1.0,0.0));

           // Specify the transforms that will position the text label
           // for each Planet and orbit at the same velocity. Make sure
           // we have a text lable before we create a transform since
           // planet labels are optional.
           //
           if (ptext[i] != null)
               ptextOrb[i] = new XZorbit(pspeed[i],
                                  position,
                                  ptextpos[i]);
           else
               ptextOrb[i] = null;

           // The first "planet" will have a "zero" radius orbit so
           // one can create a Sun for the first position. As more
           // planets are added, the radius increases by the offset
           // value.
           // *** Note, the user can change the offset value to bunch
           //     the orbits tightly together or spread them apart.
           // In any case, the radius of the orbit increases with
           // every planet. Position was initialized to zero when
           // first created, so the first loop the position will be
           // zero.
           //
           position = position + porbit;

           // initialize the Apperance node
           papp[i] = new Appearance();

           if (pcolor[i] != null) {
               // Maybe a shiny planet color is specified instead.
               //
               Color3f objColor = pcolor[i];
               papp[i].setMaterial(new Material(objColor,
                             black, objColor, white, 80.0f));
           }
           else {
               // Set the planet color to purple by default
               //
               Color3f objColor = medpurple;
               papp[i].setMaterial(new Material(objColor,
                           black, objColor, white, 80.0f));
           }

           // Texturemap an image onto the Planet if specified.
           //
           if (applet == true) {
               if (pimageURL[i] != null) {
                  //   Param pimage[i] is the URL of an texture image
                  //   Param rgb is the format which channels to use
                  //   Param this is the associated image observer
                  //
                  TextureLoader t = new TextureLoader(pimageURL[i],
                                                    rgb, this);
                  if (t != null)
                                 papp[i].setTexture(t.getTexture());

                 // Set up material properties so we can light the
                 // textured planet
                 papp[i].setMaterial(new Material(gray, black,
                                       gray, white, 1.0f));
               }
           }
           else if (pimage[i] != null) {

                  // Load a local image file
                  //
                  TextureLoader t = new TextureLoader(pimage[i],
                                                    rgb, this);
                  if (t != null)
                                 papp[i].setTexture(t.getTexture());

                 // Set up material properties so we can light the
                 // textured planet
                 papp[i].setMaterial(new Material(gray, black,
                                       gray, white, 1.0f));
           }

           // Create the Planet
           //
           planet[i] = new Sphere(psize[i],
                               Sphere.GENERATE_NORMALS |
                               Sphere.GENERATE_TEXTURE_COORDS,
                               60,  papp[i]);

           // Store URL in LocalData object and assign to this
           // primitive. Dont execute this if running -demo.
           //
           if (applet == true) {
                  LocalData ld = new LocalData(purl[i]);
                  planet[i].setUserData(ld);
           }

           // Create Planet text label, if specified.
           //
           if (ptext[i] != null)
                plabel[i] = new Text2D(ptext[i],
                                   ptcolor[i],
                                   ptfont[i],
                                   ptsize[i],
                                   ptstyle[i]);

            // If there is a Moon that orbits this planet, create the
            // moon's attributes.
            if (moons[i] != false) {

                // Create orbit transforms about the planet's
                // center point. The moon's orbit radius around
                // a planet can be specified from the HTML
                // interface. mspeed is how fast it orbits.
                //
                moonOrb[i] =  new XZorbit(mspeed[i],
                                    morbit,
                                    new Point3d(0.0,0.0,0.0));

               // Rotation transform for the moon at medium speed.
               //
               moonRot[i] = new Rotator(new Transform3D(),
                                              Rotator.MEDIUM);

               // Specify the transforms that will position the
               // text labels for each Planet and orbit at the
               // same velocity. Make sure we have a text label
               // before we create a transform since planet labels
               // are optional.
               //
               if (mtext[i] != null)
                   mtextOrb[i] = new XZorbit(mspeed[i],
                                  morbit,
                                  mtextpos[i]);
               else
                   mtextOrb[i] = null;

               // Create an Appearance object.  This will be used to
               // place the texture map onto the object.
               mapp[i] = new Appearance();

               if (mcolor[i] != null) {
                    // Maybe a shiny moon color is specified instead.
                    //
                    Color3f objColor = mcolor[i];
                    mapp[i].setMaterial(new Material(objColor,
                                      black, objColor, white, 80.0f));
               }
               else {
                    // Set the moon color to purple by default
                    //
                    Color3f objColor = medpurple;
                    mapp[i].setMaterial(new Material(objColor,
                                  black, objColor, white, 80.0f));
               }

               // Texture map or color the Moon if specified or use
               // default settings.
               //
               if (applet == true) {
                   if (mimageURL[i] != null) {
                      // Param pimage[i] is the string of an texture
                      // image Param rgb is the format which channels
                      // to use Param this is the associated image
                      // observer
                      //
                   TextureLoader t = new TextureLoader(mimageURL[i],
                                                    rgb, this);
                      if (t != null)
                                         mapp[i].setTexture(t.getTexture());

                      // Set up material properties so we can light
                      // the textured planet
                      mapp[i].setMaterial(new Material(gray, black,
                                                  gray, white, 1.0f));
                   }
               }
               else if (mimage[i] != null) {
                      TextureLoader t = new TextureLoader(mimage[i],
                                                    rgb, this);
                      if (t != null)
                                         mapp[i].setTexture(t.getTexture());

                      // Set up material properties so we can light
                      // the textured planet
                      mapp[i].setMaterial(new Material(gray, black,
                                                  gray, white, 1.0f));
               }

               // Create the Moon
               //
               moon[i] = new Sphere(msize[i],
                               Sphere.GENERATE_NORMALS |
                               Sphere.GENERATE_TEXTURE_COORDS,
                               60,  mapp[i]);


               // Store URL in LocalData object and assign to this
               // primitive. Dont execute this if running -demo.
               //
               if (applet == true) {
                  LocalData ld = new LocalData(murl[i]);
                  moon[i].setUserData(ld);
               }

               // Create Moon text label, if specified.
               //
               if (mtext[i] != null)
                         mlabel[i] = new Text2D(mtext[i],
                                         mtcolor[i],
                                         mtfont[i],
                                         mtsize[i],
                                         mtstyle[i]);

            } // END if moons statement

        }  // END for loop

              // Simulate the source of light from a direction
        //
              DirectionalLight lgt1 = new DirectionalLight(sunlight, Vsun);
        lgt1.setInfluencingBounds(bounds);
              objScale.addChild(lgt1);

              // Add everything to the Scene that was passed from the HTML
        // file or if we are running in demo mode
        //
        for (int i=0; i < numPlanets; i++) {
                   objScale.addChild(planetOrb[i]);
                   planetOrb[i].addChild(planetRot[i]);
             planetRot[i].addChild(planet[i]);

             // If it has a text label then add it
             if (plabel[i] != null) {
                        objScale.addChild(ptextOrb[i]);
                        ptextOrb[i].addChild(plabel[i]);
             }

             // If a moon was created then add it
                   if (moon[i] != null) {
                  planetOrb[i].addChild(moonOrb[i]);
                        moonOrb[i].addChild(moonRot[i]);
                        moonRot[i].addChild(moon[i]);
             }

             // If the moon had a text label then add it
             if (mlabel[i] != null) {
                  planetOrb[i].addChild(mtextOrb[i]);
                  mtextOrb[i].addChild(mlabel[i]);
             }
        }

        // Setup picking URLs.
        if (applet == true) {
            PickURL pickURL = new PickURL(c, objRoot, bounds, context);
            pickURL.setSchedulingBounds(bounds);
            objRoot.addChild(pickURL);
        }

              return objRoot;
    }

    public void init() {

        AppletContext context = null;

       // If we are running as an applet we need to
        // initialize values according to the user settings in
        // the HTML file accomplished by lookForParameters().
        // Otherwise we'll just use the values used to initialize
        // the local variable declarations at the top of the block.
        //
        if (getParameter("Planets") != null) {
                context = getAppletContext();
                lookForParameters();
        }

        // Create a Canvas3D object and add it to the applet
              setLayout(new BorderLayout());
              Canvas3D c = new Canvas3D(null);
              add("Center", c);

        // Create a simple scene.
              BranchGroup scene = createSceneGraph(c, context);

        // attach the scene to the virtual universe
              SimpleUniverse u = new SimpleUniverse(c);

              // Move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        u.getViewingPlatform().setNominalViewingTransform();

        // Add the branch graph to the Locale object to
        // make the branch "live".
              u.addBranchGraph(scene);
    }

    //
    // The following allows Planets to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {

       if (args.length > 0) {
           // Parse Input Arguments
           for (int i = 0; i < args.length; i++) {

               if (args[i].equals("-demo")) {
                   new MainFrame(new Planets(), 500, 400);
               } else {
                               System.out.println("Usage: java Planets -demo");
                   System.exit(0);
                     }
           }
       } else {
           System.out.println("Usage: java Planets -demo");
           System.exit(0);
       }

   }  // END main

} // END Class
