diff --git a/common.gradle b/common.gradle
index c225588c4..237ee5e7f 100644
--- a/common.gradle
+++ b/common.gradle
@@ -16,9 +16,6 @@ repositories {
maven {
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
}
- maven {
- url "https://oss.sonatype.org/content/repositories/snapshots"
- }
}
configurations {
diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
index 6e83e0e6b..53898883c 100644
--- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
+++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
@@ -124,6 +124,42 @@ public final class NativeLibraryLoader {
}
static {
+ // LWJGL
+ registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll");
+ registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll");
+ registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so");
+ registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so");
+ registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
+ registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
+
+ // OpenAL
+ // For OSX: Need to add lib prefix when extracting
+ registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll");
+ registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll");
+ registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so");
+ registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so");
+ registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
+ registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
+
+ // LWJGL 3.x
+ registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/lwjgl32.dll");
+ registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/lwjgl.dll");
+ registerNativeLibrary("lwjgl3", Platform.Linux32, "native/linux/liblwjgl32.so");
+ registerNativeLibrary("lwjgl3", Platform.Linux64, "native/linux/liblwjgl.so");
+ registerNativeLibrary("lwjgl3", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
+ registerNativeLibrary("lwjgl3", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
+ registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll");
+ registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll");
+
+ // OpenAL for LWJGL 3.x
+ // For OSX: Need to add lib prefix when extracting
+ registerNativeLibrary("openal-lwjgl3", Platform.Windows32, "native/windows/OpenAL32.dll");
+ registerNativeLibrary("openal-lwjgl3", Platform.Windows64, "native/windows/OpenAL.dll");
+ registerNativeLibrary("openal-lwjgl3", Platform.Linux32, "native/linux/libopenal32.so");
+ registerNativeLibrary("openal-lwjgl3", Platform.Linux64, "native/linux/libopenal.so");
+ registerNativeLibrary("openal-lwjgl3", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
+ registerNativeLibrary("openal-lwjgl3", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
+
// BulletJme
registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll");
registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll");
diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
index 415084788..802b12a0f 100644
--- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
+++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
@@ -206,7 +206,6 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
+ "Must set with JmeContext.setSystemListner().");
}
- registerNatives();
loadNatives();
logger.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
if (!initInThread()) {
diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index 70885c39b..ee12d1fea 100644
--- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -162,26 +162,7 @@ public abstract class LwjglContext implements JmeContext {
}
}
}
-
- protected void registerNatives() {
- // LWJGL
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
-
- // For OSX: Need to add lib prefix when extracting
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
- }
-
- protected void loadNatives() {
+ protected void loadNatives() {
if (JmeSystem.isLowPermissions()) {
return;
}
diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle
index c9b43e0de..3c7e4e646 100644
--- a/jme3-lwjgl3/build.gradle
+++ b/jme3-lwjgl3/build.gradle
@@ -2,6 +2,12 @@ if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
+repositories {
+ maven {
+ url "https://oss.sonatype.org/content/repositories/snapshots"
+ }
+}
+
dependencies {
compile project(':jme3-core')
compile project(':jme3-desktop')
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
deleted file mode 100644
index 1f1ef2ab5..000000000
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions 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 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.system.lwjgl;
-
-import com.jme3.system.AppSettings;
-import com.jme3.system.JmeCanvasContext;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
-
-public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext {
-
- protected static final int TASK_NOTHING = 0,
- TASK_DESTROY_DISPLAY = 1,
- TASK_CREATE_DISPLAY = 2,
- TASK_COMPLETE = 3;
-
-// protected static final boolean USE_SHARED_CONTEXT =
-// Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true"));
-
- protected static final boolean USE_SHARED_CONTEXT = false;
-
- private static final Logger logger = Logger.getLogger(LwjglCanvas.class.getName());
- private Canvas canvas;
- private int width;
- private int height;
-
- private final Object taskLock = new Object();
- private int desiredTask = TASK_NOTHING;
-
- private Thread renderThread;
- private boolean runningFirstTime = true;
- private boolean mouseWasGrabbed = false;
-
- private boolean mouseWasCreated = false;
- private boolean keyboardWasCreated = false;
-
- private long window;
-
- private class GLCanvas extends Canvas {
- @Override
- public void addNotify(){
- super.addNotify();
-
- if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) {
- return; // already destroyed.
- }
-
- if (renderThread == null){
- logger.log(Level.FINE, "EDT: Creating OGL thread.");
-
- // Also set some settings on the canvas here.
- // So we don't do it outside the AWT thread.
- canvas.setFocusable(true);
- canvas.setIgnoreRepaint(true);
-
- renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
- renderThread.start();
- }else if (needClose.get()){
- return;
- }
-
- logger.log(Level.FINE, "EDT: Telling OGL to create display ..");
- synchronized (taskLock){
- desiredTask = TASK_CREATE_DISPLAY;
-// while (desiredTask != TASK_COMPLETE){
-// try {
-// taskLock.wait();
-// } catch (InterruptedException ex) {
-// return;
-// }
-// }
-// desiredTask = TASK_NOTHING;
- }
-// logger.log(Level.FINE, "EDT: OGL has created the display");
- }
-
- @Override
- public void removeNotify(){
- if (needClose.get()){
- logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas.");
- super.removeNotify();
- return;
- }
-
- // We must tell GL context to shutdown and wait for it to
- // shutdown, otherwise, issues will occur.
- logger.log(Level.FINE, "EDT: Telling OGL to destroy display ..");
- synchronized (taskLock){
- desiredTask = TASK_DESTROY_DISPLAY;
- while (desiredTask != TASK_COMPLETE){
- try {
- taskLock.wait();
- } catch (InterruptedException ex){
- super.removeNotify();
- return;
- }
- }
- desiredTask = TASK_NOTHING;
- }
-
- logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death");
- // GL context is dead at this point
-
- super.removeNotify();
- }
- }
-
- public LwjglCanvas(){
- super(Type.Canvas);
- canvas = new GLCanvas();
- }
-
- public void create(boolean waitFor){
- if (renderThread == null){
- logger.log(Level.FINE, "MAIN: Creating OGL thread.");
-
- renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
- renderThread.start();
- }
- // do not do anything.
- // superclass's create() will be called at initInThread()
- if (waitFor) {
- waitFor(true);
- }
- }
-
- public Canvas getCanvas(){
- return canvas;
- }
-
- @Override
- protected void runLoop(){
- if (desiredTask != TASK_NOTHING){
- synchronized (taskLock){
- switch (desiredTask){
- case TASK_CREATE_DISPLAY:
- logger.log(Level.FINE, "OGL: Creating display ..");
- restoreCanvas();
- listener.gainFocus();
- desiredTask = TASK_NOTHING;
- break;
- case TASK_DESTROY_DISPLAY:
- logger.log(Level.FINE, "OGL: Destroying display ..");
- listener.loseFocus();
- pauseCanvas();
- break;
- }
- desiredTask = TASK_COMPLETE;
- taskLock.notifyAll();
- }
- }
-
- if (renderable.get()){
- int newWidth = Math.max(canvas.getWidth(), 1);
- int newHeight = Math.max(canvas.getHeight(), 1);
-
- if (width != newWidth || height != newHeight){
- width = newWidth;
- height = newHeight;
- if (listener != null){
- listener.reshape(width, height);
- }
- }
- }
-
- super.runLoop();
- }
-
- private void pauseCanvas(){
- if (mouseInput != null) {
- mouseInput.setCursorVisible(true);
- mouseWasCreated = true;
- }
-
-/*
- if (Mouse.isCreated()){
- if (Mouse.isGrabbed()){
- Mouse.setGrabbed(false);
- mouseWasGrabbed = true;
- }
- mouseWasCreated = true;
- Mouse.destroy();
- }
- if (Keyboard.isCreated()){
- keyboardWasCreated = true;
- Keyboard.destroy();
- }
-*/
-
- renderable.set(false);
- destroyContext();
- }
-
- /**
- * Called to restore the canvas.
- */
- private void restoreCanvas(){
- logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable..");
- while (!canvas.isDisplayable()){
- try {
- Thread.sleep(10);
- } catch (InterruptedException ex) {
- logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
- }
- }
-
- logger.log(Level.FINE, "OGL: Creating display context ..");
-
- // Set renderable to true, since canvas is now displayable.
- renderable.set(true);
- createContext(settings);
-
- logger.log(Level.FINE, "OGL: Display is active!");
-
- try {
- if (mouseWasCreated){
-// Mouse.create();
-// if (mouseWasGrabbed){
-// Mouse.setGrabbed(true);
-// mouseWasGrabbed = false;
-// }
- }
- if (keyboardWasCreated){
-// Keyboard.create();
-// keyboardWasCreated = false;
- }
- } catch (Exception ex){
- logger.log(Level.SEVERE, "Encountered exception when restoring input", ex);
- }
-
- SwingUtilities.invokeLater(new Runnable(){
- public void run(){
- canvas.requestFocus();
- }
- });
- }
-
-/*
- */
-/**
- * Makes sure the pbuffer is available and ready for use
- *//*
-
- protected void makePbufferAvailable() throws LWJGLException{
- if (pbuffer != null && pbuffer.isBufferLost()){
- logger.log(Level.WARNING, "PBuffer was lost!");
- pbuffer.destroy();
- pbuffer = null;
- }
-
- if (pbuffer == null) {
- pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null);
- pbuffer.makeCurrent();
- logger.log(Level.FINE, "OGL: Pbuffer has been created");
-
- // Any created objects are no longer valid
- if (!runningFirstTime){
- renderer.resetGLObjects();
- }
- }
-
- pbuffer.makeCurrent();
- if (!pbuffer.isCurrent()){
- throw new LWJGLException("Pbuffer cannot be made current");
- }
- }
-
- protected void destroyPbuffer(){
- if (pbuffer != null){
- if (!pbuffer.isBufferLost()){
- pbuffer.destroy();
- }
- pbuffer = null;
- }
- }
-*/
-
- /**
- * This is called:
- * 1) When the context thread ends
- * 2) Any time the canvas becomes non-displayable
- */
- protected void destroyContext(){
- // invalidate the state so renderer can resume operation
- if (!USE_SHARED_CONTEXT){
- renderer.cleanup();
- }
-
- if (window != 0) {
- glfwDestroyWindow(window);
- }
-
- // TODO: Destroy input
-
-
- // The canvas is no longer visible,
- // but the context thread is still running.
- if (!needClose.get()){
- renderer.invalidateState();
- }
- }
-
- /**
- * This is called:
- * 1) When the context thread starts
- * 2) Any time the canvas becomes displayable again.
- */
- @Override
- protected void createContext(final AppSettings settings) {
- // In case canvas is not visible, we still take framerate
- // from settings to prevent "100% CPU usage"
- allowSwapBuffers = settings.isSwapBuffers();
-
- if (renderable.get()){
- if (!runningFirstTime){
- // because the display is a different opengl context
- // must reset the context state.
- if (!USE_SHARED_CONTEXT){
- renderer.cleanup();
- }
- }
-
- super.createContext(settings);
- }
-
- // At this point, the OpenGL context is active.
- if (runningFirstTime) {
- // THIS is the part that creates the renderer.
- // It must always be called, now that we have the pbuffer workaround.
- initContextFirstTime();
- runningFirstTime = false;
- }
- }
-}
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index 86b6a294a..7f62a447e 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -98,41 +98,20 @@ public abstract class LwjglContext implements JmeContext {
return Integer.MAX_VALUE;
}
- protected void registerNatives() {
- // LWJGL
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl32.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl32.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/jemalloc32.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/jemalloc.dll");
-
- // OpenAL
- // For OSX: Need to add lib prefix when extracting
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal32.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
- }
-
protected void loadNatives() {
if (JmeSystem.isLowPermissions()) {
return;
}
if ("LWJGL".equals(settings.getAudioRenderer())) {
- NativeLibraryLoader.loadNativeLibrary("openal", true);
+ NativeLibraryLoader.loadNativeLibrary("openal-lwjgl3", true);
}
if (NativeLibraryLoader.isUsingNativeBullet()) {
NativeLibraryLoader.loadNativeLibrary("bulletjme", true);
}
- NativeLibraryLoader.loadNativeLibrary("lwjgl", true);
+ NativeLibraryLoader.loadNativeLibrary("lwjgl3", true);
}
protected int getNumSamplesToUse() {
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java
deleted file mode 100644
index a7960a261..000000000
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions 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 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.system.lwjgl;
-
-import com.jme3.math.FastMath;
-import com.jme3.system.Timer;
-import org.lwjgl.glfw.GLFW;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Timer
handles the system's time related functionality. This
- * allows the calculation of the framerate. To keep the framerate calculation
- * accurate, a call to update each frame is required. Timer
is a
- * singleton object and must be created via the getTimer
method.
- *
- * @author Mark Powell
- * @version $Id: LWJGLTimer.java,v 1.21 2007/09/22 16:46:35 irrisor Exp $
- */
-public class LwjglSmoothingTimer extends LwjglTimer {
- private static final Logger logger = Logger.getLogger(LwjglSmoothingTimer.class
- .getName());
-
- private long lastFrameDiff;
-
- //frame rate parameters.
- private long oldTime;
-
- private float lastTPF, lastFPS;
-
- public static int TIMER_SMOOTHNESS = 32;
-
- private long[] tpf;
-
- private int smoothIndex;
-
- private final static long LWJGL_TIMER_RES = 1;
- private final static float INV_LWJGL_TIMER_RES = ( 1f / LWJGL_TIMER_RES );
- private static float invTimerRezSmooth;
-
- public final static long LWJGL_TIME_TO_NANOS = (1000000000 / LWJGL_TIMER_RES);
-
- private long startTime;
-
- private boolean allSmooth = false;
-
- /**
- * Constructor builds a Timer
object. All values will be
- * initialized to it's default values.
- */
- public LwjglSmoothingTimer() {
- reset();
-
- //print timer resolution info
- logger.log(Level.FINE, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES);
- }
-
- public void reset() {
- lastFrameDiff = 0;
- lastFPS = 0;
- lastTPF = 0;
-
- // init to -1 to indicate this is a new timer.
- oldTime = -1;
- //reset time
- startTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS);
-
- tpf = new long[TIMER_SMOOTHNESS];
- smoothIndex = TIMER_SMOOTHNESS - 1;
- invTimerRezSmooth = ( 1f / (LWJGL_TIMER_RES * TIMER_SMOOTHNESS));
-
- // set tpf... -1 values will not be used for calculating the average in update()
- for ( int i = tpf.length; --i >= 0; ) {
- tpf[i] = -1;
- }
- }
-
- /**
- * @see Timer#getResolution()
- */
- public long getResolution() {
- return LWJGL_TIMER_RES;
- }
-
- /**
- * getFrameRate
returns the current frame rate since the last
- * call to update
.
- *
- * @return the current frame rate.
- */
- public float getFrameRate() {
- return lastFPS;
- }
-
- public float getTimePerFrame() {
- return lastTPF;
- }
-
- /**
- * update
recalulates the frame rate based on the previous
- * call to update. It is assumed that update is called each frame.
- */
- public void update() {
- long newTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS);
- long oldTime = this.oldTime;
- this.oldTime = newTime;
- if ( oldTime == -1 ) {
- // For the first frame use 60 fps. This value will not be counted in further averages.
- // This is done so initialization code between creating the timer and the first
- // frame is not counted as a single frame on it's own.
- lastTPF = 1 / 60f;
- lastFPS = 1f / lastTPF;
- return;
- }
-
- long frameDiff = newTime - oldTime;
- long lastFrameDiff = this.lastFrameDiff;
- if ( lastFrameDiff > 0 && frameDiff > lastFrameDiff *100 ) {
- frameDiff = lastFrameDiff *100;
- }
- this.lastFrameDiff = frameDiff;
- tpf[smoothIndex] = frameDiff;
- smoothIndex--;
- if ( smoothIndex < 0 ) {
- smoothIndex = tpf.length - 1;
- }
-
- lastTPF = 0.0f;
- if (!allSmooth) {
- int smoothCount = 0;
- for ( int i = tpf.length; --i >= 0; ) {
- if ( tpf[i] != -1 ) {
- lastTPF += tpf[i];
- smoothCount++;
- }
- }
- if (smoothCount == tpf.length)
- allSmooth = true;
- lastTPF *= ( INV_LWJGL_TIMER_RES / smoothCount );
- } else {
- for ( int i = tpf.length; --i >= 0; ) {
- if ( tpf[i] != -1 ) {
- lastTPF += tpf[i];
- }
- }
- lastTPF *= invTimerRezSmooth;
- }
- if ( lastTPF < FastMath.FLT_EPSILON ) {
- lastTPF = FastMath.FLT_EPSILON;
- }
-
- lastFPS = 1f / lastTPF;
- }
-
- /**
- * toString
returns the string representation of this timer
- * in the format:
- *
- * jme.utility.Timer@1db699b
- * Time: {LONG}
- * FPS: {LONG}
- *
- * @return the string representation of this object.
- */
- @Override
- public String toString() {
- String string = super.toString();
- string += "\nTime: " + oldTime;
- string += "\nFPS: " + getFrameRate();
- return string;
- }
-}
\ No newline at end of file
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
deleted file mode 100644
index c4a0e5025..000000000
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions 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 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.system.lwjgl;
-
-import com.jme3.system.Timer;
-import org.lwjgl.glfw.GLFW;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Timer
handles the system's time related functionality. This
- * allows the calculation of the framerate. To keep the framerate calculation
- * accurate, a call to update each frame is required. Timer
is a
- * singleton object and must be created via the getTimer
method.
- *
- * @author Mark Powell
- * @version $Id: LWJGLTimer.java,v 1.21 2007/09/22 16:46:35 irrisor Exp $
- */
-public class LwjglTimer extends Timer {
-
- private static final Logger logger = Logger.getLogger(LwjglTimer.class.getName());
-
- //frame rate parameters.
- private long oldTime;
- private long startTime;
-
- private float lastTPF, lastFPS;
-
- private final static long LWJGL_TIMER_RES = 1;
- private final static float INV_LWJGL_TIMER_RES = ( 1f / LWJGL_TIMER_RES );
- public final static long LWJGL_TIME_TO_NANOS = (1000000000 / LWJGL_TIMER_RES);
-
- /**
- * Constructor builds a Timer
object. All values will be
- * initialized to it's default values.
- */
- public LwjglTimer() {
- reset();
- logger.log(Level.FINE, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES);
- }
-
- public void reset() {
- startTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS);
- oldTime = getTime();
- }
-
- @Override
- public float getTimeInSeconds() {
- return getTime() * INV_LWJGL_TIMER_RES;
- }
-
- /**
- * @see Timer#getTime()
- */
- public long getTime() {
- return ((long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS) - startTime);
- }
-
- /**
- * @see Timer#getResolution()
- */
- public long getResolution() {
- return LWJGL_TIMER_RES;
- }
-
- /**
- * getFrameRate
returns the current frame rate since the last
- * call to update
.
- *
- * @return the current frame rate.
- */
- public float getFrameRate() {
- return lastFPS;
- }
-
- public float getTimePerFrame() {
- return lastTPF;
- }
-
- /**
- * update
recalulates the frame rate based on the previous
- * call to update. It is assumed that update is called each frame.
- */
- public void update() {
- long curTime = getTime();
- lastTPF = (curTime - oldTime) * (1.0f / LWJGL_TIMER_RES);
- lastFPS = 1.0f / lastTPF;
- oldTime = curTime;
- }
-
- /**
- * toString
returns the string representation of this timer
- * in the format:
- *
- * jme.utility.Timer@1db699b
- * Time: {LONG}
- * FPS: {LONG}
- *
- * @return the string representation of this object.
- */
- @Override
- public String toString() {
- String string = super.toString();
- string += "\nTime: " + oldTime;
- string += "\nFPS: " + getFrameRate();
- return string;
- }
-}
\ No newline at end of file
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
index c5cb35e03..2f00eb700 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
@@ -42,6 +42,7 @@ import com.jme3.input.lwjgl.GlfwMouseInput;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeSystem;
+import com.jme3.system.NanoTimer;
import org.lwjgl.Sys;
import org.lwjgl.glfw.*;
@@ -73,6 +74,8 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
protected boolean allowSwapBuffers = false;
private long window = -1;
private final JmeContext.Type type;
+ private int frameRateLimit = -1;
+ private double frameSleepTime;
private GLFWErrorCallback errorCallback;
private GLFWWindowSizeCallback windowSizeCallback;
@@ -160,16 +163,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits());
glfwWindowHint(GLFW_SAMPLES, settings.getSamples());
glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GL_TRUE : GL_FALSE);
-
- int frameRateCap = settings.getFrameRate();
-
- if (!autoFlush) {
- frameRateCap = 20;
- }
-
- if (frameRateCap > 0) {
- glfwWindowHint(GLFW_REFRESH_RATE, frameRateCap);
- }
+ glfwWindowHint(GLFW_REFRESH_RATE, settings.getFrequency());
// Not sure how else to support bits per pixel
if (settings.getBitsPerPixel() == 24) {
@@ -289,7 +283,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
});
}
- timer = new LwjglTimer();
+ timer = new NanoTimer();
// For canvas, this will create a pbuffer,
// allowing us to query information.
@@ -303,7 +297,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
} catch (Exception ex) {
try {
if (window != -1) {
- //glfwSetWindowShouldClose(window, GL_TRUE);
glfwDestroyWindow(window);
}
} catch (Exception ex2) {
@@ -360,11 +353,41 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
if (renderer != null) {
renderer.postFrame();
}
+
+ if (autoFlush) {
+ if (frameRateLimit != getSettings().getFrameRate()) {
+ setFrameRateLimit(getSettings().getFrameRate());
+ }
+ } else if (frameRateLimit != 20) {
+ setFrameRateLimit(20);
+ }
+
+ // If software frame rate limiting has been asked for, lets calculate sleep time based on a base value calculated
+ // from 1000 / frameRateLimit in milliseconds subtracting the time it has taken to render last frame.
+ // This gives an approximate limit within 3 fps of the given frame rate limit.
+ if (frameRateLimit > 0) {
+ final double sleep = frameSleepTime - (timer.getTimePerFrame() / 1000.0);
+ final long sleepMillis = (long) sleep;
+ final int additionalNanos = (int) ((sleep - sleepMillis) * 1000000.0);
+
+ if (sleepMillis >= 0 && additionalNanos >= 0) {
+ try {
+ Thread.sleep(sleepMillis, additionalNanos);
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+
+ private void setFrameRateLimit(int frameRateLimit) {
+ this.frameRateLimit = frameRateLimit;
+ frameSleepTime = 1000.0 / this.frameRateLimit;
}
/**
* De-initialize in the OpenGL thread.
*/
+
protected void deinitInThread() {
destroyContext();
@@ -379,7 +402,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
+ "Must set with JmeContext.setSystemListener().");
}
- registerNatives();
loadNatives();
LOGGER.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
@@ -445,6 +467,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
return window;
}
+
+ // TODO: Implement support for window icon when GLFW supports it.
+
private ByteBuffer[] imagesToByteBuffers(Object[] images) {
ByteBuffer[] out = new ByteBuffer[images.length];
for (int i = 0; i < images.length; i++) {