diff --git a/jme3-bullet-native/src/native/cpp/jmeClasses.cpp b/jme3-bullet-native/src/native/cpp/jmeClasses.cpp
index 6b7caa0e9..ae7784c82 100644
--- a/jme3-bullet-native/src/native/cpp/jmeClasses.cpp
+++ b/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;
diff --git a/jme3-bullet-native/src/native/cpp/jmeClasses.h b/jme3-bullet-native/src/native/cpp/jmeClasses.h
index bb1b0e99a..bdead6b70 100644
--- a/jme3-bullet-native/src/native/cpp/jmeClasses.h
+++ b/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;
diff --git a/jme3-bullet-native/src/native/cpp/jmePhysicsSpace.cpp b/jme3-bullet-native/src/native/cpp/jmePhysicsSpace.cpp
index 34c77c407..8cb80bc87 100644
--- a/jme3-bullet-native/src/native/cpp/jmePhysicsSpace.cpp
+++ b/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;
diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java b/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
index edea485ef..f3575bcdf 100644
--- a/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java
+++ b/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
diff --git a/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java b/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java
index 89a81be5b..d796ba309 100644
--- a/jme3-core/src/main/java/com/jme3/app/LegacyApplication.java
+++ b/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 LegacyApplication
.
*/
- public LegacyApplication(){
+ public LegacyApplication() {
+ this((AppState[])null);
+ }
+
+ /**
+ * Create a new instance of LegacyApplication
, 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);
+ }
}
/**
diff --git a/jme3-core/src/main/java/com/jme3/app/SimpleApplication.java b/jme3-core/src/main/java/com/jme3/app/SimpleApplication.java
index 310191007..2ab008c5c 100644
--- a/jme3-core/src/main/java/com/jme3/app/SimpleApplication.java
+++ b/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
diff --git a/jme3-core/src/main/java/com/jme3/light/Light.java b/jme3-core/src/main/java/com/jme3/light/Light.java
index f6ea68045..9836c7db0 100644
--- a/jme3-core/src/main/java/com/jme3/light/Light.java
+++ b/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.
*
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
index 2a7c38bb9..1fbad5c2d 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
+++ b/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+
}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java
index a0511f6ad..fd18cc7ff 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java
+++ b/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();
+ }
}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
index 76e3a873e..85d786b7e 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
+++ b/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) {
diff --git a/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java b/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java
index a7a53b915..ffe96d0f0 100644
--- a/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java
+++ b/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) {
diff --git a/jme3-core/src/main/java/com/jme3/shader/VarType.java b/jme3-core/src/main/java/com/jme3/shader/VarType.java
index b494daf57..7300294d4 100644
--- a/jme3-core/src/main/java/com/jme3/shader/VarType.java
+++ b/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");
diff --git a/jme3-core/src/main/java/com/jme3/texture/FrameBuffer.java b/jme3-core/src/main/java/com/jme3/texture/FrameBuffer.java
index bc21fd82b..a3f825d26 100644
--- a/jme3-core/src/main/java/com/jme3/texture/FrameBuffer.java
+++ b/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 gl_FragData
.
+ * 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.
*/
diff --git a/jme3-core/src/main/java/com/jme3/util/clone/Cloner.java b/jme3-core/src/main/java/com/jme3/util/clone/Cloner.java
index ba202e463..4b812006f 100644
--- a/jme3-core/src/main/java/com/jme3/util/clone/Cloner.java
+++ b/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.