1.5 FPS Animator

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

1.5 FPS Animator

BrickFarmer
Now that JOGL is moving towards 1.5 Yipee!  I thought I'd share my FPS animator I've been using recently.  You can toggle between current implementation and this new one with the boolean at the top of the code 'useOwnAnimator'.  I wrote this primarily when JOGL was having some concurrency issues adding and removing drawables from animators (since fixed).  However I've still been using this implementation which I find gives a smoother frame rate, ymmv.  

For me, when I zoom out to show my whole game world, and hold a rotate key down, I can really see the difference between the two implementations.  With gl.setSwapInterval(1) also set it's even smoother! but then my 1st person mode seems to fail with mouse detection - work in progress :)

Peter

PS. tested under latest OSX with GLCanvs only




package com.brickfarmer.gameclient.widgets;

import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import javax.media.opengl.GLAutoDrawable;

import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.AnimatorBase;
import com.jogamp.opengl.util.FPSAnimator;

public final class WHAnimator {
    private static final boolean useOwnAnimator = true;
    private static final int fpsReportingPeriodSeconds = 5;
    private final CopyOnWriteArraySet<GLAutoDrawable> drawables = new CopyOnWriteArraySet<GLAutoDrawable>();
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    private final ScheduledExecutorService fpsCounter = Executors.newSingleThreadScheduledExecutor();
    private final int delayBetweenFramesMicroSeconds;
    private final AtomicBoolean animating = new AtomicBoolean(false);
    private final AtomicInteger frames = new AtomicInteger(0);
    private final AtomicInteger fps = new AtomicInteger(0);

    //old animator
    private AnimatorBase animator;
    private final AtomicInteger lastFrameCount = new AtomicInteger(0);

    Runnable displayJob = new Runnable() {
        public void run() {
            try {
                frames.incrementAndGet();
                for (GLAutoDrawable drawable : drawables) {
                    drawable.display();
                }
            } catch (RuntimeException r) {
                r.printStackTrace();
            }
        }
    };

    Runnable fpsJob = new Runnable() {
        public void run() {
            int frameCount;
            if (useOwnAnimator) {
                frameCount = frames.getAndSet(0);
            } else {
                int newFrameCount = animator.getTotalFrames();
                frameCount = newFrameCount - lastFrameCount.getAndSet(newFrameCount);
            }
            fps.set(frameCount/fpsReportingPeriodSeconds);
            System.out.println("Animator: "+drawables.size()+" scenes. "+frameCount+" frames in "+fpsReportingPeriodSeconds+"s. "+fps.get()+"fps");
        }
    };

    /**
     * Animate as fast as possible
     */
    public WHAnimator() {
        delayBetweenFramesMicroSeconds = 1;
        if (!useOwnAnimator) {
            animator = new Animator();
        }
    }

    /**
     * @param targetFramerate 60 means 60fps
     */
    public WHAnimator(final int targetFramerate) {
        delayBetweenFramesMicroSeconds = 1000000/targetFramerate;
        //System.out.println("delay between frames: "+delayBetweenFrames);
        if (!useOwnAnimator) {
            animator = new FPSAnimator(targetFramerate, true);
        }

    }

    public void add(final GLAutoDrawable drawable) {
        if (useOwnAnimator) {
            drawables.add(drawable);
        } else {
            animator.add(drawable);
        }
    }

    public void remove(final GLAutoDrawable drawable) {
        if (useOwnAnimator) {
            drawables.remove(drawable);
        } else {
            animator.remove(drawable);
        }
    }

    public void start() {
        fpsCounter.scheduleAtFixedRate(fpsJob, 0, fpsReportingPeriodSeconds, TimeUnit.SECONDS);
        if (useOwnAnimator) {
            scheduler.scheduleAtFixedRate(displayJob, 0, delayBetweenFramesMicroSeconds, TimeUnit.MICROSECONDS);
        } else {
            animator.start();
        }
        animating.set(true);

    }

    public void stop() {
        if (useOwnAnimator) {

        } else {
            animator.stop();
        }
        animating.set(false);
    }

    public boolean isAnimating() {
        return (useOwnAnimator) ? animating.get() : animator.isAnimating();
    }

    public int getFps() {
        return fps.get();
    }

}