فهرست منبع

Merge remote-tracking branch 'origin/master' into experimental

Kirill Vainer 9 سال پیش
والد
کامیت
3bb01d6963
24فایلهای تغییر یافته به همراه233 افزوده شده و 36 حذف شده
  1. 2 0
      jme3-bullet-native/src/native/cpp/jmeClasses.cpp
  2. 1 0
      jme3-bullet-native/src/native/cpp/jmeClasses.h
  3. 22 2
      jme3-bullet-native/src/native/cpp/jmePhysicsSpace.cpp
  4. 15 0
      jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
  5. 21 2
      jme3-core/src/main/java/com/jme3/app/LegacyApplication.java
  6. 1 9
      jme3-core/src/main/java/com/jme3/app/SimpleApplication.java
  7. 16 0
      jme3-core/src/main/java/com/jme3/light/Light.java
  8. 1 0
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
  9. 6 0
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java
  10. 13 5
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  11. 6 1
      jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java
  12. 1 1
      jme3-core/src/main/java/com/jme3/shader/VarType.java
  13. 56 0
      jme3-core/src/main/java/com/jme3/texture/FrameBuffer.java
  14. 3 0
      jme3-core/src/main/java/com/jme3/util/clone/Cloner.java
  15. 1 0
      jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java
  16. 5 5
      jme3-jbullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
  17. 5 0
      jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java
  18. 5 0
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  19. 2 2
      jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
  20. 2 1
      jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java
  21. 1 1
      jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java
  22. 39 5
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java
  23. 4 2
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
  24. 5 0
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

+ 2 - 0
jme3-bullet-native/src/native/cpp/jmeClasses.cpp

@@ -40,6 +40,7 @@ jclass jmeClasses::PhysicsSpace;
 jmethodID jmeClasses::PhysicsSpace_preTick;
 jmethodID jmeClasses::PhysicsSpace_postTick;
 jmethodID jmeClasses::PhysicsSpace_addCollisionEvent;
+jmethodID jmeClasses::PhysicsSpace_notifyCollisionGroupListeners;
 
 jclass jmeClasses::PhysicsGhostObject;
 jmethodID jmeClasses::PhysicsGhostObject_addOverlappingObject;
