diff options
Diffstat (limited to 'src/demos/util')
-rwxr-xr-x | src/demos/util/FPSCounter.java | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/src/demos/util/FPSCounter.java b/src/demos/util/FPSCounter.java new file mode 100755 index 0000000..b0ca200 --- /dev/null +++ b/src/demos/util/FPSCounter.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2007 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: + * + * - Redistribution 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 + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package demos.util; + +import java.awt.Font; +import java.awt.geom.*; +import java.text.*; + +import javax.media.opengl.*; +import com.sun.opengl.util.j2d.*; + +/** A simple class which uses the TextRenderer to provide an FPS + counter overlaid on top of the scene. */ + +public class FPSCounter { + // Placement constants + public static final int UPPER_LEFT = 1; + public static final int UPPER_RIGHT = 2; + public static final int LOWER_LEFT = 3; + public static final int LOWER_RIGHT = 4; + + private int textLocation = LOWER_RIGHT; + private GLDrawable drawable; + private TextRenderer renderer; + private DecimalFormat format = new DecimalFormat("####.00"); + private int frameCount; + private long startTime; + private String fpsText; + private int fpsMagnitude; + private int fpsWidth; + private int fpsHeight; + private int fpsOffset; + + /** Creates a new FPSCounter with the given font size. An OpenGL + context must be current at the time the constructor is called. + + @param drawable the drawable to render the text to + @param textSize the point size of the font to use + @throws GLException if an OpenGL context is not current when the constructor is called + */ + public FPSCounter(GLDrawable drawable, int textSize) throws GLException { + this(drawable, new Font("SansSerif", Font.BOLD, textSize)); + } + + /** Creates a new FPSCounter with the given font. An OpenGL context + must be current at the time the constructor is called. + + @param drawable the drawable to render the text to + @param font the font to use + @throws GLException if an OpenGL context is not current when the constructor is called + */ + public FPSCounter(GLDrawable drawable, Font font) throws GLException { + this(drawable, font, true, true); + } + + /** Creates a new FPSCounter with the given font and rendering + attributes. An OpenGL context must be current at the time the + constructor is called. + + @param drawable the drawable to render the text to + @param font the font to use + @param antialiased whether to use antialiased fonts + @param useFractionalMetrics whether to use fractional font + @throws GLException if an OpenGL context is not current when the constructor is called + */ + public FPSCounter(GLDrawable drawable, + Font font, + boolean antialiased, + boolean useFractionalMetrics) throws GLException { + this.drawable = drawable; + renderer = new TextRenderer(font, antialiased, useFractionalMetrics); + } + + /** Gets the relative location where the text of this FPSCounter + will be drawn: one of UPPER_LEFT, UPPER_RIGHT, LOWER_LEFT, or + LOWER_RIGHT. Defaults to LOWER_RIGHT. */ + public int getTextLocation() { + return textLocation; + } + + /** Sets the relative location where the text of this FPSCounter + will be drawn: one of UPPER_LEFT, UPPER_RIGHT, LOWER_LEFT, or + LOWER_RIGHT. Defaults to LOWER_RIGHT. */ + public void setTextLocation(int textLocation) { + if (textLocation < UPPER_LEFT || textLocation > LOWER_RIGHT) { + throw new IllegalArgumentException("textLocation"); + } + this.textLocation = textLocation; + } + + /** Changes the current color of this TextRenderer to the supplied + one, where each component ranges from 0.0f - 1.0f. The alpha + component, if used, does not need to be premultiplied into the + color channels as described in the documentation for {@link + Texture Texture}, although premultiplied colors are used + internally. The default color is opaque white. + + @param r the red component of the new color + @param g the green component of the new color + @param b the blue component of the new color + @param alpha the alpha component of the new color, 0.0f = + completely transparent, 1.0f = completely opaque + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setColor(float r, float g, float b, float a) throws GLException { + renderer.setColor(r, g, b, a); + } + + /** Updates the FPSCounter's internal timer and counter and draws + the computed FPS. It is assumed this method will be called only + once per frame. + */ + public void draw() { + if (startTime == 0) { + startTime = System.currentTimeMillis(); + } + + if (++frameCount >= 100) { + long endTime = System.currentTimeMillis(); + float fps = 100.0f / (float) (endTime - startTime) * 1000; + recomputeFPSSize(fps); + frameCount = 0; + startTime = System.currentTimeMillis(); + + fpsText = "FPS: " + format.format(fps); + } + + if (fpsText != null) { + renderer.beginRendering(drawable.getWidth(), drawable.getHeight()); + // Figure out the location at which to draw the text + int x = 0; + int y = 0; + switch (textLocation) { + case UPPER_LEFT: + x = fpsOffset; + y = drawable.getHeight() - fpsHeight - fpsOffset; + break; + + case UPPER_RIGHT: + x = drawable.getWidth() - fpsWidth - fpsOffset; + y = drawable.getHeight() - fpsHeight - fpsOffset; + break; + + case LOWER_LEFT: + x = fpsOffset; + y = fpsOffset; + break; + + case LOWER_RIGHT: + x = drawable.getWidth() - fpsWidth - fpsOffset; + y = fpsOffset; + break; + } + + renderer.draw(fpsText, x, y); + renderer.endRendering(); + } + } + + private void recomputeFPSSize(float fps) { + String fpsText; + int fpsMagnitude; + if (fps >= 10000) { + fpsText = "10000.00"; + fpsMagnitude = 5; + } else if (fps >= 1000) { + fpsText = "1000.00"; + fpsMagnitude = 4; + } else if (fps >= 100) { + fpsText = "100.00"; + fpsMagnitude = 3; + } else if (fps >= 10) { + fpsText = "10.00"; + fpsMagnitude = 2; + } else { + fpsText = "9.00"; + fpsMagnitude = 1; + } + + if (fpsMagnitude > this.fpsMagnitude) { + Rectangle2D bounds = renderer.getBounds("FPS: " + fpsText); + fpsWidth = (int) bounds.getWidth(); + fpsHeight = (int) bounds.getHeight(); + fpsOffset = (int) (fpsHeight * 0.5f); + this.fpsMagnitude = fpsMagnitude; + } + } +} |