/*  PlanDImmed.java 0.0 09/15/01
 *  This is a program that will be used to illustrate opportunities and
 *  problems doing physics with the Java 3D API.
 *
 *  It is built using Sun Microsystem's demo example
 *  PureImmediate.java, the Copyright notice of which is 
 *  reproduced below.
 *
 *  modifications Copyright Fred Klingener 2001
 *  may be reproduced or used for any non-commercial purpose
 *  
 *  Plan D:
 *      run() ...
 *          try
 *	        {   Thread.sleep(DeltaT);
 *	        }
 *	        catch (InterruptedException e)
 *	        {
 *	        }
 *  
 /*
 *	@(#)PureImmediate.java 1.16 01/01/11 07:38:31
 *
 * Copyright (c) 1996-2001 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.GraphicsConfiguration;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

/**
 * Pure immediate mode example program.  In pure immediate mode, the
 * renderer must be stopped on the Canvas being rendered into. In our
 * example, this is done immediately after the canvas is created. A
 * separate thread is started up to do the immediate mode rendering.
 */

//  Plan D  Immediate mode

public class PlanD_Immed extends Applet implements Runnable {
    String ProgramName = "PlanD_Immed.java 09-28-2001";
    
    //  09-20-01
    //  first, add frame delay monitor
    final boolean debug = true;
    int FrameBlock;
    int Frame;
    long Then;

    //  09-20-01
    //  next add a time delay
    int DeltaT;
    
    //  then back to original example
    private Canvas3D canvas;
    private GraphicsContext3D gc = null;
    private Geometry cube = null;
    private Transform3D cmt = new Transform3D();

    // One rotation (2*PI radians) every 6 seconds
    private Alpha rotAlpha = new Alpha(-1, 6000);

    private SimpleUniverse u = null;

    //
    // Renders a single frame by clearing the canvas, drawing the
    // geometry, and swapping the draw and display buffer.
    //
    public void render() 
    {   if (gc == null) 
        {   // Set up Graphics context
	        gc = canvas.getGraphicsContext3D();
	        gc.setAppearance(new Appearance());
    	    // Set up geometry
	        cube = new ColorCube(0.4).getGeometry();
	    }
	    // Compute angle of rotation based on alpha value
	    double angle = rotAlpha.value() * 2.0*Math.PI;
	    cmt.rotY(angle);
	    // Render the geometry for this frame
	    gc.clear();
	    gc.setModelTransform(cmt);
	    gc.draw(cube);
	    canvas.swap();
    }

    //
    // Run method for our immediate mode rendering thread.
    //
    public void run() 
    {   // System.out.println("PlanD_Immed.run: starting main loop");
        java.text.NumberFormat        Double1;
        Double1 = java.text.NumberFormat.getInstance();
        Double1.setMaximumFractionDigits(1);
        Double1.setMinimumFractionDigits(1);
	    
	    
	    while (true) 
	    {   render();
	        if (debug)
	        {   if (++Frame >= FrameBlock)
	            {   long Now = System.currentTimeMillis();
	                long ET = Now - Then;
	                double AvgDelay = (double)ET/FrameBlock;
                    System.out.print("  "+DeltaT+"    "+
                                Double1.format(AvgDelay)+"    ");
                    String s = "";
                    for (int i=0; i<(int)AvgDelay-DeltaT; i++)
                    {   s += "*";
                    }
                    System.out.print(s+"\n");
        
	                Then = Now;
	                Frame = 0;
	                DeltaT++;
	            }
	        }
    	    try
	        {   Thread.sleep(DeltaT);
	        }
	        catch (InterruptedException e)
	        {
	        }
    	    //  Thread.yield();
	    }
    }

    public PlanD_Immed() {
    }

    //
    // init: create the canvas, stop the renderer,
    // create the universe, and start the drawing thread.
    //
    public void init() 
    {   java.text.DateFormat DayTime;
        DayTime = java.text.DateFormat.getDateTimeInstance(java.text.DateFormat.SHORT, java.text.DateFormat.SHORT);
        DeltaT = 10;
	    if (debug)
	    {   FrameBlock = 200;
	        Then = System.currentTimeMillis();
	        Frame = 0;
            System.out.println("");
            System.out.println("Program: "+ProgramName);
            System.out.println("Run "+DayTime.format(new java.util.Date()));
            System.out.println("OS Arch.: "+System.getProperty("os.arch"));
            System.out.println("OS: "+System.getProperty("os.name")+
                            "  Version: "+System.getProperty("os.version"));
            System.out.println("Averaging block = "+FrameBlock+" Frames");
            System.out.println("---------------------------------");
            System.out.print("        Frame\n");
            System.out.print("DeltaT  Delay      Lag\n");
            System.out.print("(ms)    (ms)       (ms)\n");
            System.out.print("------  ---------  -----------\n");
	    }
	    setLayout(new BorderLayout());
        GraphicsConfiguration config =
        SimpleUniverse.getPreferredConfiguration();
        canvas = new Canvas3D(config);
        canvas.stopRenderer();
	    add("Center", canvas);
	    // Create the universe and viewing branch
	    u = new SimpleUniverse(canvas);
        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        u.getViewingPlatform().setNominalViewingTransform();
	    // Start a new thread that will continuously render
	    new Thread(this).start();
    }

    public void destroy() 
    {   u.removeAllLocales();
    }

    //
    // The following allows PlanD_Immed to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {
	new MainFrame(new PlanD_Immed(), 256, 256);
    }
}