@@ -137,6 +138,7 @@ void jmeClasses::initJavaClasses(JNIEnv* env) {
     PhysicsSpace_preTick = env->GetMethodID(PhysicsSpace, "preTick_native", "(F)V");
     PhysicsSpace_postTick = env->GetMethodID(PhysicsSpace, "postTick_native", "(F)V");
     PhysicsSpace_addCollisionEvent = env->GetMethodID(PhysicsSpace, "addCollisionEvent_native","(Lcom/jme3/bullet/collision/PhysicsCollisionObject;Lcom/jme3/bullet/collision/PhysicsCollisionObject;J)V");
+    PhysicsSpace_notifyCollisionGroupListeners = env->GetMethodID(PhysicsSpace, "notifyCollisionGroupListeners_native","(Lcom/jme3/bullet/collision/PhysicsCollisionObject;Lcom/jme3/bullet/collision/PhysicsCollisionObject;)Z");
     if (env->ExceptionCheck()) {
         env->Throw(env->ExceptionOccurred());
         return;

+ 1 - 0
jme3-bullet-native/src/native/cpp/jmeClasses.h

@@ -46,6 +46,7 @@ public:
     static jmethodID PhysicsSpace_addCollisionEvent;
     static jclass PhysicsGhostObject;
     static jmethodID PhysicsGhostObject_addOverlappingObject;
+    static jmethodID PhysicsSpace_notifyCollisionGroupListeners;
 
     static jclass Vector3f;
     static jmethodID Vector3f_set;

+ 22 - 2
jme3-bullet-native/src/native/cpp/jmePhysicsSpace.cpp

@@ -187,8 +187,28 @@ void jmePhysicsSpace::createPhysicsSpace(jfloat minX, jfloat minY, jfloat minZ,
                 jmeUserPointer *up0 = (jmeUserPointer*) co0 -> getUserPointer();
                 jmeUserPointer *up1 = (jmeUserPointer*) co1 -> getUserPointer();
                 if (up0 != NULL && up1 != NULL) {
-                    collides = (up0->group & up1->groups) != 0;
-                    collides = collides && (up1->group & up0->groups);
+                    collides = (up0->group & up1->groups) != 0 || (up1->group & up0->groups) != 0;
+                    
+                    if(collides){
+                        jmePhysicsSpace *dynamicsWorld = (jmePhysicsSpace *)up0->space;
+                        JNIEnv* env = dynamicsWorld->getEnv();
+                        jobject javaPhysicsSpace = env->NewLocalRef(dynamicsWorld->getJavaPhysicsSpace());
+                        jobject javaCollisionObject0 = env->NewLocalRef(up0->javaCollisionObject);
+                        jobject javaCollisionObject1 = env->NewLocalRef(up1->javaCollisionObject);
+                        
+                        jboolean notifyResult = env->CallBooleanMethod(javaPhysicsSpace, jmeClasses::PhysicsSpace_notifyCollisionGroupListeners, javaCollisionObject0, javaCollisionObject1);
+                        
+                        env->DeleteLocalRef(javaPhysicsSpace);
+                        env->DeleteLocalRef(javaCollisionObject0);
+                        env->DeleteLocalRef(javaCollisionObject1);
+
+                        if (env->ExceptionCheck()) {
+                            env->Throw(env->ExceptionOccurred());
+                            return collides;
+                        }
+                        
+                        collides = (bool) notifyResult;
+                    }
 
                     //add some additional logic here that modified 'collides'
                     return collides;

+ 15 - 0
jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java

@@ -335,6 +335,21 @@ public class PhysicsSpace {
 //        System.out.println("addCollisionEvent:"+node.getObjectId()+" "+ node1.getObjectId());
         collisionEvents.add(eventFactory.getEvent(PhysicsCollisionEvent.TYPE_PROCESSED, node, node1, manifoldPointObjectId));
     }
+    
+    private boolean notifyCollisionGroupListeners_native(PhysicsCollisionObject node, PhysicsCollisionObject node1){
+        PhysicsCollisionGroupListener listener = collisionGroupListeners.get(node.getCollisionGroup());
+        PhysicsCollisionGroupListener listener1 = collisionGroupListeners.get(node1.getCollisionGroup());
+        boolean result = true;
+        
+        if(listener != null){
+            result = listener.collide(node, node1);
+        }
+        if(listener1 != null && node.getCollisionGroup() != node1.getCollisionGroup()){
+            result = listener1.collide(node, node1) && result;
+        }
+        
+        return result;
+    }
 
     /**
      * updates the physics space

+ 21 - 2
jme3-core/src/main/java/com/jme3/app/LegacyApplication.java

@@ -31,6 +31,7 @@
  */
 package com.jme3.app;
 
+import com.jme3.app.state.AppState;
 import com.jme3.app.state.AppStateManager;
 import com.jme3.asset.AssetManager;
 import com.jme3.audio.AudioContext;
@@ -100,8 +101,24 @@ public class LegacyApplication implements Application, SystemListener {
     /**
      * Create a new instance of <code>LegacyApplication</code>.
      */
-    public LegacyApplication(){
+    public LegacyApplication() {
+        this((AppState[])null);
+    }
+
+    /**
+     * Create a new instance of <code>LegacyApplication</code>, preinitialized
+     * with the specified set of app states.
+     */
+    public LegacyApplication( AppState... initialStates ) {
         initStateManager();
+
+        if (initialStates != null) {
+            for (AppState a : initialStates) {
+                if (a != null) {
+                    stateManager.attach(a);
+                }
+            }
+        }
     }
 
     /**
@@ -523,7 +540,9 @@ public class LegacyApplication implements Application, SystemListener {
      * Internal use only.
      */
     public void reshape(int w, int h){
-        renderManager.notifyReshape(w, h);
+        if (renderManager != null) {
+            renderManager.notifyReshape(w, h);
+        }
     }
 
     /**

+ 1 - 9
jme3-core/src/main/java/com/jme3/app/SimpleApplication.java

@@ -100,15 +100,7 @@ public abstract class SimpleApplication extends LegacyApplication {
     }
 
     public SimpleApplication( AppState... initialStates ) {
-        super();
-
-        if (initialStates != null) {
-            for (AppState a : initialStates) {
-                if (a != null) {
-                    stateManager.attach(a);
-                }
-            }
-        }
+        super(initialStates);
     }
 
     @Override

+ 16 - 0
jme3-core/src/main/java/com/jme3/light/Light.java

@@ -184,6 +184,22 @@ public abstract class Light implements Savable, Cloneable {
         this.enabled = enabled;
     }
 
+    public boolean isFrustumCheckNeeded() {
+      return frustumCheckNeeded;
+    }
+
+    public void setFrustumCheckNeeded(boolean frustumCheckNeeded) {
+      this.frustumCheckNeeded = frustumCheckNeeded;
+    }
+
+    public boolean isIntersectsFrustum() {
+      return intersectsFrustum;
+    }
+
+    public void setIntersectsFrustum(boolean intersectsFrustum) {
+      this.intersectsFrustum = intersectsFrustum;
+    }
+    
     /**
      * Determines if the light intersects with the given bounding box.
      * <p>

+ 1 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java

@@ -58,6 +58,7 @@ public interface GL3 extends GL2 {
     public void glBindFragDataLocation(int param1, int param2, String param3); /// GL3+
     public void glBindVertexArray(int param1); /// GL3+
     public void glDeleteVertexArrays(IntBuffer arrays); /// GL3+
+    public void glFramebufferTextureLayer(int param1, int param2, int param3, int param4, int param5); /// GL3+
     public void glGenVertexArrays(IntBuffer param1); /// GL3+
     public String glGetString(int param1, int param2); /// GL3+
 }

+ 6 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java

@@ -94,4 +94,10 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 {
         gl4.glPatchParameter(count);
         checkError();
     }
+
+    @Override
+    public void glFramebufferTextureLayer(int param1, int param2, int param3, int param4, int param5) {
+        gl3.glFramebufferTextureLayer(param1, param2, param3, param4, param5);
+        checkError();
+    }
 }

+ 13 - 5
jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

@@ -1461,11 +1461,19 @@ public final class GLRenderer implements Renderer {
             setupTextureParams(0, tex);
         }
 
-        glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT,
-                convertAttachmentSlot(rb.getSlot()),
-                convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()),
-                image.getId(),
-                0);
+        if (rb.getLayer() < 0){
+            glfbo.glFramebufferTexture2DEXT(GLFbo.GL_FRAMEBUFFER_EXT,
+                    convertAttachmentSlot(rb.getSlot()),
+                    convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()),
+                    image.getId(),
+                    0);
+        } else {
+            gl3.glFramebufferTextureLayer(GLFbo.GL_FRAMEBUFFER_EXT, 
+                    convertAttachmentSlot(rb.getSlot()), 
+                    image.getId(), 
+                    0,
+                    rb.getLayer());
+        }
     }
 
     public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {

+ 6 - 1
jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java

@@ -258,7 +258,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
         }
        
         for (ShaderNodeVariable var : shaderNode.getDefinition().getOutputs()) {
-            ShaderNodeVariable v = new ShaderNodeVariable(var.getType(), shaderNode.getName(), var.getName());
+            ShaderNodeVariable v = new ShaderNodeVariable(var.getType(), shaderNode.getName(), var.getName(), var.getMultiplicity());
             if (!declaredInputs.contains(shaderNode.getName() + "_" + var.getName())) {
                 if (!isVarying(info, v)) {
                     declareVariable(source, v);
@@ -397,6 +397,11 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
         source.append(mapping.getLeftVariable().getNameSpace());
         source.append("_");
         source.append(mapping.getLeftVariable().getName());
+        if (mapping.getLeftVariable().getMultiplicity() != null){
+            source.append("[");
+            source.append(mapping.getLeftVariable().getMultiplicity());
+            source.append("]");
+        }
         
         //left swizzle, the variable can't be declared and assigned on the same line. 
         if (mapping.getLeftSwizzling().length() > 0) {

+ 1 - 1
jme3-core/src/main/java/com/jme3/shader/VarType.java

@@ -55,7 +55,7 @@ public enum VarType {
     TextureBuffer(false,true,"sampler1D|sampler1DShadow"),
     Texture2D(false,true,"sampler2D|sampler2DShadow"),
     Texture3D(false,true,"sampler3D"),
-    TextureArray(false,true,"sampler2DArray"),
+    TextureArray(false,true,"sampler2DArray|sampler2DArrayShadow"),
     TextureCubeMap(false,true,"samplerCube"),
     Int("int");
 

+ 56 - 0
jme3-core/src/main/java/com/jme3/texture/FrameBuffer.java

@@ -97,6 +97,7 @@ public class FrameBuffer extends NativeObject {
         int id = -1;
         int slot = SLOT_UNDEF;
         int face = -1;
+        int layer = -1;
         
         /**
          * @return The image format of the render buffer.
@@ -160,6 +161,10 @@ public class FrameBuffer extends NativeObject {
                 return "BufferTarget[format=" + format + "]";
             }
         }
+
+        public int getLayer() {
+            return this.layer;
+        }
     }
 
     /**
@@ -324,6 +329,19 @@ public class FrameBuffer extends NativeObject {
         addColorTexture(tex);
     }
     
+    /**
+     * Set the color texture array to use for this framebuffer.
+     * This automatically clears all existing textures added previously
+     * with {@link FrameBuffer#addColorTexture } and adds this texture as the
+     * only target.
+     * 
+     * @param tex The color texture array to set.
+     */
+    public void setColorTexture(TextureArray tex, int layer){
+        clearColorTargets();
+        addColorTexture(tex, layer);
+    }
+    
     /**
      * Set the color texture to use for this framebuffer.
      * This automatically clears all existing textures added previously
@@ -369,6 +387,31 @@ public class FrameBuffer extends NativeObject {
         colorBufs.add(colorBuf);
     }
     
+    /**
+     * Add a color texture array to use for this framebuffer.
+     * If MRT is enabled, then each subsequently added texture can be
+     * rendered to through a shader that writes to the array <code>gl_FragData</code>.
+     * If MRT is not enabled, then the index set with {@link FrameBuffer#setTargetIndex(int) }
+     * is rendered to by the shader.
+     * 
+     * @param tex The texture array to add.
+     */
+    public void addColorTexture(TextureArray tex, int layer) {
+        if (id != -1)
+            throw new UnsupportedOperationException("FrameBuffer already initialized.");
+
+        Image img = tex.getImage();
+        checkSetTexture(tex, false);
+
+        RenderBuffer colorBuf = new RenderBuffer();
+        colorBuf.slot = colorBufs.size();
+        colorBuf.tex = tex;
+        colorBuf.format = img.getFormat();
+        colorBuf.layer = layer;
+
+        colorBufs.add(colorBuf);
+    }
+    
      /**
      * Add a color texture to use for this framebuffer.
      * If MRT is enabled, then each subsequently added texture can be
@@ -412,7 +455,20 @@ public class FrameBuffer extends NativeObject {
         depthBuf.tex = tex;
         depthBuf.format = img.getFormat();
     }
+    public void setDepthTexture(TextureArray tex, int layer){
+        if (id != -1)
+            throw new UnsupportedOperationException("FrameBuffer already initialized.");
 
+        Image img = tex.getImage();
+        checkSetTexture(tex, true);
+        
+        depthBuf = new RenderBuffer();
+        depthBuf.slot = img.getFormat().isDepthStencilFormat() ?  SLOT_DEPTH_STENCIL : SLOT_DEPTH;
+        depthBuf.tex = tex;
+        depthBuf.format = img.getFormat();
+        depthBuf.layer = layer;
+    }
+    
     /**
      * @return The number of color buffers attached to this texture. 
      */

+ 3 - 0
jme3-core/src/main/java/com/jme3/util/clone/Cloner.java

@@ -354,6 +354,9 @@ public class Cloner {
      *  clone() and objects without necessarily knowing their real type.</p>
      */
     public <T> T javaClone( T object ) throws CloneNotSupportedException {
+        if( object == null ) {
+            return null;
+        }
         Method m = methodCache.get(object.getClass());
         if( m == null ) {
             try {

+ 1 - 0
jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java

@@ -753,6 +753,7 @@ public class ShaderNodeLoaderDelegate {
             }
             right.setNameSpace(node.getName());
             right.setType(var.getType());
+            right.setMultiplicity(var.getMultiplicity());
             mapping.setRightVariable(right);            
             storeVaryings(node, mapping.getRightVariable());
 

+ 5 - 5
jme3-jbullet/src/main/java/com/jme3/bullet/PhysicsSpace.java

@@ -237,12 +237,12 @@ public class PhysicsSpace {
                             || (collisionObject1.getCollideWithGroups() & collisionObject.getCollisionGroup()) > 0) {
                         PhysicsCollisionGroupListener listener = collisionGroupListeners.get(collisionObject.getCollisionGroup());
                         PhysicsCollisionGroupListener listener1 = collisionGroupListeners.get(collisionObject1.getCollisionGroup());
-                        if (listener != null) {
-                            return listener.collide(collisionObject, collisionObject1);
-                        } else if (listener1 != null) {
-                            return listener1.collide(collisionObject, collisionObject1);
+                        if(listener != null){
+                            collides = listener.collide(collisionObject, collisionObject1);
+                        }
+                        if(listener1 != null && collisionObject.getCollisionGroup() != collisionObject1.getCollisionGroup()){
+                            collides = listener1.collide(collisionObject, collisionObject1) && collides;
                         }
-                        return true;
                     } else {
                         return false;
                     }

+ 5 - 0
jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java

@@ -600,4 +600,9 @@ public class JoglGL implements GL, GL2, GL3, GL4 {
         checkLimit(arrays);
         GLContext.getCurrentGL().getGL2ES3().glDeleteVertexArrays(arrays.limit(), arrays);
     }
+
+    @Override
+    public void glFramebufferTextureLayer(int param1, int param2, int param3, int param4, int param5) {
+        GLContext.getCurrentGL().getGL3().glFramebufferTextureLayer(param1, param2, param3, param4, param5);
+    }
 }

+ 5 - 0
jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

@@ -457,4 +457,9 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 {
         checkLimit(arrays);
         ARBVertexArrayObject.glDeleteVertexArrays(arrays);
     }
+
+    @Override
+    public void glFramebufferTextureLayer(int param1, int param2, int param3, int param4, int param5) {
+        GL30.glFramebufferTextureLayer(param1, param2, param3, param4, param5);
+    }
 }

+ 2 - 2
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java

@@ -301,7 +301,7 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
             // crashes on bad drivers
             if (pbufferFormat == null){
                 pbufferFormat = new PixelFormat(settings.getBitsPerPixel(),
-                                                0,
+                                                settings.getAlphaBits(),
                                                 settings.getDepthBits(),
                                                 settings.getStencilBits(),
                                                 0, // samples
@@ -315,7 +315,7 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
             if (canvasFormat == null){
                 int samples = getNumSamplesToUse();
                 canvasFormat = new PixelFormat(settings.getBitsPerPixel(),
-                                               0,
+                                               settings.getAlphaBits(),
                                                settings.getDepthBits(),
                                                settings.getStencilBits(),
                                                samples,

+ 2 - 1
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java

@@ -84,7 +84,7 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
 
         int samples = getNumSamplesToUse();
         PixelFormat pf = new PixelFormat(settings.getBitsPerPixel(),
-                                         0,
+                                         settings.getAlphaBits(),
                                          settings.getDepthBits(),
                                          settings.getStencilBits(),
                                          samples, 
@@ -99,6 +99,7 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
 
         boolean pixelFormatChanged = false;
         if (created.get() && (pixelFormat.getBitsPerPixel() != pf.getBitsPerPixel()
+        					||pixelFormat.getAlphaBits() != pf.getAlphaBits()
                             ||pixelFormat.getDepthBits() != pf.getDepthBits()
                             ||pixelFormat.getStencilBits() != pf.getStencilBits()
                             ||pixelFormat.getSamples() != pf.getSamples())){

+ 1 - 1
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java

@@ -62,7 +62,7 @@ public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
 
         int samples = getNumSamplesToUse();
         pixelFormat = new PixelFormat(settings.getBitsPerPixel(),
-                                      0,
+                                      settings.getAlphaBits(),
                                       settings.getDepthBits(),
                                       settings.getStencilBits(),
                                       samples);

+ 39 - 5
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java

@@ -36,13 +36,21 @@ import com.jme3.input.KeyInput;
 import com.jme3.input.RawInputListener;
 import com.jme3.input.event.KeyInputEvent;
 import com.jme3.system.lwjgl.LwjglWindow;
+
+import org.lwjgl.glfw.GLFWCharCallback;
 import org.lwjgl.glfw.GLFWKeyCallback;
 
 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.logging.Logger;
 
-import static org.lwjgl.glfw.GLFW.*;
+import static org.lwjgl.glfw.GLFW.GLFW_KEY_LAST;
+import static org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE;
+import static org.lwjgl.glfw.GLFW.GLFW_PRESS;
+import static org.lwjgl.glfw.GLFW.GLFW_REPEAT;
+import static org.lwjgl.glfw.GLFW.glfwGetTime;
+import static org.lwjgl.glfw.GLFW.glfwSetCharCallback;
+import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
 
 public class GlfwKeyInput implements KeyInput {
 
@@ -52,6 +60,7 @@ public class GlfwKeyInput implements KeyInput {
     private RawInputListener listener;
     private boolean initialized;
     private GLFWKeyCallback keyCallback;
+    private GLFWCharCallback charCallback;
     private Queue<KeyInputEvent> keyInputEvents = new LinkedList<KeyInputEvent>();
 
     public GlfwKeyInput(LwjglWindow context) {
@@ -66,14 +75,38 @@ public class GlfwKeyInput implements KeyInput {
         glfwSetKeyCallback(context.getWindowHandle(), keyCallback = new GLFWKeyCallback() {
             @Override
             public void invoke(long window, int key, int scancode, int action, int mods) {
+
+                if (key < 0 || key > GLFW_KEY_LAST) {
+                    return;
+                }
+
                 int jmeKey = GlfwKeyMap.toJmeKeyCode(key);
-                final KeyInputEvent evt = new KeyInputEvent(jmeKey, (char) key, GLFW_PRESS == action, GLFW_REPEAT == action);
-                evt.setTime(getInputTimeNanos());
-                keyInputEvents.add(evt);
+
+                final KeyInputEvent event = new KeyInputEvent(jmeKey, '\0', GLFW_PRESS == action, GLFW_REPEAT == action);
+                event.setTime(getInputTimeNanos());
+
+                keyInputEvents.add(event);
             }
         });
 
-        glfwSetInputMode(context.getWindowHandle(), GLFW_STICKY_KEYS, 1);
+        glfwSetCharCallback(context.getWindowHandle(), charCallback = new GLFWCharCallback() {
+
+            @Override
+            public void invoke(long window, int codepoint) {
+
+                final char keyChar = (char) codepoint;
+
+                final KeyInputEvent pressed = new KeyInputEvent(KeyInput.KEY_UNKNOWN, keyChar, true, false);
+                pressed.setTime(getInputTimeNanos());
+
+                keyInputEvents.add(pressed);
+
+                final KeyInputEvent released = new KeyInputEvent(KeyInput.KEY_UNKNOWN, keyChar, false, false);
+                released.setTime(getInputTimeNanos());
+
+                keyInputEvents.add(released);
+            }
+        });
 
         initialized = true;
         logger.fine("Keyboard created.");
@@ -100,6 +133,7 @@ public class GlfwKeyInput implements KeyInput {
         }
 
         keyCallback.release();
+        charCallback.release();
         logger.fine("Keyboard destroyed.");
     }
 

+ 4 - 2
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java

@@ -67,6 +67,8 @@ public class GlfwMouseInput implements MouseInput {
 
     private static final Logger logger = Logger.getLogger(GlfwMouseInput.class.getName());
 
+    private static final int WHEEL_SCALE = 120;
+
     private LwjglWindow context;
     private RawInputListener listener;
     private boolean cursorVisible = true;
@@ -136,7 +138,7 @@ public class GlfwMouseInput implements MouseInput {
         glfwSetScrollCallback(context.getWindowHandle(), scrollCallback = new GLFWScrollCallback() {
             @Override
             public void invoke(final long window, final double xOffset, final double yOffset) {
-                onWheelScroll(window, xOffset, yOffset);
+                onWheelScroll(window, xOffset, yOffset * WHEEL_SCALE);
             }
         });
 
@@ -213,7 +215,7 @@ public class GlfwMouseInput implements MouseInput {
 
         // TODO: currently animated cursors are not supported
         IntBuffer imageData = jmeCursor.getImagesData();
-        ByteBuffer buf = BufferUtils.createByteBuffer(imageData.capacity());
+        ByteBuffer buf = BufferUtils.createByteBuffer(imageData.capacity() * 4);
         buf.asIntBuffer().put(imageData);
 
         glfwImage.set(jmeCursor.getWidth(), jmeCursor.getHeight(), buf);

+ 5 - 0
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

@@ -486,4 +486,9 @@ public class LwjglGL implements GL, GL2, GL3, GL4 {
         checkLimit(arrays);
         ARBVertexArrayObject.glDeleteVertexArrays(arrays);
     }
+
+    @Override
+    public void glFramebufferTextureLayer(int param1, int param2, int param3, int param4, int param5) {
+        GL30.glFramebufferTextureLayer(param1, param2, param3, param4, param5);
+    }
 }