java left logo
java middle logo
java right logo
 

Home arrow Other API Tips arrow Java3D arrow How to create a frames per second counter
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Java Network
Java Forums
Java Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 4089
Java SE Tips: 614
Java ME Tips: 202
Java EE Tips: 183
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
How to create a frames per second counter E-mail
User Rating: / 11
PoorBest 

This Java 3D program demonstrates the use of the frames per second counter. The program displays a rotating cube and sets up the FPSCounter to compute the frame rate. The FPSCounter is set up with default values: - run indefinitely - 2 sec. warmup time - display average frame rate every fifth sampling interval. The default values can be changed through the command line arguments. Use FPSCounterDemo -h for help on the various arguments.


Image

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.text.NumberFormat;

import javax.media.j3d.Alpha;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.swing.JOptionPane;
import javax.vecmath.Point3d;

import com.sun.j3d.utils.applet.JMainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * This program demonstrates the use of the frames per second counter. The
 * program displays a rotating cube and sets up the FPSCounter to compute the
 * frame rate. The FPSCounter is set up with default values: - run indefinitely -
 * 2 sec. warmup time - display average frame rate every fifth sampling
 * interval. The default values can be changed through the command line
 * arguments. Use FPSCounterDemo -h for help on the various arguments.
 */

public class FPSCounterDemo extends Applet {
  private SimpleUniverse u = null;

  \private FPSCounter fpsCounter = new FPSCounter();

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

    // Create the TransformGroup node and initialize it to the
    // identity. Enable the TRANSFORM_WRITE capability so that
    // our behavior code can modify it at run time. Add it to
    // the root of the subgraph.
    TransformGroup objTrans = new TransformGroup();
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objRoot.addChild(objTrans);

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

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

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

    // Create the Framecounter behavior
    fpsCounter.setSchedulingBounds(bounds);
    objRoot.addChild(fpsCounter);

