Added jme3-lwjgl3 module which ultimately adds support for LWJGL 3.x and GLFW.
This commit is contained in:
parent
7f2626af65
commit
89f10eca58
@ -17,6 +17,9 @@ repositories {
|
|||||||
maven {
|
maven {
|
||||||
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
|
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
url "https://oss.sonatype.org/content/repositories/snapshots"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -63,3 +63,9 @@ Xbox\ 360\ Wireless\ Receiver.AXIS_RX=z
|
|||||||
Xbox\ 360\ Wireless\ Receiver.AXIS_RY=rz
|
Xbox\ 360\ Wireless\ Receiver.AXIS_RY=rz
|
||||||
Xbox\ 360\ Wireless\ Receiver.z=AXIS_RX
|
Xbox\ 360\ Wireless\ Receiver.z=AXIS_RX
|
||||||
Xbox\ 360\ Wireless\ Receiver.rz=AXIS_RY
|
Xbox\ 360\ Wireless\ Receiver.rz=AXIS_RY
|
||||||
|
|
||||||
|
# Microsoft PC-joystick driver
|
||||||
|
Microsoft\ PC-joystick\ driver.12=POV +Y
|
||||||
|
Microsoft\ PC-joystick\ driver.13=POV +X
|
||||||
|
Microsoft\ PC-joystick\ driver.14=POV -Y
|
||||||
|
Microsoft\ PC-joystick\ driver.15=POV -X
|
||||||
|
@ -48,9 +48,8 @@ import java.util.logging.Logger;
|
|||||||
/**
|
/**
|
||||||
* Utility class to register, extract, and load native libraries.
|
* Utility class to register, extract, and load native libraries.
|
||||||
* <br>
|
* <br>
|
||||||
* Register your own libraries via the
|
* Register your own libraries via the {@link #registerNativeLibrary(String, Platform, String, String)} method, for
|
||||||
* {@link #registerNativeLibrary(java.lang.String, com.jme3.system.Platform, java.lang.String, boolean) }
|
* each platform.
|
||||||
* method, for each platform.
|
|
||||||
* You can then extract this library (depending on platform), by
|
* You can then extract this library (depending on platform), by
|
||||||
* using {@link #loadNativeLibrary(java.lang.String, boolean) }.
|
* using {@link #loadNativeLibrary(java.lang.String, boolean) }.
|
||||||
* <br>
|
* <br>
|
||||||
@ -125,23 +124,6 @@ public final class NativeLibraryLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
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");
|
|
||||||
|
|
||||||
// BulletJme
|
// BulletJme
|
||||||
registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll");
|
registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll");
|
||||||
registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll");
|
registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll");
|
||||||
|
@ -40,7 +40,6 @@ import com.jme3.input.lwjgl.JInputJoyInput;
|
|||||||
import com.jme3.input.lwjgl.LwjglKeyInput;
|
import com.jme3.input.lwjgl.LwjglKeyInput;
|
||||||
import com.jme3.input.lwjgl.LwjglMouseInput;
|
import com.jme3.input.lwjgl.LwjglMouseInput;
|
||||||
import com.jme3.system.AppSettings;
|
import com.jme3.system.AppSettings;
|
||||||
import com.jme3.system.JmeContext.Type;
|
|
||||||
import com.jme3.system.JmeSystem;
|
import com.jme3.system.JmeSystem;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -207,6 +206,7 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
+ "Must set with JmeContext.setSystemListner().");
|
+ "Must set with JmeContext.setSystemListner().");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerNatives();
|
||||||
loadNatives();
|
loadNatives();
|
||||||
logger.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
|
logger.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
|
||||||
if (!initInThread()) {
|
if (!initInThread()) {
|
||||||
|
@ -52,12 +52,8 @@ import com.jme3.renderer.opengl.GLRenderer;
|
|||||||
import com.jme3.renderer.opengl.GLTiming;
|
import com.jme3.renderer.opengl.GLTiming;
|
||||||
import com.jme3.renderer.opengl.GLTimingState;
|
import com.jme3.renderer.opengl.GLTimingState;
|
||||||
import com.jme3.renderer.opengl.GLTracer;
|
import com.jme3.renderer.opengl.GLTracer;
|
||||||
import com.jme3.system.AppSettings;
|
import com.jme3.system.*;
|
||||||
import com.jme3.system.JmeContext;
|
|
||||||
import com.jme3.system.JmeSystem;
|
|
||||||
import com.jme3.system.NativeLibraryLoader;
|
|
||||||
import com.jme3.system.SystemListener;
|
|
||||||
import com.jme3.system.Timer;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -167,6 +163,24 @@ 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()) {
|
if (JmeSystem.isLowPermissions()) {
|
||||||
return;
|
return;
|
||||||
|
12
jme3-lwjgl3/build.gradle
Normal file
12
jme3-lwjgl3/build.gradle
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
if (!hasProperty('mainClass')) {
|
||||||
|
ext.mainClass = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':jme3-core')
|
||||||
|
compile project(':jme3-desktop')
|
||||||
|
compile 'org.lwjgl:lwjgl:3.0.0b-SNAPSHOT'
|
||||||
|
compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0b-SNAPSHOT', classifier: 'natives-windows'
|
||||||
|
compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0b-SNAPSHOT', classifier: 'natives-linux'
|
||||||
|
compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0b-SNAPSHOT', classifier: 'natives-osx'
|
||||||
|
}
|
140
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java
Normal file
140
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.audio.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.audio.openal.AL;
|
||||||
|
import com.jme3.system.NativeLibraryLoader;
|
||||||
|
import com.jme3.system.Platform;
|
||||||
|
import org.lwjgl.openal.AL10;
|
||||||
|
import org.lwjgl.openal.AL11;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
public final class LwjglAL implements AL {
|
||||||
|
|
||||||
|
public LwjglAL() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String alGetString(int parameter) {
|
||||||
|
return AL10.alGetString(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int alGenSources() {
|
||||||
|
return AL10.alGenSources();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int alGetError() {
|
||||||
|
return AL10.alGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alDeleteSources(int numSources, IntBuffer sources) {
|
||||||
|
if (sources.position() != 0) throw new AssertionError();
|
||||||
|
if (sources.limit() != numSources) throw new AssertionError();
|
||||||
|
AL10.alDeleteSources(sources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alGenBuffers(int numBuffers, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numBuffers) throw new AssertionError();
|
||||||
|
AL10.alGenBuffers(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alDeleteBuffers(int numBuffers, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numBuffers) throw new AssertionError();
|
||||||
|
AL10.alDeleteBuffers(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourceStop(int source) {
|
||||||
|
AL10.alSourceStop(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourcei(int source, int param, int value) {
|
||||||
|
AL10.alSourcei(source, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency) {
|
||||||
|
if (data.position() != 0) throw new AssertionError();
|
||||||
|
if (data.limit() != size) throw new AssertionError();
|
||||||
|
AL10.alBufferData(buffer, format, data, frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourcePlay(int source) {
|
||||||
|
AL10.alSourcePlay(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourcePause(int source) {
|
||||||
|
AL10.alSourcePause(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourcef(int source, int param, float value) {
|
||||||
|
AL10.alSourcef(source, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSource3f(int source, int param, float value1, float value2, float value3) {
|
||||||
|
AL10.alSource3f(source, param, value1, value2, value3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int alGetSourcei(int source, int param) {
|
||||||
|
return AL10.alGetSourcei(source, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numBuffers) throw new AssertionError();
|
||||||
|
AL10.alSourceUnqueueBuffers(source, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numBuffers) throw new AssertionError();
|
||||||
|
AL10.alSourceQueueBuffers(source, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alListener(int param, FloatBuffer data) {
|
||||||
|
AL10.alListenerfv(param, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alListenerf(int param, float value) {
|
||||||
|
AL10.alListenerf(param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alListener3f(int param, float value1, float value2, float value3) {
|
||||||
|
AL10.alListener3f(param, value1, value2, value3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alSource3i(int source, int param, int value1, int value2, int value3) {
|
||||||
|
AL11.alSource3i(source, param, value1, value2, value3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
58
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
Normal file
58
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package com.jme3.audio.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.audio.openal.ALC;
|
||||||
|
import org.lwjgl.openal.ALC10;
|
||||||
|
import org.lwjgl.openal.ALContext;
|
||||||
|
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import static org.lwjgl.openal.ALC10.alcGetContextsDevice;
|
||||||
|
import static org.lwjgl.openal.ALC10.alcGetCurrentContext;
|
||||||
|
|
||||||
|
public class LwjglALC implements ALC {
|
||||||
|
|
||||||
|
private ALContext context;
|
||||||
|
|
||||||
|
public void createALC() {
|
||||||
|
context = ALContext.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroyALC() {
|
||||||
|
if (context != null) {
|
||||||
|
context.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCreated() {
|
||||||
|
return context != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String alcGetString(final int parameter) {
|
||||||
|
final long context = alcGetCurrentContext();
|
||||||
|
final long device = alcGetContextsDevice(context);
|
||||||
|
return ALC10.alcGetString(device, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean alcIsExtensionPresent(final String extension) {
|
||||||
|
final long context = alcGetCurrentContext();
|
||||||
|
final long device = alcGetContextsDevice(context);
|
||||||
|
return ALC10.alcIsExtensionPresent(device, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alcGetInteger(final int param, final IntBuffer buffer, final int size) {
|
||||||
|
if (buffer.position() != 0) throw new AssertionError();
|
||||||
|
if (buffer.limit() != size) throw new AssertionError();
|
||||||
|
|
||||||
|
final long context = alcGetCurrentContext();
|
||||||
|
final long device = alcGetContextsDevice(context);
|
||||||
|
final int value = ALC10.alcGetInteger(device, param);
|
||||||
|
//buffer.put(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alcDevicePauseSOFT() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alcDeviceResumeSOFT() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java
Normal file
66
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package com.jme3.audio.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.audio.openal.EFX;
|
||||||
|
import org.lwjgl.openal.EXTEfx;
|
||||||
|
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
public class LwjglEFX implements EFX {
|
||||||
|
|
||||||
|
public void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numSlots) throw new AssertionError();
|
||||||
|
EXTEfx.alGenAuxiliaryEffectSlots(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alGenEffects(int numEffects, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numEffects) throw new AssertionError();
|
||||||
|
EXTEfx.alGenEffects(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alEffecti(int effect, int param, int value) {
|
||||||
|
EXTEfx.alEffecti(effect, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alAuxiliaryEffectSloti(int effectSlot, int param, int value) {
|
||||||
|
EXTEfx.alAuxiliaryEffectSloti(effectSlot, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alDeleteEffects(int numEffects, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numEffects) throw new AssertionError();
|
||||||
|
EXTEfx.alDeleteEffects(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numEffectSlots) throw new AssertionError();
|
||||||
|
EXTEfx.alDeleteAuxiliaryEffectSlots(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alGenFilters(int numFilters, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numFilters) throw new AssertionError();
|
||||||
|
EXTEfx.alGenFilters(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alFilteri(int filter, int param, int value) {
|
||||||
|
EXTEfx.alFilteri(filter, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alFilterf(int filter, int param, float value) {
|
||||||
|
EXTEfx.alFilterf(filter, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alDeleteFilters(int numFilters, IntBuffer buffers) {
|
||||||
|
if (buffers.position() != 0) throw new AssertionError();
|
||||||
|
if (buffers.limit() != numFilters) throw new AssertionError();
|
||||||
|
EXTEfx.alDeleteFilters(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alEffectf(int effect, int param, float value) {
|
||||||
|
EXTEfx.alEffectf(effect, param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* 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.input.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.input.*;
|
||||||
|
import com.jme3.input.event.JoyAxisEvent;
|
||||||
|
import com.jme3.input.event.JoyButtonEvent;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Daniel Johansson (dannyjo)
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public class GlfwJoystickInput implements JoyInput {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(InputManager.class.getName());
|
||||||
|
|
||||||
|
private boolean initialized = false;
|
||||||
|
private RawInputListener listener;
|
||||||
|
private Map<Integer, GlfwJoystick> joysticks = new HashMap<Integer, GlfwJoystick>();
|
||||||
|
|
||||||
|
public void setJoyRumble(int joyId, float amount) {
|
||||||
|
if (joyId >= joysticks.size()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Joystick[] loadJoysticks(final InputManager inputManager) {
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
for (int i = 0; i < GLFW_JOYSTICK_LAST; i++) {
|
||||||
|
if (glfwJoystickPresent(i) == GL11.GL_TRUE) {
|
||||||
|
final String name = glfwGetJoystickName(i);
|
||||||
|
final GlfwJoystick joystick = new GlfwJoystick(inputManager, this, i, name);
|
||||||
|
joysticks.put(i, joystick);
|
||||||
|
|
||||||
|
final FloatBuffer floatBuffer = glfwGetJoystickAxes(i);
|
||||||
|
|
||||||
|
int axisIndex = 0;
|
||||||
|
while (floatBuffer.hasRemaining()) {
|
||||||
|
floatBuffer.get();
|
||||||
|
|
||||||
|
final String logicalId = JoystickCompatibilityMappings.remapComponent(joystick.getName(), convertAxisIndex(axisIndex));
|
||||||
|
final JoystickAxis joystickAxis = new DefaultJoystickAxis(inputManager, joystick, axisIndex, convertAxisIndex(axisIndex), logicalId, true, false, 0.0f);
|
||||||
|
joystick.addAxis(axisIndex, joystickAxis);
|
||||||
|
axisIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ByteBuffer byteBuffer = glfwGetJoystickButtons(i);
|
||||||
|
|
||||||
|
int buttonIndex = 0;
|
||||||
|
while (byteBuffer.hasRemaining()) {
|
||||||
|
byteBuffer.get();
|
||||||
|
final String logicalId = JoystickCompatibilityMappings.remapComponent(joystick.getName(), String.valueOf(buttonIndex));
|
||||||
|
joystick.addButton(new DefaultJoystickButton(inputManager, joystick, buttonIndex, String.valueOf(buttonIndex), logicalId));
|
||||||
|
buttonIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return joysticks.values().toArray(new GlfwJoystick[joysticks.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String convertAxisIndex(final int index) {
|
||||||
|
if (index == 0) {
|
||||||
|
return "pov_x";
|
||||||
|
} else if (index == 1) {
|
||||||
|
return "pov_y";
|
||||||
|
} else if (index == 2) {
|
||||||
|
return "z";
|
||||||
|
} else if (index == 3) {
|
||||||
|
return "rz";
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.valueOf(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
for (final Map.Entry<Integer, GlfwJoystick> entry : joysticks.entrySet()) {
|
||||||
|
// Axes
|
||||||
|
final FloatBuffer axisValues = glfwGetJoystickAxes(entry.getKey());
|
||||||
|
|
||||||
|
for (final JoystickAxis axis : entry.getValue().getAxes()) {
|
||||||
|
final float value = axisValues.get(axis.getAxisId());
|
||||||
|
listener.onJoyAxisEvent(new JoyAxisEvent(axis, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
final ByteBuffer byteBuffer = glfwGetJoystickButtons(entry.getKey());
|
||||||
|
|
||||||
|
for (final JoystickButton button : entry.getValue().getButtons()) {
|
||||||
|
final boolean pressed = byteBuffer.get(button.getButtonId()) == GLFW_PRESS;
|
||||||
|
listener.onJoyButtonEvent(new JoyButtonEvent(button, pressed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputListener(RawInputListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInputTimeNanos() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class GlfwJoystick extends AbstractJoystick {
|
||||||
|
|
||||||
|
private JoystickAxis povAxisX;
|
||||||
|
private JoystickAxis povAxisY;
|
||||||
|
|
||||||
|
public GlfwJoystick(InputManager inputManager, JoyInput joyInput, int joyId, String name) {
|
||||||
|
super(inputManager, joyInput, joyId, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAxis(final int index, final JoystickAxis axis) {
|
||||||
|
super.addAxis(axis);
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
povAxisX = axis;
|
||||||
|
} else if (index == 1) {
|
||||||
|
povAxisY = axis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addButton(JoystickButton button) {
|
||||||
|
super.addButton(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JoystickAxis getXAxis() {
|
||||||
|
return povAxisX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JoystickAxis getYAxis() {
|
||||||
|
return povAxisY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JoystickAxis getPovXAxis() {
|
||||||
|
return povAxisX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JoystickAxis getPovYAxis() {
|
||||||
|
return povAxisY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getXAxisIndex() {
|
||||||
|
return povAxisX.getAxisId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getYAxisIndex() {
|
||||||
|
return povAxisY.getAxisId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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.input.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.RawInputListener;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
import com.jme3.system.lwjgl.LwjglTimer;
|
||||||
|
import com.jme3.system.lwjgl.LwjglWindow;
|
||||||
|
import org.lwjgl.glfw.GLFWKeyCallback;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
public class LwjglKeyInput implements KeyInput {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LwjglKeyInput.class.getName());
|
||||||
|
|
||||||
|
private LwjglWindow context;
|
||||||
|
private RawInputListener listener;
|
||||||
|
private boolean initialized;
|
||||||
|
private GLFWKeyCallback keyCallback;
|
||||||
|
private Queue<KeyInputEvent> keyInputEvents = new LinkedList<KeyInputEvent>();
|
||||||
|
|
||||||
|
public LwjglKeyInput(LwjglWindow context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
if (!context.isRenderable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwSetKeyCallback(context.getWindowHandle(), keyCallback = new GLFWKeyCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(long window, int key, int scancode, int action, int mods) {
|
||||||
|
final KeyInputEvent evt = new KeyInputEvent(scancode, (char) key, GLFW_PRESS == action, GLFW_REPEAT == action);
|
||||||
|
evt.setTime(getInputTimeNanos());
|
||||||
|
keyInputEvents.add(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
glfwSetInputMode(context.getWindowHandle(), GLFW_STICKY_KEYS, 1);
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
logger.fine("Keyboard created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeyCount() {
|
||||||
|
return 0; // TODO: How do we figure this out?
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
if (!context.isRenderable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!keyInputEvents.isEmpty()) {
|
||||||
|
listener.onKeyEvent(keyInputEvents.poll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
if (!context.isRenderable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyCallback.release();
|
||||||
|
logger.fine("Keyboard destroyed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputListener(RawInputListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInputTimeNanos() {
|
||||||
|
return (long) (glfwGetTime() * LwjglTimer.LWJGL_TIME_TO_NANOS);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* 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.input.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.cursors.plugins.JmeCursor;
|
||||||
|
import com.jme3.input.MouseInput;
|
||||||
|
import com.jme3.input.RawInputListener;
|
||||||
|
import com.jme3.input.event.MouseButtonEvent;
|
||||||
|
import com.jme3.input.event.MouseMotionEvent;
|
||||||
|
import com.jme3.system.lwjgl.LwjglTimer;
|
||||||
|
import com.jme3.system.lwjgl.LwjglWindow;
|
||||||
|
import org.lwjgl.glfw.GLFWCursorPosCallback;
|
||||||
|
import org.lwjgl.glfw.GLFWMouseButtonCallback;
|
||||||
|
import org.lwjgl.glfw.GLFWScrollCallback;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
public class LwjglMouseInput implements MouseInput {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LwjglMouseInput.class.getName());
|
||||||
|
|
||||||
|
private LwjglWindow context;
|
||||||
|
private RawInputListener listener;
|
||||||
|
private boolean cursorVisible = true;
|
||||||
|
private int mouseX;
|
||||||
|
private int mouseY;
|
||||||
|
private int mouseWheel;
|
||||||
|
private boolean initialized;
|
||||||
|
private GLFWCursorPosCallback cursorPosCallback;
|
||||||
|
private GLFWScrollCallback scrollCallback;
|
||||||
|
private GLFWMouseButtonCallback mouseButtonCallback;
|
||||||
|
private Queue<MouseMotionEvent> mouseMotionEvents = new LinkedList<MouseMotionEvent>();
|
||||||
|
private Queue<MouseButtonEvent> mouseButtonEvents = new LinkedList<MouseButtonEvent>();
|
||||||
|
|
||||||
|
public LwjglMouseInput(LwjglWindow context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
glfwSetCursorPosCallback(context.getWindowHandle(), cursorPosCallback = new GLFWCursorPosCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(long window, double xpos, double ypos) {
|
||||||
|
int xDelta;
|
||||||
|
int yDelta;
|
||||||
|
int x = (int) Math.round(xpos);
|
||||||
|
int y = (int) Math.round(ypos);
|
||||||
|
|
||||||
|
if (mouseX == 0) {
|
||||||
|
mouseX = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseY == 0) {
|
||||||
|
mouseY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
xDelta = x - mouseX;
|
||||||
|
yDelta = y - mouseY;
|
||||||
|
mouseX = x;
|
||||||
|
mouseY = y;
|
||||||
|
|
||||||
|
if (xDelta != 0 || yDelta != 0) {
|
||||||
|
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(x, y * -1, xDelta, yDelta * -1, mouseWheel, 0);
|
||||||
|
mouseMotionEvent.setTime(getInputTimeNanos());
|
||||||
|
mouseMotionEvents.add(mouseMotionEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
glfwSetScrollCallback(context.getWindowHandle(), scrollCallback = new GLFWScrollCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(final long window, final double xOffset, final double yOffset) {
|
||||||
|
mouseWheel += yOffset;
|
||||||
|
|
||||||
|
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset));
|
||||||
|
mouseMotionEvent.setTime(getInputTimeNanos());
|
||||||
|
mouseMotionEvents.add(mouseMotionEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
glfwSetMouseButtonCallback(context.getWindowHandle(), mouseButtonCallback = new GLFWMouseButtonCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(final long window, final int button, final int action, final int mods) {
|
||||||
|
final MouseButtonEvent mouseButtonEvent = new MouseButtonEvent(button, action == GLFW_PRESS, mouseX, mouseY);
|
||||||
|
mouseButtonEvent.setTime(getInputTimeNanos());
|
||||||
|
mouseButtonEvents.add(mouseButtonEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setCursorVisible(cursorVisible);
|
||||||
|
logger.fine("Mouse created.");
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getButtonCount() {
|
||||||
|
return 2; // TODO: How to determine this?
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
while (!mouseMotionEvents.isEmpty()) {
|
||||||
|
listener.onMouseMotionEvent(mouseMotionEvents.poll());
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!mouseButtonEvents.isEmpty()) {
|
||||||
|
listener.onMouseButtonEvent(mouseButtonEvents.poll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
if (!context.isRenderable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorPosCallback.release();
|
||||||
|
scrollCallback.release();
|
||||||
|
mouseButtonCallback.release();
|
||||||
|
|
||||||
|
logger.fine("Mouse destroyed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCursorVisible(boolean visible) {
|
||||||
|
cursorVisible = visible;
|
||||||
|
|
||||||
|
if (!context.isRenderable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorVisible) {
|
||||||
|
glfwSetInputMode(context.getWindowHandle(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
} else {
|
||||||
|
glfwSetInputMode(context.getWindowHandle(), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputListener(RawInputListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInputTimeNanos() {
|
||||||
|
return (long) (glfwGetTime() * LwjglTimer.LWJGL_TIME_TO_NANOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNativeCursor(final JmeCursor jmeCursor) {
|
||||||
|
if (jmeCursor != null) {
|
||||||
|
final ByteBuffer byteBuffer = org.lwjgl.BufferUtils.createByteBuffer(jmeCursor.getImagesData().capacity());
|
||||||
|
byteBuffer.asIntBuffer().put(jmeCursor.getImagesData().array());
|
||||||
|
final long cursor = glfwCreateCursor(byteBuffer, jmeCursor.getXHotSpot(), jmeCursor.getYHotSpot());
|
||||||
|
glfwSetCursor(context.getWindowHandle(), cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
458
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
Normal file
458
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
package com.jme3.renderer.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.renderer.RendererException;
|
||||||
|
import com.jme3.renderer.opengl.GL;
|
||||||
|
import com.jme3.renderer.opengl.GL2;
|
||||||
|
import com.jme3.renderer.opengl.GL3;
|
||||||
|
import com.jme3.renderer.opengl.GL4;
|
||||||
|
import com.jme3.system.NativeLibraryLoader;
|
||||||
|
import com.jme3.system.Platform;
|
||||||
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
|
import java.nio.*;
|
||||||
|
|
||||||
|
public class LwjglGL implements GL, GL2, GL3, GL4 {
|
||||||
|
|
||||||
|
private static void checkLimit(Buffer buffer) {
|
||||||
|
if (buffer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buffer.limit() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
|
||||||
|
}
|
||||||
|
if (buffer.remaining() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetStats() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glActiveTexture(int param1) {
|
||||||
|
GL13.glActiveTexture(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glAlphaFunc(int param1, float param2) {
|
||||||
|
GL11.glAlphaFunc(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glAttachShader(int param1, int param2) {
|
||||||
|
GL20.glAttachShader(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBindBuffer(int param1, int param2) {
|
||||||
|
GL15.glBindBuffer(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBindTexture(int param1, int param2) {
|
||||||
|
GL11.glBindTexture(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBlendFunc(int param1, int param2) {
|
||||||
|
GL11.glBlendFunc(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferData(int param1, long param2, int param3) {
|
||||||
|
GL15.glBufferData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferData(int param1, FloatBuffer param2, int param3) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL15.glBufferData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferData(int param1, ShortBuffer param2, int param3) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL15.glBufferData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferData(int param1, ByteBuffer param2, int param3) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL15.glBufferData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferSubData(int param1, long param2, FloatBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL15.glBufferSubData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferSubData(int param1, long param2, ShortBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL15.glBufferSubData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glBufferSubData(int param1, long param2, ByteBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL15.glBufferSubData(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glClear(int param1) {
|
||||||
|
GL11.glClear(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glClearColor(float param1, float param2, float param3, float param4) {
|
||||||
|
GL11.glClearColor(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glColorMask(boolean param1, boolean param2, boolean param3, boolean param4) {
|
||||||
|
GL11.glColorMask(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glCompileShader(int param1) {
|
||||||
|
GL20.glCompileShader(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glCompressedTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) {
|
||||||
|
checkLimit(param7);
|
||||||
|
GL13.glCompressedTexImage2D(param1, param2, param3, param4, param5, param6, param7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glCompressedTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) {
|
||||||
|
checkLimit(param8);
|
||||||
|
GL13.glCompressedTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glCompressedTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) {
|
||||||
|
checkLimit(param8);
|
||||||
|
GL13.glCompressedTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glCompressedTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) {
|
||||||
|
checkLimit(param10);
|
||||||
|
GL13.glCompressedTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int glCreateProgram() {
|
||||||
|
return GL20.glCreateProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int glCreateShader(int param1) {
|
||||||
|
return GL20.glCreateShader(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glCullFace(int param1) {
|
||||||
|
GL11.glCullFace(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDeleteBuffers(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL15.glDeleteBuffers(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDeleteProgram(int param1) {
|
||||||
|
GL20.glDeleteProgram(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDeleteShader(int param1) {
|
||||||
|
GL20.glDeleteShader(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDeleteTextures(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL11.glDeleteTextures(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDepthFunc(int param1) {
|
||||||
|
GL11.glDepthFunc(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDepthMask(boolean param1) {
|
||||||
|
GL11.glDepthMask(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDepthRange(double param1, double param2) {
|
||||||
|
GL11.glDepthRange(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDetachShader(int param1, int param2) {
|
||||||
|
GL20.glDetachShader(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDisable(int param1) {
|
||||||
|
GL11.glDisable(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDisableVertexAttribArray(int param1) {
|
||||||
|
GL20.glDisableVertexAttribArray(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDrawArrays(int param1, int param2, int param3) {
|
||||||
|
GL11.glDrawArrays(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDrawBuffer(int param1) {
|
||||||
|
GL11.glDrawBuffer(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glDrawRangeElements(int param1, int param2, int param3, int param4, int param5, long param6) {
|
||||||
|
GL12.glDrawRangeElements(param1, param2, param3, param4, param5, param6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glEnable(int param1) {
|
||||||
|
GL11.glEnable(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glEnableVertexAttribArray(int param1) {
|
||||||
|
GL20.glEnableVertexAttribArray(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGenBuffers(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL15.glGenBuffers(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGenTextures(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL11.glGenTextures(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGetBoolean(int param1, ByteBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL11.glGetBooleanv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGetBufferSubData(int target, long offset, ByteBuffer data) {
|
||||||
|
checkLimit(data);
|
||||||
|
GL15.glGetBufferSubData(target, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int glGetError() {
|
||||||
|
return GL11.glGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGetInteger(int param1, IntBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL11.glGetIntegerv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGetProgram(int param1, int param2, IntBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL20.glGetProgramiv(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glGetShader(int param1, int param2, IntBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL20.glGetShaderiv(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String glGetString(int param1) {
|
||||||
|
return GL11.glGetString(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String glGetString(int param1, int param2) {
|
||||||
|
return GL30.glGetStringi(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean glIsEnabled(int param1) {
|
||||||
|
return GL11.glIsEnabled(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glLineWidth(float param1) {
|
||||||
|
GL11.glLineWidth(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glLinkProgram(int param1) {
|
||||||
|
GL20.glLinkProgram(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glPixelStorei(int param1, int param2) {
|
||||||
|
GL11.glPixelStorei(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glPointSize(float param1) {
|
||||||
|
GL11.glPointSize(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glPolygonMode(int param1, int param2) {
|
||||||
|
GL11.glPolygonMode(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glPolygonOffset(float param1, float param2) {
|
||||||
|
GL11.glPolygonOffset(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glReadBuffer(int param1) {
|
||||||
|
GL11.glReadBuffer(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) {
|
||||||
|
checkLimit(param7);
|
||||||
|
GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, long param7) {
|
||||||
|
GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glScissor(int param1, int param2, int param3, int param4) {
|
||||||
|
GL11.glScissor(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glStencilFuncSeparate(int param1, int param2, int param3, int param4) {
|
||||||
|
GL20.glStencilFuncSeparate(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glStencilOpSeparate(int param1, int param2, int param3, int param4) {
|
||||||
|
GL20.glStencilOpSeparate(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) {
|
||||||
|
checkLimit(param9);
|
||||||
|
GL11.glTexImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) {
|
||||||
|
checkLimit(param10);
|
||||||
|
GL12.glTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glTexParameterf(int param1, int param2, float param3) {
|
||||||
|
GL11.glTexParameterf(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glTexParameteri(int param1, int param2, int param3) {
|
||||||
|
GL11.glTexParameteri(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) {
|
||||||
|
checkLimit(param9);
|
||||||
|
GL11.glTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10, ByteBuffer param11) {
|
||||||
|
checkLimit(param11);
|
||||||
|
GL12.glTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform1(int param1, FloatBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform1fv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform1(int param1, IntBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform1iv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform1f(int param1, float param2) {
|
||||||
|
GL20.glUniform1f(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform1i(int param1, int param2) {
|
||||||
|
GL20.glUniform1i(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform2(int param1, IntBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform2iv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform2(int param1, FloatBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform2fv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform2f(int param1, float param2, float param3) {
|
||||||
|
GL20.glUniform2f(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform3(int param1, IntBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform3iv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform3(int param1, FloatBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform3fv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform3f(int param1, float param2, float param3, float param4) {
|
||||||
|
GL20.glUniform3f(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform4(int param1, FloatBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform4fv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform4(int param1, IntBuffer param2) {
|
||||||
|
checkLimit(param2);
|
||||||
|
GL20.glUniform4iv(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniform4f(int param1, float param2, float param3, float param4, float param5) {
|
||||||
|
GL20.glUniform4f(param1, param2, param3, param4, param5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniformMatrix3(int param1, boolean param2, FloatBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL20.glUniformMatrix3fv(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUniformMatrix4(int param1, boolean param2, FloatBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL20.glUniformMatrix4fv(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glUseProgram(int param1) {
|
||||||
|
GL20.glUseProgram(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glVertexAttribPointer(int param1, int param2, int param3, boolean param4, int param5, long param6) {
|
||||||
|
GL20.glVertexAttribPointer(param1, param2, param3, param4, param5, param6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glViewport(int param1, int param2, int param3, int param4) {
|
||||||
|
GL11.glViewport(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int glGetAttribLocation(int param1, String param2) {
|
||||||
|
// NOTE: LWJGL requires null-terminated strings
|
||||||
|
return GL20.glGetAttribLocation(param1, param2 + "\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int glGetUniformLocation(int param1, String param2) {
|
||||||
|
// NOTE: LWJGL requires null-terminated strings
|
||||||
|
return GL20.glGetUniformLocation(param1, param2 + "\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void glShaderSource(int param1, String[] param2, IntBuffer param3) {
|
||||||
|
checkLimit(param3);
|
||||||
|
GL20.glShaderSource(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String glGetProgramInfoLog(int program, int maxSize) {
|
||||||
|
return GL20.glGetProgramInfoLog(program, maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String glGetShaderInfoLog(int shader, int maxSize) {
|
||||||
|
return GL20.glGetShaderInfoLog(shader, maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBindFragDataLocation(int param1, int param2, String param3) {
|
||||||
|
GL30.glBindFragDataLocation(param1, param2, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBindVertexArray(int param1) {
|
||||||
|
GL30.glBindVertexArray(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenVertexArrays(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL30.glGenVertexArrays(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glPatchParameter(int count) {
|
||||||
|
GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDeleteVertexArrays(IntBuffer arrays) {
|
||||||
|
checkLimit(arrays);
|
||||||
|
ARBVertexArrayObject.glDeleteVertexArrays(arrays);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.jme3.renderer.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.renderer.RendererException;
|
||||||
|
import com.jme3.renderer.opengl.GLExt;
|
||||||
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
|
import java.nio.Buffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
public class LwjglGLExt implements GLExt {
|
||||||
|
|
||||||
|
private static void checkLimit(Buffer buffer) {
|
||||||
|
if (buffer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buffer.limit() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
|
||||||
|
}
|
||||||
|
if (buffer.remaining() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBufferData(int target, IntBuffer data, int usage) {
|
||||||
|
checkLimit(data);
|
||||||
|
GL15.glBufferData(target, data, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBufferSubData(int target, long offset, IntBuffer data) {
|
||||||
|
checkLimit(data);
|
||||||
|
GL15.glBufferSubData(target, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) {
|
||||||
|
ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDrawBuffers(IntBuffer bufs) {
|
||||||
|
checkLimit(bufs);
|
||||||
|
GL20.glDrawBuffers(bufs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) {
|
||||||
|
ARBDrawInstanced.glDrawElementsInstancedARB(mode, indices_count, type, indices_buffer_offset, primcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGetMultisample(int pname, int index, FloatBuffer val) {
|
||||||
|
checkLimit(val);
|
||||||
|
ARBTextureMultisample.glGetMultisamplefv(pname, index, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) {
|
||||||
|
ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glVertexAttribDivisorARB(int index, int divisor) {
|
||||||
|
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object glFenceSync(int condition, int flags) {
|
||||||
|
return ARBSync.glFenceSync(condition, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int glClientWaitSync(final Object sync, final int flags, final long timeout) {
|
||||||
|
return ARBSync.glClientWaitSync((Long) sync, flags, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDeleteSync(final Object sync) {
|
||||||
|
ARBSync.glDeleteSync((Long) sync);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.jme3.renderer.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.renderer.RendererException;
|
||||||
|
import com.jme3.renderer.opengl.GLFbo;
|
||||||
|
import org.lwjgl.opengl.EXTFramebufferBlit;
|
||||||
|
import org.lwjgl.opengl.EXTFramebufferMultisample;
|
||||||
|
import org.lwjgl.opengl.EXTFramebufferObject;
|
||||||
|
|
||||||
|
import java.nio.Buffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements GLFbo via GL_EXT_framebuffer_object.
|
||||||
|
*
|
||||||
|
* @author Kirill Vainer
|
||||||
|
*/
|
||||||
|
public class LwjglGLFboEXT implements GLFbo {
|
||||||
|
|
||||||
|
private static void checkLimit(Buffer buffer) {
|
||||||
|
if (buffer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buffer.limit() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
|
||||||
|
}
|
||||||
|
if (buffer.remaining() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
|
||||||
|
EXTFramebufferBlit.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
|
||||||
|
EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBindFramebufferEXT(int param1, int param2) {
|
||||||
|
EXTFramebufferObject.glBindFramebufferEXT(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBindRenderbufferEXT(int param1, int param2) {
|
||||||
|
EXTFramebufferObject.glBindRenderbufferEXT(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int glCheckFramebufferStatusEXT(int param1) {
|
||||||
|
return EXTFramebufferObject.glCheckFramebufferStatusEXT(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDeleteFramebuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
EXTFramebufferObject.glDeleteFramebuffersEXT(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDeleteRenderbuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
EXTFramebufferObject.glDeleteRenderbuffersEXT(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
|
||||||
|
EXTFramebufferObject.glFramebufferRenderbufferEXT(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
|
||||||
|
EXTFramebufferObject.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenFramebuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
EXTFramebufferObject.glGenFramebuffersEXT(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenRenderbuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
EXTFramebufferObject.glGenRenderbuffersEXT(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenerateMipmapEXT(int param1) {
|
||||||
|
EXTFramebufferObject.glGenerateMipmapEXT(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
|
||||||
|
EXTFramebufferObject.glRenderbufferStorageEXT(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package com.jme3.renderer.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.renderer.RendererException;
|
||||||
|
import com.jme3.renderer.opengl.GLFbo;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
|
import java.nio.Buffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements GLFbo via OpenGL3+.
|
||||||
|
*
|
||||||
|
* @author Kirill Vainer
|
||||||
|
*/
|
||||||
|
public class LwjglGLFboGL3 implements GLFbo {
|
||||||
|
|
||||||
|
private static void checkLimit(Buffer buffer) {
|
||||||
|
if (buffer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buffer.limit() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
|
||||||
|
}
|
||||||
|
if (buffer.remaining() == 0) {
|
||||||
|
throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
|
||||||
|
GL30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
|
||||||
|
GL30.glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBindFramebufferEXT(int param1, int param2) {
|
||||||
|
GL30.glBindFramebuffer(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glBindRenderbufferEXT(int param1, int param2) {
|
||||||
|
GL30.glBindRenderbuffer(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int glCheckFramebufferStatusEXT(int param1) {
|
||||||
|
return GL30.glCheckFramebufferStatus(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDeleteFramebuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL30.glDeleteFramebuffers(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glDeleteRenderbuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL30.glDeleteRenderbuffers(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
|
||||||
|
GL30.glFramebufferRenderbuffer(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
|
||||||
|
GL30.glFramebufferTexture2D(param1, param2, param3, param4, param5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenFramebuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL30.glGenFramebuffers(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenRenderbuffersEXT(IntBuffer param1) {
|
||||||
|
checkLimit(param1);
|
||||||
|
GL30.glGenRenderbuffers(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glGenerateMipmapEXT(int param1) {
|
||||||
|
GL30.glGenerateMipmap(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
|
||||||
|
GL30.glRenderbufferStorage(param1, param2, param3, param4);
|
||||||
|
}
|
||||||
|
}
|
369
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
Normal file
369
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
* 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.input.lwjgl.GlfwJoystickInput;
|
||||||
|
import com.jme3.input.lwjgl.LwjglKeyInput;
|
||||||
|
import com.jme3.input.lwjgl.LwjglMouseInput;
|
||||||
|
import com.jme3.renderer.Renderer;
|
||||||
|
import com.jme3.renderer.RendererException;
|
||||||
|
import com.jme3.renderer.lwjgl.LwjglGL;
|
||||||
|
import com.jme3.renderer.lwjgl.LwjglGLExt;
|
||||||
|
import com.jme3.renderer.lwjgl.LwjglGLFboEXT;
|
||||||
|
import com.jme3.renderer.lwjgl.LwjglGLFboGL3;
|
||||||
|
import com.jme3.renderer.opengl.*;
|
||||||
|
import com.jme3.renderer.opengl.GL;
|
||||||
|
import com.jme3.system.*;
|
||||||
|
import org.lwjgl.Sys;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL.createCapabilities;
|
||||||
|
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
||||||
|
import static org.lwjgl.opengl.GL11.glGetInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A LWJGL implementation of a graphics context.
|
||||||
|
*/
|
||||||
|
public abstract class LwjglContext implements JmeContext {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(LwjglContext.class.getName());
|
||||||
|
|
||||||
|
protected static final String THREAD_NAME = "jME3 Main";
|
||||||
|
|
||||||
|
protected AtomicBoolean created = new AtomicBoolean(false);
|
||||||
|
protected AtomicBoolean renderable = new AtomicBoolean(false);
|
||||||
|
protected final Object createdLock = new Object();
|
||||||
|
|
||||||
|
protected AppSettings settings = new AppSettings(true);
|
||||||
|
protected Renderer renderer;
|
||||||
|
protected LwjglKeyInput keyInput;
|
||||||
|
protected LwjglMouseInput mouseInput;
|
||||||
|
protected GlfwJoystickInput joyInput;
|
||||||
|
protected Timer timer;
|
||||||
|
protected SystemListener listener;
|
||||||
|
|
||||||
|
public void setSystemListener(SystemListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void printContextInitInfo() {
|
||||||
|
logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n" +
|
||||||
|
" * Graphics Adapter: GLFW {2}",
|
||||||
|
new Object[]{Sys.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int determineMaxSamples() {
|
||||||
|
// If we already have a valid context, determine samples using current context.
|
||||||
|
if (GLFW.glfwExtensionSupported("GL_ARB_framebuffer_object") == GL_TRUE) {
|
||||||
|
return glGetInteger(ARBFramebufferObject.GL_MAX_SAMPLES);
|
||||||
|
} else if (GLFW.glfwExtensionSupported("GL_EXT_framebuffer_multisample") == GL_TRUE) {
|
||||||
|
return glGetInteger(EXTFramebufferMultisample.GL_MAX_SAMPLES_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (settings.useJoysticks()) {
|
||||||
|
//NativeLibraryLoader.loadNativeLibrary("jinput", true);
|
||||||
|
//NativeLibraryLoader.loadNativeLibrary("jinput-dx8", true);
|
||||||
|
}
|
||||||
|
if (NativeLibraryLoader.isUsingNativeBullet()) {
|
||||||
|
NativeLibraryLoader.loadNativeLibrary("bulletjme", true);
|
||||||
|
}
|
||||||
|
NativeLibraryLoader.loadNativeLibrary("lwjgl", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getNumSamplesToUse() {
|
||||||
|
int samples = 0;
|
||||||
|
if (settings.getSamples() > 1) {
|
||||||
|
samples = settings.getSamples();
|
||||||
|
final int supportedSamples = determineMaxSamples();
|
||||||
|
if (supportedSamples < samples) {
|
||||||
|
logger.log(Level.WARNING,
|
||||||
|
"Couldn't satisfy antialiasing samples requirement: x{0}. "
|
||||||
|
+ "Video hardware only supports: x{1}",
|
||||||
|
new Object[]{samples, supportedSamples});
|
||||||
|
|
||||||
|
samples = supportedSamples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initContextFirstTime() {
|
||||||
|
final GLCapabilities capabilities = createCapabilities(settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3));
|
||||||
|
|
||||||
|
if (!capabilities.OpenGL20) {
|
||||||
|
throw new RendererException("OpenGL 2.0 or higher is required for jMonkeyEngine");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2)
|
||||||
|
|| settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)) {
|
||||||
|
GL gl = new LwjglGL();
|
||||||
|
GLExt glext = new LwjglGLExt();
|
||||||
|
GLFbo glfbo;
|
||||||
|
|
||||||
|
if (capabilities.OpenGL30) {
|
||||||
|
glfbo = new LwjglGLFboGL3();
|
||||||
|
} else {
|
||||||
|
glfbo = new LwjglGLFboEXT();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.getBoolean("GraphicsDebug")) {
|
||||||
|
gl = new GLDebugDesktop(gl, glext, glfbo);
|
||||||
|
glext = (GLExt) gl;
|
||||||
|
glfbo = (GLFbo) gl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.getBoolean("GraphicsTiming")) {
|
||||||
|
GLTimingState timingState = new GLTimingState();
|
||||||
|
gl = (GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
|
||||||
|
glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class);
|
||||||
|
glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.getBoolean("GraphicsTrace")) {
|
||||||
|
gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
|
||||||
|
glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
|
||||||
|
glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer = new GLRenderer(gl, glext, glfbo);
|
||||||
|
renderer.initialize();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (capabilities.GL_ARB_debug_output && settings.getBoolean("GraphicsDebug")) {
|
||||||
|
ARBDebugOutput.glDebugMessageCallbackARB(new LwjglGLDebugOutputHandler(), 0); // User param is zero. Not sure what we could use that for.
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
|
||||||
|
renderer.setLinearizeSrgbImages(settings.getGammaCorrection());
|
||||||
|
|
||||||
|
// Init input
|
||||||
|
if (keyInput != null) {
|
||||||
|
keyInput.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseInput != null) {
|
||||||
|
mouseInput.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joyInput != null) {
|
||||||
|
joyInput.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderable.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void internalDestroy() {
|
||||||
|
renderer = null;
|
||||||
|
timer = null;
|
||||||
|
renderable.set(false);
|
||||||
|
synchronized (createdLock) {
|
||||||
|
created.set(false);
|
||||||
|
createdLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void internalCreate() {
|
||||||
|
synchronized (createdLock) {
|
||||||
|
created.set(true);
|
||||||
|
createdLock.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (renderable.get()) {
|
||||||
|
initContextFirstTime();
|
||||||
|
//} else {
|
||||||
|
// assert getType() == Type.Canvas;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void create() {
|
||||||
|
create(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
destroy(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void waitFor(boolean createdVal) {
|
||||||
|
synchronized (createdLock) {
|
||||||
|
while (created.get() != createdVal) {
|
||||||
|
try {
|
||||||
|
createdLock.wait();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCreated() {
|
||||||
|
return created.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRenderable() {
|
||||||
|
return renderable.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSettings(AppSettings settings) {
|
||||||
|
this.settings.copyFrom(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppSettings getSettings() {
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Renderer getRenderer() {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Timer getTimer() {
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.jme3.system.lwjgl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Daniel Johansson
|
||||||
|
* @since 2015-08-11
|
||||||
|
*/
|
||||||
|
public class LwjglDisplay extends LwjglWindow {
|
||||||
|
|
||||||
|
public LwjglDisplay() {
|
||||||
|
super(Type.Display);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2015 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 org.lwjgl.opengl.ARBDebugOutput;
|
||||||
|
import org.lwjgl.opengl.GLDebugMessageARBCallback;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
class LwjglGLDebugOutputHandler extends GLDebugMessageARBCallback {
|
||||||
|
|
||||||
|
private static final HashMap<Integer, String> constMap = new HashMap<Integer, String>();
|
||||||
|
private static final String MESSAGE_FORMAT =
|
||||||
|
"[JME3] OpenGL debug message\r\n" +
|
||||||
|
" ID: %d\r\n" +
|
||||||
|
" Source: %s\r\n" +
|
||||||
|
" Type: %s\r\n" +
|
||||||
|
" Severity: %s\r\n" +
|
||||||
|
" Message: %s";
|
||||||
|
|
||||||
|
static {
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_API_ARB, "API");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_APPLICATION_ARB, "APPLICATION");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_OTHER_ARB, "OTHER");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_SHADER_COMPILER_ARB, "SHADER_COMPILER");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_THIRD_PARTY_ARB, "THIRD_PARTY");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, "WINDOW_SYSTEM");
|
||||||
|
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, "DEPRECATED_BEHAVIOR");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_ERROR_ARB, "ERROR");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_OTHER_ARB, "OTHER");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_PERFORMANCE_ARB, "PERFORMANCE");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_PORTABILITY_ARB, "PORTABILITY");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, "UNDEFINED_BEHAVIOR");
|
||||||
|
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SEVERITY_HIGH_ARB, "HIGH");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SEVERITY_MEDIUM_ARB, "MEDIUM");
|
||||||
|
constMap.put(ARBDebugOutput.GL_DEBUG_SEVERITY_LOW_ARB, "LOW");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(int source, int type, int id, int severity, int length, long message, long userParam) {
|
||||||
|
String sourceStr = constMap.get(source);
|
||||||
|
String typeStr = constMap.get(type);
|
||||||
|
String severityStr = constMap.get(severity);
|
||||||
|
|
||||||
|
System.err.println(String.format(MESSAGE_FORMAT, id, sourceStr, typeStr, severityStr, message));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.jme3.system.lwjgl;
|
||||||
|
|
||||||
|
import com.jme3.system.JmeContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Daniel Johansson
|
||||||
|
* @since 2015-08-11
|
||||||
|
*/
|
||||||
|
public class LwjglOffscreenBuffer extends LwjglWindow {
|
||||||
|
|
||||||
|
public LwjglOffscreenBuffer() {
|
||||||
|
super(JmeContext.Type.OffscreenSurface);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>Timer</code> 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. <code>Timer</code> is a
|
||||||
|
* singleton object and must be created via the <code>getTimer</code> 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 <code>Timer</code> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>getFrameRate</code> returns the current frame rate since the last
|
||||||
|
* call to <code>update</code>.
|
||||||
|
*
|
||||||
|
* @return the current frame rate.
|
||||||
|
*/
|
||||||
|
public float getFrameRate() {
|
||||||
|
return lastFPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTimePerFrame() {
|
||||||
|
return lastTPF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>update</code> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>toString</code> returns the string representation of this timer
|
||||||
|
* in the format: <br>
|
||||||
|
* <br>
|
||||||
|
* jme.utility.Timer@1db699b <br>
|
||||||
|
* Time: {LONG} <br>
|
||||||
|
* FPS: {LONG} <br>
|
||||||
|
*
|
||||||
|
* @return the string representation of this object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String string = super.toString();
|
||||||
|
string += "\nTime: " + oldTime;
|
||||||
|
string += "\nFPS: " + getFrameRate();
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
}
|
139
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
Normal file
139
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>Timer</code> 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. <code>Timer</code> is a
|
||||||
|
* singleton object and must be created via the <code>getTimer</code> 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 <code>Timer</code> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>getFrameRate</code> returns the current frame rate since the last
|
||||||
|
* call to <code>update</code>.
|
||||||
|
*
|
||||||
|
* @return the current frame rate.
|
||||||
|
*/
|
||||||
|
public float getFrameRate() {
|
||||||
|
return lastFPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTimePerFrame() {
|
||||||
|
return lastTPF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>update</code> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>toString</code> returns the string representation of this timer
|
||||||
|
* in the format: <br>
|
||||||
|
* <br>
|
||||||
|
* jme.utility.Timer@1db699b <br>
|
||||||
|
* Time: {LONG} <br>
|
||||||
|
* FPS: {LONG} <br>
|
||||||
|
*
|
||||||
|
* @return the string representation of this object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String string = super.toString();
|
||||||
|
string += "\nTime: " + oldTime;
|
||||||
|
string += "\nFPS: " + getFrameRate();
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
}
|
489
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
Normal file
489
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
/*
|
||||||
|
* 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.input.JoyInput;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.MouseInput;
|
||||||
|
import com.jme3.input.TouchInput;
|
||||||
|
import com.jme3.input.lwjgl.GlfwJoystickInput;
|
||||||
|
import com.jme3.input.lwjgl.LwjglKeyInput;
|
||||||
|
import com.jme3.input.lwjgl.LwjglMouseInput;
|
||||||
|
import com.jme3.system.AppSettings;
|
||||||
|
import com.jme3.system.JmeContext;
|
||||||
|
import com.jme3.system.JmeSystem;
|
||||||
|
import org.lwjgl.PointerBuffer;
|
||||||
|
import org.lwjgl.Sys;
|
||||||
|
import org.lwjgl.glfw.*;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
import static org.lwjgl.opengl.GL11.GL_FALSE;
|
||||||
|
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
||||||
|
import static org.lwjgl.system.MemoryUtil.NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper class over the GLFW framework in LWJGL 3.
|
||||||
|
*
|
||||||
|
* @author Daniel Johansson (dannyjo)
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(LwjglWindow.class.getName());
|
||||||
|
|
||||||
|
protected AtomicBoolean needClose = new AtomicBoolean(false);
|
||||||
|
protected final AtomicBoolean needRestart = new AtomicBoolean(false);
|
||||||
|
protected boolean wasActive = false;
|
||||||
|
protected boolean autoFlush = true;
|
||||||
|
protected boolean allowSwapBuffers = false;
|
||||||
|
private long window = -1;
|
||||||
|
private final JmeContext.Type type;
|
||||||
|
|
||||||
|
private GLFWErrorCallback errorCallback;
|
||||||
|
private GLFWWindowSizeCallback windowSizeCallback;
|
||||||
|
private GLFWWindowFocusCallback windowFocusCallback;
|
||||||
|
|
||||||
|
public LwjglWindow(final JmeContext.Type type) {
|
||||||
|
if (!JmeContext.Type.Display.equals(type) && !JmeContext.Type.OffscreenSurface.equals(type) && !JmeContext.Type.Canvas.equals(type)) {
|
||||||
|
throw new IllegalArgumentException("Unsupported type '" + type.name() + "' provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Type.Display or Type.Canvas
|
||||||
|
*/
|
||||||
|
public JmeContext.Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the title if its a windowed display
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
*/
|
||||||
|
public void setTitle(final String title) {
|
||||||
|
if (created.get() && window != -1) {
|
||||||
|
glfwSetWindowTitle(window, title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restart if its a windowed or full-screen display.
|
||||||
|
*/
|
||||||
|
public void restart() {
|
||||||
|
if (created.get()) {
|
||||||
|
needRestart.set(true);
|
||||||
|
} else {
|
||||||
|
LOGGER.warning("Display is not created, cannot restart window.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the settings, changing resolution, etc.
|
||||||
|
*
|
||||||
|
* @param settings
|
||||||
|
*/
|
||||||
|
protected void createContext(final AppSettings settings) {
|
||||||
|
glfwSetErrorCallback(errorCallback = new GLFWErrorCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(int error, long description) {
|
||||||
|
final String message = Callbacks.errorCallbackDescriptionString(description);
|
||||||
|
listener.handleError(message, new Exception(message));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (glfwInit() != GL_TRUE) {
|
||||||
|
throw new IllegalStateException("Unable to initialize GLFW");
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwDefaultWindowHints();
|
||||||
|
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
||||||
|
|
||||||
|
// TODO: Add support for monitor selection
|
||||||
|
long monitor = NULL;
|
||||||
|
|
||||||
|
if (settings.isFullscreen()) {
|
||||||
|
monitor = glfwGetPrimaryMonitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ByteBuffer videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||||
|
|
||||||
|
if (settings.getWidth() <= 0 || settings.getHeight() <= 0) {
|
||||||
|
settings.setResolution(GLFWvidmode.width(videoMode), GLFWvidmode.height(videoMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
window = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.getTitle(), monitor, NULL);
|
||||||
|
|
||||||
|
if (window == NULL) {
|
||||||
|
throw new RuntimeException("Failed to create the GLFW window");
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, settings.isResizable() ? GL_TRUE : GL_FALSE);
|
||||||
|
glfwWindowHint(GLFW_DEPTH_BITS, settings.getDepthBits());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not sure how else to support bits per pixel
|
||||||
|
if (settings.getBitsPerPixel() == 24) {
|
||||||
|
glfwWindowHint(GLFW_RED_BITS, 8);
|
||||||
|
glfwWindowHint(GLFW_GREEN_BITS, 8);
|
||||||
|
glfwWindowHint(GLFW_BLUE_BITS, 8);
|
||||||
|
} else if (settings.getBitsPerPixel() == 16) {
|
||||||
|
glfwWindowHint(GLFW_RED_BITS, 5);
|
||||||
|
glfwWindowHint(GLFW_GREEN_BITS, 6);
|
||||||
|
glfwWindowHint(GLFW_BLUE_BITS, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_ALPHA_BITS, settings.getAlphaBits());
|
||||||
|
|
||||||
|
glfwSetWindowFocusCallback(window, windowFocusCallback = new GLFWWindowFocusCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(final long window, final int focused) {
|
||||||
|
final boolean focus = (focused == 1);
|
||||||
|
|
||||||
|
if (wasActive != focus) {
|
||||||
|
if (!wasActive) {
|
||||||
|
listener.gainFocus();
|
||||||
|
timer.reset();
|
||||||
|
} else {
|
||||||
|
listener.loseFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
wasActive = !wasActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Center the window
|
||||||
|
if (!settings.isFullscreen() && Type.Display.equals(type)) {
|
||||||
|
glfwSetWindowPos(window, (GLFWvidmode.width(videoMode) - settings.getWidth()) / 2, (GLFWvidmode.height(videoMode) - settings.getHeight()) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the OpenGL context current
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
|
// Enable vsync
|
||||||
|
if (settings.isVSync()) {
|
||||||
|
glfwSwapInterval(1);
|
||||||
|
} else {
|
||||||
|
glfwSwapInterval(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make the window visible
|
||||||
|
if (Type.Display.equals(type)) {
|
||||||
|
glfwShowWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a resize callback which delegates to the listener
|
||||||
|
glfwSetWindowSizeCallback(window, windowSizeCallback = new GLFWWindowSizeCallback() {
|
||||||
|
@Override
|
||||||
|
public void invoke(final long window, final int width, final int height) {
|
||||||
|
settings.setResolution(width, height);
|
||||||
|
listener.reshape(width, height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
allowSwapBuffers = settings.isSwapBuffers();
|
||||||
|
|
||||||
|
// TODO: When GLFW 3.2 is released and included in LWJGL 3.x then we should hopefully be able to set the window icon.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the context.
|
||||||
|
*/
|
||||||
|
protected void destroyContext() {
|
||||||
|
try {
|
||||||
|
if (renderer != null) {
|
||||||
|
renderer.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCallback.release();
|
||||||
|
windowSizeCallback.release();
|
||||||
|
windowFocusCallback.release();
|
||||||
|
|
||||||
|
if (window != 0) {
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
}
|
||||||
|
//glfwTerminate();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
listener.handleError("Failed to destroy context", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void create(boolean waitFor) {
|
||||||
|
if (created.get()) {
|
||||||
|
LOGGER.warning("create() called when display is already created!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Thread(this, THREAD_NAME).start();
|
||||||
|
if (waitFor)
|
||||||
|
waitFor(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does LWJGL display initialization in the OpenGL thread
|
||||||
|
*/
|
||||||
|
protected boolean initInThread() {
|
||||||
|
try {
|
||||||
|
if (!JmeSystem.isLowPermissions()) {
|
||||||
|
// Enable uncaught exception handler only for current thread
|
||||||
|
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
|
public void uncaughtException(Thread thread, Throwable thrown) {
|
||||||
|
listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown);
|
||||||
|
if (needClose.get()) {
|
||||||
|
// listener.handleError() has requested the
|
||||||
|
// context to close. Satisfy request.
|
||||||
|
deinitInThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = new LwjglTimer();
|
||||||
|
|
||||||
|
// For canvas, this will create a pbuffer,
|
||||||
|
// allowing us to query information.
|
||||||
|
// When the canvas context becomes available, it will
|
||||||
|
// be replaced seamlessly.
|
||||||
|
createContext(settings);
|
||||||
|
printContextInitInfo();
|
||||||
|
|
||||||
|
created.set(true);
|
||||||
|
super.internalCreate();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
try {
|
||||||
|
if (window != -1) {
|
||||||
|
//glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
}
|
||||||
|
} catch (Exception ex2) {
|
||||||
|
LOGGER.log(Level.WARNING, null, ex2);
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.handleError("Failed to create display", ex);
|
||||||
|
return false; // if we failed to create display, do not continue
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.initialize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute one iteration of the render loop in the OpenGL thread
|
||||||
|
*/
|
||||||
|
protected void runLoop() {
|
||||||
|
// If a restart is required, lets recreate the context.
|
||||||
|
if (needRestart.getAndSet(false)) {
|
||||||
|
try {
|
||||||
|
createContext(settings);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Failed to set display settings!", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.fine("Display restarted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!created.get()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.update();
|
||||||
|
|
||||||
|
// All this does is call swap buffers
|
||||||
|
// If the canvas is not active, there's no need to waste time
|
||||||
|
// doing that ..
|
||||||
|
if (renderable.get()) {
|
||||||
|
// calls swap buffers, etc.
|
||||||
|
try {
|
||||||
|
if (allowSwapBuffers && autoFlush) {
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
listener.handleError("Error while swapping buffers", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glfwGetWindowAttrib(window, GLFW_FOCUSED) == GL_TRUE) {
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subclasses just call GLObjectManager clean up objects here
|
||||||
|
// it is safe .. for now.
|
||||||
|
if (renderer != null) {
|
||||||
|
renderer.postFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-initialize in the OpenGL thread.
|
||||||
|
*/
|
||||||
|
protected void deinitInThread() {
|
||||||
|
destroyContext();
|
||||||
|
|
||||||
|
listener.destroy();
|
||||||
|
LOGGER.fine("Display destroyed.");
|
||||||
|
super.internalDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
if (listener == null) {
|
||||||
|
throw new IllegalStateException("SystemListener is not set on context!"
|
||||||
|
+ "Must set with JmeContext.setSystemListner().");
|
||||||
|
}
|
||||||
|
|
||||||
|
registerNatives();
|
||||||
|
loadNatives();
|
||||||
|
LOGGER.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
|
||||||
|
|
||||||
|
if (!initInThread()) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Display initialization failed. Cannot continue.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (glfwWindowShouldClose(window) == GL_TRUE) {
|
||||||
|
listener.requestClose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
runLoop();
|
||||||
|
|
||||||
|
if (needClose.get()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deinitInThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JoyInput getJoyInput() {
|
||||||
|
if (joyInput == null) {
|
||||||
|
joyInput = new GlfwJoystickInput();
|
||||||
|
}
|
||||||
|
return joyInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MouseInput getMouseInput() {
|
||||||
|
if (mouseInput == null) {
|
||||||
|
mouseInput = new LwjglMouseInput(this);
|
||||||
|
}
|
||||||
|
return mouseInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyInput getKeyInput() {
|
||||||
|
if (keyInput == null) {
|
||||||
|
keyInput = new LwjglKeyInput(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchInput getTouchInput() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoFlushFrames(boolean enabled) {
|
||||||
|
this.autoFlush = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy(boolean waitFor) {
|
||||||
|
needClose.set(true);
|
||||||
|
|
||||||
|
if (waitFor) {
|
||||||
|
waitFor(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getWindowHandle() {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuffer[] imagesToByteBuffers(Object[] images) {
|
||||||
|
ByteBuffer[] out = new ByteBuffer[images.length];
|
||||||
|
for (int i = 0; i < images.length; i++) {
|
||||||
|
BufferedImage image = (BufferedImage) images[i];
|
||||||
|
out[i] = imageToByteBuffer(image);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuffer imageToByteBuffer(BufferedImage image) {
|
||||||
|
if (image.getType() != BufferedImage.TYPE_INT_ARGB_PRE) {
|
||||||
|
BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
|
||||||
|
Graphics2D g = convertedImage.createGraphics();
|
||||||
|
double width = image.getWidth() * (double) 1;
|
||||||
|
double height = image.getHeight() * (double) 1;
|
||||||
|
g.drawImage(image, (int) ((convertedImage.getWidth() - width) / 2),
|
||||||
|
(int) ((convertedImage.getHeight() - height) / 2),
|
||||||
|
(int) (width), (int) (height), null);
|
||||||
|
g.dispose();
|
||||||
|
image = convertedImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] imageBuffer = new byte[image.getWidth() * image.getHeight() * 4];
|
||||||
|
int counter = 0;
|
||||||
|
for (int i = 0; i < image.getHeight(); i++) {
|
||||||
|
for (int j = 0; j < image.getWidth(); j++) {
|
||||||
|
int colorSpace = image.getRGB(j, i);
|
||||||
|
imageBuffer[counter + 0] = (byte) ((colorSpace << 8) >> 24);
|
||||||
|
imageBuffer[counter + 1] = (byte) ((colorSpace << 16) >> 24);
|
||||||
|
imageBuffer[counter + 2] = (byte) ((colorSpace << 24) >> 24);
|
||||||
|
imageBuffer[counter + 3] = (byte) (colorSpace >> 24);
|
||||||
|
counter += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ByteBuffer.wrap(imageBuffer);
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ include 'jme3-desktop'
|
|||||||
include 'jme3-blender'
|
include 'jme3-blender'
|
||||||
include 'jme3-jogl'
|
include 'jme3-jogl'
|
||||||
include 'jme3-lwjgl'
|
include 'jme3-lwjgl'
|
||||||
|
include 'jme3-lwjgl3'
|
||||||
|
|
||||||
// Other external dependencies
|
// Other external dependencies
|
||||||
include 'jme3-jbullet'
|
include 'jme3-jbullet'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user