    return objRoot;
  }

  public FPSCounterDemo(String args[]) {
  }

  public FPSCounterDemo() {
  }

  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();

    // Parse the command line to set the various parameters

    // Have Java 3D perform optimizations on this scene graph.
    scene.compile();
    u = new SimpleUniverse(c);

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

    u.addBranchGraph(scene);

    JOptionPane
        .showMessageDialog(
            this,
            "\nThis program measures the number of frames rendered per second.\nNote that"+
      " the frame rate is limited by the refresh rate of the monitor.\nTo get the"+
      " true frame rate you need to disable vertical retrace.\n\nOn Windows(tm) you"+
      " do this through the Control Panel.\n\nOn Unix set the environment variable"+
      " OGL_NO_VBLANK\n(i.e. type \"setenv OGL_NO_VBLANK\" at the command prompt)",
            "Frame Counter", JOptionPane.INFORMATION_MESSAGE);
  }

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

  //
  // The following allows FPSCounterDemo to be run as an application
  // as well as an applet
  //
  public static void main(String[] args) {
    FPSCounterDemo fp = new FPSCounterDemo();
    fp.parseArgs(args);
    JMainFrame frame = new JMainFrame(fp, 256256);
  }

  /**
   * Parses the commandline for the various switches to set the FPSCounter
   * variables. All arguments are of the form <i>-name value </i>. All -name
   * arguments can be shortened to one character. All the value arguments take
   * a number. The arguments accepted are :
   <ul>
   <li>warmupTime : Specifies amount of time the FPSCounter should wait for
   * the HotSpot <sup><font size="-2">TM </font> </sup> VM to perform initial
   * optimizations. Specified in milliseconds <br>
   <li>loopCount : Specifies the number of sampling intervals over which
   * the FPSCounter should calculate the aggregate and average frame rate.
   * Specified as a count. <br>
   <li>maxLoops : Specifies that the FPSCounter should run for only these
   * many sampling intervals. Specified as number. If this argument is not
   * specified, the FPSCounter runs indefinitely. <br>
   <li>help : Prints the accepted arguments. <br>
   </ul>
   */

  private void parseArgs(String args[]) {
    for (int i = 0; i < args.length; i++) {
      if (args[i].startsWith("-")) {
        if (args[i].startsWith("w"1)) {
          i++;
          System.out.println("Warmup time : " + args[i]);
          int w = new Integer(args[i]).intValue();
          fpsCounter.setWarmupTime(w);
        else if (args[i].startsWith("l"1)) {
          i++;
          System.out.println("Loop count : " + args[i]);
          int l = new Integer(args[i]).intValue();
          fpsCounter.setLoopCount(l);
        else if (args[i].startsWith("m"1)) {
          i++;
          System.out.println("Max Loop Count : " + args[i]);
          int m = new Integer(args[i]).intValue();
          fpsCounter.setMaxLoops(m);
        else if (args[i].startsWith("h"1)) {
          System.out.println("Usage : FPSCounterDemo [-name value]\n All arguments are"+
      " of the form -name value. All -name arguments can be shortened to one"+
    " character. All the value arguments take a number. The arguments accepted"+
    " are :\n  warmupTime : Specifies amount of time the FPSCounter should wait"+
    " for the HotSpot(tm) VM to perform initial optimizations. Specified in "+
    "milliseconds\n  loopCount : Specifies the number of sampling intervals "+
    "over which the FPSCounter should calculate the aggregate and average"+
    " frame rate. Specified as a count\n  maxLoops : Specifies that the"+
    " FPSCounter should run for only these many sampling intervals. Specified"+
    " as number. If this argument is not specified, the FPSCounter runs"+
    " indefinitely.\n  help : Prints this message.");
        }
      }
    }
  }

}

/**
 * This behavior calculates the frame rate and average frame rate of a Java3D
 * application. The behavior sets itself up to wakeup every time a new frame is
 * rendered.
 
 <p>
 * The HotSpot(tm) compiler performs some initial optimizations before running
 * at optimal speed. Frame rates measured during this warmup period will be
 * inaccurate and not indicative of the true performance of the the application.
 * Therefore, before beginning the frame rate computation, the frame counter
 * waits for a fixed time period to allow the HotSpot(tm) compiler to
 * stablilize.
 
 <p>
 * To avoid computing the frame rate too frequently (which would also hamper
 * rendering performance), the frame counter only computes the frame rate at
 * fixed time intervals. The default sampling duration is 10 seconds. After
 * waiting for the warmup period, the frame counter needs to calibrate itself.
 * It computes the number of frames rendered during the sampling period. After
 * doing this calibration, the frame counter reports the frame rate after these
 * many frames are rendered. It also reports the average frame rate after a
 * fixed number of sampling intervals (the default is 5).
 
 <p>
 * The frame counter can be set up to run for a fixed number of sampling
 * intervals or to run indefinitely. The defaultis to run indefinitely.
 */

class FPSCounter extends Behavior {
  // Wakeup condition - framecount = 0 -> wakeup on every frame
  WakeupOnElapsedFrames FPSwakeup = new WakeupOnElapsedFrames(0);

  // Do calibration for these many millisec
  private static final long testduration = 1000;

  // Report frame rate after every sampleduration milliseconds
  private static final long sampleduration = 10000;

  // Flag to indicate that it is time to (re)calibrate
  private boolean doCalibration = true;

  // Flag to indicate the counter has started
  private boolean startup = true;

  // Wait for HotSpot compiler to perform optimizations
  private boolean warmup = true;

  // Time to wait for HotSpot compiler to stabilize (in milliseconds)
  private long warmupTime = 20000;

  // Counter for number of frames rendered
  private int numframes = 0;

  // Report frame rate after maxframe number of frames have been rendered
  private int maxframes = 1;

  // Variables to keep track of elapsed time
  private long startuptime = 0;

  private long currtime = 0;

  private long lasttime = 0;

  private long deltatime;

  // Run indefinitely or for a fixed duration
  private boolean finiteLoop = false;

  // No. of sampling intervals to run for if not running indefinitely
  private long maxLoops;

  // No. of sampling intervals run for so far
  private long numLoops = 0;

  // Total number of frames rendered so far
  private int sumFrames = 0;

  // Total time since last reporting of average frame rate
  private long sumTimes = 0;

  // Counts no. of sampling intervals
  private int loop = 0;

  // Average frame rate is reported after loopCount number of
  // sampling intervals
  private int loopCount = 5;

  private double sumFps = 0.0;

  private String symbol[] "\\""|""|""/""-""|""-" };

  int index = 0;

  private NumberFormat nf = null;

  public FPSCounter() {
    setEnable(true);
    nf = NumberFormat.getNumberInstance();
  }

  // Called to init the behavior
  public void initialize() {
    // Set the trigger for the behavior to wakeup on every frame rendered
    wakeupOn(FPSwakeup);
  }

  // Called every time the behavior is activated
  public void processStimulus(java.util.Enumeration critera) {
    // Apply calibration algorithm to determine number of frames to
    // wait before computing frames per second.
    // sampleduration = 10000 -> to run test, pass for 10 seconds.

    if (doCalibration) { // start calibration
      if (startup) {
        // Record time at which the behavior was first invoked
        startuptime = System.currentTimeMillis();
        startup = false;
      else if (warmup) { // Wait for the system to stabilize.
        System.out.print("\rFPSCounter warming up..."
            + symbol[(index++% symbol.length]);
        currtime = System.currentTimeMillis();
        deltatime = currtime - startuptime;
        if (deltatime > warmupTime) {
          // Done waiting for warmup
          warmup = false;
          lasttime = System.currentTimeMillis();
          System.out.println("\rFPSCounter warming up...Done");
        }
      else {
        numframes += 1;
        // Wait till at least maxframe no. of frames have been rendered
        if (numframes >= maxframes) {
          currtime = System.currentTimeMillis();
          deltatime = currtime - lasttime;
          // Do the calibration for testduration no. of millisecs
          if (deltatime > testduration) {
            // Compute total no. of frames rendered so far in the
            // current sampling duration
            maxframes = (intMath
                .ceil((doublenumframes
                    ((doublesampleduration / (doubledeltatime));

            // Done with calibration
            doCalibration = false;
            // reset the value for the measurement
            numframes = 0;
            lasttime = System.currentTimeMillis();
          else {
            // Need to run the calibration routine for some more
            // time. Increase the no. of frames to be rendered
            maxframes *= 2;
          }
        }
      }
    else // do the measurement
      numframes += 1;
      if (numframes >= maxframes) {
        currtime = System.currentTimeMillis();
        deltatime = currtime - lasttime;
        // time is in millisec, so multiply by 1000 to get frames/sec
        double fps = (doublenumframes / ((doubledeltatime / 1000.0);

        System.out.println("Frame Rate : \n\tNo. of frames : "
            + numframes + "\n\tTime : "
            ((doubledeltatime / 1000.0" sec."
            "\n\tFrames/sec : " + nf.format(fps));

        // Calculate average frame rate
        sumFrames += numframes;
        sumTimes += deltatime;
        sumFps += fps;
        loop++;
        if (loop >= loopCount) {
          double avgFps = (doublesumFrames * 1000.0
              (doublesumTimes;
          double ravgFps = sumFps / (doubleloopCount;
          System.out.println("Aggregate frame rate "
              + nf.format(avgFps" frames/sec");
          System.out.println("Average frame rate "
              + nf.format(ravgFps" frames/sec");
          numLoops++;
          if (finiteLoop && numLoops >= maxLoops) {
            System.out
                .println("************** The End **************\n");
            setEnable(false);
          }
          loop = 0;
          sumFps = 0;
        }
        numframes = 0;
        lasttime = System.currentTimeMillis();
        ;
      }
    }
    // Set the trigger for the behavior
    wakeupOn(FPSwakeup);
  }

  /**
   * The frame counter waits for some time before computing the frame rate.
   * This allows the HotSpot compiler to perform initial optimizations. The
   * amount of time to wait for is set by this method. The default is 20000
   * (20 sec)
   
   @param Amount
   *            of time to wait for before computing frame rate (specified in
   *            milliseconds)
   */
  public void setWarmupTime(long wt) {
    warmupTime = wt;
  }

  /**
   * Sets the number of sampling intervals to wait for before computing the
   * average frame rate. The default is 5.
   
   @param No.
   *            of sampling intervals over which to compute frame rate. A
   *            value of 0 implies the average frame rate is computed over one
   *            sampling interval
   */
  public void setLoopCount(int lc) {
    loopCount = lc;
  }

  /**
   * This method sets the number of sampling intervals for which the frame
   * counter should run.
   
   @param No.
   *            of sampling intervals to run for
   */
  public void setMaxLoops(int ml) {
    maxLoops = ml;
    finiteLoop = true;
  }

}

 Related Tips

 
< Prev   Next >

Page 1 of 0 ( 0 comments )

You can share your information about this topic using the form below!

Please do not post your questions with this form! Thanks.


Name (required)


E-Mail (required)

Your email will not be displayed on the site - only to our administrator
Homepage(optional)



Comment Enable HTML code : Yes No



 
       
         
     
 
 
 
   
 
 
java bottom left
java bottom middle
java bottom right
RSS 0.91 FeedRSS 1.0 FeedRSS 2.0 FeedATOM FeedOPML Feed

Home - About Us - Privacy Policy
Copyright 2005 - 2008 www.java-tips.org
Java is a trademark of Sun Microsystems, Inc.