Date: Sun, 13 Sep 2015 20:30:36 +0100
Subject: [PATCH 41/94] Reverted some more light code which should not be in
this branch.
---
.../src/main/java/com/jme3/light/AmbientLight.java | 6 +++---
.../main/java/com/jme3/light/DirectionalLight.java | 12 ++++++------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
index 101a4efc7..8dd5f9266 100644
--- a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
@@ -45,7 +45,7 @@ import com.jme3.util.TempVars;
* regardless of the model's location. The material's ambient color is
* multiplied by the ambient light color to get the final ambient color of
* an object.
- *
+ *
* @author Kirill Vainer
*/
public class AmbientLight extends Light {
@@ -61,12 +61,12 @@ public class AmbientLight extends Light {
public boolean intersectsBox(BoundingBox box, TempVars vars) {
return true;
}
-
+
@Override
public boolean intersectsFrustum(Camera camera, TempVars vars) {
return true;
}
-
+
@Override
public void computeLastDistance(Spatial owner) {
}
diff --git a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
index 333154b2d..87fbf695a 100644
--- a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
@@ -85,10 +85,10 @@ public class DirectionalLight extends Light {
/**
* Returns the direction vector of the light.
- *
+ *
* @return The direction vector of the light.
- *
- * @see DirectionalLight#setDirection(com.jme3.math.Vector3f)
+ *
+ * @see DirectionalLight#setDirection(com.jme3.math.Vector3f)
*/
public Vector3f getDirection() {
return direction;
@@ -99,7 +99,7 @@ public class DirectionalLight extends Light {
*
* Represents the direction the light is shining.
* (1, 0, 0) would represent light shining in the +X direction.
- *
+ *
* @param dir the direction of the light.
*/
public final void setDirection(Vector3f dir){
@@ -113,12 +113,12 @@ public class DirectionalLight extends Light {
public boolean intersectsBox(BoundingBox box, TempVars vars) {
return true;
}
-
+
@Override
public boolean intersectsFrustum(Camera camera, TempVars vars) {
return true;
}
-
+
@Override
public Type getType() {
return Type.Directional;
From d8e964b2f0f7b1c7e729fcd748cbc9c6ea062596 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Sun, 13 Sep 2015 20:43:41 +0100
Subject: [PATCH 42/94] Added copyright headers to some files.
---
.../java/com/jme3/audio/lwjgl/LwjglALC.java | 31 ++++++++++++++++++
.../java/com/jme3/audio/lwjgl/LwjglEFX.java | 31 ++++++++++++++++++
.../java/com/jme3/renderer/lwjgl/LwjglGL.java | 31 ++++++++++++++++++
.../com/jme3/renderer/lwjgl/LwjglGLExt.java | 31 ++++++++++++++++++
.../jme3/renderer/lwjgl/LwjglGLFboEXT.java | 31 ++++++++++++++++++
.../jme3/renderer/lwjgl/LwjglGLFboGL3.java | 31 ++++++++++++++++++
.../com/jme3/system/lwjgl/LwjglDisplay.java | 32 ++++++++++++++++++-
.../system/lwjgl/LwjglOffscreenBuffer.java | 32 ++++++++++++++++++-
.../com/jme3/system/lwjgl/LwjglWindow.java | 3 +-
9 files changed, 249 insertions(+), 4 deletions(-)
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
index e0aed80ee..b0b1bc1e3 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
@@ -1,3 +1,34 @@
+/*
+ * 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.ALC;
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java
index 2ddd09ed8..ecd67211f 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java
@@ -1,3 +1,34 @@
+/*
+ * 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.EFX;
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
index 80e7f3513..187b232f2 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
@@ -1,3 +1,34 @@
+/*
+ * 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.renderer.lwjgl;
import com.jme3.renderer.RendererException;
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java
index 00b3f688c..2ed2ec215 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java
@@ -1,3 +1,34 @@
+/*
+ * 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.renderer.lwjgl;
import com.jme3.renderer.RendererException;
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java
index 969d7ae1d..5d9fe8dc1 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java
@@ -1,3 +1,34 @@
+/*
+ * 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.renderer.lwjgl;
import com.jme3.renderer.RendererException;
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java
index aa15aeb09..5a7a9825e 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java
@@ -1,3 +1,34 @@
+/*
+ * 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.renderer.lwjgl;
import com.jme3.renderer.RendererException;
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java
index 4a13c30af..3eb749adc 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java
@@ -1,8 +1,38 @@
+/*
+ * 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;
/**
* @author Daniel Johansson
- * @since 2015-08-11
*/
public class LwjglDisplay extends LwjglWindow {
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java
index e374e1841..8fdde51af 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java
@@ -1,10 +1,40 @@
+/*
+ * 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.JmeContext;
/**
* @author Daniel Johansson
- * @since 2015-08-11
*/
public class LwjglOffscreenBuffer extends LwjglWindow {
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
index 6eac34cdc..c5cb35e03 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
@@ -60,8 +60,7 @@ import static org.lwjgl.system.MemoryUtil.NULL;
/**
* A wrapper class over the GLFW framework in LWJGL 3.
*
- * @author Daniel Johansson (dannyjo)
- * @since 3.1
+ * @author Daniel Johansson
*/
public abstract class LwjglWindow extends LwjglContext implements Runnable {
From 45f8893f13ea19c16287da95734baabb10e3ff5d Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 18:40:08 -0400
Subject: [PATCH 43/94] bounding: properly implement collideWith against other
bounds
---
.../main/java/com/jme3/bounding/BoundingBox.java | 10 ++++++++++
.../main/java/com/jme3/bounding/BoundingSphere.java | 12 +++++++++++-
.../main/java/com/jme3/bounding/BoundingVolume.java | 13 +++++++------
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
index bdba19fe3..11ee8b2ea 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
@@ -790,6 +790,7 @@ public class BoundingBox extends BoundingVolume {
}
}
+ @Override
public int collideWith(Collidable other, CollisionResults results) {
if (other instanceof Ray) {
Ray ray = (Ray) other;
@@ -802,6 +803,13 @@ public class BoundingBox extends BoundingVolume {
return 1;
}
return 0;
+ } else if (other instanceof BoundingVolume) {
+ if (intersects((BoundingVolume) other)) {
+ CollisionResult r = new CollisionResult();
+ results.addCollision(r);
+ return 1;
+ }
+ return 0;
} else {
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
}
@@ -818,6 +826,8 @@ public class BoundingBox extends BoundingVolume {
return 1;
}
return 0;
+ } else if (other instanceof BoundingVolume) {
+ return intersects((BoundingVolume) other) ? 1 : 0;
} else {
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
}
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
index d5dd56203..adb763f83 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
@@ -1013,17 +1013,27 @@ public class BoundingSphere extends BoundingVolume {
} else if (other instanceof Triangle){
Triangle t = (Triangle) other;
return collideWithTri(t, results);
+ } else if (other instanceof BoundingVolume) {
+ if (intersects((BoundingVolume)other)) {
+ CollisionResult result = new CollisionResult();
+ results.addCollision(result);
+ return 1;
+ }
+ return 0;
} else {
throw new UnsupportedCollisionException();
}
}
- @Override public int collideWith(Collidable other) {
+ @Override
+ public int collideWith(Collidable other) {
if (other instanceof Ray) {
Ray ray = (Ray) other;
return collideWithRay(ray);
} else if (other instanceof Triangle){
return super.collideWith(other);
+ } else if (other instanceof BoundingVolume) {
+ return intersects((BoundingVolume)other) ? 1 : 0;
} else {
throw new UnsupportedCollisionException();
}
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java
index f9be2e573..4491fcedf 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java
@@ -327,12 +327,13 @@ public abstract class BoundingVolume implements Savable, Cloneable, Collidable {
public int collideWith(Collidable other) {
TempVars tempVars = TempVars.get();
- CollisionResults tempResults = tempVars.collisionResults;
- tempResults.clear();
- int retval = collideWith(other, tempResults);
- tempVars.release();
- return retval;
+ try {
+ CollisionResults tempResults = tempVars.collisionResults;
+ tempResults.clear();
+ return collideWith(other, tempResults);
+ } finally {
+ tempVars.release();
+ }
}
-
}
From 1fa6c4ac11619aeeeaf9d617749865e5d93c8120 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 22:05:18 -0400
Subject: [PATCH 44/94] bounding: move intersection algorithms to shared class
These algorithms are to be shared with the light filter.
---
.../java/com/jme3/bounding/BoundingBox.java | 13 +----
.../com/jme3/bounding/BoundingSphere.java | 23 +--------
.../java/com/jme3/bounding/Intersection.java | 48 ++++++++++++++++++-
3 files changed, 50 insertions(+), 34 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
index 11ee8b2ea..06f78154e 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
@@ -593,18 +593,7 @@ public class BoundingBox extends BoundingVolume {
* @see BoundingVolume#intersectsSphere(com.jme3.bounding.BoundingSphere)
*/
public boolean intersectsSphere(BoundingSphere bs) {
- assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
-
- if (FastMath.abs(center.x - bs.center.x) < bs.getRadius()
- + xExtent
- && FastMath.abs(center.y - bs.center.y) < bs.getRadius()
- + yExtent
- && FastMath.abs(center.z - bs.center.z) < bs.getRadius()
- + zExtent) {
- return true;
- }
-
- return false;
+ return bs.intersectsBoundingBox(this);
}
/**
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
index adb763f83..5eecf040a 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
@@ -670,15 +670,7 @@ public class BoundingSphere extends BoundingVolume {
* @see com.jme.bounding.BoundingVolume#intersectsSphere(com.jme.bounding.BoundingSphere)
*/
public boolean intersectsSphere(BoundingSphere bs) {
- assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
-
- TempVars vars = TempVars.get();
-
- Vector3f diff = center.subtract(bs.center, vars.vect1);
- float rsum = getRadius() + bs.getRadius();
- boolean eq = (diff.dot(diff) <= rsum * rsum);
- vars.release();
- return eq;
+ return Intersection.intersect(bs, center, radius);
}
/*
@@ -687,18 +679,7 @@ public class BoundingSphere extends BoundingVolume {
* @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox)
*/
public boolean intersectsBoundingBox(BoundingBox bb) {
- assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center);
-
- if (FastMath.abs(bb.center.x - center.x) < getRadius()
- + bb.xExtent
- && FastMath.abs(bb.center.y - center.y) < getRadius()
- + bb.yExtent
- && FastMath.abs(bb.center.z - center.z) < getRadius()
- + bb.zExtent) {
- return true;
- }
-
- return false;
+ return Intersection.intersect(bb, center, radius);
}
/*
diff --git a/jme3-core/src/main/java/com/jme3/bounding/Intersection.java b/jme3-core/src/main/java/com/jme3/bounding/Intersection.java
index 9deb62abc..c627e23e5 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/Intersection.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/Intersection.java
@@ -41,10 +41,56 @@ import static java.lang.Math.min;
/**
* This class includes some utility methods for computing intersection
* between bounding volumes and triangles.
+ *
* @author Kirill
*/
-public class Intersection {
+public final class Intersection {
+ private Intersection() {
+ }
+
+ public static boolean intersect(BoundingSphere sphere, Vector3f center, float radius) {
+ assert Vector3f.isValidVector(center) && Vector3f.isValidVector(sphere.center);
+
+ TempVars vars = TempVars.get();
+ try {
+ Vector3f diff = center.subtract(sphere.center, vars.vect1);
+ float rsum = sphere.getRadius() + radius;
+ return (diff.dot(diff) <= rsum * rsum);
+ } finally {
+ vars.release();
+ }
+ }
+
+ public static boolean intersect(BoundingBox bbox, Vector3f center, float radius) {
+ assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bbox.center);
+
+ // Arvo's algorithm
+ float distSqr = radius * radius;
+
+ float minX = bbox.center.x - bbox.xExtent;
+ float maxX = bbox.center.x + bbox.xExtent;
+
+ float minY = bbox.center.y - bbox.yExtent;
+ float maxY = bbox.center.y + bbox.yExtent;
+
+ float minZ = bbox.center.z - bbox.zExtent;
+ float maxZ = bbox.center.z + bbox.zExtent;
+
+ if (center.x < minX) distSqr -= FastMath.sqr(center.x - minX);
+ else if (center.x > maxX) distSqr -= FastMath.sqr(center.x - maxX);
+
+
+ if (center.y < minY) distSqr -= FastMath.sqr(center.y - minY);
+ else if (center.y > maxY) distSqr -= FastMath.sqr(center.y - maxY);
+
+
+ if (center.z < minZ) distSqr -= FastMath.sqr(center.z - minZ);
+ else if (center.z > maxZ) distSqr -= FastMath.sqr(center.z - maxZ);
+
+ return distSqr > 0;
+ }
+
private static final void findMinMax(float x0, float x1, float x2, Vector3f minMax) {
minMax.set(x0, x0, 0);
if (x1 < minMax.x) {
From 31383778d9d578c74d12e6cf2aaaddb582f8c082 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 22:06:32 -0400
Subject: [PATCH 45/94] light: ensure directional lights are sorted to be
always first
---
jme3-core/src/main/java/com/jme3/light/AmbientLight.java | 2 ++
jme3-core/src/main/java/com/jme3/light/DirectionalLight.java | 4 +++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
index 8dd5f9266..58676851c 100644
--- a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
@@ -69,6 +69,8 @@ public class AmbientLight extends Light {
@Override
public void computeLastDistance(Spatial owner) {
+ // ambient lights must always be before directional lights.
+ lastDistance = -2;
}
@Override
diff --git a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
index 87fbf695a..b8e1a1979 100644
--- a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
@@ -80,7 +80,9 @@ public class DirectionalLight extends Light {
@Override
public void computeLastDistance(Spatial owner) {
- lastDistance = 0; // directional lights are always closest to their owner
+ // directional lights are after ambient lights
+ // but before all other lights.
+ lastDistance = -1;
}
/**
From 6238088688be5913fd40518f2d01dbdfcaa65720 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 22:07:34 -0400
Subject: [PATCH 46/94] light: minor non-functional changes
---
jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java | 2 ++
jme3-core/src/main/java/com/jme3/light/Light.java | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java b/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java
index 81287279e..c8456529d 100644
--- a/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java
+++ b/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java
@@ -44,6 +44,7 @@ public final class DefaultLightFilter implements LightFilter {
private Camera camera;
private final HashSet processedLights = new HashSet();
+ @Override
public void setCamera(Camera camera) {
this.camera = camera;
for (Light light : processedLights) {
@@ -51,6 +52,7 @@ public final class DefaultLightFilter implements LightFilter {
}
}
+ @Override
public void filterLights(Geometry geometry, LightList filteredLightList) {
TempVars vars = TempVars.get();
try {
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 b1c48be7a..bac775aeb 100644
--- a/jme3-core/src/main/java/com/jme3/light/Light.java
+++ b/jme3-core/src/main/java/com/jme3/light/Light.java
@@ -197,7 +197,7 @@ public abstract class Light implements Savable, Cloneable {
public abstract boolean intersectsBox(BoundingBox box, TempVars vars);
/**
- * Determines if the lgiht intersects with the given camera frustum.
+ * Determines if the light intersects with the given camera frustum.
*
* For non-local lights, such as {@link DirectionalLight directional lights},
* {@link AmbientLight ambient lights}, or {@link PointLight point lights}
From 22dde7f718ed9da787f94d6cfc46557bb6d1615b Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 22:08:17 -0400
Subject: [PATCH 47/94] point light: more accurate sphere vs box filter
---
jme3-core/src/main/java/com/jme3/light/PointLight.java | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/PointLight.java b/jme3-core/src/main/java/com/jme3/light/PointLight.java
index ff3b3295f..1f515e71c 100644
--- a/jme3-core/src/main/java/com/jme3/light/PointLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/PointLight.java
@@ -33,12 +33,12 @@ package com.jme3.light;
import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingVolume;
+import com.jme3.bounding.Intersection;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Spatial;
@@ -191,9 +191,7 @@ public class PointLight extends Light {
return true;
} else {
// Sphere v. box collision
- return FastMath.abs(box.getCenter().x - position.x) < radius + box.getXExtent()
- && FastMath.abs(box.getCenter().y - position.y) < radius + box.getYExtent()
- && FastMath.abs(box.getCenter().z - position.z) < radius + box.getZExtent();
+ return Intersection.intersect(box, position, radius);
}
}
From c41058a5a04e17e509cab24282597ed3f2490722 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 22:09:20 -0400
Subject: [PATCH 48/94] spot light: fix broken filter for infinite range
---
jme3-core/src/main/java/com/jme3/light/SpotLight.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
index 9b551d3d8..de24280ab 100644
--- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
@@ -227,7 +227,10 @@ public class SpotLight extends Light {
@Override
public boolean intersectsFrustum(Camera cam, TempVars vars) {
-
+ if (spotRange == 0) {
+ // The algorithm below does not support infinite spot range.
+ return true;
+ }
Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange));
for (int i = 5; i >= 0; i--) {
//check origin against the plane
From 81b5c48fb014eb127eef356e5eb40b242898a34d Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 22:11:11 -0400
Subject: [PATCH 49/94] unit test: add unit tests for bounds and light filter /
sort
---
.../jme3/collision/BoundingCollisionTest.java | 166 ++++++++++++++++
.../com/jme3/collision/CollisionUtil.java | 80 ++++++++
.../java/com/jme3/light/LightFilterTest.java | 179 ++++++++++++++++++
.../java/com/jme3/light/LightSortTest.java | 115 +++++++++++
4 files changed, 540 insertions(+)
create mode 100644 jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java
create mode 100644 jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java
create mode 100644 jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
create mode 100644 jme3-core/src/test/java/com/jme3/light/LightSortTest.java
diff --git a/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java b/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java
new file mode 100644
index 000000000..7c3104292
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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.collision;
+
+import static com.jme3.collision.CollisionUtil.*;
+
+import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
+import com.jme3.math.FastMath;
+import com.jme3.math.Ray;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Quad;
+import org.junit.Test;
+
+/**
+ * Tests collision detection between bounding volumes.
+ *
+ * @author Kirill Vainer
+ */
+public class BoundingCollisionTest {
+
+ @Test
+ public void testBoxBoxCollision() {
+ BoundingBox box1 = new BoundingBox(Vector3f.ZERO, 1, 1, 1);
+ BoundingBox box2 = new BoundingBox(Vector3f.ZERO, 1, 1, 1);
+ checkCollision(box1, box2, 1);
+
+ // Put it at the very edge - should still intersect.
+ box2.setCenter(new Vector3f(2f, 0f, 0f));
+ checkCollision(box1, box2, 1);
+
+ // Put it a wee bit farther - no intersection expected
+ box2.setCenter(new Vector3f(2f + FastMath.ZERO_TOLERANCE, 0, 0));
+ checkCollision(box1, box2, 0);
+
+ // Check the corners.
+ box2.setCenter(new Vector3f(2f, 2f, 2f));
+ checkCollision(box1, box2, 1);
+
+ box2.setCenter(new Vector3f(2f, 2f, 2f + FastMath.ZERO_TOLERANCE));
+ checkCollision(box1, box2, 0);
+ }
+
+ @Test
+ public void testSphereSphereCollision() {
+ BoundingSphere sphere1 = new BoundingSphere(1, Vector3f.ZERO);
+ BoundingSphere sphere2 = new BoundingSphere(1, Vector3f.ZERO);
+ checkCollision(sphere1, sphere2, 1);
+
+ // Put it at the very edge - should still intersect.
+ sphere2.setCenter(new Vector3f(2f, 0f, 0f));
+ checkCollision(sphere1, sphere2, 1);
+
+ // Put it a wee bit farther - no intersection expected
+ sphere2.setCenter(new Vector3f(2f + FastMath.ZERO_TOLERANCE, 0, 0));
+ checkCollision(sphere1, sphere2, 0);
+ }
+
+ @Test
+ public void testBoxSphereCollision() {
+ BoundingBox box1 = new BoundingBox(Vector3f.ZERO, 1, 1, 1);
+ BoundingSphere sphere2 = new BoundingSphere(1, Vector3f.ZERO);
+ checkCollision(box1, sphere2, 1);
+
+ // Put it at the very edge - for sphere vs. box, it will not intersect
+ sphere2.setCenter(new Vector3f(2f, 0f, 0f));
+ checkCollision(box1, sphere2, 0);
+
+ // Put it a wee bit closer - should intersect.
+ sphere2.setCenter(new Vector3f(2f - FastMath.ZERO_TOLERANCE, 0, 0));
+ checkCollision(box1, sphere2, 1);
+
+ // Test if the algorithm converts the sphere
+ // to a box before testing the collision (incorrect)
+ float sqrt3 = FastMath.sqrt(3);
+
+ sphere2.setCenter(Vector3f.UNIT_XYZ.mult(2));
+ sphere2.setRadius(sqrt3);
+ checkCollision(box1, sphere2, 0);
+
+ // Make it a wee bit larger.
+ sphere2.setRadius(sqrt3 + FastMath.ZERO_TOLERANCE);
+ checkCollision(box1, sphere2, 1);
+ }
+
+ @Test
+ public void testBoxRayCollision() {
+ BoundingBox box = new BoundingBox(Vector3f.ZERO, 1, 1, 1);
+ Ray ray = new Ray(Vector3f.ZERO, Vector3f.UNIT_Z);
+
+ // XXX: seems incorrect, ray inside box should only generate
+ // one result...
+ checkCollision(box, ray, 2);
+
+ ray.setOrigin(new Vector3f(0, 0, -5));
+ checkCollision(box, ray, 2);
+
+ // XXX: is this right? the ray origin is on the box's side..
+ ray.setOrigin(new Vector3f(0, 0, 2f));
+ checkCollision(box, ray, 0);
+
+ ray.setOrigin(new Vector3f(0, 0, -2f));
+ checkCollision(box, ray, 2);
+
+ // parallel to the edge, touching the side
+ ray.setOrigin(new Vector3f(0, 1f, -2f));
+ checkCollision(box, ray, 2);
+
+ // still parallel, but not touching the side
+ ray.setOrigin(new Vector3f(0, 1f + FastMath.ZERO_TOLERANCE, -2f));
+ checkCollision(box, ray, 0);
+ }
+
+ @Test
+ public void testBoxTriangleCollision() {
+ BoundingBox box = new BoundingBox(Vector3f.ZERO, 1, 1, 1);
+ Geometry geom = new Geometry("geom", new Quad(1, 1));
+ checkCollision(box, geom, 2); // Both triangles intersect
+
+ // The box touches the edges of the triangles.
+ box.setCenter(new Vector3f(-1f, 0, 0));
+ checkCollision(box, geom, 2);
+
+ // Move it slightly farther..
+ box.setCenter(new Vector3f(-1f - FastMath.ZERO_TOLERANCE, 0, 0));
+ checkCollision(box, geom, 0);
+
+ // Parallel triangle / box side, touching
+ box.setCenter(new Vector3f(0, 0, -1f));
+ checkCollision(box, geom, 2);
+
+ // Not touching
+ box.setCenter(new Vector3f(0, 0, -1f - FastMath.ZERO_TOLERANCE));
+ checkCollision(box, geom, 0);
+ }
+}
diff --git a/jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java b/jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java
new file mode 100644
index 000000000..43d7b20f0
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/collision/CollisionUtil.java
@@ -0,0 +1,80 @@
+/*
+ * 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.collision;
+
+import com.jme3.bounding.BoundingVolume;
+
+/**
+ * Utilities for testing collision.
+ *
+ * @author Kirill Vainer
+ */
+final class CollisionUtil {
+
+ private static void checkCollisionBase(Collidable a, Collidable b, int expected) {
+ // Test bounding volume methods
+ if (a instanceof BoundingVolume && b instanceof BoundingVolume) {
+ BoundingVolume bv1 = (BoundingVolume) a;
+ BoundingVolume bv2 = (BoundingVolume) b;
+ assert bv1.intersects(bv2) == (expected != 0);
+ }
+
+ // Test standard collideWith method
+ CollisionResults results = new CollisionResults();
+ int numCollisions = a.collideWith(b, results);
+ assert results.size() == numCollisions;
+ assert numCollisions == expected;
+
+ // force the results to be sorted here..
+ results.getClosestCollision();
+
+ if (results.size() > 0) {
+ assert results.getCollision(0) == results.getClosestCollision();
+ }
+ if (results.size() == 1) {
+ assert results.getClosestCollision() == results.getFarthestCollision();
+ }
+ }
+
+ /**
+ * Tests various collisions between the two collidables and
+ * the transitive property.
+ *
+ * @param a First collidable
+ * @param b Second collidable
+ * @param expect Number of expected results
+ */
+ public static void checkCollision(Collidable a, Collidable b, int expected) {
+ checkCollisionBase(a, b, expected);
+ checkCollisionBase(b, a, expected);
+ }
+}
diff --git a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
new file mode 100644
index 000000000..0d1e71988
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.light;
+
+import com.jme3.math.FastMath;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.Camera;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.util.TempVars;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test light filtering for various light types.
+ *
+ * @author Kirill Vainer
+ */
+public class LightFilterTest {
+
+ private DefaultLightFilter filter;
+ private Camera cam;
+ private Geometry geom;
+ private LightList list;
+
+ private void checkFilteredLights(int expected) {
+ geom.updateGeometricState();
+ filter.setCamera(cam); // setCamera resets the intersection cache
+ list.clear();
+ filter.filterLights(geom, list);
+ assert list.size() == expected;
+ }
+
+ @Before
+ public void setUp() {
+ filter = new DefaultLightFilter();
+
+ cam = new Camera(512, 512);
+ cam.setFrustumPerspective(45, 1, 1, 1000);
+ cam.setLocation(Vector3f.ZERO);
+ cam.lookAtDirection(Vector3f.UNIT_Z, Vector3f.UNIT_Y);
+ filter.setCamera(cam);
+
+ Box box = new Box(1, 1, 1);
+ geom = new Geometry("geom", box);
+ geom.setLocalTranslation(0, 0, 10);
+ geom.updateGeometricState();
+ list = new LightList(geom);
+ }
+
+ @Test
+ public void testAmbientFiltering() {
+ geom.addLight(new AmbientLight());
+ checkFilteredLights(1); // Ambient lights must never be filtered
+ }
+
+ @Test
+ public void testDirectionalFiltering() {
+ geom.addLight(new DirectionalLight(Vector3f.UNIT_Y));
+ checkFilteredLights(1); // Directional lights must never be filtered
+ }
+
+ @Test
+ public void testPointFiltering() {
+ PointLight pl = new PointLight(Vector3f.ZERO);
+ geom.addLight(pl);
+ checkFilteredLights(1); // Infinite point lights must never be filtered
+
+ // Light at origin does not intersect geom which is at Z=10
+ pl.setRadius(1);
+ checkFilteredLights(0);
+
+ // Put it closer to geom, the very edge of the sphere touches the box.
+ // Still not considered an intersection though.
+ pl.setPosition(new Vector3f(0, 0, 8f));
+ checkFilteredLights(0);
+
+ // And more close - now its an intersection.
+ pl.setPosition(new Vector3f(0, 0, 8f + FastMath.ZERO_TOLERANCE));
+ checkFilteredLights(1);
+
+ // Move the geometry away
+ geom.move(0, 0, FastMath.ZERO_TOLERANCE);
+ checkFilteredLights(0);
+
+ // Test if the algorithm converts the sphere
+ // to a box before testing the collision (incorrect)
+ float sqrt3 = FastMath.sqrt(3);
+
+ pl.setPosition(new Vector3f(2, 2, 8));
+ pl.setRadius(sqrt3);
+ checkFilteredLights(0);
+
+ // Make it a wee bit larger.
+ pl.setRadius(sqrt3 + FastMath.ZERO_TOLERANCE);
+ checkFilteredLights(1);
+
+ // Rotate the camera so it is up, light is outside frustum.
+ cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y);
+ checkFilteredLights(0);
+ }
+
+ @Test
+ public void testSpotFiltering() {
+ SpotLight sl = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_Z);
+ sl.setSpotRange(0);
+ geom.addLight(sl);
+ checkFilteredLights(1); // Infinite spot lights are only filtered
+ // if the geometry is outside the infinite cone.
+
+ TempVars vars = TempVars.get();
+ try {
+ // The spot is not touching the near plane of the camera yet,
+ // should still be culled.
+ sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE);
+ assert !sl.intersectsFrustum(cam, vars);
+ // should be culled from the geometry's PoV
+ checkFilteredLights(0);
+
+ // Now it touches the near plane.
+ sl.setSpotRange(1f);
+ // still culled from the geometry's PoV
+ checkFilteredLights(0);
+ assert sl.intersectsFrustum(cam, vars);
+ } finally {
+ vars.release();
+ }
+
+ // make it barely reach the geometry
+ sl.setSpotRange(9f);
+ checkFilteredLights(0);
+
+ // make it reach the geometry (touching its bound)
+ sl.setSpotRange(9f + FastMath.ZERO_TOLERANCE);
+ checkFilteredLights(1);
+
+ // rotate the cone a bit so it no longer faces the geom
+ sl.setDirection(new Vector3f(0.316f, 0, 0.948f).normalizeLocal());
+ checkFilteredLights(0);
+
+ // extent the range much farther
+ sl.setSpotRange(20);
+ checkFilteredLights(0);
+
+ // Create box of size X=10 (double the extent)
+ // now, the spot will touch the box.
+ geom.setMesh(new Box(5, 1, 1));
+ checkFilteredLights(1);
+ }
+}
diff --git a/jme3-core/src/test/java/com/jme3/light/LightSortTest.java b/jme3-core/src/test/java/com/jme3/light/LightSortTest.java
new file mode 100644
index 000000000..593cc9d3e
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/light/LightSortTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.light;
+
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import org.junit.Test;
+
+/**
+ * Test light sorting (in the scene graph) for various light types.
+ *
+ * @author Kirill Vainer
+ */
+public class LightSortTest {
+
+ @Test
+ public void testSimpleSort() {
+ Geometry g = new Geometry("test", new Mesh());
+ LightList list = new LightList(g);
+
+ list.add(new SpotLight(Vector3f.ZERO, Vector3f.UNIT_X));
+ list.add(new PointLight(Vector3f.UNIT_X));
+ list.add(new DirectionalLight(Vector3f.UNIT_X));
+ list.add(new AmbientLight());
+
+ list.sort(true);
+
+ assert list.get(0) instanceof AmbientLight; // Ambients always first
+ assert list.get(1) instanceof DirectionalLight; // .. then directionals
+ assert list.get(2) instanceof SpotLight; // Spot is 0 units away from geom
+ assert list.get(3) instanceof PointLight; // .. and point is 1 unit away.
+ }
+
+ @Test
+ public void testSceneGraphSort() {
+ Node n = new Node("node");
+ Geometry g = new Geometry("geom", new Mesh());
+ SpotLight spot = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_X);
+ PointLight point = new PointLight(Vector3f.UNIT_X);
+ DirectionalLight directional = new DirectionalLight(Vector3f.UNIT_X);
+ AmbientLight ambient = new AmbientLight();
+
+ // Some lights are on the node
+ n.addLight(spot);
+ n.addLight(point);
+
+ // .. and some on the geometry.
+ g.addLight(directional);
+ g.addLight(ambient);
+
+ n.attachChild(g);
+ n.updateGeometricState();
+
+ LightList list = g.getWorldLightList();
+
+ // check the sorting (when geom is at 0,0,0)
+ assert list.get(0) instanceof AmbientLight;
+ assert list.get(1) instanceof DirectionalLight;
+ assert list.get(2) instanceof SpotLight;
+ assert list.get(3) instanceof PointLight;
+
+ // move the geometry closer to the point light
+ g.setLocalTranslation(Vector3f.UNIT_X);
+ n.updateGeometricState();
+
+ assert list.get(0) instanceof AmbientLight;
+ assert list.get(1) instanceof DirectionalLight;
+ assert list.get(2) instanceof PointLight;
+ assert list.get(3) instanceof SpotLight;
+
+ // now move the point light away from the geometry
+ // and the spot light closer
+
+ // XXX: doesn't work! jME can't detect that the light moved!
+// point.setPosition(Vector3f.ZERO);
+// spot.setPosition(Vector3f.UNIT_X);
+// n.updateGeometricState();
+//
+// assert list.get(0) instanceof AmbientLight;
+// assert list.get(1) instanceof DirectionalLight;
+// assert list.get(2) instanceof SpotLight;
+// assert list.get(3) instanceof PointLight;
+ }
+}
From f32d92ef301fbfa6456695fe89f2bbbd5522eb92 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Sun, 13 Sep 2015 23:02:49 -0400
Subject: [PATCH 50/94] bounding: add bound vs. spatial, also improve unit test
---
.../java/com/jme3/bounding/BoundingBox.java | 3 ++
.../com/jme3/bounding/BoundingSphere.java | 3 ++
.../jme3/collision/BoundingCollisionTest.java | 37 +++++++++++++++++++
3 files changed, 43 insertions(+)
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
index 06f78154e..5baf3e3d6 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
@@ -41,6 +41,7 @@ import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.*;
import com.jme3.scene.Mesh;
+import com.jme3.scene.Spatial;
import com.jme3.util.TempVars;
import java.io.IOException;
import java.nio.FloatBuffer;
@@ -799,6 +800,8 @@ public class BoundingBox extends BoundingVolume {
return 1;
}
return 0;
+ } else if (other instanceof Spatial) {
+ return ((Spatial)other).collideWith(this, results);
} else {
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
}
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
index 5eecf040a..3137f2cbf 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
@@ -38,6 +38,7 @@ import com.jme3.collision.UnsupportedCollisionException;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.math.*;
+import com.jme3.scene.Spatial;
import com.jme3.util.BufferUtils;
import com.jme3.util.TempVars;
import java.io.IOException;
@@ -1001,6 +1002,8 @@ public class BoundingSphere extends BoundingVolume {
return 1;
}
return 0;
+ } else if (other instanceof Spatial) {
+ return ((Spatial)other).collideWith(this, results);
} else {
throw new UnsupportedCollisionException();
}
diff --git a/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java b/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java
index 7c3104292..506a1732d 100644
--- a/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java
+++ b/jme3-core/src/test/java/com/jme3/collision/BoundingCollisionTest.java
@@ -162,5 +162,42 @@ public class BoundingCollisionTest {
// Not touching
box.setCenter(new Vector3f(0, 0, -1f - FastMath.ZERO_TOLERANCE));
checkCollision(box, geom, 0);
+
+ // Test collisions only against one of the triangles
+ box.setCenter(new Vector3f(-1f, 1.5f, 0f));
+ checkCollision(box, geom, 1);
+
+ box.setCenter(new Vector3f(1.5f, -1f, 0f));
+ checkCollision(box, geom, 1);
+ }
+
+ @Test
+ public void testSphereTriangleCollision() {
+ BoundingSphere sphere = new BoundingSphere(1, Vector3f.ZERO);
+ Geometry geom = new Geometry("geom", new Quad(1, 1));
+ checkCollision(sphere, geom, 2);
+
+ // The box touches the edges of the triangles.
+ sphere.setCenter(new Vector3f(-1f + FastMath.ZERO_TOLERANCE, 0, 0));
+ checkCollision(sphere, geom, 2);
+
+ // Move it slightly farther..
+ sphere.setCenter(new Vector3f(-1f - FastMath.ZERO_TOLERANCE, 0, 0));
+ checkCollision(sphere, geom, 0);
+
+ // Parallel triangle / box side, touching
+ sphere.setCenter(new Vector3f(0, 0, -1f));
+ checkCollision(sphere, geom, 2);
+
+ // Not touching
+ sphere.setCenter(new Vector3f(0, 0, -1f - FastMath.ZERO_TOLERANCE));
+ checkCollision(sphere, geom, 0);
+
+ // Test collisions only against one of the triangles
+ sphere.setCenter(new Vector3f(-0.9f, 1.2f, 0f));
+ checkCollision(sphere, geom, 1);
+
+ sphere.setCenter(new Vector3f(1.2f, -0.9f, 0f));
+ checkCollision(sphere, geom, 1);
}
}
From 78d2d6e944116fa61b24b4aee89cdf13459d2795 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Mon, 14 Sep 2015 22:51:57 -0400
Subject: [PATCH 51/94] GLRenderer: fix invalid enum error when using
framebuffers
---
.../com/jme3/renderer/opengl/GLRenderer.java | 190 ++++++++++--------
.../com/jme3/renderer/opengl/GLTracer.java | 18 ++
2 files changed, 123 insertions(+), 85 deletions(-)
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 0aa0d693f..276453117 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
@@ -1459,25 +1459,44 @@ public class GLRenderer implements Renderer {
rb.getId());
}
}
+
+ private void bindFrameBuffer(FrameBuffer fb) {
+ if (fb == null) {
+ if (context.boundFBO != 0) {
+ glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0);
+ statistics.onFrameBufferUse(null, true);
+ context.boundFBO = 0;
+ context.boundFB = null;
+ }
+ } else {
+ assert fb.getId() != -1 && fb.getId() != 0;
+ if (context.boundFBO != fb.getId()) {
+ glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId());
+ context.boundFBO = fb.getId();
+ context.boundFB = fb;
+ statistics.onFrameBufferUse(fb, true);
+ } else {
+ statistics.onFrameBufferUse(fb, false);
+ }
+ }
+ }
public void updateFrameBuffer(FrameBuffer fb) {
+ if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
+ throw new IllegalArgumentException("The framebuffer: " + fb
+ + "\nDoesn't have any color/depth buffers");
+ }
+
int id = fb.getId();
if (id == -1) {
- // create FBO
glfbo.glGenFramebuffersEXT(intBuf1);
id = intBuf1.get(0);
fb.setId(id);
objManager.registerObject(fb);
-
statistics.onNewFrameBuffer();
}
- if (context.boundFBO != id) {
- glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, id);
- // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
- context.boundDrawBuf = 0;
- context.boundFBO = id;
- }
+ bindFrameBuffer(fb);
FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
if (depthBuf != null) {
@@ -1488,7 +1507,8 @@ public class GLRenderer implements Renderer {
FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
updateFrameBufferAttachment(fb, colorBuf);
}
-
+
+ setReadDrawBuffers(fb);
checkFrameBufferError();
fb.clearUpdateNeeded();
@@ -1516,93 +1536,45 @@ public class GLRenderer implements Renderer {
}
public void setMainFrameBufferOverride(FrameBuffer fb) {
+ mainFbOverride = null;
+ if (context.boundFBO == 0) {
+ // Main FB is now set to fb, make sure its bound
+ setFrameBuffer(fb);
+ }
mainFbOverride = fb;
}
- public void setFrameBuffer(FrameBuffer fb) {
- if (fb == null && mainFbOverride != null) {
- fb = mainFbOverride;
- }
-
- if (context.boundFB == fb) {
- if (fb == null || !fb.isUpdateNeeded()) {
- return;
- }
- }
-
- if (!caps.contains(Caps.FrameBuffer)) {
- throw new RendererException("Framebuffer objects are not supported"
- + " by the video hardware");
- }
-
- // generate mipmaps for last FB if needed
- if (context.boundFB != null) {
- for (int i = 0; i < context.boundFB.getNumColorBuffers(); i++) {
- RenderBuffer rb = context.boundFB.getColorBuffer(i);
- Texture tex = rb.getTexture();
- if (tex != null
- && tex.getMinFilter().usesMipMapLevels()) {
- setTexture(0, rb.getTexture());
-
- int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
- glfbo.glGenerateMipmapEXT(textureType);
- }
- }
+ public void setReadDrawBuffers(FrameBuffer fb) {
+ if (gl2 == null) {
+ return;
}
-
+
+ final int NONE = -2;
+ final int INITIAL = -1;
+ final int MRT_OFF = 100;
+
if (fb == null) {
- // unbind any fbos
- if (context.boundFBO != 0) {
- glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, 0);
- statistics.onFrameBufferUse(null, true);
-
- context.boundFBO = 0;
+ // Set Read/Draw buffers to initial value.
+ if (context.boundDrawBuf != INITIAL) {
+ gl2.glDrawBuffer(context.initialDrawBuf);
+ context.boundDrawBuf = INITIAL;
}
- // select back buffer
- if (gl2 != null) {
- if (context.boundDrawBuf != -1) {
- gl2.glDrawBuffer(context.initialDrawBuf);
- context.boundDrawBuf = -1;
- }
- if (context.boundReadBuf != -1) {
- gl2.glReadBuffer(context.initialReadBuf);
- context.boundReadBuf = -1;
- }
+ if (context.boundReadBuf != INITIAL) {
+ gl2.glReadBuffer(context.initialReadBuf);
+ context.boundReadBuf = INITIAL;
}
-
- context.boundFB = null;
} else {
- if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
- throw new IllegalArgumentException("The framebuffer: " + fb
- + "\nDoesn't have any color/depth buffers");
- }
-
- if (fb.isUpdateNeeded()) {
- updateFrameBuffer(fb);
- }
-
- // update viewport to reflect framebuffer's resolution
- setViewPort(0, 0, fb.getWidth(), fb.getHeight());
-
- if (context.boundFBO != fb.getId()) {
- glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId());
- statistics.onFrameBufferUse(fb, true);
-
- context.boundFBO = fb.getId();
- } else {
- statistics.onFrameBufferUse(fb, false);
- }
if (fb.getNumColorBuffers() == 0) {
// make sure to select NONE as draw buf
- // no color buffer attached. select NONE
+ // no color buffer attached.
if (gl2 != null) {
- if (context.boundDrawBuf != -2) {
+ if (context.boundDrawBuf != NONE) {
gl2.glDrawBuffer(GL.GL_NONE);
- context.boundDrawBuf = -2;
+ context.boundDrawBuf = NONE;
}
- if (context.boundReadBuf != -2) {
+ if (context.boundReadBuf != NONE) {
gl2.glReadBuffer(GL.GL_NONE);
- context.boundReadBuf = -2;
+ context.boundReadBuf = NONE;
}
}
} else {
@@ -1622,7 +1594,7 @@ public class GLRenderer implements Renderer {
+ " by the video hardware!");
}
- if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
+ if (context.boundDrawBuf != MRT_OFF + fb.getNumColorBuffers()) {
intBuf16.clear();
for (int i = 0; i < fb.getNumColorBuffers(); i++) {
intBuf16.put(GLFbo.GL_COLOR_ATTACHMENT0_EXT + i);
@@ -1630,7 +1602,7 @@ public class GLRenderer implements Renderer {
intBuf16.flip();
glext.glDrawBuffers(intBuf16);
- context.boundDrawBuf = 100 + fb.getNumColorBuffers();
+ context.boundDrawBuf = MRT_OFF + fb.getNumColorBuffers();
}
} else {
RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
@@ -1643,8 +1615,56 @@ public class GLRenderer implements Renderer {
}
}
}
+ }
+
+ }
+
+ public void setFrameBuffer(FrameBuffer fb) {
+ if (fb == null && mainFbOverride != null) {
+ fb = mainFbOverride;
+ }
+
+ if (context.boundFB == fb) {
+ if (fb == null || !fb.isUpdateNeeded()) {
+ return;
+ }
+ }
+
+ if (!caps.contains(Caps.FrameBuffer)) {
+ throw new RendererException("Framebuffer objects are not supported"
+ + " by the video hardware");
+ }
+
+ // generate mipmaps for last FB if needed
+ if (context.boundFB != null) {
+ for (int i = 0; i < context.boundFB.getNumColorBuffers(); i++) {
+ RenderBuffer rb = context.boundFB.getColorBuffer(i);
+ Texture tex = rb.getTexture();
+ if (tex != null
+ && tex.getMinFilter().usesMipMapLevels()) {
+ setTexture(0, rb.getTexture());
+
+ int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
+ glfbo.glGenerateMipmapEXT(textureType);
+ }
+ }
+ }
+
+ if (fb == null) {
+ bindFrameBuffer(null);
+ setReadDrawBuffers(null);
+ } else {
+ if (fb.isUpdateNeeded()) {
+ updateFrameBuffer(fb);
+ } else {
+ bindFrameBuffer(fb);
+ setReadDrawBuffers(fb);
+ }
+
+ // update viewport to reflect framebuffer's resolution
+ setViewPort(0, 0, fb.getWidth(), fb.getHeight());
- assert fb.getId() >= 0;
+ assert fb.getId() > 0;
assert context.boundFBO == fb.getId();
context.boundFB = fb;
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java
index a2775ba0a..f252d22dc 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLTracer.java
@@ -336,6 +336,21 @@ public final class GLTracer implements InvocationHandler {
print(")");
}
+ private void printArgsGetInteger(Object[] args) {
+ print("(");
+ int param = (Integer)args[0];
+ IntBuffer ib = (IntBuffer) args[1];
+ printEnum(param);
+ print(", ");
+ printOut();
+ if (param == GL2.GL_DRAW_BUFFER || param == GL2.GL_READ_BUFFER) {
+ printEnum(ib.get(0));
+ } else {
+ printInt(ib.get(0));
+ }
+ print(")");
+ }
+
private void printArgsTexParameter(Object[] args) {
print("(");
@@ -389,6 +404,9 @@ public final class GLTracer implements InvocationHandler {
} else if (methodName.equals("glTexParameteri")) {
printArgsTexParameter(args);
return;
+ } else if (methodName.equals("glGetInteger")) {
+ printArgsGetInteger(args);
+ return;
}
if (args == null) {
From 1aaf806c65a3c4e87b38e74c4d88111102ad32a1 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Mon, 14 Sep 2015 23:00:55 -0400
Subject: [PATCH 52/94] test: fix crash due to deprecated material
---
.../jme3test/renderer/TestInconsistentCompareDetection.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java b/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java
index a93a75c16..c1f99b35d 100644
--- a/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java
+++ b/jme3-examples/src/main/java/jme3test/renderer/TestInconsistentCompareDetection.java
@@ -63,7 +63,7 @@ public class TestInconsistentCompareDetection extends SimpleApplication {
cam.setLocation(new Vector3f(-11.674385f, 7.892636f, 33.133106f));
cam.setRotation(new Quaternion(0.06426433f, 0.90940624f, -0.15329266f, 0.38125014f));
- Material m = new Material(assetManager, "Common/MatDefs/Misc/ColoredTextured.j3md");
+ Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
m.setColor("Color", ColorRGBA.White);
t1 = assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg");
From 6970c8db8ad25012cf165e225de1aacbb1230a31 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Mon, 14 Sep 2015 23:01:46 -0400
Subject: [PATCH 53/94] shapes: set static usage on all VBs
---
jme3-core/src/main/java/com/jme3/scene/debug/Grid.java | 1 +
jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java | 2 ++
jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java | 1 +
jme3-core/src/main/java/com/jme3/scene/shape/Quad.java | 1 +
jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java | 2 +-
5 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java b/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java
index 5b6d0661e..563981804 100644
--- a/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java
+++ b/jme3-core/src/main/java/com/jme3/scene/debug/Grid.java
@@ -99,6 +99,7 @@ public class Grid extends Mesh {
updateBound();
updateCounts();
+ setStatic();
}
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java b/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java
index c050d1edb..4f5364753 100644
--- a/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java
+++ b/jme3-core/src/main/java/com/jme3/scene/debug/WireFrustum.java
@@ -35,6 +35,7 @@ import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Type;
+import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.util.BufferUtils;
import java.nio.FloatBuffer;
@@ -62,6 +63,7 @@ public class WireFrustum extends Mesh {
3, 7,
}
);
+ getBuffer(Type.Index).setUsage(Usage.Static);
setMode(Mode.Lines);
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java b/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java
index f0966328f..1d215eb6b 100644
--- a/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java
+++ b/jme3-core/src/main/java/com/jme3/scene/shape/Cylinder.java
@@ -389,6 +389,7 @@ public class Cylinder extends Mesh {
}
updateBound();
+ setStatic();
}
@Override
diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java b/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java
index 194535851..3e0c6ce7e 100644
--- a/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java
+++ b/jme3-core/src/main/java/com/jme3/scene/shape/Quad.java
@@ -124,6 +124,7 @@ public class Quad extends Mesh {
}
updateBound();
+ setStatic();
}
diff --git a/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java b/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java
index 89db073a7..44aa41723 100644
--- a/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java
+++ b/jme3-core/src/main/java/com/jme3/scene/shape/Sphere.java
@@ -299,7 +299,6 @@ public class Sphere extends Mesh {
}
updateBound();
- setStatic();
}
/**
@@ -400,6 +399,7 @@ public class Sphere extends Mesh {
this.interior = interior;
setGeometryData();
setIndexData();
+ setStatic();
}
public void read(JmeImporter e) throws IOException {
From aee7d1f1956fe8638221966d29a4dad3e89c9719 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Mon, 14 Sep 2015 23:02:31 -0400
Subject: [PATCH 54/94] GLSLCompat.glsllib: fix incorrect preprocessor define
---
.../src/main/resources/Common/ShaderLib/GLSLCompat.glsllib | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib
index 3a3173997..3d23b7915 100644
--- a/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib
+++ b/jme3-core/src/main/resources/Common/ShaderLib/GLSLCompat.glsllib
@@ -1,4 +1,4 @@
-#if defined _GL_ES_
+#if defined GL_ES
# define hfloat highp float
# define hvec2 highp vec2
# define hvec3 highp vec3
From 7659a7b986c1779158cb70082bf10a9a2ed1822d Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Mon, 14 Sep 2015 23:03:08 -0400
Subject: [PATCH 55/94] TestCustomAnim: fix crash when enabling HW skinning
---
.../src/main/java/jme3test/model/anim/TestCustomAnim.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java b/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java
index e220eeb37..b5eeb5365 100644
--- a/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java
+++ b/jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java
@@ -73,6 +73,13 @@ public class TestCustomAnim extends SimpleApplication {
Box box = new Box(1, 1, 1);
+ VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight);
+ VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex);
+ indicesHW.setUsage(Usage.CpuOnly);
+ weightsHW.setUsage(Usage.CpuOnly);
+ box.setBuffer(weightsHW);
+ box.setBuffer(indicesHW);
+
// Setup bone weight buffer
FloatBuffer weights = FloatBuffer.allocate( box.getVertexCount() * 4 );
VertexBuffer weightsBuf = new VertexBuffer(Type.BoneWeight);
From 500f57a64fb3ad75820120f5115bc7f14c3548a6 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Mon, 14 Sep 2015 23:19:43 -0400
Subject: [PATCH 56/94] AssetManager: set locator path only once per thread
---
.../main/java/com/jme3/asset/ImplHandler.java | 21 ++++++-----
.../java/jme3test/asset/TestOnlineJar.java | 37 +++++++++++--------
2 files changed, 32 insertions(+), 26 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java b/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java
index 73e6d8df3..3bbd19c14 100644
--- a/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java
+++ b/jme3-core/src/main/java/com/jme3/asset/ImplHandler.java
@@ -75,7 +75,7 @@ final class ImplHandler {
this.assetManager = assetManager;
}
- protected static class ImplThreadLocal extends ThreadLocal {
+ protected static class ImplThreadLocal extends ThreadLocal {
private final Class type;
private final String path;
@@ -112,9 +112,13 @@ final class ImplHandler {
}
@Override
- protected Object initialValue(){
+ protected T initialValue(){
try {
- return type.newInstance();
+ T obj = type.newInstance();
+ if (path != null) {
+ ((AssetLocator)obj).setRootPath(path);
+ }
+ return obj;
} catch (InstantiationException ex) {
logger.log(Level.SEVERE,"Cannot create locator of type {0}, does"
+ " the class have an empty and publically accessible"+
@@ -169,14 +173,11 @@ final class ImplHandler {
return null;
}
- for (ImplThreadLocal local : locatorsList){
- AssetLocator locator = (AssetLocator) local.get();
- if (local.getPath() != null){
- locator.setRootPath((String) local.getPath());
- }
- AssetInfo info = locator.locate(assetManager, key);
- if (info != null)
+ for (ImplThreadLocal local : locatorsList){
+ AssetInfo info = local.get().locate(assetManager, key);
+ if (info != null) {
return info;
+ }
}
return null;
diff --git a/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java b/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java
index e12769cd8..036d9318c 100644
--- a/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java
+++ b/jme3-examples/src/main/java/jme3test/asset/TestOnlineJar.java
@@ -36,10 +36,10 @@ import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.asset.plugins.HttpZipLocator;
import com.jme3.material.Material;
-import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
+import com.jme3.ui.Picture;
/**
* This tests loading a file from a jar stored online.
@@ -59,22 +59,27 @@ public class TestOnlineJar extends SimpleApplication {
quadMesh.updateGeometry(1, 1, true);
Geometry quad = new Geometry("Textured Quad", quadMesh);
- assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/town.zip",
- HttpZipLocator.class);
+
+ assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/town.zip",
+ HttpZipLocator.class);
+ assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/wildhouse.zip",
+ HttpZipLocator.class);
- TextureKey key = new TextureKey("grass.jpg", false);
- key.setGenerateMips(true);
- Texture tex = assetManager.loadTexture(key);
-
- Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
- mat.setTexture("ColorMap", tex);
- quad.setMaterial(mat);
-
- float aspect = tex.getImage().getWidth() / (float) tex.getImage().getHeight();
- quad.setLocalScale(new Vector3f(aspect * 1.5f, 1.5f, 1));
- quad.center();
-
- rootNode.attachChild(quad);
+ Picture pic1 = new Picture("Picture1");
+ pic1.move(0, 0, -1);
+ pic1.setPosition(0, 0);
+ pic1.setWidth(128);
+ pic1.setHeight(128);
+ pic1.setImage(assetManager, "grass.jpg", false);
+ guiNode.attachChild(pic1);
+
+ Picture pic2 = new Picture("Picture1");
+ pic2.move(0, 0, -1);
+ pic2.setPosition(128, 0);
+ pic2.setWidth(128);
+ pic2.setHeight(128);
+ pic2.setImage(assetManager, "glasstile2.png", false);
+ guiNode.attachChild(pic2);
}
}
From 30cdca7ad727bc79fe1946fb80ee8375d3938350 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Thu, 17 Sep 2015 11:59:44 +0100
Subject: [PATCH 57/94] Native library loading is back to the way it used to be
with the addition of LWJGL 3.x libraries added with a different key. Moved
LWJGL 3.x repository definition to build.grade in that module. Fixed an issue
where frame rate limit would cause GLFW frequency window hint to be set
rather than use a software limiter. Removed LWJGLTimer for lwjgl3 module, no
need for it any more, we'll just use the NanoTimer. Removed LWJGLCanvas for
lwjgl3 module, can't implement this so we'll leave it for now.
---
common.gradle | 3 -
.../com/jme3/system/NativeLibraryLoader.java | 36 ++
.../system/lwjgl/LwjglAbstractDisplay.java | 1 -
.../com/jme3/system/lwjgl/LwjglContext.java | 21 +-
jme3-lwjgl3/build.gradle | 6 +
.../com/jme3/system/lwjgl/LwjglCanvas.java | 369 ------------------
.../com/jme3/system/lwjgl/LwjglContext.java | 25 +-
.../system/lwjgl/LwjglSmoothingTimer.java | 203 ----------
.../com/jme3/system/lwjgl/LwjglTimer.java | 139 -------
.../com/jme3/system/lwjgl/LwjglWindow.java | 51 ++-
10 files changed, 83 insertions(+), 771 deletions(-)
delete mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
delete mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java
delete mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
diff --git a/common.gradle b/common.gradle
index c225588c4..237ee5e7f 100644
--- a/common.gradle
+++ b/common.gradle
@@ -16,9 +16,6 @@ repositories {
maven {
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
}
- maven {
- url "https://oss.sonatype.org/content/repositories/snapshots"
- }
}
configurations {
diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
index 6e83e0e6b..53898883c 100644
--- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
+++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
@@ -124,6 +124,42 @@ public final class NativeLibraryLoader {
}
static {
+ // LWJGL
+ registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll");
+ registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll");
+ registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so");
+ registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so");
+ registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
+ registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
+
+ // OpenAL
+ // For OSX: Need to add lib prefix when extracting
+ registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll");
+ registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll");
+ registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so");
+ registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so");
+ registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
+ registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
+
+ // LWJGL 3.x
+ registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/lwjgl32.dll");
+ registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/lwjgl.dll");
+ registerNativeLibrary("lwjgl3", Platform.Linux32, "native/linux/liblwjgl32.so");
+ registerNativeLibrary("lwjgl3", Platform.Linux64, "native/linux/liblwjgl.so");
+ registerNativeLibrary("lwjgl3", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
+ registerNativeLibrary("lwjgl3", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
+ registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll");
+ registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll");
+
+ // OpenAL for LWJGL 3.x
+ // For OSX: Need to add lib prefix when extracting
+ registerNativeLibrary("openal-lwjgl3", Platform.Windows32, "native/windows/OpenAL32.dll");
+ registerNativeLibrary("openal-lwjgl3", Platform.Windows64, "native/windows/OpenAL.dll");
+ registerNativeLibrary("openal-lwjgl3", Platform.Linux32, "native/linux/libopenal32.so");
+ registerNativeLibrary("openal-lwjgl3", Platform.Linux64, "native/linux/libopenal.so");
+ registerNativeLibrary("openal-lwjgl3", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
+ registerNativeLibrary("openal-lwjgl3", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
+
// BulletJme
registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll");
registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll");
diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
index 415084788..802b12a0f 100644
--- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
+++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java
@@ -206,7 +206,6 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
+ "Must set with JmeContext.setSystemListner().");
}
- registerNatives();
loadNatives();
logger.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
if (!initInThread()) {
diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index 70885c39b..ee12d1fea 100644
--- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -162,26 +162,7 @@ public abstract class LwjglContext implements JmeContext {
}
}
}
-
- protected void registerNatives() {
- // LWJGL
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
-
- // For OSX: Need to add lib prefix when extracting
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
- }
-
- protected void loadNatives() {
+ protected void loadNatives() {
if (JmeSystem.isLowPermissions()) {
return;
}
diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle
index c9b43e0de..3c7e4e646 100644
--- a/jme3-lwjgl3/build.gradle
+++ b/jme3-lwjgl3/build.gradle
@@ -2,6 +2,12 @@ if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
+repositories {
+ maven {
+ url "https://oss.sonatype.org/content/repositories/snapshots"
+ }
+}
+
dependencies {
compile project(':jme3-core')
compile project(':jme3-desktop')
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
deleted file mode 100644
index 1f1ef2ab5..000000000
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.system.lwjgl;
-
-import com.jme3.system.AppSettings;
-import com.jme3.system.JmeCanvasContext;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
-
-public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext {
-
- protected static final int TASK_NOTHING = 0,
- TASK_DESTROY_DISPLAY = 1,
- TASK_CREATE_DISPLAY = 2,
- TASK_COMPLETE = 3;
-
-// protected static final boolean USE_SHARED_CONTEXT =
-// Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true"));
-
- protected static final boolean USE_SHARED_CONTEXT = false;
-
- private static final Logger logger = Logger.getLogger(LwjglCanvas.class.getName());
- private Canvas canvas;
- private int width;
- private int height;
-
- private final Object taskLock = new Object();
- private int desiredTask = TASK_NOTHING;
-
- private Thread renderThread;
- private boolean runningFirstTime = true;
- private boolean mouseWasGrabbed = false;
-
- private boolean mouseWasCreated = false;
- private boolean keyboardWasCreated = false;
-
- private long window;
-
- private class GLCanvas extends Canvas {
- @Override
- public void addNotify(){
- super.addNotify();
-
- if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) {
- return; // already destroyed.
- }
-
- if (renderThread == null){
- logger.log(Level.FINE, "EDT: Creating OGL thread.");
-
- // Also set some settings on the canvas here.
- // So we don't do it outside the AWT thread.
- canvas.setFocusable(true);
- canvas.setIgnoreRepaint(true);
-
- renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
- renderThread.start();
- }else if (needClose.get()){
- return;
- }
-
- logger.log(Level.FINE, "EDT: Telling OGL to create display ..");
- synchronized (taskLock){
- desiredTask = TASK_CREATE_DISPLAY;
-// while (desiredTask != TASK_COMPLETE){
-// try {
-// taskLock.wait();
-// } catch (InterruptedException ex) {
-// return;
-// }
-// }
-// desiredTask = TASK_NOTHING;
- }
-// logger.log(Level.FINE, "EDT: OGL has created the display");
- }
-
- @Override
- public void removeNotify(){
- if (needClose.get()){
- logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas.");
- super.removeNotify();
- return;
- }
-
- // We must tell GL context to shutdown and wait for it to
- // shutdown, otherwise, issues will occur.
- logger.log(Level.FINE, "EDT: Telling OGL to destroy display ..");
- synchronized (taskLock){
- desiredTask = TASK_DESTROY_DISPLAY;
- while (desiredTask != TASK_COMPLETE){
- try {
- taskLock.wait();
- } catch (InterruptedException ex){
- super.removeNotify();
- return;
- }
- }
- desiredTask = TASK_NOTHING;
- }
-
- logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death");
- // GL context is dead at this point
-
- super.removeNotify();
- }
- }
-
- public LwjglCanvas(){
- super(Type.Canvas);
- canvas = new GLCanvas();
- }
-
- public void create(boolean waitFor){
- if (renderThread == null){
- logger.log(Level.FINE, "MAIN: Creating OGL thread.");
-
- renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
- renderThread.start();
- }
- // do not do anything.
- // superclass's create() will be called at initInThread()
- if (waitFor) {
- waitFor(true);
- }
- }
-
- public Canvas getCanvas(){
- return canvas;
- }
-
- @Override
- protected void runLoop(){
- if (desiredTask != TASK_NOTHING){
- synchronized (taskLock){
- switch (desiredTask){
- case TASK_CREATE_DISPLAY:
- logger.log(Level.FINE, "OGL: Creating display ..");
- restoreCanvas();
- listener.gainFocus();
- desiredTask = TASK_NOTHING;
- break;
- case TASK_DESTROY_DISPLAY:
- logger.log(Level.FINE, "OGL: Destroying display ..");
- listener.loseFocus();
- pauseCanvas();
- break;
- }
- desiredTask = TASK_COMPLETE;
- taskLock.notifyAll();
- }
- }
-
- if (renderable.get()){
- int newWidth = Math.max(canvas.getWidth(), 1);
- int newHeight = Math.max(canvas.getHeight(), 1);
-
- if (width != newWidth || height != newHeight){
- width = newWidth;
- height = newHeight;
- if (listener != null){
- listener.reshape(width, height);
- }
- }
- }
-
- super.runLoop();
- }
-
- private void pauseCanvas(){
- if (mouseInput != null) {
- mouseInput.setCursorVisible(true);
- mouseWasCreated = true;
- }
-
-/*
- if (Mouse.isCreated()){
- if (Mouse.isGrabbed()){
- Mouse.setGrabbed(false);
- mouseWasGrabbed = true;
- }
- mouseWasCreated = true;
- Mouse.destroy();
- }
- if (Keyboard.isCreated()){
- keyboardWasCreated = true;
- Keyboard.destroy();
- }
-*/
-
- renderable.set(false);
- destroyContext();
- }
-
- /**
- * Called to restore the canvas.
- */
- private void restoreCanvas(){
- logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable..");
- while (!canvas.isDisplayable()){
- try {
- Thread.sleep(10);
- } catch (InterruptedException ex) {
- logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
- }
- }
-
- logger.log(Level.FINE, "OGL: Creating display context ..");
-
- // Set renderable to true, since canvas is now displayable.
- renderable.set(true);
- createContext(settings);
-
- logger.log(Level.FINE, "OGL: Display is active!");
-
- try {
- if (mouseWasCreated){
-// Mouse.create();
-// if (mouseWasGrabbed){
-// Mouse.setGrabbed(true);
-// mouseWasGrabbed = false;
-// }
- }
- if (keyboardWasCreated){
-// Keyboard.create();
-// keyboardWasCreated = false;
- }
- } catch (Exception ex){
- logger.log(Level.SEVERE, "Encountered exception when restoring input", ex);
- }
-
- SwingUtilities.invokeLater(new Runnable(){
- public void run(){
- canvas.requestFocus();
- }
- });
- }
-
-/*
- */
-/**
- * Makes sure the pbuffer is available and ready for use
- *//*
-
- protected void makePbufferAvailable() throws LWJGLException{
- if (pbuffer != null && pbuffer.isBufferLost()){
- logger.log(Level.WARNING, "PBuffer was lost!");
- pbuffer.destroy();
- pbuffer = null;
- }
-
- if (pbuffer == null) {
- pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null);
- pbuffer.makeCurrent();
- logger.log(Level.FINE, "OGL: Pbuffer has been created");
-
- // Any created objects are no longer valid
- if (!runningFirstTime){
- renderer.resetGLObjects();
- }
- }
-
- pbuffer.makeCurrent();
- if (!pbuffer.isCurrent()){
- throw new LWJGLException("Pbuffer cannot be made current");
- }
- }
-
- protected void destroyPbuffer(){
- if (pbuffer != null){
- if (!pbuffer.isBufferLost()){
- pbuffer.destroy();
- }
- pbuffer = null;
- }
- }
-*/
-
- /**
- * This is called:
- * 1) When the context thread ends
- * 2) Any time the canvas becomes non-displayable
- */
- protected void destroyContext(){
- // invalidate the state so renderer can resume operation
- if (!USE_SHARED_CONTEXT){
- renderer.cleanup();
- }
-
- if (window != 0) {
- glfwDestroyWindow(window);
- }
-
- // TODO: Destroy input
-
-
- // The canvas is no longer visible,
- // but the context thread is still running.
- if (!needClose.get()){
- renderer.invalidateState();
- }
- }
-
- /**
- * This is called:
- * 1) When the context thread starts
- * 2) Any time the canvas becomes displayable again.
- */
- @Override
- protected void createContext(final AppSettings settings) {
- // In case canvas is not visible, we still take framerate
- // from settings to prevent "100% CPU usage"
- allowSwapBuffers = settings.isSwapBuffers();
-
- if (renderable.get()){
- if (!runningFirstTime){
- // because the display is a different opengl context
- // must reset the context state.
- if (!USE_SHARED_CONTEXT){
- renderer.cleanup();
- }
- }
-
- super.createContext(settings);
- }
-
- // At this point, the OpenGL context is active.
- if (runningFirstTime) {
- // THIS is the part that creates the renderer.
- // It must always be called, now that we have the pbuffer workaround.
- initContextFirstTime();
- runningFirstTime = false;
- }
- }
-}
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index 86b6a294a..7f62a447e 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -98,41 +98,20 @@ public abstract class LwjglContext implements JmeContext {
return Integer.MAX_VALUE;
}
- protected void registerNatives() {
- // LWJGL
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl32.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl32.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl.so");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/jemalloc32.dll");
- NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/jemalloc.dll");
-
- // OpenAL
- // For OSX: Need to add lib prefix when extracting
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL.dll");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal32.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal.so");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib");
- NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib");
- }
-
protected void loadNatives() {
if (JmeSystem.isLowPermissions()) {
return;
}
if ("LWJGL".equals(settings.getAudioRenderer())) {
- NativeLibraryLoader.loadNativeLibrary("openal", true);
+ NativeLibraryLoader.loadNativeLibrary("openal-lwjgl3", true);
}
if (NativeLibraryLoader.isUsingNativeBullet()) {
NativeLibraryLoader.loadNativeLibrary("bulletjme", true);
}
- NativeLibraryLoader.loadNativeLibrary("lwjgl", true);
+ NativeLibraryLoader.loadNativeLibrary("lwjgl3", true);
}
protected int getNumSamplesToUse() {
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java
deleted file mode 100644
index a7960a261..000000000
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.system.lwjgl;
-
-import com.jme3.math.FastMath;
-import com.jme3.system.Timer;
-import org.lwjgl.glfw.GLFW;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Timer
handles the system's time related functionality. This
- * allows the calculation of the framerate. To keep the framerate calculation
- * accurate, a call to update each frame is required. Timer
is a
- * singleton object and must be created via the getTimer
method.
- *
- * @author Mark Powell
- * @version $Id: LWJGLTimer.java,v 1.21 2007/09/22 16:46:35 irrisor Exp $
- */
-public class LwjglSmoothingTimer extends LwjglTimer {
- private static final Logger logger = Logger.getLogger(LwjglSmoothingTimer.class
- .getName());
-
- private long lastFrameDiff;
-
- //frame rate parameters.
- private long oldTime;
-
- private float lastTPF, lastFPS;
-
- public static int TIMER_SMOOTHNESS = 32;
-
- private long[] tpf;
-
- private int smoothIndex;
-
- private final static long LWJGL_TIMER_RES = 1;
- private final static float INV_LWJGL_TIMER_RES = ( 1f / LWJGL_TIMER_RES );
- private static float invTimerRezSmooth;
-
- public final static long LWJGL_TIME_TO_NANOS = (1000000000 / LWJGL_TIMER_RES);
-
- private long startTime;
-
- private boolean allSmooth = false;
-
- /**
- * Constructor builds a Timer
object. All values will be
- * initialized to it's default values.
- */
- public LwjglSmoothingTimer() {
- reset();
-
- //print timer resolution info
- logger.log(Level.FINE, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES);
- }
-
- public void reset() {
- lastFrameDiff = 0;
- lastFPS = 0;
- lastTPF = 0;
-
- // init to -1 to indicate this is a new timer.
- oldTime = -1;
- //reset time
- startTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS);
-
- tpf = new long[TIMER_SMOOTHNESS];
- smoothIndex = TIMER_SMOOTHNESS - 1;
- invTimerRezSmooth = ( 1f / (LWJGL_TIMER_RES * TIMER_SMOOTHNESS));
-
- // set tpf... -1 values will not be used for calculating the average in update()
- for ( int i = tpf.length; --i >= 0; ) {
- tpf[i] = -1;
- }
- }
-
- /**
- * @see Timer#getResolution()
- */
- public long getResolution() {
- return LWJGL_TIMER_RES;
- }
-
- /**
- * getFrameRate
returns the current frame rate since the last
- * call to update
.
- *
- * @return the current frame rate.
- */
- public float getFrameRate() {
- return lastFPS;
- }
-
- public float getTimePerFrame() {
- return lastTPF;
- }
-
- /**
- * update
recalulates the frame rate based on the previous
- * call to update. It is assumed that update is called each frame.
- */
- public void update() {
- long newTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS);
- long oldTime = this.oldTime;
- this.oldTime = newTime;
- if ( oldTime == -1 ) {
- // For the first frame use 60 fps. This value will not be counted in further averages.
- // This is done so initialization code between creating the timer and the first
- // frame is not counted as a single frame on it's own.
- lastTPF = 1 / 60f;
- lastFPS = 1f / lastTPF;
- return;
- }
-
- long frameDiff = newTime - oldTime;
- long lastFrameDiff = this.lastFrameDiff;
- if ( lastFrameDiff > 0 && frameDiff > lastFrameDiff *100 ) {
- frameDiff = lastFrameDiff *100;
- }
- this.lastFrameDiff = frameDiff;
- tpf[smoothIndex] = frameDiff;
- smoothIndex--;
- if ( smoothIndex < 0 ) {
- smoothIndex = tpf.length - 1;
- }
-
- lastTPF = 0.0f;
- if (!allSmooth) {
- int smoothCount = 0;
- for ( int i = tpf.length; --i >= 0; ) {
- if ( tpf[i] != -1 ) {
- lastTPF += tpf[i];
- smoothCount++;
- }
- }
- if (smoothCount == tpf.length)
- allSmooth = true;
- lastTPF *= ( INV_LWJGL_TIMER_RES / smoothCount );
- } else {
- for ( int i = tpf.length; --i >= 0; ) {
- if ( tpf[i] != -1 ) {
- lastTPF += tpf[i];
- }
- }
- lastTPF *= invTimerRezSmooth;
- }
- if ( lastTPF < FastMath.FLT_EPSILON ) {
- lastTPF = FastMath.FLT_EPSILON;
- }
-
- lastFPS = 1f / lastTPF;
- }
-
- /**
- * toString
returns the string representation of this timer
- * in the format:
- *
- * jme.utility.Timer@1db699b
- * Time: {LONG}
- * FPS: {LONG}
- *
- * @return the string representation of this object.
- */
- @Override
- public String toString() {
- String string = super.toString();
- string += "\nTime: " + oldTime;
- string += "\nFPS: " + getFrameRate();
- return string;
- }
-}
\ No newline at end of file
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
deleted file mode 100644
index c4a0e5025..000000000
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.system.lwjgl;
-
-import com.jme3.system.Timer;
-import org.lwjgl.glfw.GLFW;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Timer
handles the system's time related functionality. This
- * allows the calculation of the framerate. To keep the framerate calculation
- * accurate, a call to update each frame is required. Timer
is a
- * singleton object and must be created via the getTimer
method.
- *
- * @author Mark Powell
- * @version $Id: LWJGLTimer.java,v 1.21 2007/09/22 16:46:35 irrisor Exp $
- */
-public class LwjglTimer extends Timer {
-
- private static final Logger logger = Logger.getLogger(LwjglTimer.class.getName());
-
- //frame rate parameters.
- private long oldTime;
- private long startTime;
-
- private float lastTPF, lastFPS;
-
- private final static long LWJGL_TIMER_RES = 1;
- private final static float INV_LWJGL_TIMER_RES = ( 1f / LWJGL_TIMER_RES );
- public final static long LWJGL_TIME_TO_NANOS = (1000000000 / LWJGL_TIMER_RES);
-
- /**
- * Constructor builds a Timer
object. All values will be
- * initialized to it's default values.
- */
- public LwjglTimer() {
- reset();
- logger.log(Level.FINE, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES);
- }
-
- public void reset() {
- startTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS);
- oldTime = getTime();
- }
-
- @Override
- public float getTimeInSeconds() {
- return getTime() * INV_LWJGL_TIMER_RES;
- }
-
- /**
- * @see Timer#getTime()
- */
- public long getTime() {
- return ((long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS) - startTime);
- }
-
- /**
- * @see Timer#getResolution()
- */
- public long getResolution() {
- return LWJGL_TIMER_RES;
- }
-
- /**
- * getFrameRate
returns the current frame rate since the last
- * call to update
.
- *
- * @return the current frame rate.
- */
- public float getFrameRate() {
- return lastFPS;
- }
-
- public float getTimePerFrame() {
- return lastTPF;
- }
-
- /**
- * update
recalulates the frame rate based on the previous
- * call to update. It is assumed that update is called each frame.
- */
- public void update() {
- long curTime = getTime();
- lastTPF = (curTime - oldTime) * (1.0f / LWJGL_TIMER_RES);
- lastFPS = 1.0f / lastTPF;
- oldTime = curTime;
- }
-
- /**
- * toString
returns the string representation of this timer
- * in the format:
- *
- * jme.utility.Timer@1db699b
- * Time: {LONG}
- * FPS: {LONG}
- *
- * @return the string representation of this object.
- */
- @Override
- public String toString() {
- String string = super.toString();
- string += "\nTime: " + oldTime;
- string += "\nFPS: " + getFrameRate();
- return string;
- }
-}
\ No newline at end of file
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
index c5cb35e03..2f00eb700 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
@@ -42,6 +42,7 @@ import com.jme3.input.lwjgl.GlfwMouseInput;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeSystem;
+import com.jme3.system.NanoTimer;
import org.lwjgl.Sys;
import org.lwjgl.glfw.*;
@@ -73,6 +74,8 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
protected boolean allowSwapBuffers = false;
private long window = -1;
private final JmeContext.Type type;
+ private int frameRateLimit = -1;
+ private double frameSleepTime;
private GLFWErrorCallback errorCallback;
private GLFWWindowSizeCallback windowSizeCallback;
@@ -160,16 +163,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits());
glfwWindowHint(GLFW_SAMPLES, settings.getSamples());
glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GL_TRUE : GL_FALSE);
-
- int frameRateCap = settings.getFrameRate();
-
- if (!autoFlush) {
- frameRateCap = 20;
- }
-
- if (frameRateCap > 0) {
- glfwWindowHint(GLFW_REFRESH_RATE, frameRateCap);
- }
+ glfwWindowHint(GLFW_REFRESH_RATE, settings.getFrequency());
// Not sure how else to support bits per pixel
if (settings.getBitsPerPixel() == 24) {
@@ -289,7 +283,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
});
}
- timer = new LwjglTimer();
+ timer = new NanoTimer();
// For canvas, this will create a pbuffer,
// allowing us to query information.
@@ -303,7 +297,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
} catch (Exception ex) {
try {
if (window != -1) {
- //glfwSetWindowShouldClose(window, GL_TRUE);
glfwDestroyWindow(window);
}
} catch (Exception ex2) {
@@ -360,11 +353,41 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
if (renderer != null) {
renderer.postFrame();
}
+
+ if (autoFlush) {
+ if (frameRateLimit != getSettings().getFrameRate()) {
+ setFrameRateLimit(getSettings().getFrameRate());
+ }
+ } else if (frameRateLimit != 20) {
+ setFrameRateLimit(20);
+ }
+
+ // If software frame rate limiting has been asked for, lets calculate sleep time based on a base value calculated
+ // from 1000 / frameRateLimit in milliseconds subtracting the time it has taken to render last frame.
+ // This gives an approximate limit within 3 fps of the given frame rate limit.
+ if (frameRateLimit > 0) {
+ final double sleep = frameSleepTime - (timer.getTimePerFrame() / 1000.0);
+ final long sleepMillis = (long) sleep;
+ final int additionalNanos = (int) ((sleep - sleepMillis) * 1000000.0);
+
+ if (sleepMillis >= 0 && additionalNanos >= 0) {
+ try {
+ Thread.sleep(sleepMillis, additionalNanos);
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+
+ private void setFrameRateLimit(int frameRateLimit) {
+ this.frameRateLimit = frameRateLimit;
+ frameSleepTime = 1000.0 / this.frameRateLimit;
}
/**
* De-initialize in the OpenGL thread.
*/
+
protected void deinitInThread() {
destroyContext();
@@ -379,7 +402,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
+ "Must set with JmeContext.setSystemListener().");
}
- registerNatives();
loadNatives();
LOGGER.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion());
@@ -445,6 +467,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
return window;
}
+
+ // TODO: Implement support for window icon when GLFW supports it.
+
private ByteBuffer[] imagesToByteBuffers(Object[] images) {
ByteBuffer[] out = new ByteBuffer[images.length];
for (int i = 0; i < images.length; i++) {
From c375974a9a88d9484122e358c89b7ea2db5fd98b Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Thu, 17 Sep 2015 14:48:02 +0100
Subject: [PATCH 58/94] Fixed a compiler error where glfw input classes wanted
to use the old LwjglTimer class.
---
.../src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java | 3 +--
.../src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java
index 5b7d8e267..20cd07672 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java
@@ -35,7 +35,6 @@ 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;
@@ -112,6 +111,6 @@ public class GlfwKeyInput implements KeyInput {
}
public long getInputTimeNanos() {
- return (long) (glfwGetTime() * LwjglTimer.LWJGL_TIME_TO_NANOS);
+ return (long) (glfwGetTime() * 1000000000);
}
}
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
index 41e76a29d..05a2df5db 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
@@ -37,7 +37,6 @@ 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;
@@ -183,7 +182,7 @@ public class GlfwMouseInput implements MouseInput {
}
public long getInputTimeNanos() {
- return (long) (glfwGetTime() * LwjglTimer.LWJGL_TIME_TO_NANOS);
+ return (long) (glfwGetTime() * 1000000000);
}
public void setNativeCursor(final JmeCursor jmeCursor) {
From 495e0cf6d5603a871aa5b604b068845c9f370b70 Mon Sep 17 00:00:00 2001
From: Georg
Date: Mon, 21 Sep 2015 14:28:54 +0200
Subject: [PATCH 59/94] Fixed wrong BoundingBox transformation, when using
negative scaling values
---
jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
index 5baf3e3d6..c087950a3 100644
--- a/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
+++ b/jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
@@ -314,7 +314,7 @@ public class BoundingBox extends BoundingVolume {
transMatrix.absoluteLocal();
Vector3f scale = trans.getScale();
- vars.vect1.set(xExtent * scale.x, yExtent * scale.y, zExtent * scale.z);
+ vars.vect1.set(xExtent * FastMath.abs(scale.x), yExtent * FastMath.abs(scale.y), zExtent * FastMath.abs(scale.z));
transMatrix.mult(vars.vect1, vars.vect2);
// Assign the biggest rotations after scales.
box.xExtent = FastMath.abs(vars.vect2.getX());
From e3a45755c64a8624c04963c57271d915deb2c6e8 Mon Sep 17 00:00:00 2001
From: Julien Gouesse
Date: Tue, 22 Sep 2015 22:50:31 +0200
Subject: [PATCH 60/94] The JOGL backend doesn't need null-terminated strings
for the attributes and the uniforms
---
.../src/main/java/com/jme3/renderer/jogl/JoglGL.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java
index 6f335e960..e1c2a2505 100644
--- a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java
+++ b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java
@@ -519,14 +519,14 @@ public class JoglGL implements GL, GL2, GL3, GL4 {
@Override
public int glGetAttribLocation(int param1, String param2) {
- // FIXME: Does JOGL require null-terminated strings?????
- return GLContext.getCurrentGL().getGL2ES2().glGetAttribLocation(param1, param2 + "\0");
+ // JOGL 2.0 doesn't need a null-terminated string
+ return GLContext.getCurrentGL().getGL2ES2().glGetAttribLocation(param1, param2);
}
@Override
public int glGetUniformLocation(int param1, String param2) {
- // FIXME: Does JOGL require null-terminated strings????????
- return GLContext.getCurrentGL().getGL2ES2().glGetUniformLocation(param1, param2 + "\0");
+ // JOGL 2.0 doesn't need a null-terminated string
+ return GLContext.getCurrentGL().getGL2ES2().glGetUniformLocation(param1, param2);
}
@Override
From daa18429d1403a6b9f930a9b9678caddb7347d68 Mon Sep 17 00:00:00 2001
From: Julien Gouesse
Date: Tue, 22 Sep 2015 23:06:16 +0200
Subject: [PATCH 61/94] Removes the old JOGL renderer and uses the new unified
renderer as it works correctly now
---
.../com/jme3/renderer/jogl/JoglRenderer.java | 2699 -----------------
.../com/jme3/system/jogl/JoglContext.java | 5 +-
2 files changed, 1 insertion(+), 2703 deletions(-)
delete mode 100644 jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java
diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java
deleted file mode 100644
index 111719265..000000000
--- a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglRenderer.java
+++ /dev/null
@@ -1,2699 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.renderer.jogl;
-
-import com.jme3.light.LightList;
-import com.jme3.material.RenderState;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.math.Vector4f;
-import com.jme3.renderer.Caps;
-import com.jme3.renderer.IDList;
-import com.jme3.renderer.RenderContext;
-import com.jme3.renderer.Renderer;
-import com.jme3.renderer.RendererException;
-import com.jme3.renderer.Statistics;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.Mesh.Mode;
-import com.jme3.scene.VertexBuffer;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.VertexBuffer.Usage;
-import com.jme3.shader.Attribute;
-import com.jme3.shader.Shader;
-import com.jme3.shader.Shader.ShaderSource;
-import com.jme3.shader.Uniform;
-import com.jme3.texture.FrameBuffer;
-import com.jme3.texture.FrameBuffer.RenderBuffer;
-import com.jme3.texture.Image;
-import com.jme3.texture.Texture;
-import com.jme3.texture.Texture.WrapAxis;
-import com.jme3.util.BufferUtils;
-import com.jme3.util.ListMap;
-import com.jme3.util.NativeObjectManager;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import com.jogamp.nativewindow.NativeWindowFactory;
-import com.jogamp.opengl.GL;
-import com.jogamp.opengl.GL2;
-import com.jogamp.opengl.GL2ES1;
-import com.jogamp.opengl.GL2ES2;
-import com.jogamp.opengl.GL2ES3;
-import com.jogamp.opengl.GL2GL3;
-import com.jogamp.opengl.GL3;
-import com.jogamp.opengl.GLContext;
-import jme3tools.converters.MipMapGenerator;
-import jme3tools.shader.ShaderDebug;
-
-public class JoglRenderer implements Renderer {
-
- private static final Logger logger = Logger.getLogger(JoglRenderer.class.getName());
- private static final boolean VALIDATE_SHADER = false;
- private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
- private final StringBuilder stringBuf = new StringBuilder(250);
- private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1);
- private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16);
- protected FloatBuffer fb16 = BufferUtils.createFloatBuffer(16);
- private RenderContext context = new RenderContext();
- private NativeObjectManager objManager = new NativeObjectManager();
- private EnumSet caps = EnumSet.noneOf(Caps.class);
- //current state
- private Shader boundShader;
- private int initialDrawBuf, initialReadBuf;
- private int glslVer;
- private int vertexTextureUnits;
- private int fragTextureUnits;
- private int vertexUniforms;
- private int fragUniforms;
- private int vertexAttribs;
- private int maxFBOSamples;
- private int maxFBOAttachs;
- private int maxMRTFBOAttachs;
- private int maxRBSize;
- private int maxTexSize;
- private int maxCubeTexSize;
- private int maxVertCount;
- private int maxTriCount;
- private int maxColorTexSamples;
- private int maxDepthTexSamples;
- private FrameBuffer lastFb = null;
- private FrameBuffer mainFbOverride = null;
- private final Statistics statistics = new Statistics();
- private int vpX, vpY, vpW, vpH;
- private int clipX, clipY, clipW, clipH;
- private boolean linearizeSrgbImages;
-
- public JoglRenderer() {
- }
-
- protected void updateNameBuffer() {
- int len = stringBuf.length();
-
- nameBuf.position(0);
- nameBuf.limit(len);
- for (int i = 0; i < len; i++) {
- nameBuf.put((byte) stringBuf.charAt(i));
- }
-
- nameBuf.rewind();
- }
-
- @Override
- public Statistics getStatistics() {
- return statistics;
- }
-
- @Override
- public EnumSet getCaps() {
- return caps;
- }
-
- public void initialize() {
- GL gl = GLContext.getCurrentGL();
- //logger.log(Level.FINE, "Vendor: {0}", gl.glGetString(GL.GL_VENDOR));
- //logger.log(Level.FINE, "Renderer: {0}", gl.glGetString(GL.GL_RENDERER));
- //logger.log(Level.FINE, "Version: {0}", gl.glGetString(GL.GL_VERSION));
- if (gl.isExtensionAvailable("GL_VERSION_2_0")) {
- caps.add(Caps.OpenGL20);
- if (gl.isExtensionAvailable("GL_VERSION_2_1")) {
- caps.add(Caps.OpenGL21);
- if (gl.isExtensionAvailable("GL_VERSION_3_0")) {
- caps.add(Caps.OpenGL30);
- if (gl.isExtensionAvailable("GL_VERSION_3_1")) {
- caps.add(Caps.OpenGL31);
- if (gl.isExtensionAvailable("GL_VERSION_3_2")) {
- caps.add(Caps.OpenGL32);
- }
- }
- }
- }
- }
-
- //workaround, always assume we support GLSL100
- //some cards just don't report this correctly
- caps.add(Caps.GLSL100);
-
- String versionStr = null;
- if (caps.contains(Caps.OpenGL20) || gl.isGL2ES2()) {
- versionStr = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
- }
- if (versionStr == null || versionStr.equals("")) {
- glslVer = -1;
- throw new UnsupportedOperationException("GLSL and OpenGL2 is " +
- "required for the JOGL " +
- "renderer!");
- }
-
- // Fix issue in TestRenderToMemory when GL_FRONT is the main
- // buffer being used.
- gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, intBuf1);
- initialDrawBuf = intBuf1.get(0);
- gl.glGetIntegerv(GL2GL3.GL_READ_BUFFER, intBuf1);
- initialReadBuf = intBuf1.get(0);
-
- // XXX: This has to be GL_BACK for canvas on Mac
- // Since initialDrawBuf is GL_FRONT for pbuffer, gotta
- // change this value later on ...
-// initialDrawBuf = GL_BACK;
-// initialReadBuf = GL_BACK;
-
- int spaceIdx = versionStr.indexOf(" ");
- if (spaceIdx >= 1) {
- versionStr = versionStr.substring(0, spaceIdx);
- }
-
- try {
- float version = Float.parseFloat(versionStr);
- glslVer = (int) (version * 100);
- } catch (NumberFormatException e) {
- // the parsing fails on Raspberry Pi
- if (NativeWindowFactory.getNativeWindowType(false).equals(NativeWindowFactory.TYPE_BCM_VC_IV)) {
- logger.warning("Failed parsing GLSL version assuming it's v1.00");
- glslVer = 100;
- }
- }
-
- switch (glslVer) {
- default:
- if (glslVer < 400) {
- break;
- }
-
- // so that future OpenGL revisions wont break jme3
-
- // fall through intentional
- case 400:
- case 330:
- case 150:
- caps.add(Caps.GLSL150);
- case 140:
- caps.add(Caps.GLSL140);
- case 130:
- caps.add(Caps.GLSL130);
- case 120:
- caps.add(Caps.GLSL120);
- case 110:
- caps.add(Caps.GLSL110);
- case 100:
- caps.add(Caps.GLSL100);
- break;
- }
-
- if (!caps.contains(Caps.GLSL100)) {
- logger.log(Level.WARNING, "Force-adding GLSL100 support, since OpenGL2 is supported.");
- caps.add(Caps.GLSL100);
- }
-
- gl.glGetIntegerv(GL2ES2.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16);
- vertexTextureUnits = intBuf16.get(0);
- logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits);
- if (vertexTextureUnits > 0) {
- caps.add(Caps.VertexTextureFetch);
- }
-
- gl.glGetIntegerv(GL2ES2.GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16);
- fragTextureUnits = intBuf16.get(0);
- logger.log(Level.FINER, "Texture Units: {0}", fragTextureUnits);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16);
- vertexUniforms = intBuf16.get(0);
- logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16);
- fragUniforms = intBuf16.get(0);
- logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms);
-
- gl.glGetIntegerv(GL2ES2.GL_MAX_VERTEX_ATTRIBS, intBuf16);
- vertexAttribs = intBuf16.get(0);
- logger.log(Level.FINER, "Vertex Attributes: {0}", vertexAttribs);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_VARYING_FLOATS, intBuf16);
- int varyingFloats = intBuf16.get(0);
- logger.log(Level.FINER, "Varying Floats: {0}", varyingFloats);
-
- gl.glGetIntegerv(GL.GL_SUBPIXEL_BITS, intBuf16);
- int subpixelBits = intBuf16.get(0);
- logger.log(Level.FINER, "Subpixel Bits: {0}", subpixelBits);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_ELEMENTS_VERTICES, intBuf16);
- maxVertCount = intBuf16.get(0);
- logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_ELEMENTS_INDICES, intBuf16);
- maxTriCount = intBuf16.get(0);
- logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount);
-
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, intBuf16);
- maxTexSize = intBuf16.get(0);
- logger.log(Level.FINER, "Maximum Texture Resolution: {0}", maxTexSize);
-
- gl.glGetIntegerv(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16);
- maxCubeTexSize = intBuf16.get(0);
- logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize);
-
- if (gl.isExtensionAvailable("GL_ARB_color_buffer_float")) {
- // XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
- if (gl.isExtensionAvailable("GL_ARB_half_float_pixel")) {
- caps.add(Caps.FloatColorBuffer);
- }
- }
-
- if (gl.isExtensionAvailable("GL_ARB_depth_buffer_float")) {
- caps.add(Caps.FloatDepthBuffer);
- }
-
- if (caps.contains(Caps.OpenGL30)) {
- caps.add(Caps.PackedDepthStencilBuffer);
- }
-
- if (gl.isExtensionAvailable("GL_ARB_draw_instanced") || gl.isExtensionAvailable("GL_ARB_instanced_arrays")) {
- caps.add(Caps.MeshInstancing);
- }
-
- if (gl.isExtensionAvailable("GL_ARB_texture_buffer_object")) {
- caps.add(Caps.TextureBuffer);
- }
-
- if (gl.isExtensionAvailable("GL_ARB_texture_float")) {
- if (gl.isExtensionAvailable("GL_ARB_half_float_pixel")) {
- caps.add(Caps.FloatTexture);
- }
- }
-
- if (gl.isExtensionAvailable("GL_ARB_vertex_array_object")) {
- caps.add(Caps.VertexBufferArray);
- }
-
- if (gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two")) {
- caps.add(Caps.NonPowerOfTwoTextures);
- }
- else {
- logger.log(Level.WARNING, "Your graphics card does not "
- + "support non-power-of-2 textures. "
- + "Some features might not work.");
- }
-
- if (gl.isExtensionAvailable("GL_EXT_packed_float") || gl.isExtensionAvailable("GL_VERSION_3_0")) {
- // This format is part of the OGL3 specification
- caps.add(Caps.PackedFloatColorBuffer);
- if (gl.isExtensionAvailable("GL_ARB_half_float_pixel")) {
- // because textures are usually uploaded as RGB16F
- // need half-float pixel
- caps.add(Caps.PackedFloatTexture);
- }
- }
-
- if (gl.isExtensionAvailable("GL_EXT_texture_array") || gl.isExtensionAvailable("GL_VERSION_3_0")) {
- caps.add(Caps.TextureArray);
- }
-
- if (gl.isExtensionAvailable("GL_EXT_texture_shared_exponent") || gl.isExtensionAvailable("GL_VERSION_3_0")) {
- caps.add(Caps.SharedExponentTexture);
- }
-
- if (gl.isExtensionAvailable("GL_EXT_framebuffer_object")) {
- caps.add(Caps.FrameBuffer);
-
- gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, intBuf16);
- maxRBSize = intBuf16.get(0);
- logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, intBuf16);
- maxFBOAttachs = intBuf16.get(0);
- logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs);
-
- if (gl.isExtensionAvailable("GL_EXT_framebuffer_multisample")) {
- caps.add(Caps.FrameBufferMultisample);
-
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, intBuf16);
- maxFBOSamples = intBuf16.get(0);
- logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples);
- }
-
- if (gl.isExtensionAvailable("GL_ARB_texture_multisample")) {
- caps.add(Caps.TextureMultisample);
-
- gl.glGetIntegerv(GL3.GL_MAX_COLOR_TEXTURE_SAMPLES, intBuf16);
- maxColorTexSamples = intBuf16.get(0);
- logger.log(Level.FINER, "Texture Multisample Color Samples: {0}", maxColorTexSamples);
-
- gl.glGetIntegerv(GL3.GL_MAX_DEPTH_TEXTURE_SAMPLES, intBuf16);
- maxDepthTexSamples = intBuf16.get(0);
- logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples);
- }
-
- gl.glGetIntegerv(GL2ES2.GL_MAX_DRAW_BUFFERS, intBuf16);
- maxMRTFBOAttachs = intBuf16.get(0);
- if (maxMRTFBOAttachs > 1) {
- caps.add(Caps.FrameBufferMRT);
- logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
- }
-
- //if (gl.isExtensionAvailable("GL_ARB_draw_buffers")) {
- // caps.add(Caps.FrameBufferMRT);
- // gl.glGetIntegerv(GL2GL3.GL_MAX_DRAW_BUFFERS, intBuf16);
- // maxMRTFBOAttachs = intBuf16.get(0);
- // logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
- //}
- }
-
- if (gl.isExtensionAvailable("GL_ARB_multisample")) {
- gl.glGetIntegerv(GL.GL_SAMPLE_BUFFERS, intBuf16);
- boolean available = intBuf16.get(0) != 0;
- gl.glGetIntegerv(GL.GL_SAMPLES, intBuf16);
- int samples = intBuf16.get(0);
- logger.log(Level.FINER, "Samples: {0}", samples);
- boolean enabled = gl.glIsEnabled(GL.GL_MULTISAMPLE);
- if (samples > 0 && available && !enabled) {
- gl.glEnable(GL.GL_MULTISAMPLE);
- }
- caps.add(Caps.Multisample);
- }
-
- //supports sRGB pipeline
- if ((gl.isExtensionAvailable("GL_ARB_framebuffer_sRGB") && gl.isExtensionAvailable("GL_EXT_texture_sRGB")) || gl.isExtensionAvailable("GL_VERSION_3_0")){
- caps.add(Caps.Srgb);
- }
-
- logger.log(Level.FINE, "Caps: {0}", caps);
- }
-
- @Override
- public void invalidateState() {
- context.reset();
- boundShader = null;
- lastFb = null;
-
- GL gl = GLContext.getCurrentGL();
- gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, intBuf1);
- initialDrawBuf = intBuf1.get(0);
- gl.glGetIntegerv(GL2GL3.GL_READ_BUFFER, intBuf1);
- initialReadBuf = intBuf1.get(0);
- }
-
- @Override
- public void resetGLObjects() {
- logger.log(Level.FINE, "Reseting objects and invalidating state");
- objManager.resetObjects();
- statistics.clearMemory();
- invalidateState();
- }
-
- @Override
- public void cleanup() {
- logger.log(Level.FINE, "Deleting objects and invalidating state");
- objManager.deleteAllObjects(this);
- statistics.clearMemory();
- invalidateState();
- }
-
-// private void checkCap(Caps cap) {
-// if (!caps.contains(cap)) {
-// throw new UnsupportedOperationException("Required capability missing: " + cap.name());
-// }
-// }
-
- /*********************************************************************\
- |* Render State *|
- \*********************************************************************/
- @Override
- public void setDepthRange(float start, float end) {
- GL gl = GLContext.getCurrentGL();
- gl.glDepthRange(start, end);
- }
-
- @Override
- public void clearBuffers(boolean color, boolean depth, boolean stencil) {
- GL gl = GLContext.getCurrentGL();
- int bits = 0;
- if (color) {
- //See explanations of the depth below, we must enable color write to be able to clear the color buffer
- if (context.colorWriteEnabled == false) {
- gl.glColorMask(true, true, true, true);
- context.colorWriteEnabled = true;
- }
- bits = GL.GL_COLOR_BUFFER_BIT;
- }
- if (depth) {
-
- //glClear(GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false
- //here s some link on openl board
- //http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223
- //if depth clear is requested, we enable the depthMask
- if (context.depthWriteEnabled == false) {
- gl.glDepthMask(true);
- context.depthWriteEnabled = true;
- }
- bits |= GL.GL_DEPTH_BUFFER_BIT;
- }
- if (stencil) {
- bits |= GL.GL_STENCIL_BUFFER_BIT;
- }
- if (bits != 0) {
- gl.glClear(bits);
- }
- }
-
- @Override
- public void setBackgroundColor(ColorRGBA color) {
- GL gl = GLContext.getCurrentGL();
- gl.glClearColor(color.r, color.g, color.b, color.a);
- }
-
- @Override
- public void setAlphaToCoverage(boolean value) {
- if (caps.contains(Caps.Multisample)) {
- GL gl = GLContext.getCurrentGL();
- if (value) {
- gl.glEnable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE);
- } else {
- gl.glDisable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE);
- }
- }
- }
-
- @Override
- public void applyRenderState(RenderState state) {
- GL gl = GLContext.getCurrentGL();
- if (state.isWireframe() && !context.wireframe) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
- }
- context.wireframe = true;
- } else if (!state.isWireframe() && context.wireframe) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
- }
- context.wireframe = false;
- }
-
- if (state.isDepthTest() && !context.depthTestEnabled) {
- gl.glEnable(GL.GL_DEPTH_TEST);
- gl.glDepthFunc(convertTestFunction(context.depthFunc));
- context.depthTestEnabled = true;
- } else if (!state.isDepthTest() && context.depthTestEnabled) {
- gl.glDisable(GL.GL_DEPTH_TEST);
- context.depthTestEnabled = false;
- }
- if (state.getDepthFunc() != context.depthFunc) {
- gl.glDepthFunc(convertTestFunction(state.getDepthFunc()));
- context.depthFunc = state.getDepthFunc();
- }
- if (gl.isGL2ES1()) {
- if (state.isAlphaTest() && !context.alphaTestEnabled) {
- gl.glEnable(GL2ES1.GL_ALPHA_TEST);
- gl.getGL2ES1().glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff);
- context.alphaTestEnabled = true;
- } else if (!state.isAlphaTest() && context.alphaTestEnabled) {
- gl.glDisable(GL2ES1.GL_ALPHA_TEST);
- context.alphaTestEnabled = false;
- }
- if (state.getAlphaFallOff() != context.alphaTestFallOff) {
- gl.getGL2ES1().glAlphaFunc(convertTestFunction(context.alphaFunc), context.alphaTestFallOff);
- context.alphaTestFallOff = state.getAlphaFallOff();
- }
- if (state.getAlphaFunc() != context.alphaFunc) {
- gl.getGL2ES1().glAlphaFunc(convertTestFunction(state.getAlphaFunc()), context.alphaTestFallOff);
- context.alphaFunc = state.getAlphaFunc();
- }
- }
-
- if (state.isDepthWrite() && !context.depthWriteEnabled) {
- gl.glDepthMask(true);
- context.depthWriteEnabled = true;
- } else if (!state.isDepthWrite() && context.depthWriteEnabled) {
- gl.glDepthMask(false);
- context.depthWriteEnabled = false;
- }
-
- if (state.isColorWrite() && !context.colorWriteEnabled) {
- gl.glColorMask(true, true, true, true);
- context.colorWriteEnabled = true;
- } else if (!state.isColorWrite() && context.colorWriteEnabled) {
- gl.glColorMask(false, false, false, false);
- context.colorWriteEnabled = false;
- }
-
- if (state.isPointSprite() && !context.pointSprite) {
- // Only enable/disable sprite
- if (context.boundTextures[0] != null) {
- if (context.boundTextureUnit != 0) {
- gl.glActiveTexture(GL.GL_TEXTURE0);
- context.boundTextureUnit = 0;
- }
- if (gl.isGL2ES1()) {
- gl.glEnable(GL2ES1.GL_POINT_SPRITE);
- }
- if (gl.isGL2GL3()) {
- gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
- }
- }
- context.pointSprite = true;
- } else if (!state.isPointSprite() && context.pointSprite) {
- if (context.boundTextures[0] != null) {
- if (context.boundTextureUnit != 0) {
- gl.glActiveTexture(GL.GL_TEXTURE0);
- context.boundTextureUnit = 0;
- }
- if (gl.isGL2ES1()) {
- gl.glDisable(GL2ES1.GL_POINT_SPRITE);
- }
- if (gl.isGL2GL3()) {
- gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
- }
- context.pointSprite = false;
- }
- }
-
- if (state.isPolyOffset()) {
- if (!context.polyOffsetEnabled) {
- gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
- gl.glPolygonOffset(state.getPolyOffsetFactor(),
- state.getPolyOffsetUnits());
- context.polyOffsetEnabled = true;
- context.polyOffsetFactor = state.getPolyOffsetFactor();
- context.polyOffsetUnits = state.getPolyOffsetUnits();
- } else {
- if (state.getPolyOffsetFactor() != context.polyOffsetFactor
- || state.getPolyOffsetUnits() != context.polyOffsetUnits) {
- gl.glPolygonOffset(state.getPolyOffsetFactor(),
- state.getPolyOffsetUnits());
- context.polyOffsetFactor = state.getPolyOffsetFactor();
- context.polyOffsetUnits = state.getPolyOffsetUnits();
- }
- }
- } else {
- if (context.polyOffsetEnabled) {
- gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
- context.polyOffsetEnabled = false;
- context.polyOffsetFactor = 0;
- context.polyOffsetUnits = 0;
- }
- }
-
- if (state.getFaceCullMode() != context.cullMode) {
- if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) {
- gl.glDisable(GL.GL_CULL_FACE);
- } else {
- gl.glEnable(GL.GL_CULL_FACE);
- }
-
- switch (state.getFaceCullMode()) {
- case Off:
- break;
- case Back:
- gl.glCullFace(GL.GL_BACK);
- break;
- case Front:
- gl.glCullFace(GL.GL_FRONT);
- break;
- case FrontAndBack:
- gl.glCullFace(GL.GL_FRONT_AND_BACK);
- break;
- default:
- throw new UnsupportedOperationException("Unrecognized face cull mode: "
- + state.getFaceCullMode());
- }
-
- context.cullMode = state.getFaceCullMode();
- }
-
- if (state.getBlendMode() != context.blendMode) {
- if (state.getBlendMode() == RenderState.BlendMode.Off) {
- gl.glDisable(GL.GL_BLEND);
- } else {
- gl.glEnable(GL.GL_BLEND);
- switch (state.getBlendMode()) {
- case Off:
- break;
- case Additive:
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE);
- break;
- case AlphaAdditive:
- gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);
- break;
- case Color:
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR);
- break;
- case Alpha:
- gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
- break;
- case PremultAlpha:
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
- break;
- case Modulate:
- gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_ZERO);
- break;
- case ModulateX2:
- gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_SRC_COLOR);
- break;
- case Screen:
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR);
- break;
- case Exclusion:
- gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR);
- break;
- default:
- throw new UnsupportedOperationException("Unrecognized blend mode: "
- + state.getBlendMode());
- }
- }
-
- context.blendMode = state.getBlendMode();
- }
-
- if (context.stencilTest != state.isStencilTest()
- || context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation()
- || context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation()
- || context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation()
- || context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation()
- || context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation()
- || context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation()
- || context.frontStencilFunction != state.getFrontStencilFunction()
- || context.backStencilFunction != state.getBackStencilFunction()) {
-
- context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation(); //terrible looking, I know
- context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation();
- context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation();
- context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation();
- context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation();
- context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation();
- context.frontStencilFunction = state.getFrontStencilFunction();
- context.backStencilFunction = state.getBackStencilFunction();
-
- if (state.isStencilTest()) {
- gl.glEnable(GL.GL_STENCIL_TEST);
- gl.getGL2ES2().glStencilOpSeparate(GL.GL_FRONT,
- convertStencilOperation(state.getFrontStencilStencilFailOperation()),
- convertStencilOperation(state.getFrontStencilDepthFailOperation()),
- convertStencilOperation(state.getFrontStencilDepthPassOperation()));
- gl.getGL2ES2().glStencilOpSeparate(GL.GL_BACK,
- convertStencilOperation(state.getBackStencilStencilFailOperation()),
- convertStencilOperation(state.getBackStencilDepthFailOperation()),
- convertStencilOperation(state.getBackStencilDepthPassOperation()));
- gl.getGL2ES2().glStencilFuncSeparate(GL.GL_FRONT,
- convertTestFunction(state.getFrontStencilFunction()),
- 0, Integer.MAX_VALUE);
- gl.getGL2ES2().glStencilFuncSeparate(GL.GL_BACK,
- convertTestFunction(state.getBackStencilFunction()),
- 0, Integer.MAX_VALUE);
- } else {
- gl.glDisable(GL.GL_STENCIL_TEST);
- }
- }
- }
-
- private int convertStencilOperation(RenderState.StencilOperation stencilOp) {
- switch (stencilOp) {
- case Keep:
- return GL.GL_KEEP;
- case Zero:
- return GL.GL_ZERO;
- case Replace:
- return GL.GL_REPLACE;
- case Increment:
- return GL.GL_INCR;
- case IncrementWrap:
- return GL.GL_INCR_WRAP;
- case Decrement:
- return GL.GL_DECR;
- case DecrementWrap:
- return GL.GL_DECR_WRAP;
- case Invert:
- return GL.GL_INVERT;
- default:
- throw new UnsupportedOperationException("Unrecognized stencil operation: " + stencilOp);
- }
- }
-
- private int convertTestFunction(RenderState.TestFunction testFunc) {
- switch (testFunc) {
- case Never:
- return GL.GL_NEVER;
- case Less:
- return GL.GL_LESS;
- case LessOrEqual:
- return GL.GL_LEQUAL;
- case Greater:
- return GL.GL_GREATER;
- case GreaterOrEqual:
- return GL.GL_GEQUAL;
- case Equal:
- return GL.GL_EQUAL;
- case NotEqual:
- return GL.GL_NOTEQUAL;
- case Always:
- return GL.GL_ALWAYS;
- default:
- throw new UnsupportedOperationException("Unrecognized test function: " + testFunc);
- }
- }
-
- /*********************************************************************\
- |* Camera and World transforms *|
- \*********************************************************************/
- @Override
- public void setViewPort(int x, int y, int w, int h) {
- if (x != vpX || vpY != y || vpW != w || vpH != h) {
- GL gl = GLContext.getCurrentGL();
- gl.glViewport(x, y, w, h);
- vpX = x;
- vpY = y;
- vpW = w;
- vpH = h;
- }
- }
-
- @Override
- public void setClipRect(int x, int y, int width, int height) {
- GL gl = GLContext.getCurrentGL();
- if (!context.clipRectEnabled) {
- gl.glEnable(GL.GL_SCISSOR_TEST);
- context.clipRectEnabled = true;
- }
- if (clipX != x || clipY != y || clipW != width || clipH != height) {
- gl.glScissor(x, y, width, height);
- clipX = x;
- clipY = y;
- clipW = width;
- clipH = height;
- }
- }
-
- @Override
- public void clearClipRect() {
- if (context.clipRectEnabled) {
- GL gl = GLContext.getCurrentGL();
- gl.glDisable(GL.GL_SCISSOR_TEST);
- context.clipRectEnabled = false;
-
- clipX = 0;
- clipY = 0;
- clipW = 0;
- clipH = 0;
- }
- }
-
- @Override
- public void postFrame() {
- objManager.deleteUnused(this);
- }
-
- /*********************************************************************\
- |* Shaders *|
- \*********************************************************************/
- protected void updateUniformLocation(Shader shader, Uniform uniform) {
- GL gl = GLContext.getCurrentGL();
- // passing a null terminated string is not necessary with JOGL 2.0
- int loc = gl.getGL2ES2().glGetUniformLocation(shader.getId(), uniform.getName());
- if (loc < 0) {
- uniform.setLocation(-1);
- // uniform is not declared in shader
- logger.log(Level.FINE, "Uniform {0} is not declared in shader {1}.", new Object[]{uniform.getName(), shader.getSources()});
-
- } else {
- uniform.setLocation(loc);
- }
- }
-
- protected void bindProgram(Shader shader) {
- int shaderId = shader.getId();
- if (context.boundShaderProgram != shaderId) {
- GL gl = GLContext.getCurrentGL();
- gl.getGL2ES2().glUseProgram(shaderId);
- statistics.onShaderUse(shader, true);
- boundShader = shader;
- context.boundShaderProgram = shaderId;
- } else {
- statistics.onShaderUse(shader, false);
- }
- }
-
- protected void updateUniform(Shader shader, Uniform uniform) {
- int shaderId = shader.getId();
-
- assert uniform.getName() != null;
- assert shaderId > 0;
-
- bindProgram(shader);
-
- int loc = uniform.getLocation();
- if (loc == -1) {
- return;
- }
-
- if (loc == -2) {
- // get uniform location
- updateUniformLocation(shader, uniform);
- if (uniform.getLocation() == -1) {
- // not declared, ignore
- uniform.clearUpdateNeeded();
- return;
- }
- loc = uniform.getLocation();
- }
-
- if (uniform.getVarType() == null) {
- return; // value not set yet..
- }
- statistics.onUniformSet();
-
- uniform.clearUpdateNeeded();
- FloatBuffer fb;
- IntBuffer ib;
- GL gl = GLContext.getCurrentGL();
- switch (uniform.getVarType()) {
- case Float:
- Float f = (Float) uniform.getValue();
- gl.getGL2ES2().glUniform1f(loc, f.floatValue());
- break;
- case Vector2:
- Vector2f v2 = (Vector2f) uniform.getValue();
- gl.getGL2ES2().glUniform2f(loc, v2.getX(), v2.getY());
- break;
- case Vector3:
- Vector3f v3 = (Vector3f) uniform.getValue();
- gl.getGL2ES2().glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ());
- break;
- case Vector4:
- Object val = uniform.getValue();
- if (val instanceof ColorRGBA) {
- ColorRGBA c = (ColorRGBA) val;
- gl.getGL2ES2().glUniform4f(loc, c.r, c.g, c.b, c.a);
- } else if (val instanceof Vector4f) {
- Vector4f c = (Vector4f) val;
- gl.getGL2ES2().glUniform4f(loc, c.x, c.y, c.z, c.w);
- } else {
- Quaternion c = (Quaternion) uniform.getValue();
- gl.getGL2ES2().glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW());
- }
- break;
- case Boolean:
- Boolean b = (Boolean) uniform.getValue();
- gl.getGL2ES2().glUniform1i(loc, b.booleanValue() ? GL.GL_TRUE : GL.GL_FALSE);
- break;
- case Matrix3:
- fb = (FloatBuffer) uniform.getValue();
- assert fb.remaining() == 9;
- gl.getGL2ES2().glUniformMatrix3fv(loc, 1, false, fb);
- break;
- case Matrix4:
- fb = (FloatBuffer) uniform.getValue();
- assert fb.remaining() == 16;
- gl.getGL2ES2().glUniformMatrix4fv(loc, 1, false, fb);
- break;
- case IntArray:
- ib = (IntBuffer) uniform.getValue();
- gl.getGL2ES2().glUniform1iv(loc, ib.remaining(), ib);
- break;
- case FloatArray:
- fb = (FloatBuffer) uniform.getValue();
- gl.getGL2ES2().glUniform1fv(loc, fb.remaining(), fb);
- break;
- case Vector2Array:
- fb = (FloatBuffer) uniform.getValue();
- gl.getGL2ES2().glUniform2fv(loc, fb.remaining(), fb);
- break;
- case Vector3Array:
- fb = (FloatBuffer) uniform.getValue();
- gl.getGL2ES2().glUniform3fv(loc, fb.remaining(), fb);
- break;
- case Vector4Array:
- fb = (FloatBuffer) uniform.getValue();
- gl.getGL2ES2().glUniform4fv(loc, fb.remaining(), fb);
- break;
- case Matrix4Array:
- fb = (FloatBuffer) uniform.getValue();
- gl.getGL2ES2().glUniformMatrix4fv(loc, 1, false, fb);
- break;
- case Int:
- Integer i = (Integer) uniform.getValue();
- gl.getGL2ES2().glUniform1i(loc, i.intValue());
- break;
- default:
- throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType());
- }
- }
-
- protected void updateShaderUniforms(Shader shader) {
- ListMap uniforms = shader.getUniformMap();
- for (int i = 0; i < uniforms.size(); i++) {
- Uniform uniform = uniforms.getValue(i);
- if (uniform.isUpdateNeeded()) {
- updateUniform(shader, uniform);
- }
- }
- }
-
- protected void resetUniformLocations(Shader shader) {
- ListMap uniforms = shader.getUniformMap();
- for (int i = 0; i < uniforms.size(); i++) {
- Uniform uniform = uniforms.getValue(i);
- uniform.reset(); // e.g check location again
- }
- }
-
- public int convertShaderType(Shader.ShaderType type) {
- switch (type) {
- case Fragment:
- return GL2ES2.GL_FRAGMENT_SHADER;
- case Vertex:
- return GL2ES2.GL_VERTEX_SHADER;
-// case Geometry:
-// return GL3.GL_GEOMETRY_SHADER_ARB;
- default:
- throw new UnsupportedOperationException("Unrecognized shader type.");
- }
- }
-
- public void updateShaderSourceData(ShaderSource source) {
- int id = source.getId();
- GL gl = GLContext.getCurrentGL();
- if (id == -1) {
- // Create id
-// if (gl.isGL2ES2()) {
- id = gl.getGL2ES2().glCreateShader(convertShaderType(source.getType()));
-// }
-// else {
-// if (gl.isGL2()) {
-// id = gl.getGL2().glCreateShaderObjectARB(convertShaderType(source.getType()));
-// }
-// }
- if (id <= 0) {
- throw new RendererException("Invalid ID received when trying to create shader.");
- }
-
- source.setId(id);
- } else {
- throw new RendererException("Cannot recompile shader source");
- }
-
- // Upload shader source.
- // Merge the defines and source code.
- String language = source.getLanguage();
- stringBuf.setLength(0);
- if (language.startsWith("GLSL")) {
- int version = Integer.parseInt(language.substring(4));
- if (version > 100) {
- stringBuf.append("#version ");
- stringBuf.append(language.substring(4));
- if (version >= 150) {
- stringBuf.append(" core");
- }
- stringBuf.append("\n");
- }
- }
- updateNameBuffer();
-
- byte[] definesCodeData = source.getDefines().getBytes();
- byte[] sourceCodeData = source.getSource().getBytes();
- ByteBuffer codeBuf = BufferUtils.createByteBuffer(nameBuf.limit()
- + definesCodeData.length
- + sourceCodeData.length);
- codeBuf.put(nameBuf);
- codeBuf.put(definesCodeData);
- codeBuf.put(sourceCodeData);
- codeBuf.flip();
-
- byte[] array = new byte[codeBuf.limit()];
- codeBuf.rewind();
- codeBuf.get(array);
- codeBuf.rewind();
-
- gl.getGL2ES2().glShaderSource(id, 1, new String[]{new String(array)}, new int[]{array.length}, 0);
- gl.getGL2ES2().glCompileShader(id);
-
- gl.getGL2ES2().glGetShaderiv(id, GL2ES2.GL_COMPILE_STATUS, intBuf1);
-
- boolean compiledOK = intBuf1.get(0) == GL.GL_TRUE;
- String infoLog = null;
-
- if (VALIDATE_SHADER || !compiledOK) {
- // even if compile succeeded, check
- // log for warnings
- gl.getGL2ES2().glGetShaderiv(id, GL2ES2.GL_INFO_LOG_LENGTH, intBuf1);
- int length = intBuf1.get(0);
- if (length > 3) {
- // get infos
- ByteBuffer logBuf = BufferUtils.createByteBuffer(length);
- gl.getGL2ES2().glGetShaderInfoLog(id, length, null, logBuf);
- byte[] logBytes = new byte[length];
- logBuf.get(logBytes, 0, length);
- // convert to string, etc
- infoLog = new String(logBytes);
- }
- }
-
- if (compiledOK) {
- if (infoLog != null) {
- logger.log(Level.FINE, "{0} compile success\n{1}",
- new Object[]{source.getName(), infoLog});
- } else {
- logger.log(Level.FINE, "{0} compile success", source.getName());
- }
- source.clearUpdateNeeded();
- } else {
- logger.log(Level.WARNING, "Bad compile of:\n{0}",
- new Object[]{ShaderDebug.formatShaderSource(stringBuf.toString() + source.getDefines() + source.getSource())});
- if (infoLog != null) {
- throw new RendererException("compile error in: " + source + "\n" + infoLog);
- } else {
- throw new RendererException("compile error in: " + source + "\nerror: ");
- }
- }
- }
-
- public void updateShaderData(Shader shader) {
- GL gl = GLContext.getCurrentGL();
- int id = shader.getId();
- boolean needRegister = false;
- if (id == -1) {
- // create program
- id = gl.getGL2ES2().glCreateProgram();
- if (id == 0) {
- throw new RendererException("Invalid ID (" + id + ") received when trying to create shader program.");
- }
-
- shader.setId(id);
- needRegister = true;
- }
-
- for (ShaderSource source : shader.getSources()) {
- if (source.isUpdateNeeded()) {
- updateShaderSourceData(source);
- }
- gl.getGL2ES2().glAttachShader(id, source.getId());
- }
-
- if (gl.isGL2GL3() && gl.isExtensionAvailable("GL_EXT_gpu_shader4")) {
- // Check if GLSL version is 1.5 for shader
- gl.getGL2GL3().glBindFragDataLocation(id, 0, "outFragColor");
- // For MRT
- for (int i = 0; i < maxMRTFBOAttachs; i++) {
- gl.getGL2GL3().glBindFragDataLocation(id, i, "outFragData[" + i + "]");
- }
- }
-
- // Link shaders to program
- gl.getGL2ES2().glLinkProgram(id);
-
- // Check link status
- gl.getGL2ES2().glGetProgramiv(id, GL2ES2.GL_LINK_STATUS, intBuf1);
- boolean linkOK = intBuf1.get(0) == GL.GL_TRUE;
- String infoLog = null;
-
- if (VALIDATE_SHADER || !linkOK) {
- gl.getGL2ES2().glGetProgramiv(id, GL2ES2.GL_INFO_LOG_LENGTH, intBuf1);
- int length = intBuf1.get(0);
- if (length > 3) {
- // get infos
- ByteBuffer logBuf = BufferUtils.createByteBuffer(length);
- gl.getGL2ES2().glGetProgramInfoLog(id, length, null, logBuf);
-
- // convert to string, etc
- byte[] logBytes = new byte[length];
- logBuf.get(logBytes, 0, length);
- infoLog = new String(logBytes);
- }
- }
-
- if (linkOK) {
- if (infoLog != null) {
- logger.log(Level.FINE, "shader link success. \n{0}", infoLog);
- } else {
- logger.fine("shader link success");
- }
- shader.clearUpdateNeeded();
- if (needRegister) {
- // Register shader for clean up if it was created in this method.
- objManager.registerObject(shader);
- statistics.onNewShader();
- } else {
- // OpenGL spec: uniform locations may change after re-link
- resetUniformLocations(shader);
- }
- } else {
- if (infoLog != null) {
- throw new RendererException("Shader failed to link, shader:" + shader + "\n" + infoLog);
- } else {
- throw new RendererException("Shader failed to link, shader:" + shader + "\ninfo: ");
- }
- }
- }
-
- @Override
- public void setShader(Shader shader) {
- if (shader == null) {
- throw new IllegalArgumentException("Shader cannot be null");
- } else {
- if (shader.isUpdateNeeded()) {
- updateShaderData(shader);
- }
-
- // NOTE: might want to check if any of the
- // sources need an update?
-
- assert shader.getId() > 0;
-
- updateShaderUniforms(shader);
- bindProgram(shader);
- }
- }
-
- @Override
- public void deleteShaderSource(ShaderSource source) {
- if (source.getId() < 0) {
- logger.warning("Shader source is not uploaded to GPU, cannot delete.");
- return;
- }
- source.clearUpdateNeeded();
- GL gl = GLContext.getCurrentGL();
- gl.getGL2ES2().glDeleteShader(source.getId());
- source.resetObject();
- }
-
- @Override
- public void deleteShader(Shader shader) {
- if (shader.getId() == -1) {
- logger.warning("Shader is not uploaded to GPU, cannot delete.");
- return;
- }
-
- GL gl = GLContext.getCurrentGL();
- for (ShaderSource source : shader.getSources()) {
- if (source.getId() != -1) {
- gl.getGL2ES2().glDetachShader(shader.getId(), source.getId());
- deleteShaderSource(source);
- }
- }
-
- gl.getGL2ES2().glDeleteProgram(shader.getId());
- statistics.onDeleteShader();
- shader.resetObject();
- }
-
- /*********************************************************************\
- |* Framebuffers *|
- \*********************************************************************/
- @Override
- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
- GL gl = GLContext.getCurrentGL();
- if (gl.isExtensionAvailable("GL_EXT_framebuffer_blit") && gl.isGL2GL3()) {
- int srcX0 = 0;
- int srcY0 = 0;
- int srcX1;
- int srcY1;
-
- int dstX0 = 0;
- int dstY0 = 0;
- int dstX1;
- int dstY1;
-
- int prevFBO = context.boundFBO;
-
- if (mainFbOverride != null) {
- if (src == null) {
- src = mainFbOverride;
- }
- if (dst == null) {
- dst = mainFbOverride;
- }
- }
-
- if (src != null && src.isUpdateNeeded()) {
- updateFrameBuffer(src);
- }
-
- if (dst != null && dst.isUpdateNeeded()) {
- updateFrameBuffer(dst);
- }
-
- if (src == null) {
- gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0);
- srcX0 = vpX;
- srcY0 = vpY;
- srcX1 = vpX + vpW;
- srcY1 = vpY + vpH;
- } else {
- gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, src.getId());
- srcX1 = src.getWidth();
- srcY1 = src.getHeight();
- }
- if (dst == null) {
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0);
- dstX0 = vpX;
- dstY0 = vpY;
- dstX1 = vpX + vpW;
- dstY1 = vpY + vpH;
- } else {
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, dst.getId());
- dstX1 = dst.getWidth();
- dstY1 = dst.getHeight();
- }
- int mask = GL.GL_COLOR_BUFFER_BIT;
- if (copyDepth) {
- mask |= GL.GL_DEPTH_BUFFER_BIT;
- }
- gl.getGL2GL3().glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask,
- GL.GL_NEAREST);
- gl.glBindFramebuffer(GL2GL3.GL_FRAMEBUFFER, prevFBO);
-
-
- try {
- checkFrameBufferError();
- } catch (IllegalStateException ex) {
- logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
- logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
- throw ex;
- }
- } else {
- throw new RendererException("EXT_framebuffer_blit required.");
- // TODO: support non-blit copies?
- }
- }
-
- private String getTargetBufferName(int buffer) {
- switch (buffer) {
- case GL.GL_NONE:
- return "NONE";
- case GL.GL_FRONT:
- return "GL_FRONT";
- case GL.GL_BACK:
- return "GL_BACK";
- default:
- if (buffer >= GL.GL_COLOR_ATTACHMENT0
- && buffer <= GL2ES2.GL_COLOR_ATTACHMENT15) {
- return "GL_COLOR_ATTACHMENT"
- + (buffer - GL.GL_COLOR_ATTACHMENT0);
- } else {
- return "UNKNOWN? " + buffer;
- }
- }
- }
-
- private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) {
- GL gl = GLContext.getCurrentGL();
- System.out.println("== Renderbuffer " + name + " ==");
- System.out.println("RB ID: " + rb.getId());
- System.out.println("Is proper? " + gl.glIsRenderbuffer(rb.getId()));
-
- int attachment = convertAttachmentSlot(rb.getSlot());
-
- gl.glGetFramebufferAttachmentParameteriv(GL2GL3.GL_DRAW_FRAMEBUFFER,
- attachment,
- GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16);
- int type = intBuf16.get(0);
- gl.glGetFramebufferAttachmentParameteriv(GL2GL3.GL_DRAW_FRAMEBUFFER,
- attachment,
- GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16);
- int rbName = intBuf16.get(0);
-
- switch (type) {
- case GL.GL_NONE:
- System.out.println("Type: None");
- break;
- case GL.GL_TEXTURE:
- System.out.println("Type: Texture");
- break;
- case GL.GL_RENDERBUFFER:
- System.out.println("Type: Buffer");
- System.out.println("RB ID: " + rbName);
- break;
- }
-
-
-
- }
-
- private void printRealFrameBufferInfo(FrameBuffer fb) {
- GL gl = GLContext.getCurrentGL();
- final byte[] param = new byte[1];
- gl.glGetBooleanv(GL2GL3.GL_DOUBLEBUFFER, param, 0);
- boolean doubleBuffer = param[0] != (byte) 0x00;
- gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, intBuf16);
- String drawBuf = getTargetBufferName(intBuf16.get(0));
- gl.glGetIntegerv(GL2GL3.GL_READ_BUFFER, intBuf16);
- String readBuf = getTargetBufferName(intBuf16.get(0));
-
- int fbId = fb.getId();
- gl.glGetIntegerv(GL2GL3.GL_DRAW_FRAMEBUFFER_BINDING, intBuf16);
- int curDrawBinding = intBuf16.get(0);
- gl.glGetIntegerv(GL2GL3.GL_READ_FRAMEBUFFER_BINDING, intBuf16);
- int curReadBinding = intBuf16.get(0);
-
- System.out.println("=== OpenGL FBO State ===");
- System.out.println("Context doublebuffered? " + doubleBuffer);
- System.out.println("FBO ID: " + fbId);
- System.out.println("Is proper? " + gl.glIsFramebuffer(fbId));
- System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
- System.out.println("Is bound to read? " + (fbId == curReadBinding));
- System.out.println("Draw buffer: " + drawBuf);
- System.out.println("Read buffer: " + readBuf);
-
- if (context.boundFBO != fbId) {
- gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, fbId);
- context.boundFBO = fbId;
- }
-
- if (fb.getDepthBuffer() != null) {
- printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
- }
- for (int i = 0; i < fb.getNumColorBuffers(); i++) {
- printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
- }
- }
-
- private void checkFrameBufferError() {
- GL gl = GLContext.getCurrentGL();
- int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
- switch (status) {
- case GL.GL_FRAMEBUFFER_COMPLETE:
- break;
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- // Choose different formats
- throw new IllegalStateException("Framebuffer object format is "
- + "unsupported by the video hardware.");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- throw new IllegalStateException("Framebuffer has erronous attachment.");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- throw new IllegalStateException("Framebuffer is missing required attachment.");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- throw new IllegalStateException(
- "Framebuffer attachments must have same dimensions.");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- throw new IllegalStateException("Framebuffer attachments must have same formats.");
- case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- throw new IllegalStateException("Incomplete draw buffer.");
- case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- throw new IllegalStateException("Incomplete read buffer.");
- case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- throw new IllegalStateException("Incomplete multisample buffer.");
- default:
- // Programming error; will fail on all hardware
- throw new IllegalStateException("Some video driver error "
- + "or programming error occured. "
- + "Framebuffer object status is invalid. ");
- }
- }
-
- private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
- GL gl = GLContext.getCurrentGL();
- int id = rb.getId();
- if (id == -1) {
- gl.glGenRenderbuffers(1, intBuf1);
- id = intBuf1.get(0);
- rb.setId(id);
- }
-
- if (context.boundRB != id) {
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, id);
- context.boundRB = id;
- }
-
- if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) {
- throw new RendererException("Resolution " + fb.getWidth()
- + ":" + fb.getHeight() + " is not supported.");
- }
-
- TextureUtil.GLImageFormat glFmt = TextureUtil.getImageFormatWithError(rb.getFormat(), fb.isSrgb());
-
- if (fb.getSamples() > 1 && gl.isExtensionAvailable("GL_EXT_framebuffer_multisample")
- && gl.isGL2GL3()/*&& gl.isFunctionAvailable("glRenderbufferStorageMultisample")*/) {
- int samples = fb.getSamples();
- if (maxFBOSamples < samples) {
- samples = maxFBOSamples;
- }
- gl.getGL2GL3()
- .glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples,
- glFmt.internalFormat, fb.getWidth(),
- fb.getHeight());
- } else {
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER,
- glFmt.internalFormat, fb.getWidth(), fb.getHeight());
- }
- }
-
- private int convertAttachmentSlot(int attachmentSlot) {
- // can also add support for stencil here
- if (attachmentSlot == FrameBuffer.SLOT_DEPTH) {
- return GL.GL_DEPTH_ATTACHMENT;
- } else if (attachmentSlot == FrameBuffer.SLOT_DEPTH_STENCIL) {
- return GL2ES3.GL_DEPTH_STENCIL_ATTACHMENT;
- } else if (attachmentSlot < 0 || attachmentSlot >= 16) {
- throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot);
- }
-
- return GL.GL_COLOR_ATTACHMENT0 + attachmentSlot;
- }
-
- public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
- GL gl = GLContext.getCurrentGL();
- Texture tex = rb.getTexture();
- Image image = tex.getImage();
- if (image.isUpdateNeeded()) {
- updateTexImageData(image, tex.getType(), 0);
-
- // NOTE: For depth textures, sets nearest/no-mips mode
- // Required to fix "framebuffer unsupported"
- // for old NVIDIA drivers!
- setupTextureParams(tex);
- }
-
- gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
- convertAttachmentSlot(rb.getSlot()),
- convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()),
- image.getId(),
- 0);
- }
-
- public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
- boolean needAttach;
- if (rb.getTexture() == null) {
- // if it hasn't been created yet, then attach is required.
- needAttach = rb.getId() == -1;
- updateRenderBuffer(fb, rb);
- } else {
- needAttach = false;
- updateRenderTexture(fb, rb);
- }
- if (needAttach) {
- GL gl = GLContext.getCurrentGL();
- gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, convertAttachmentSlot(rb.getSlot()),
- GL.GL_RENDERBUFFER, rb.getId());
- }
- }
-
- public void updateFrameBuffer(FrameBuffer fb) {
- GL gl = GLContext.getCurrentGL();
- int id = fb.getId();
- if (id == -1) {
- // create FBO
- gl.glGenFramebuffers(1, intBuf1);
- id = intBuf1.get(0);
- fb.setId(id);
- objManager.registerObject(fb);
-
- statistics.onNewFrameBuffer();
- }
-
- if (context.boundFBO != id) {
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, id);
- // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
- context.boundDrawBuf = 0;
- context.boundFBO = id;
- }
-
- FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
- if (depthBuf != null) {
- updateFrameBufferAttachment(fb, depthBuf);
- }
-
- for (int i = 0; i < fb.getNumColorBuffers(); i++) {
- FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
- updateFrameBufferAttachment(fb, colorBuf);
- }
-
- fb.clearUpdateNeeded();
- }
-
- public Vector2f[] getFrameBufferSamplePositions(FrameBuffer fb) {
- if (fb.getSamples() <= 1) {
- throw new IllegalArgumentException("Framebuffer must be multisampled");
- }
-
- setFrameBuffer(fb);
-
- Vector2f[] samplePositions = new Vector2f[fb.getSamples()];
- FloatBuffer samplePos = BufferUtils.createFloatBuffer(2);
- GL gl = GLContext.getCurrentGL();
- if (gl.isGL2GL3()) {
- for (int i = 0; i < samplePositions.length; i++) {
- gl.getGL3().glGetMultisamplefv(GL3.GL_SAMPLE_POSITION, i, samplePos);
- samplePos.clear();
- samplePositions[i] = new Vector2f(samplePos.get(0) - 0.5f,
- samplePos.get(1) - 0.5f);
- }
- }
- return samplePositions;
- }
-
- @Override
- public void setMainFrameBufferOverride(FrameBuffer fb) {
- mainFbOverride = fb;
- }
-
- @Override
- public void setFrameBuffer(FrameBuffer fb) {
- GL gl = GLContext.getCurrentGL();
- if (!gl.isExtensionAvailable("GL_EXT_framebuffer_object")) {
- throw new RendererException("Framebuffer objects are not supported" +
- " by the video hardware");
- }
-
- if (fb == null && mainFbOverride != null) {
- fb = mainFbOverride;
- }
-
- if (lastFb == fb) {
- if (fb == null || !fb.isUpdateNeeded()) {
- return;
- }
- }
-
- // generate mipmaps for last FB if needed
- if (lastFb != null) {
- for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
- RenderBuffer rb = lastFb.getColorBuffer(i);
- Texture tex = rb.getTexture();
- if (tex != null
- && tex.getMinFilter().usesMipMapLevels()) {
- setTexture(0, rb.getTexture());
-
- int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
- gl.glEnable(textureType);
- gl.glGenerateMipmap(textureType);
- gl.glDisable(textureType);
- }
- }
- }
-
- if (fb == null) {
- // unbind any fbos
- if (context.boundFBO != 0) {
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
- statistics.onFrameBufferUse(null, true);
-
- context.boundFBO = 0;
- }
- // select back buffer
- if (context.boundDrawBuf != -1) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawBuffer(initialDrawBuf);
- }
- context.boundDrawBuf = -1;
- }
- if (context.boundReadBuf != -1) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glReadBuffer(initialReadBuf);
- }
- context.boundReadBuf = -1;
- }
-
- lastFb = null;
- } else {
- if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
- throw new IllegalArgumentException("The framebuffer: " + fb
- + "\nDoesn't have any color/depth buffers");
- }
-
- if (fb.isUpdateNeeded()) {
- updateFrameBuffer(fb);
- }
-
- if (context.boundFBO != fb.getId()) {
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb.getId());
- statistics.onFrameBufferUse(fb, true);
-
- // update viewport to reflect framebuffer's resolution
- setViewPort(0, 0, fb.getWidth(), fb.getHeight());
-
- context.boundFBO = fb.getId();
- } else {
- statistics.onFrameBufferUse(fb, false);
- }
- if (fb.getNumColorBuffers() == 0) {
- // make sure to select NONE as draw buf
- // no color buffer attached. select NONE
- if (context.boundDrawBuf != -2) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawBuffer(GL.GL_NONE);
- }
- context.boundDrawBuf = -2;
- }
- if (context.boundReadBuf != -2) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glReadBuffer(GL.GL_NONE);
- }
- context.boundReadBuf = -2;
- }
- } else {
- if (fb.getNumColorBuffers() > maxFBOAttachs) {
- throw new RendererException("Framebuffer has more color "
- + "attachments than are supported"
- + " by the video hardware!");
- }
- if (fb.isMultiTarget()) {
- if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
- throw new RendererException("Framebuffer has more"
- + " multi targets than are supported"
- + " by the video hardware!");
- }
-
- if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
- intBuf16.clear();
- for (int i = 0; i < fb.getNumColorBuffers(); i++) {
- intBuf16.put(GL.GL_COLOR_ATTACHMENT0 + i);
- }
-
- intBuf16.flip();
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawBuffers(intBuf16.limit(), intBuf16);
- }
- context.boundDrawBuf = 100 + fb.getNumColorBuffers();
- }
- } else {
- RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
- // select this draw buffer
- if (context.boundDrawBuf != rb.getSlot()) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawBuffer(GL.GL_COLOR_ATTACHMENT0 + rb.getSlot());
- }
- context.boundDrawBuf = rb.getSlot();
- }
- }
- }
-
- assert fb.getId() >= 0;
- assert context.boundFBO == fb.getId();
- lastFb = fb;
-
- try {
- checkFrameBufferError();
- } catch (IllegalStateException ex) {
- logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
- printRealFrameBufferInfo(fb);
- throw ex;
- }
- }
- }
-
- @Override
- public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
- GL gl = GLContext.getCurrentGL();
- if (fb != null) {
- RenderBuffer rb = fb.getColorBuffer();
- if (rb == null) {
- throw new IllegalArgumentException("Specified framebuffer"
- + " does not have a colorbuffer");
- }
-
- setFrameBuffer(fb);
- if (context.boundReadBuf != rb.getSlot()) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glReadBuffer(GL.GL_COLOR_ATTACHMENT0 + rb.getSlot());
- }
- context.boundReadBuf = rb.getSlot();
- }
- } else {
- setFrameBuffer(null);
- }
-
- gl.glReadPixels(vpX, vpY, vpW, vpH, /*GL.GL_RGBA*/ GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, byteBuf);
- }
-
- private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
- intBuf1.put(0, rb.getId());
- GL gl = GLContext.getCurrentGL();
- gl.glDeleteRenderbuffers(1, intBuf1);
- }
-
- @Override
- public void deleteFrameBuffer(FrameBuffer fb) {
- if (fb.getId() != -1) {
- GL gl = GLContext.getCurrentGL();
- if (context.boundFBO == fb.getId()) {
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
- context.boundFBO = 0;
- }
-
- if (fb.getDepthBuffer() != null) {
- deleteRenderBuffer(fb, fb.getDepthBuffer());
- }
- if (fb.getColorBuffer() != null) {
- deleteRenderBuffer(fb, fb.getColorBuffer());
- }
-
- intBuf1.put(0, fb.getId());
- gl.glDeleteFramebuffers(1, intBuf1);
- fb.resetObject();
-
- statistics.onDeleteFrameBuffer();
- }
- }
-
- /*********************************************************************\
- |* Textures *|
- \*********************************************************************/
- private int convertTextureType(Texture.Type type, int samples, int face) {
- GL gl = GLContext.getCurrentGL();
- if (samples > 1 && !gl.isExtensionAvailable("GL_ARB_texture_multisample")) {
- throw new RendererException("Multisample textures are not supported" +
- " by the video hardware.");
- }
-
- switch (type) {
- case TwoDimensional:
- if (samples > 1) {
- return GL3.GL_TEXTURE_2D_MULTISAMPLE;
- } else {
- return GL.GL_TEXTURE_2D;
- }
- case TwoDimensionalArray:
- if (samples > 1) {
- return GL3.GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
- } else {
- return GL2ES3.GL_TEXTURE_2D_ARRAY;
- }
- case ThreeDimensional:
- return GL2ES2.GL_TEXTURE_3D;
- case CubeMap:
- if (face < 0) {
- return GL.GL_TEXTURE_CUBE_MAP;
- } else if (face < 6) {
- return GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
- } else {
- throw new UnsupportedOperationException("Invalid cube map face index: " + face);
- }
- default:
- throw new UnsupportedOperationException("Unknown texture type: " + type);
- }
- }
-
- private int convertMagFilter(Texture.MagFilter filter) {
- switch (filter) {
- case Bilinear:
- return GL.GL_LINEAR;
- case Nearest:
- return GL.GL_NEAREST;
- default:
- throw new UnsupportedOperationException("Unknown mag filter: " + filter);
- }
- }
-
- private int convertMinFilter(Texture.MinFilter filter) {
- switch (filter) {
- case Trilinear:
- return GL.GL_LINEAR_MIPMAP_LINEAR;
- case BilinearNearestMipMap:
- return GL.GL_LINEAR_MIPMAP_NEAREST;
- case NearestLinearMipMap:
- return GL.GL_NEAREST_MIPMAP_LINEAR;
- case NearestNearestMipMap:
- return GL.GL_NEAREST_MIPMAP_NEAREST;
- case BilinearNoMipMaps:
- return GL.GL_LINEAR;
- case NearestNoMipMaps:
- return GL.GL_NEAREST;
- default:
- throw new UnsupportedOperationException("Unknown min filter: " + filter);
- }
- }
-
- private int convertWrapMode(Texture.WrapMode mode) {
- switch (mode) {
- case BorderClamp:
- return GL2GL3.GL_CLAMP_TO_BORDER;
- case Clamp:
- // Falldown intentional.
- case EdgeClamp:
- return GL.GL_CLAMP_TO_EDGE;
- case Repeat:
- return GL.GL_REPEAT;
- case MirroredRepeat:
- return GL.GL_MIRRORED_REPEAT;
- default:
- throw new UnsupportedOperationException("Unknown wrap mode: " + mode);
- }
- }
-
- @SuppressWarnings("fallthrough")
- private void setupTextureParams(Texture tex) {
- GL gl = GLContext.getCurrentGL();
- Image image = tex.getImage();
- int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1);
-
- // filter things
- int minFilter = convertMinFilter(tex.getMinFilter());
- int magFilter = convertMagFilter(tex.getMagFilter());
- gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter);
- gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter);
-
- if (tex.getAnisotropicFilter() > 1) {
- if (gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic")) {
- gl.glTexParameterf(target,
- GL.GL_TEXTURE_MAX_ANISOTROPY_EXT,
- tex.getAnisotropicFilter());
- }
- }
-
- if (context.pointSprite) {
- return; // Attempt to fix glTexParameter crash for some ATI GPUs
- }
- // repeat modes
- switch (tex.getType()) {
- case ThreeDimensional:
- case CubeMap: // cubemaps use 3D coords
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
- case TwoDimensional:
- case TwoDimensionalArray:
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
- // fall down here is intentional..
-// case OneDimensional:
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
- break;
- default:
- throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
- }
-
- if (tex.isNeedCompareModeUpdate()) {
- // R to Texture compare mode
- if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) {
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE);
- gl.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY);
- if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) {
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL);
- } else {
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL);
- }
- } else {
- //restoring default value
- gl.glTexParameteri(target, GL2ES2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
- }
- tex.compareModeUpdated();
- }
- }
-
- /**
- * Uploads the given image to the GL driver.
- *
- * @param img The image to upload
- * @param type How the data in the image argument should be interpreted.
- * @param unit The texture slot to be used to upload the image, not important
- */
- public void updateTexImageData(Image img, Texture.Type type, int unit) {
- int texId = img.getId();
- GL gl = GLContext.getCurrentGL();
- if (texId == -1) {
- // create texture
- gl.glGenTextures(1, intBuf1);
- texId = intBuf1.get(0);
- img.setId(texId);
- objManager.registerObject(img);
-
- statistics.onNewTexture();
- }
-
- // bind texture
- int target = convertTextureType(type, img.getMultiSamples(), -1);
- if (context.boundTextureUnit != unit) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
- context.boundTextureUnit = unit;
- }
- if (context.boundTextures[unit] != img) {
- gl.glBindTexture(target, texId);
- context.boundTextures[unit] = img;
-
- statistics.onTextureUse(img, true);
- }
-
- if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired()) {
- // Image does not have mipmaps, but they are required.
- // Generate from base level.
-
- if (!gl.isExtensionAvailable("GL_VERSION_3_0")) {
- if (gl.isGL2ES1()) {
- gl.glTexParameteri(target, GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE);
- img.setMipmapsGenerated(true);
- }
- } else {
- // For OpenGL3 and up.
- // We'll generate mipmaps via glGenerateMipmapEXT (see below)
- }
- } else if (img.hasMipmaps()) {
- // Image already has mipmaps, set the max level based on the
- // number of mipmaps we have.
- if (gl.isGL2GL3()) {
- gl.glTexParameteri(target, GL2ES3.GL_TEXTURE_MAX_LEVEL, img.getMipMapSizes().length - 1);
- }
- } else {
- // Image does not have mipmaps and they are not required.
- // Specify that that the texture has no mipmaps.
- gl.glTexParameteri(target, GL2ES3.GL_TEXTURE_MAX_LEVEL, 0);
- }
-
- int imageSamples = img.getMultiSamples();
- if (imageSamples > 1) {
- if (img.getFormat().isDepthFormat()) {
- img.setMultiSamples(Math.min(maxDepthTexSamples, imageSamples));
- } else {
- img.setMultiSamples(Math.min(maxColorTexSamples, imageSamples));
- }
- }
-
- // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT.
- if (!gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") && img.isNPOT()) {
- if (img.getData(0) == null) {
- throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware");
- } else {
- MipMapGenerator.resizeToPowerOf2(img);
- }
- }
-
- // Check if graphics card doesn't support multisample textures
- if (!gl.isExtensionAvailable("GL_ARB_texture_multisample")) {
- if (img.getMultiSamples() > 1) {
- throw new RendererException("Multisample textures not supported by graphics hardware");
- }
- }
-
- if (target == GL.GL_TEXTURE_CUBE_MAP) {
- List data = img.getData();
- if (data.size() != 6) {
- logger.log(Level.WARNING, "Invalid texture: {0}\n"
- + "Cubemap textures must contain 6 data units.", img);
- return;
- }
- for (int i = 0; i < 6; i++) {
- TextureUtil.uploadTexture(img, GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, linearizeSrgbImages);
- }
- } else if (target == GL2ES3.GL_TEXTURE_2D_ARRAY) {
- if (!caps.contains(Caps.TextureArray)) {
- throw new RendererException("Texture arrays not supported by graphics hardware");
- }
-
- List data = img.getData();
-
- // -1 index specifies prepare data for 2D Array
- TextureUtil.uploadTexture(img, target, -1, 0, linearizeSrgbImages);
-
- for (int i = 0; i < data.size(); i++) {
- // upload each slice of 2D array in turn
- // this time with the appropriate index
- TextureUtil.uploadTexture(img, target, i, 0, linearizeSrgbImages);
- }
- } else {
- TextureUtil.uploadTexture(img, target, 0, 0, linearizeSrgbImages);
- }
-
- if (img.getMultiSamples() != imageSamples) {
- img.setMultiSamples(imageSamples);
- }
-
- if (gl.isExtensionAvailable("GL_VERSION_3_0")) {
- if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired() && img.getData() != null) {
- // XXX: Required for ATI
- gl.glEnable(target);
- gl.glGenerateMipmap(target);
- gl.glDisable(target);
- img.setMipmapsGenerated(true);
- }
- }
-
- img.clearUpdateNeeded();
- }
-
- @Override
- public void setTexture(int unit, Texture tex) {
- GL gl = GLContext.getCurrentGL();
- Image image = tex.getImage();
- if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) {
- updateTexImageData(image, tex.getType(), unit);
- }
-
- int texId = image.getId();
- assert texId != -1;
-
- Image[] textures = context.boundTextures;
-
- int type = convertTextureType(tex.getType(), image.getMultiSamples(), -1);
-// if (!context.textureIndexList.moveToNew(unit)) {
-// if (context.boundTextureUnit != unit){
-// gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
-// context.boundTextureUnit = unit;
-// }
-// gl.glEnable(type);
-// }
-
- if (context.boundTextureUnit != unit) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + unit);
- context.boundTextureUnit = unit;
- }
- if (textures[unit] != image) {
- gl.glBindTexture(type, texId);
- textures[unit] = image;
-
- statistics.onTextureUse(image, true);
- } else {
- statistics.onTextureUse(image, false);
- }
-
- setupTextureParams(tex);
- }
-
- @Override
- public void modifyTexture(Texture tex, Image pixels, int x, int y) {
- setTexture(0, tex);
- TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), -1), 0, x, y, linearizeSrgbImages);
- }
-
- public void clearTextureUnits() {
- /*GL gl = GLContext.getCurrentGL();
- IDList textureList = context.textureIndexList;
- Texture[] textures = context.boundTextures;
- for (int i = 0; i < textureList.oldLen; i++) {
- int idx = textureList.oldList[i];
-
- if (context.boundTextureUnit != idx) {
- gl.glActiveTexture(GL.GL_TEXTURE0 + idx);
- context.boundTextureUnit = idx;
- }
- gl.glDisable(convertTextureType(textures[idx].getType()));
- textures[idx] = null;
- }
- context.textureIndexList.copyNewToOld();*/
- }
-
- @Override
- public void deleteImage(Image image) {
- int texId = image.getId();
- if (texId != -1) {
- intBuf1.put(0, texId);
- intBuf1.position(0).limit(1);
- GL gl = GLContext.getCurrentGL();
- gl.glDeleteTextures(1, intBuf1);
- image.resetObject();
-
- statistics.onDeleteTexture();
- }
- }
-
- /*********************************************************************\
- |* Vertex Buffers and Attributes *|
- \*********************************************************************/
- private int convertUsage(Usage usage) {
- switch (usage) {
- case Static:
- return GL.GL_STATIC_DRAW;
- case Dynamic:
- return GL.GL_DYNAMIC_DRAW;
- case Stream:
- return GL2ES2.GL_STREAM_DRAW;
- default:
- throw new RuntimeException("Unknown usage type: " + usage);
- }
- }
-
- private int convertFormat(VertexBuffer.Format format) {
- switch (format) {
- case Byte:
- return GL.GL_BYTE;
- case UnsignedByte:
- return GL.GL_UNSIGNED_BYTE;
- case Short:
- return GL.GL_SHORT;
- case UnsignedShort:
- return GL.GL_UNSIGNED_SHORT;
- case Int:
- return GL2ES2.GL_INT;
- case UnsignedInt:
- return GL.GL_UNSIGNED_INT;
- case Float:
- return GL.GL_FLOAT;
- case Double:
- return GL2GL3.GL_DOUBLE;
- default:
- throw new UnsupportedOperationException("Unknown buffer format.");
-
- }
- }
-
- @Override
- public void updateBufferData(VertexBuffer vb) {
- GL gl = GLContext.getCurrentGL();
- int bufId = vb.getId();
- boolean created = false;
- if (bufId == -1) {
- // create buffer
- gl.glGenBuffers(1, intBuf1);
- bufId = intBuf1.get(0);
- vb.setId(bufId);
- objManager.registerObject(vb);
-
- //statistics.onNewVertexBuffer();
-
- created = true;
- }
-
- // bind buffer
- int target;
- if (vb.getBufferType() == VertexBuffer.Type.Index) {
- target = GL.GL_ELEMENT_ARRAY_BUFFER;
- if (context.boundElementArrayVBO != bufId) {
- gl.glBindBuffer(target, bufId);
- context.boundElementArrayVBO = bufId;
- //statistics.onVertexBufferUse(vb, true);
- } else {
- //statistics.onVertexBufferUse(vb, false);
- }
- } else {
- target = GL.GL_ARRAY_BUFFER;
- if (context.boundArrayVBO != bufId) {
- gl.glBindBuffer(target, bufId);
- context.boundArrayVBO = bufId;
- //statistics.onVertexBufferUse(vb, true);
- } else {
- //statistics.onVertexBufferUse(vb, false);
- }
- }
-
- int usage = convertUsage(vb.getUsage());
- Buffer data = vb.getData();
- data.rewind();
-
- if (created || vb.hasDataSizeChanged()) {
- // upload data based on format
- gl.glBufferData(target, data.capacity() * vb.getFormat().getComponentSize(), data, usage);
- } else {
- gl.glBufferSubData(target, 0, data.capacity() * vb.getFormat().getComponentSize(), data);
- }
-
- vb.clearUpdateNeeded();
- }
-
- @Override
- public void deleteBuffer(VertexBuffer vb) {
- GL gl = GLContext.getCurrentGL();
- int bufId = vb.getId();
- if (bufId != -1) {
- // delete buffer
- intBuf1.put(0, bufId);
- intBuf1.position(0).limit(1);
- gl.glDeleteBuffers(1, intBuf1);
- vb.resetObject();
-
- //statistics.onDeleteVertexBuffer();
- }
- }
-
- public void clearVertexAttribs() {
- GL gl = GLContext.getCurrentGL();
- IDList attribList = context.attribIndexList;
- for (int i = 0; i < attribList.oldLen; i++) {
- int idx = attribList.oldList[i];
- gl.getGL2ES2().glDisableVertexAttribArray(idx);
- if (context.boundAttribs[idx].isInstanced() && gl.isGL3ES3()) {
- gl.getGL3ES3().glVertexAttribDivisor(idx, 0);
- }
- context.boundAttribs[idx] = null;
- }
- context.attribIndexList.copyNewToOld();
- }
-
- public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) {
- if (vb.getBufferType() == VertexBuffer.Type.Index) {
- throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib");
- }
-
- int programId = context.boundShaderProgram;
- if (programId > 0) {
- GL gl = GLContext.getCurrentGL();
- Attribute attrib = boundShader.getAttribute(vb.getBufferType());
- int loc = attrib.getLocation();
- if (loc == -1) {
- return; // not defined
- }
- if (loc == -2) {
- stringBuf.setLength(0);
- // JOGL 2.0 doesn't need a null terminated string
- stringBuf.append("in").append(vb.getBufferType().name());
- loc = gl.getGL2ES2().glGetAttribLocation(programId, stringBuf.toString());
-
- // not really the name of it in the shader (inPosition\0) but
- // the internal name of the enum (Position).
- if (loc < 0) {
- attrib.setLocation(-1);
- return; // not available in shader.
- } else {
- attrib.setLocation(loc);
- }
- }
-
- if (vb.isInstanced()) {
- if (!gl.isExtensionAvailable("GL_ARB_instanced_arrays")
- || !gl.isExtensionAvailable("GL_ARB_draw_instanced")) {
- throw new RendererException("Instancing is required, "
- + "but not supported by the "
- + "graphics hardware");
- }
- }
- int slotsRequired = 1;
- if (vb.getNumComponents() > 4) {
- if (vb.getNumComponents() % 4 != 0) {
- throw new RendererException("Number of components in multi-slot "
- + "buffers must be divisible by 4");
- }
- slotsRequired = vb.getNumComponents() / 4;
- }
-
- if (vb.isUpdateNeeded() && idb == null) {
- updateBufferData(vb);
- }
-
- VertexBuffer[] attribs = context.boundAttribs;
- for (int i = 0; i < slotsRequired; i++) {
- if (!context.attribIndexList.moveToNew(loc + i)) {
- gl.getGL2ES2().glEnableVertexAttribArray(loc + i);
- //System.out.println("Enabled ATTRIB IDX: "+loc + i);
- }
- }
- if (attribs[loc] != vb) {
- // NOTE: Use id from interleaved buffer if specified
- int bufId = idb != null ? idb.getId() : vb.getId();
- assert bufId != -1;
- if (context.boundArrayVBO != bufId) {
- gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId);
- context.boundArrayVBO = bufId;
- //statistics.onVertexBufferUse(vb, true);
- } else {
- //statistics.onVertexBufferUse(vb, false);
- }
-
- if (slotsRequired == 1) {
- gl.getGL2ES2().glVertexAttribPointer(loc,
- vb.getNumComponents(),
- convertFormat(vb.getFormat()),
- vb.isNormalized(),
- vb.getStride(),
- vb.getOffset());
- } else {
- for (int i = 0; i < slotsRequired; i++) {
- // The pointer maps the next 4 floats in the slot.
- // E.g.
- // P1: XXXX____________XXXX____________
- // P2: ____XXXX____________XXXX________
- // P3: ________XXXX____________XXXX____
- // P4: ____________XXXX____________XXXX
- // stride = 4 bytes in float * 4 floats in slot * num slots
- // offset = 4 bytes in float * 4 floats in slot * slot index
- gl.getGL2ES2().glVertexAttribPointer(loc + i,
- 4,
- convertFormat(vb.getFormat()),
- vb.isNormalized(),
- 4 * 4 * slotsRequired,
- 4 * 4 * i);
- }
- }
-
- for (int i = 0; i < slotsRequired; i++) {
- int slot = loc + i;
- if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) {
- // non-instanced -> instanced
- gl.getGL3ES3().glVertexAttribDivisor(slot, vb.getInstanceSpan());
- } else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) {
- // instanced -> non-instanced
- gl.getGL3ES3().glVertexAttribDivisor(slot, 0);
- }
- attribs[slot] = vb;
- }
- }
- } else {
- throw new IllegalStateException("Cannot render mesh without shader bound");
- }
- }
-
- public void setVertexAttrib(VertexBuffer vb) {
- setVertexAttrib(vb, null);
- }
-
- public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) {
- boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
- GL gl = GLContext.getCurrentGL();
- if (useInstancing) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawArraysInstanced(convertElementMode(mode), 0,
- vertCount, count);
- }
- } else {
- gl.glDrawArrays(convertElementMode(mode), 0, vertCount);
- }
- }
-
- public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) {
- if (indexBuf.getBufferType() != VertexBuffer.Type.Index) {
- throw new IllegalArgumentException("Only index buffers are allowed as triangle lists.");
- }
-
- if (indexBuf.isUpdateNeeded()) {
- updateBufferData(indexBuf);
- }
-
- int bufId = indexBuf.getId();
- assert bufId != -1;
-
- GL gl = GLContext.getCurrentGL();
-
- if (context.boundElementArrayVBO != bufId) {
- gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, bufId);
- context.boundElementArrayVBO = bufId;
- //statistics.onVertexBufferUse(indexBuf, true);
- } else {
- //statistics.onVertexBufferUse(indexBuf, true);
- }
-
- int vertCount = mesh.getVertexCount();
- boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
-
- if (mesh.getMode() == Mode.Hybrid) {
- int[] modeStart = mesh.getModeStart();
- int[] elementLengths = mesh.getElementLengths();
-
- int elMode = convertElementMode(Mode.Triangles);
- int fmt = convertFormat(indexBuf.getFormat());
- int elSize = indexBuf.getFormat().getComponentSize();
- int listStart = modeStart[0];
- int stripStart = modeStart[1];
- int fanStart = modeStart[2];
- int curOffset = 0;
- for (int i = 0; i < elementLengths.length; i++) {
- if (i == stripStart) {
- elMode = convertElementMode(Mode.TriangleStrip);
- } else if (i == fanStart) {
- elMode = convertElementMode(Mode.TriangleStrip);
- }
- int elementLength = elementLengths[i];
-
- if (useInstancing) {
- if (gl.isGL2()) {
- indexBuf.getData().position(curOffset);
- indexBuf.getData().limit(curOffset + elementLength);
-
- gl.getGL2().glDrawElementsInstanced(elMode,
- elementLength,
- fmt,
- indexBuf.getData(),
- count);
- } else {
- throw new IllegalArgumentException(
- "instancing is not supported.");
- }
- } else {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawRangeElements(elMode,
- 0,
- vertCount,
- elementLength,
- fmt,
- curOffset);
- } else {
- indexBuf.getData().position(curOffset);
- gl.getGL2().glDrawElements(elMode, elementLength, fmt,
- indexBuf.getData());
- }
- }
-
- curOffset += elementLength * elSize;
- }
- } else {
- if (useInstancing) {
- if (gl.isGL2()) {
- gl.getGL2().glDrawElementsInstanced(convertElementMode(mesh.getMode()),
- indexBuf.getData().limit(),
- convertFormat(indexBuf.getFormat()),
- indexBuf.getData(),
- count);
- } else {
- throw new IllegalArgumentException(
- "instancing is not supported.");
- }
- } else {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glDrawRangeElements(convertElementMode(mesh.getMode()),
- 0,
- vertCount,
- indexBuf.getData().limit(),
- convertFormat(indexBuf.getFormat()),
- 0);
- } else {
- indexBuf.getData().rewind();
- gl.glDrawElements(convertElementMode(mesh.getMode()),
- indexBuf.getData().limit(),
- convertFormat(indexBuf.getFormat()), 0);
- }
- }
- }
- }
-
- /**
- * *******************************************************************\ |*
- * Render Calls *|
- \********************************************************************
- */
- private int convertElementMode(Mesh.Mode mode) {
- switch (mode) {
- case Points:
- return GL.GL_POINTS;
- case Lines:
- return GL.GL_LINES;
- case LineLoop:
- return GL.GL_LINE_LOOP;
- case LineStrip:
- return GL.GL_LINE_STRIP;
- case Triangles:
- return GL.GL_TRIANGLES;
- case TriangleFan:
- return GL.GL_TRIANGLE_FAN;
- case TriangleStrip:
- return GL.GL_TRIANGLE_STRIP;
- default:
- throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode);
- }
- }
-
- public void updateVertexArray(Mesh mesh, VertexBuffer instanceData) {
- int id = mesh.getId();
- GL gl = GLContext.getCurrentGL();
-
- if (id == -1) {
- IntBuffer temp = intBuf1;
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glGenVertexArrays(1, temp);
- }
- id = temp.get(0);
- mesh.setId(id);
- }
-
- if (context.boundVertexArray != id) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glBindVertexArray(id);
- }
- context.boundVertexArray = id;
- }
-
- VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
- if (interleavedData != null && interleavedData.isUpdateNeeded()) {
- updateBufferData(interleavedData);
- }
-
- if (instanceData != null) {
- setVertexAttrib(instanceData, null);
- }
-
- for (VertexBuffer vb : mesh.getBufferList().getArray()) {
- if (vb.getBufferType() == Type.InterleavedData
- || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
- || vb.getBufferType() == Type.Index) {
- continue;
- }
-
- if (vb.getStride() == 0) {
- // not interleaved
- setVertexAttrib(vb);
- } else {
- // interleaved
- setVertexAttrib(vb, interleavedData);
- }
- }
- }
-
- private void renderMeshVertexArray(Mesh mesh, int lod, int count, VertexBuffer instanceData) {
- if (mesh.getId() == -1) {
- updateVertexArray(mesh, instanceData);
- } else {
- // TODO: Check if it was updated
- }
-
- if (context.boundVertexArray != mesh.getId()) {
- GL gl = GLContext.getCurrentGL();
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glBindVertexArray(mesh.getId());
- }
- context.boundVertexArray = mesh.getId();
- }
-
-// IntMap buffers = mesh.getBuffers();
- VertexBuffer indices;
- if (mesh.getNumLodLevels() > 0) {
- indices = mesh.getLodLevel(lod);
- } else {
- indices = mesh.getBuffer(Type.Index);
- }
- if (indices != null) {
- drawTriangleList(indices, mesh, count);
- } else {
- drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
- }
- clearVertexAttribs();
- clearTextureUnits();
- }
-
- private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
-
- // Here while count is still passed in. Can be removed when/if
- // the method is collapsed again. -pspeed
- count = Math.max(mesh.getInstanceCount(), count);
-
- VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
- if (interleavedData != null && interleavedData.isUpdateNeeded()) {
- updateBufferData(interleavedData);
- }
-
- VertexBuffer indices;
- if (mesh.getNumLodLevels() > 0) {
- indices = mesh.getLodLevel(lod);
- } else {
- indices = mesh.getBuffer(Type.Index);
- }
-
- if (instanceData != null) {
- for (VertexBuffer vb : instanceData) {
- setVertexAttrib(vb, null);
- }
- }
-
- for (VertexBuffer vb : mesh.getBufferList().getArray()) {
- if (vb.getBufferType() == Type.InterleavedData
- || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
- || vb.getBufferType() == Type.Index) {
- continue;
- }
-
- if (vb.getStride() == 0) {
- // not interleaved
- setVertexAttrib(vb);
- } else {
- // interleaved
- setVertexAttrib(vb, interleavedData);
- }
- }
-
- if (indices != null) {
- drawTriangleList(indices, mesh, count);
- } else {
- drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
- }
- clearVertexAttribs();
- clearTextureUnits();
- }
-
- @Override
- public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
- if (mesh.getVertexCount() == 0) {
- return;
- }
-
- GL gl = GLContext.getCurrentGL();
- if (context.pointSprite && mesh.getMode() != Mode.Points) {
- // XXX: Hack, disable point sprite mode if mesh not in point mode
- if (context.boundTextures[0] != null) {
- if (context.boundTextureUnit != 0) {
- gl.glActiveTexture(GL.GL_TEXTURE0);
- context.boundTextureUnit = 0;
- }
- if (gl.isGL2ES1()) {
- gl.glDisable(GL2ES1.GL_POINT_SPRITE);
- }
- if (gl.isGL2GL3()) {
- gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
- }
- context.pointSprite = false;
- }
- }
-
- if (context.pointSize != mesh.getPointSize()) {
- if (gl.isGL2GL3()) {
- gl.getGL2GL3().glPointSize(mesh.getPointSize());
- }
- context.pointSize = mesh.getPointSize();
- }
- if (context.lineWidth != mesh.getLineWidth()) {
- gl.glLineWidth(mesh.getLineWidth());
- context.lineWidth = mesh.getLineWidth();
- }
-
- statistics.onMeshDrawn(mesh, lod);
-// if (gl.isExtensionAvailable("GL_ARB_vertex_array_object")){
-// renderMeshVertexArray(mesh, lod, count);
-// }else{
- renderMeshDefault(mesh, lod, count, instanceData);
-// }
- }
-
- @Override
- public void setMainFrameBufferSrgb(boolean srgb) {
- //Gamma correction
- if(srgb && caps.contains(Caps.Srgb)){
- GLContext.getCurrentGL().glEnable(GL3.GL_FRAMEBUFFER_SRGB);
- logger.log(Level.FINER, "SRGB FrameBuffer enabled (Gamma Correction)");
- }else{
- GLContext.getCurrentGL().glDisable(GL3.GL_FRAMEBUFFER_SRGB);
- }
-
- }
-
- @Override
- public void setLinearizeSrgbImages(boolean linearize) {
- linearizeSrgbImages = linearize;
- }
-
- public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) {
- throw new UnsupportedOperationException("Not supported yet. URA will make that work seamlessly");
- }
-}
diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java
index 3b90877df..25ad4fc8e 100644
--- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java
+++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java
@@ -40,7 +40,6 @@ import com.jme3.renderer.RendererException;
import com.jme3.renderer.jogl.JoglGL;
import com.jme3.renderer.jogl.JoglGLExt;
import com.jme3.renderer.jogl.JoglGLFbo;
-import com.jme3.renderer.jogl.JoglRenderer;
import com.jme3.renderer.opengl.GL2;
import com.jme3.renderer.opengl.GL3;
import com.jme3.renderer.opengl.GL4;
@@ -192,9 +191,7 @@ public abstract class JoglContext implements JmeContext {
glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
}
- //FIXME uncomment the line below when the unified renderer is ready for the prime time :)
- //renderer = new GLRenderer(gl, glext, glfbo);
- renderer = new JoglRenderer();
+ renderer = new GLRenderer(gl, glext, glfbo);
renderer.initialize();
} else {
throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
From 9f56a45d56c024d0161b6343fe6e97766b5953ce Mon Sep 17 00:00:00 2001
From: Julien Gouesse
Date: Tue, 22 Sep 2015 23:11:16 +0200
Subject: [PATCH 62/94] Adds some options into AppSettings for JogAmp's JOGL
and JOAL
---
.../main/java/com/jme3/system/AppSettings.java | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/jme3-core/src/main/java/com/jme3/system/AppSettings.java b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
index 484458929..6bf826236 100644
--- a/jme3-core/src/main/java/com/jme3/system/AppSettings.java
+++ b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
@@ -110,6 +110,24 @@ public final class AppSettings extends HashMap {
* @see AppSettings#setAudioRenderer(java.lang.String)
*/
public static final String ANDROID_OPENAL_SOFT = "OpenAL_SOFT";
+
+ /**
+ * Use JogAmp's JOGL as the display system
+ *
+ * N.B: This backend is EXPERIMENTAL
+ *
+ * @see AppSettings#setRenderer(java.lang.String)
+ */
+ public static final String JOGL = "JOGL";
+
+ /**
+ * Use JogAmp's JOAL as the display system
+ *
+ * N.B: This backend is EXPERIMENTAL
+ *
+ * @see AppSettings#setRenderer(java.lang.String)
+ */
+ public static final String JOAL = "JOAL";
static {
defaults.put("Width", 640);
From 5f77ff021bb3eb17af4ac400ad0661f96bd3ba6d Mon Sep 17 00:00:00 2001
From: Julien Gouesse
Date: Tue, 22 Sep 2015 23:50:28 +0200
Subject: [PATCH 63/94] Fixes the NullPointerException in the demos when using
JoglNewtDisplay
---
.../src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java
index 84a99e8d2..56eab406a 100644
--- a/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java
+++ b/jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtDisplay.java
@@ -173,6 +173,8 @@ public class JoglNewtDisplay extends JoglNewtAbstractDisplay {
if (waitFor){
waitFor(false);
}
+ if (animator.isAnimating())
+ animator.stop();
}
public void restart() {
From d269839efb1470b3f44c5d201baf49e117783118 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 21:53:50 -0400
Subject: [PATCH 64/94] FastMath: faster nearestPowerOfTwo and unit test
---
.../src/main/java/com/jme3/math/FastMath.java | 19 +++++-
.../test/java/com/jme3/math/FastMathTest.java | 59 +++++++++++++++++++
2 files changed, 77 insertions(+), 1 deletion(-)
create mode 100644 jme3-core/src/test/java/com/jme3/math/FastMathTest.java
diff --git a/jme3-core/src/main/java/com/jme3/math/FastMath.java b/jme3-core/src/main/java/com/jme3/math/FastMath.java
index d9d944057..4f1a7feed 100644
--- a/jme3-core/src/main/java/com/jme3/math/FastMath.java
+++ b/jme3-core/src/main/java/com/jme3/math/FastMath.java
@@ -87,8 +87,25 @@ final public class FastMath {
return (number > 0) && (number & (number - 1)) == 0;
}
+ /**
+ * Get the next power of two of the given number.
+ *
+ * E.g. for an input 100, this returns 128.
+ * Returns 1 for all numbers <= 1.
+ *
+ * @param number The number to obtain the POT for.
+ * @return The next power of two.
+ */
public static int nearestPowerOfTwo(int number) {
- return (int) Math.pow(2, Math.ceil(Math.log(number) / Math.log(2)));
+ number--;
+ number |= number >> 1;
+ number |= number >> 2;
+ number |= number >> 4;
+ number |= number >> 8;
+ number |= number >> 16;
+ number++;
+ number += (number == 0) ? 1 : 0;
+ return number;
}
/**
diff --git a/jme3-core/src/test/java/com/jme3/math/FastMathTest.java b/jme3-core/src/test/java/com/jme3/math/FastMathTest.java
new file mode 100644
index 000000000..a74390d42
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/math/FastMathTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.math;
+
+import org.junit.Test;
+
+/**
+ * Verifies that algorithms in {@link FastMath} are working correctly.
+ *
+ * @author Kirill Vainer
+ */
+public class FastMathTest {
+
+ private int nearestPowerOfTwoSlow(int number) {
+ return (int) Math.pow(2, Math.ceil(Math.log(number) / Math.log(2)));
+ }
+
+ @Test
+ public void testNearestPowerOfTwo() {
+ for (int i = -100; i < 1; i++) {
+ assert FastMath.nearestPowerOfTwo(i) == 1;
+ }
+ for (int i = 1; i < 10000; i++) {
+ int nextPowerOf2 = FastMath.nearestPowerOfTwo(i);
+ assert i <= nextPowerOf2;
+ assert FastMath.isPowerOfTwo(nextPowerOf2);
+ assert nextPowerOf2 == nearestPowerOfTwoSlow(i);
+ }
+ }
+}
From efe600c38d0a862a4034a7b8ca8aeb42f247cbea Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 21:57:42 -0400
Subject: [PATCH 65/94] GLRenderer: put max anisotropy into limits map
---
jme3-core/src/main/java/com/jme3/renderer/Limits.java | 2 ++
jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java | 1 +
.../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 1 +
3 files changed, 4 insertions(+)
diff --git a/jme3-core/src/main/java/com/jme3/renderer/Limits.java b/jme3-core/src/main/java/com/jme3/renderer/Limits.java
index 86cddb178..81db88f5e 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/Limits.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/Limits.java
@@ -77,4 +77,6 @@ public enum Limits {
DepthTextureSamples,
VertexUniformVectors,
+
+ TextureAnisotropy,
}
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java
index 27f0eb8bd..c77ff6449 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java
@@ -68,6 +68,7 @@ public interface GLExt {
public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES = 0x910F;
public static final int GL_MAX_DRAW_BUFFERS_ARB = 0x8824;
public static final int GL_MAX_SAMPLES_EXT = 0x8D57;
+ public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
public static final int GL_MULTISAMPLE_ARB = 0x809D;
public static final int GL_NUM_PROGRAM_BINARY_FORMATS = 0x87FE;
public static final int GL_PIXEL_PACK_BUFFER_ARB = 0x88EB;
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 276453117..ee7f7a560 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
@@ -374,6 +374,7 @@ public class GLRenderer implements Renderer {
if (hasExtension("GL_EXT_texture_filter_anisotropic")) {
caps.add(Caps.TextureFilterAnisotropic);
+ limits.put(Limits.TextureAnisotropy, getInteger(GLExt.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
}
if (hasExtension("GL_EXT_framebuffer_object")
From aa54947ff36ac2591abef4c8e10c09c97cdddf72 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:01:17 -0400
Subject: [PATCH 66/94] GLRenderer: cleanup to shadow compare mode
Store compare mode in LastTextureState instead of on Texture object
---
.../java/com/jme3/renderer/opengl/GL2.java | 2 +-
.../com/jme3/renderer/opengl/GLRenderer.java | 52 +++++++++----------
.../main/java/com/jme3/texture/Texture.java | 14 +----
.../jme3/texture/image/LastTextureState.java | 9 +++-
4 files changed, 33 insertions(+), 44 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java
index db09fdd02..abf6a77d7 100644
--- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java
+++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java
@@ -44,7 +44,7 @@ public interface GL2 extends GL {
public static final int GL_ALPHA_TEST = 0xBC0;
public static final int GL_BGR = 0x80E0;
public static final int GL_BGRA = 0x80E1;
- public static final int GL_COMPARE_R_TO_TEXTURE = 0x884E;
+ public static final int GL_COMPARE_REF_TO_TEXTURE = 0x884E;
public static final int GL_DEPTH_COMPONENT24 = 0x81A6;
public static final int GL_DEPTH_COMPONENT32 = 0x81A7;
public static final int GL_DEPTH_TEXTURE_MODE = 0x884B;
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 ee7f7a560..7b40994ad 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
@@ -51,7 +51,9 @@ import com.jme3.texture.FrameBuffer;
import com.jme3.texture.FrameBuffer.RenderBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
+import com.jme3.texture.Texture.ShadowCompareMode;
import com.jme3.texture.Texture.WrapAxis;
+import com.jme3.texture.image.LastTextureState;
import com.jme3.util.BufferUtils;
import com.jme3.util.ListMap;
import com.jme3.util.MipMapGenerator;
@@ -1842,77 +1844,71 @@ public class GLRenderer implements Renderer {
int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1);
boolean haveMips = true;
-
if (image != null) {
haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps();
}
+
+ LastTextureState curState = image.getLastTextureState();
- // filter things
- if (image.getLastTextureState().magFilter != tex.getMagFilter()) {
- int magFilter = convertMagFilter(tex.getMagFilter());
+ if (curState.magFilter != tex.getMagFilter()) {
bindTextureAndUnit(target, image, unit);
- gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter);
- image.getLastTextureState().magFilter = tex.getMagFilter();
+ gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, convertMagFilter(tex.getMagFilter()));
+ curState.magFilter = tex.getMagFilter();
}
- if (image.getLastTextureState().minFilter != tex.getMinFilter()) {
- int minFilter = convertMinFilter(tex.getMinFilter(), haveMips);
+ if (curState.minFilter != tex.getMinFilter()) {
bindTextureAndUnit(target, image, unit);
- gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter);
- image.getLastTextureState().minFilter = tex.getMinFilter();
+ gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, convertMinFilter(tex.getMinFilter(), haveMips));
+ curState.minFilter = tex.getMinFilter();
}
if (caps.contains(Caps.TextureFilterAnisotropic)
- && image.getLastTextureState().anisoFilter != tex.getAnisotropicFilter()) {
+ && curState.anisoFilter != tex.getAnisotropicFilter()) {
bindTextureAndUnit(target, image, unit);
gl.glTexParameterf(target,
GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT,
tex.getAnisotropicFilter());
- image.getLastTextureState().anisoFilter = tex.getAnisotropicFilter();
+ curState.anisoFilter = tex.getAnisotropicFilter();
}
- // repeat modes
switch (tex.getType()) {
case ThreeDimensional:
case CubeMap: // cubemaps use 3D coords
- if (gl2 != null && image.getLastTextureState().rWrap != tex.getWrap(WrapAxis.R)) {
+ if (gl2 != null && curState.rWrap != tex.getWrap(WrapAxis.R)) {
bindTextureAndUnit(target, image, unit);
gl2.glTexParameteri(target, GL2.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
- image.getLastTextureState().rWrap = tex.getWrap(WrapAxis.R);
+ curState.rWrap = tex.getWrap(WrapAxis.R);
}
//There is no break statement on purpose here
case TwoDimensional:
case TwoDimensionalArray:
- if (image.getLastTextureState().tWrap != tex.getWrap(WrapAxis.T)) {
+ if (curState.tWrap != tex.getWrap(WrapAxis.T)) {
bindTextureAndUnit(target, image, unit);
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
image.getLastTextureState().tWrap = tex.getWrap(WrapAxis.T);
}
- if (image.getLastTextureState().sWrap != tex.getWrap(WrapAxis.S)) {
+ if (curState.sWrap != tex.getWrap(WrapAxis.S)) {
bindTextureAndUnit(target, image, unit);
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
- image.getLastTextureState().sWrap = tex.getWrap(WrapAxis.S);
+ curState.sWrap = tex.getWrap(WrapAxis.S);
}
break;
default:
throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
}
- if (tex.isNeedCompareModeUpdate() && gl2 != null) {
- // R to Texture compare mode
- if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) {
- bindTextureAndUnit(target, image, unit);
- gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE);
- gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY);
- if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) {
+ ShadowCompareMode texCompareMode = tex.getShadowCompareMode();
+ if (gl2 != null && curState.shadowCompareMode != texCompareMode) {
+ bindTextureAndUnit(target, image, unit);
+ if (texCompareMode != ShadowCompareMode.Off) {
+ gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_REF_TO_TEXTURE);
+ if (texCompareMode == ShadowCompareMode.GreaterOrEqual) {
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL);
} else {
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL);
}
} else {
- bindTextureAndUnit(target, image, unit);
- //restoring default value
gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
}
- tex.compareModeUpdated();
+ curState.shadowCompareMode = texCompareMode;
}
// If at this point we didn't bind the texture, bind it now
diff --git a/jme3-core/src/main/java/com/jme3/texture/Texture.java b/jme3-core/src/main/java/com/jme3/texture/Texture.java
index 582d06565..6be00700b 100644
--- a/jme3-core/src/main/java/com/jme3/texture/Texture.java
+++ b/jme3-core/src/main/java/com/jme3/texture/Texture.java
@@ -316,7 +316,6 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
private MinFilter minificationFilter = MinFilter.BilinearNoMipMaps;
private MagFilter magnificationFilter = MagFilter.Bilinear;
private ShadowCompareMode shadowCompareMode = ShadowCompareMode.Off;
- private boolean needCompareModeUpdate = false;
private int anisotropicFilter;
/**
@@ -404,7 +403,6 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
"compareMode can not be null.");
}
this.shadowCompareMode = compareMode;
- needCompareModeUpdate = true;
}
/**
@@ -489,7 +487,7 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
/**
* @return the anisotropic filtering level for this texture. Default value
* is 0 (use value from config),
- * 1 means 1x (no anisotrophy), 2 means x2, 4 is x4, etc.
+ * 1 means 1x (no anisotropy), 2 means x2, 4 is x4, etc.
*/
public int getAnisotropicFilter() {
return anisotropicFilter;
@@ -636,14 +634,4 @@ public abstract class Texture implements CloneableSmartAsset, Savable, Cloneable
magnificationFilter = capsule.readEnum("magnificationFilter",
MagFilter.class, MagFilter.Bilinear);
}
-
- public boolean isNeedCompareModeUpdate() {
- return needCompareModeUpdate;
- }
-
- public void compareModeUpdated() {
- this.needCompareModeUpdate = false;
- }
-
-
}
diff --git a/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java b/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java
index 3b85563ef..32c1b718b 100644
--- a/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java
+++ b/jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java
@@ -45,10 +45,11 @@ public final class LastTextureState {
public Texture.WrapMode sWrap, tWrap, rWrap;
public Texture.MagFilter magFilter;
public Texture.MinFilter minFilter;
- public int anisoFilter = 0;
+ public int anisoFilter;
+ public Texture.ShadowCompareMode shadowCompareMode;
public LastTextureState() {
- // All parameters initialized to null (meaning unset).
+ reset();
}
public void reset() {
@@ -58,5 +59,9 @@ public final class LastTextureState {
magFilter = null;
minFilter = null;
anisoFilter = 0;
+
+ // The default in OpenGL is OFF, so we avoid setting this per texture
+ // if its not used.
+ shadowCompareMode = Texture.ShadowCompareMode.Off;
}
}
From 62186362a8ba68846b6cfb77fc62ca9d1810ef7e Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:02:12 -0400
Subject: [PATCH 67/94] GLDebugOutputHandler: dump stack on debug messages
---
.../java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java
index c8f329f13..d943fe6ee 100644
--- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java
+++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java
@@ -73,6 +73,7 @@ class LwjglGLDebugOutputHandler implements ARBDebugOutputCallback.Handler {
String severityStr = constMap.get(severity);
System.err.println(String.format(MESSAGE_FORMAT, id, sourceStr, typeStr, severityStr, message));
+ Thread.dumpStack();
}
}
From cba39fa0ffa49092fe20c43a609b109bdae86bed Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:02:55 -0400
Subject: [PATCH 68/94] GLRenderer: make the class final
---
.../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 7b40994ad..69ef39b2c 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
@@ -70,7 +70,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jme3tools.shader.ShaderDebug;
-public class GLRenderer implements Renderer {
+public final class GLRenderer implements Renderer {
private static final Logger logger = Logger.getLogger(GLRenderer.class.getName());
private static final boolean VALIDATE_SHADER = false;
From 4fef16ee9fef4539aff0067842cefdc97920aeb9 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:04:25 -0400
Subject: [PATCH 69/94] GLRenderer: fix incorrect gl3 check
Should check against caps; since gl3 is always
set on desktop regardless if GL3 is available or not.
Also add FBO blit support if we have GL3.
---
.../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
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 69ef39b2c..50e603d2f 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
@@ -380,14 +380,14 @@ public final class GLRenderer implements Renderer {
}
if (hasExtension("GL_EXT_framebuffer_object")
- || gl3 != null
+ || caps.contains(Caps.OpenGL30)
|| caps.contains(Caps.OpenGLES20)) {
caps.add(Caps.FrameBuffer);
limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT));
limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT));
- if (hasExtension("GL_EXT_framebuffer_blit")) {
+ if (hasExtension("GL_EXT_framebuffer_blit") || caps.contains(Caps.OpenGL30)) {
caps.add(Caps.FrameBufferBlit);
}
@@ -406,7 +406,7 @@ public final class GLRenderer implements Renderer {
}
}
- if (hasExtension("GL_ARB_draw_buffers") || gl3 != null) {
+ if (hasExtension("GL_ARB_draw_buffers") || caps.contains(Caps.OpenGL30)) {
limits.put(Limits.FrameBufferMrtAttachments, getInteger(GLExt.GL_MAX_DRAW_BUFFERS_ARB));
if (limits.get(Limits.FrameBufferMrtAttachments) > 1) {
caps.add(Caps.FrameBufferMRT);
From 4a37a8f8514c67613c0874ef1ff15825a939e3f1 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:09:38 -0400
Subject: [PATCH 70/94] FXAA: quality regression fix
FXAA wants input texture to use bilinear filtering
so it can be smoothed further, so allow filters to
request bilinear filtering.
---
jme3-core/src/main/java/com/jme3/post/Filter.java | 13 +++++++++++++
.../java/com/jme3/post/FilterPostProcessor.java | 12 ++++++++++++
.../main/java/com/jme3/post/filters/FXAAFilter.java | 6 ++++++
3 files changed, 31 insertions(+)
diff --git a/jme3-core/src/main/java/com/jme3/post/Filter.java b/jme3-core/src/main/java/com/jme3/post/Filter.java
index a6e2e3c01..feaacbe5d 100644
--- a/jme3-core/src/main/java/com/jme3/post/Filter.java
+++ b/jme3-core/src/main/java/com/jme3/post/Filter.java
@@ -409,6 +409,19 @@ public abstract class Filter implements Savable {
return true;
}
+ /**
+ * Override this method and return true if you want the scene (input) texture
+ * to use bilinear filtering or false to use nearest filtering.
+ *
+ * Typically filters that perform samples in between pixels
+ * should enable filtering.
+ *
+ * @return true to use linear filtering, false to use nearest filtering.
+ */
+ protected boolean isRequiresBilinear() {
+ return false;
+ }
+
/**
* returns the list of the postRender passes
* @return
diff --git a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
index b28aecece..2f52eb425 100644
--- a/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
+++ b/jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java
@@ -38,6 +38,7 @@ import com.jme3.renderer.*;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image.Format;
+import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import com.jme3.util.SafeArrayList;
@@ -284,6 +285,12 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
mat.clearParam("NumSamples");
}
}
+
+ boolean wantsBilinear = filter.isRequiresBilinear();
+ if (wantsBilinear) {
+ tex.setMagFilter(Texture.MagFilter.Bilinear);
+ tex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
+ }
buff = outputBuffer;
if (i != lastFilterIndex) {
@@ -293,6 +300,11 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
}
renderProcessing(r, buff, mat);
filter.postFilter(r, buff);
+
+ if (wantsBilinear) {
+ tex.setMagFilter(Texture.MagFilter.Nearest);
+ tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
+ }
}
}
}
diff --git a/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java b/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java
index 7b1dfb37a..37fec3bcd 100644
--- a/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java
+++ b/jme3-effects/src/main/java/com/jme3/post/filters/FXAAFilter.java
@@ -69,6 +69,12 @@ public class FXAAFilter extends Filter {
protected Material getMaterial() {
return material;
}
+
+ @Override
+ protected boolean isRequiresBilinear() {
+ // FXAA wants the input texture to be filtered.
+ return true;
+ }
public void setSpanMax(float spanMax) {
this.spanMax = spanMax;
From 01227d31b022302c986acbeb0cb4a3af359c30eb Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:10:16 -0400
Subject: [PATCH 71/94] Lighting: fix colorramp feature
---
.../main/resources/Common/MatDefs/Light/Lighting.frag | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag
index d2ade5199..0aa4d3f36 100644
--- a/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag
+++ b/jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag
@@ -154,8 +154,9 @@ void main(){
#ifdef VERTEX_LIGHTING
vec2 light = vertexLightValues.xy;
#ifdef COLORRAMP
- light.x = texture2D(m_ColorRamp, vec2(light.x, 0.0)).r;
- light.y = texture2D(m_ColorRamp, vec2(light.y, 0.0)).r;
+ diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
+ specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
+ light.xy = vec2(1.0);
#endif
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb +
@@ -183,8 +184,9 @@ void main(){
vec2 light = computeLighting(normal, viewDir, lightDir.xyz, lightDir.w * spotFallOff, m_Shininess) ;
#ifdef COLORRAMP
- diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
- specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
+ diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
+ specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
+ light.xy = vec2(1.0);
#endif
// Workaround, since it is not possible to modify varying variables
From e4f3c06b1df56999c582b5c770c593852108bcc9 Mon Sep 17 00:00:00 2001
From: Kirill Vainer
Date: Tue, 22 Sep 2015 22:12:13 -0400
Subject: [PATCH 72/94] ListMap: create unit test
---
.../src/main/java/com/jme3/util/ListMap.java | 15 ----
.../test/java/com/jme3/util/ListMapTest.java | 73 +++++++++++++++++++
2 files changed, 73 insertions(+), 15 deletions(-)
create mode 100644 jme3-core/src/test/java/com/jme3/util/ListMapTest.java
diff --git a/jme3-core/src/main/java/com/jme3/util/ListMap.java b/jme3-core/src/main/java/com/jme3/util/ListMap.java
index 0de4d3f75..379fff741 100644
--- a/jme3-core/src/main/java/com/jme3/util/ListMap.java
+++ b/jme3-core/src/main/java/com/jme3/util/ListMap.java
@@ -43,21 +43,6 @@ import java.util.Map.Entry;
*/
public final class ListMap extends AbstractMap implements Cloneable, Serializable {
- public static void main(String[] args){
- Map map = new ListMap();
- map.put( "bob", "hello");
- System.out.println(map.get("bob"));
- map.remove("bob");
- System.out.println(map.size());
-
- map.put("abc", "1");
- map.put("def", "2");
- map.put("ghi", "3");
- map.put("jkl", "4");
- map.put("mno", "5");
- System.out.println(map.get("ghi"));
- }
-
private final static class ListMapEntry implements Map.Entry, Cloneable {
private final K key;
diff --git a/jme3-core/src/test/java/com/jme3/util/ListMapTest.java b/jme3-core/src/test/java/com/jme3/util/ListMapTest.java
new file mode 100644
index 000000000..5f4cf3eee
--- /dev/null
+++ b/jme3-core/src/test/java/com/jme3/util/ListMapTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.util;
+
+import java.util.Map.Entry;
+import org.junit.Test;
+
+/**
+ * Check if the {@link ListMap} class is working correctly.
+ *
+ * @author Kirill Vainer
+ */
+public class ListMapTest {
+
+ @Test
+ public void testListMap() {
+ ListMap listMap = new ListMap();
+ listMap.put("bob", "hello");
+ assert "hello".equals(listMap.get("bob"));
+ assert "hello".equals(listMap.remove("bob"));
+ assert listMap.size() == 0;
+ assert listMap.isEmpty();
+
+ listMap.put("abc", "1");
+ listMap.put("def", "2");
+ listMap.put("ghi", "3");
+ listMap.put("jkl", "4");
+ listMap.put("mno", "5");
+ assert "3".equals(listMap.get("ghi"));
+ assert listMap.size() == 5;
+ assert !listMap.isEmpty();
+
+ // check iteration order, should be consistent
+ for (int i = 0; i < listMap.size(); i++) {
+ String expectedValue = Integer.toString(i + 1);
+ String key = listMap.getKey(i);
+ String value = listMap.getValue(i);
+ Entry entry = listMap.getEntry(i);
+ assert key.equals(entry.getKey());
+ assert value.equals(entry.getValue());
+ assert expectedValue.equals(value);
+ }
+ }
+}
From 2eb2cdac604abcbd94a44ceb366cb2fec5f9314c Mon Sep 17 00:00:00 2001
From: alexVengrovsk
Date: Wed, 23 Sep 2015 12:22:11 +0300
Subject: [PATCH 73/94] Delete close() of ByteArrayOutputStream type objecs
According to the Oracle's docummentation: "Closing a ByteArrayOutputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException." (http://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html#close())
---
.../main/java/com/jme3/app/state/MjpegFileWriter.java | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java b/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java
index 4c4cd6562..b3d751465 100644
--- a/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java
+++ b/jme3-desktop/src/main/java/com/jme3/app/state/MjpegFileWriter.java
@@ -205,7 +205,6 @@ public class MjpegFileWriter {
baos.write(fcc3);
baos.write(intBytes(swapInt(listSize)));
baos.write(fcc4);
- baos.close();
return baos.toByteArray();
}
@@ -275,7 +274,6 @@ public class MjpegFileWriter {
baos.write(intBytes(swapInt(dwReserved[1])));
baos.write(intBytes(swapInt(dwReserved[2])));
baos.write(intBytes(swapInt(dwReserved[3])));
- baos.close();
return baos.toByteArray();
}
@@ -295,7 +293,6 @@ public class MjpegFileWriter {
baos.write(fcc);
baos.write(intBytes(swapInt(size)));
baos.write(fcc2);
- baos.close();
return baos.toByteArray();
}
@@ -365,7 +362,6 @@ public class MjpegFileWriter {
baos.write(intBytes(swapInt(top)));
baos.write(intBytes(swapInt(right)));
baos.write(intBytes(swapInt(bottom)));
- baos.close();
return baos.toByteArray();
}
@@ -420,7 +416,6 @@ public class MjpegFileWriter {
baos.write(intBytes(swapInt(biYPelsPerMeter)));
baos.write(intBytes(swapInt(biClrUsed)));
baos.write(intBytes(swapInt(biClrImportant)));
- baos.close();
return baos.toByteArray();
}
@@ -445,7 +440,6 @@ public class MjpegFileWriter {
baos.write(fcc);
baos.write(intBytes(swapInt(listSize)));
baos.write(fcc2);
- baos.close();
return baos.toByteArray();
}
@@ -480,8 +474,6 @@ public class MjpegFileWriter {
baos.write(in.toBytes());
}
- baos.close();
-
return baos.toByteArray();
}
}
@@ -504,7 +496,6 @@ public class MjpegFileWriter {
baos.write(intBytes(swapInt(dwFlags)));
baos.write(intBytes(swapInt(dwOffset)));
baos.write(intBytes(swapInt(dwSize)));
- baos.close();
return baos.toByteArray();
}
@@ -525,7 +516,6 @@ public class MjpegFileWriter {
baos.write(fcc);
baos.write(intBytes(swapInt(size)));
baos.write(data);
- baos.close();
return baos.toByteArray();
}
@@ -552,7 +542,6 @@ public class MjpegFileWriter {
imgWrtr.write(null, new IIOImage(bi, null, null), jpgWrtPrm);
imgOutStrm.close();
- baos.close();
return baos.toByteArray();
}
}
From f4706373618215e3868f9779b68f8da4918ebd37 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Thu, 24 Sep 2015 11:02:47 +0100
Subject: [PATCH 74/94] Fixed a build issue regarding lwjgl 3.x by now using
3.0.0a for longer stability as 3.0.0b-SNAPSHOT is a moving target and APIs
are changing constantly.
---
jme3-lwjgl3/build.gradle | 8 ++++----
.../main/java/com/jme3/system/lwjgl/LwjglContext.java | 10 ++++++----
.../main/java/com/jme3/system/lwjgl/LwjglWindow.java | 4 ++--
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle
index 3c7e4e646..e81175700 100644
--- a/jme3-lwjgl3/build.gradle
+++ b/jme3-lwjgl3/build.gradle
@@ -11,8 +11,8 @@ repositories {
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'
+ compile 'org.lwjgl:lwjgl:3.0.0a'
+ compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0a', classifier: 'natives-windows'
+ compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0a', classifier: 'natives-linux'
+ compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0a', classifier: 'natives-osx'
}
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index 7f62a447e..f4d9a7b57 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -42,11 +42,13 @@ 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 org.lwjgl.opengl.ARBDebugOutput;
+import org.lwjgl.opengl.ARBFramebufferObject;
+import org.lwjgl.opengl.ContextCapabilities;
+import org.lwjgl.opengl.EXTFramebufferMultisample;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
@@ -132,7 +134,7 @@ public abstract class LwjglContext implements JmeContext {
}
protected void initContextFirstTime() {
- final GLCapabilities capabilities = createCapabilities(settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3));
+ final ContextCapabilities capabilities = createCapabilities(settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3));
if (!capabilities.OpenGL20) {
throw new RendererException("OpenGL 2.0 or higher is required for jMonkeyEngine");
@@ -230,7 +232,7 @@ public abstract class LwjglContext implements JmeContext {
while (created.get() != createdVal) {
try {
createdLock.wait();
- } catch (InterruptedException ex) {
+ } catch (InterruptedException ignored) {
}
}
}
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
index 2f00eb700..e1f4dcf73 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
@@ -99,7 +99,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
/**
* Set the title if its a windowed display
*
- * @param title
+ * @param title the title to set
*/
public void setTitle(final String title) {
if (created.get() && window != -1) {
@@ -121,7 +121,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
/**
* Apply the settings, changing resolution, etc.
*
- * @param settings
+ * @param settings the settings to apply when creating the context.
*/
protected void createContext(final AppSettings settings) {
glfwSetErrorCallback(errorCallback = new GLFWErrorCallback() {
From 109c5e80cf0645a5fef16f4aee89831cf5b9b302 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Thu, 24 Sep 2015 13:41:22 +0100
Subject: [PATCH 75/94] Fixed #316 where some post processing effects were not
working when using OPENGL_3 renderer due to an error in the fragment shader.
---
.../main/resources/Common/MatDefs/Post/CrossHatch15.frag | 6 ++++--
.../main/resources/Common/MatDefs/Post/DepthOfField15.frag | 6 ++++--
.../src/main/resources/Common/MatDefs/Post/Fade15.frag | 3 ++-
.../src/main/resources/Common/MatDefs/Post/Fog15.frag | 3 ++-
.../src/main/resources/Common/MatDefs/Post/Overlay15.frag | 3 ++-
.../main/resources/Common/MatDefs/Post/Posterization15.frag | 5 +++--
.../main/resources/Common/MatDefs/Post/bloomFinal15.frag | 3 ++-
.../src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag | 3 ++-
8 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag
index 8daa4f7fd..842484604 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/CrossHatch15.frag
@@ -17,7 +17,9 @@ uniform float m_Luminance5;
uniform float m_LineDistance;
uniform float m_LineThickness;
-
+
+out vec4 fragColor;
+
void main() {
vec4 texVal = getColor(m_Texture, texCoord);
float linePixel = 0;
@@ -49,5 +51,5 @@ void main() {
// Mix paper color with existing color information
vec4 paperColor = mix(m_PaperColor, texVal, m_ColorInfluencePaper);
- gl_FragColor = mix(paperColor, lineColor, linePixel);
+ fragColor = mix(paperColor, lineColor, linePixel);
}
\ No newline at end of file
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag
index 80cf3c530..de3c586ae 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField15.frag
@@ -11,6 +11,8 @@ uniform float m_YScale;
vec2 m_NearFar = vec2( 0.1, 1000.0 );
+out vec4 fragColor;
+
void main() {
vec4 texVal = getColor( m_Texture, texCoord );
@@ -44,7 +46,7 @@ void main() {
if( unfocus < 0.2 ) {
// If we are mostly in focus then don't bother with the
// convolution filter
- gl_FragColor = texVal;
+ fragColor = texVal;
} else {
// Perform a wide convolution filter and we scatter it
// a bit to avoid some texture look-ups. Instead of
@@ -83,7 +85,7 @@ void main() {
sum = sum / 12.0;
- gl_FragColor = mix( texVal, sum, unfocus );
+ fragColor = mix( texVal, sum, unfocus );
// I used this for debugging the range
// gl_FragColor.r = unfocus;
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag
index c99de34ad..7bd2d4882 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fade15.frag
@@ -4,8 +4,9 @@ uniform COLORTEXTURE m_Texture;
uniform float m_Value;
in vec2 texCoord;
+out vec4 fragColor;
void main() {
vec4 texVal = getColor(m_Texture, texCoord);
- gl_FragColor = texVal * m_Value;
+ fragColor = texVal * m_Value;
}
\ No newline at end of file
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag
index 65a340723..7a1f756be 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Fog15.frag
@@ -8,6 +8,7 @@ uniform float m_FogDensity;
uniform float m_FogDistance;
in vec2 texCoord;
+out vec4 fragColor;
vec2 m_FrustumNearFar=vec2(1.0,m_FogDistance);
const float LOG2 = 1.442695;
@@ -19,6 +20,6 @@ void main() {
float fogFactor = exp2( -m_FogDensity * m_FogDensity * depth * depth * LOG2 );
fogFactor = clamp(fogFactor, 0.0, 1.0);
- gl_FragColor =mix(m_FogColor,texVal,fogFactor);
+ fragColor =mix(m_FogColor,texVal,fogFactor);
}
\ No newline at end of file
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag
index 7dc4d1e4b..d6609f38f 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Overlay15.frag
@@ -3,9 +3,10 @@
uniform COLORTEXTURE m_Texture;
uniform vec4 m_Color;
in vec2 texCoord;
+out vec4 fragColor;
void main() {
vec4 texVal = getColor(m_Texture, texCoord);
- gl_FragColor = texVal * m_Color;
+ fragColor = texVal * m_Color;
}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag
index f55ac5bf2..5d8d7072b 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/Posterization15.frag
@@ -2,7 +2,8 @@
uniform COLORTEXTURE m_Texture;
in vec2 texCoord;
-
+out vec4 fragColor;
+
uniform int m_NumColors;
uniform float m_Gamma;
uniform float m_Strength;
@@ -16,5 +17,5 @@ void main() {
texVal = texVal / m_NumColors;
texVal = pow(texVal, vec4(1.0/m_Gamma));
- gl_FragColor = mix(getColor(m_Texture, texCoord), texVal, m_Strength);
+ fragColor = mix(getColor(m_Texture, texCoord), texVal, m_Strength);
}
\ No newline at end of file
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag b/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag
index 34268c565..b8f322d11 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/Post/bloomFinal15.frag
@@ -6,10 +6,11 @@ uniform sampler2D m_BloomTex;
uniform float m_BloomIntensity;
in vec2 texCoord;
+out vec4 fragColor;
void main(){
vec4 colorRes = getColor(m_Texture,texCoord);
vec4 bloom = texture2D(m_BloomTex, texCoord);
- gl_FragColor = bloom * m_BloomIntensity + colorRes;
+ fragColor = bloom * m_BloomIntensity + colorRes;
}
diff --git a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag
index c1112b23b..be2e6bcde 100644
--- a/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag
+++ b/jme3-effects/src/main/resources/Common/MatDefs/SSAO/ssaoBlur15.frag
@@ -10,6 +10,7 @@ uniform float m_YScale;
uniform vec2 m_FrustumNearFar;
in vec2 texCoord;
+out vec4 fragColor;
vec4 getResult(vec4 color){
@@ -125,7 +126,7 @@ float readDepth(in vec2 uv){
void main(){
// float depth =texture2D(m_DepthTexture,uv).r;
- gl_FragColor=getResult(convolutionFilter());
+ fragColor=getResult(convolutionFilter());
// gl_FragColor=getResult(bilateralFilter());
// gl_FragColor=getColor(m_SSAOMap,texCoord);
From 5da9fa6bc204e306beec7c10264c6abb675df004 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Thu, 24 Sep 2015 13:51:46 +0100
Subject: [PATCH 76/94] Changed the default app title in AppSettings to use the
full name string from JmeVersion. This way no more manual changing of this
will be needed for future versions. This also closes #320 which highlighted
this issue. Thanks @8Keep.
---
jme3-core/src/main/java/com/jme3/system/AppSettings.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jme3-core/src/main/java/com/jme3/system/AppSettings.java b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
index 6bf826236..c98845e41 100644
--- a/jme3-core/src/main/java/com/jme3/system/AppSettings.java
+++ b/jme3-core/src/main/java/com/jme3/system/AppSettings.java
@@ -138,7 +138,7 @@ public final class AppSettings extends HashMap {
defaults.put("StencilBits", 0);
defaults.put("Samples", 0);
defaults.put("Fullscreen", false);
- defaults.put("Title", "jMonkey Engine 3.0");
+ defaults.put("Title", JmeVersion.FULL_NAME);
defaults.put("Renderer", LWJGL_OPENGL2);
defaults.put("AudioRenderer", LWJGL_OPENAL);
defaults.put("DisableJoysticks", true);
From 14349695a963940b9d25418af5b36224b26b89c3 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Fri, 25 Sep 2015 10:32:11 +0100
Subject: [PATCH 77/94] The LWJGL 3 renderer was missing a call to
GLContext.createFromCurrent(), sorted now.
---
.../src/main/java/com/jme3/system/lwjgl/LwjglContext.java | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
index f4d9a7b57..9974693ce 100644
--- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
+++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
@@ -42,13 +42,11 @@ 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.ARBDebugOutput;
-import org.lwjgl.opengl.ARBFramebufferObject;
-import org.lwjgl.opengl.ContextCapabilities;
-import org.lwjgl.opengl.EXTFramebufferMultisample;
+import org.lwjgl.opengl.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
@@ -134,6 +132,7 @@ public abstract class LwjglContext implements JmeContext {
}
protected void initContextFirstTime() {
+ GLContext.createFromCurrent();
final ContextCapabilities capabilities = createCapabilities(settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3));
if (!capabilities.OpenGL20) {
From f1a0125dc232473481d7ab8a3ef5dfe9f8cd8fcc Mon Sep 17 00:00:00 2001
From: kaelthas
Date: Sat, 26 Sep 2015 12:26:31 +0200
Subject: [PATCH 78/94] Bugfix: fixed a bug that caused subdivision surface
modifier to crash if at least one not connected vertex was in the mesh.
---
.../modifiers/SubdivisionSurfaceModifier.java | 48 +++++++++++--------
1 file changed, 28 insertions(+), 20 deletions(-)
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java
index 2f3d12d60..2945b3413 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java
@@ -2,6 +2,7 @@ package com.jme3.scene.plugins.blender.modifiers;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -129,13 +130,18 @@ public class SubdivisionSurfaceModifier extends Modifier {
for (int i = 0; i < temporalMesh.getVertexCount(); ++i) {
// finding adjacent edges that were created by dividing original edges
List adjacentOriginalEdges = new ArrayList();
- for (Edge edge : temporalMesh.getAdjacentEdges(i)) {
- if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) {
- adjacentOriginalEdges.add(edge);
+ Collection adjacentEdges = temporalMesh.getAdjacentEdges(i);
+ if(adjacentEdges != null) {// this can be null if a vertex with index 'i' is not connected to any face nor edge
+ for (Edge edge : temporalMesh.getAdjacentEdges(i)) {
+ if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) {
+ adjacentOriginalEdges.add(edge);
+ }
}
+
+ creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh));
+ } else {
+ creasePoints.add(null);//the count of crease points must be equal to vertex count; otherwise we'll get IndexOutofBoundsException later
}
-
- creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh));
}
Vector3f[] averageVert = new Vector3f[temporalMesh.getVertexCount()];
@@ -174,23 +180,25 @@ public class SubdivisionSurfaceModifier extends Modifier {
}
for (int i = 0; i < averageVert.length; ++i) {
- Vector3f v = temporalMesh.getVertices().get(i);
- averageVert[i].divideLocal(averageCount[i]);
-
- // computing translation vector
- Vector3f t = averageVert[i].subtract(v);
- if (!boundaryVertices.contains(i)) {
- t.multLocal(4 / (float) averageCount[i]);
- }
-
- // moving the vertex
- v.addLocal(t);
+ if(averageVert[i] != null && averageCount[i] > 0) {
+ Vector3f v = temporalMesh.getVertices().get(i);
+ averageVert[i].divideLocal(averageCount[i]);
+
+ // computing translation vector
+ Vector3f t = averageVert[i].subtract(v);
+ if (!boundaryVertices.contains(i)) {
+ t.multLocal(4 / (float) averageCount[i]);
+ }
- // applying crease weight if neccessary
- CreasePoint creasePoint = creasePoints.get(i);
- if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) {
- t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight());
+ // moving the vertex
v.addLocal(t);
+
+ // applying crease weight if neccessary
+ CreasePoint creasePoint = creasePoints.get(i);
+ if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) {
+ t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight());
+ v.addLocal(t);
+ }
}
}
}
From 953a301d5e27a730449031e13174a30d21dfa74d Mon Sep 17 00:00:00 2001
From: kaelthas
Date: Sat, 26 Sep 2015 12:30:26 +0200
Subject: [PATCH 79/94] Bugfix: fixed a bug that caused importer to crash when
the author of the blend file assigned non existing UV coordinates group name
to a mesh.
---
.../scene/plugins/blender/materials/MaterialContext.java | 8 +++++---
.../scene/plugins/blender/textures/CombinedTexture.java | 3 +++
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java
index 51c7072b1..3b5a8eefb 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java
@@ -168,9 +168,11 @@ public final class MaterialContext implements Savable {
this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture());
List uvs = combinedTexture.getResultUVS();
- VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
- uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
- geometry.getMesh().setBuffer(uvCoordsBuffer);
+ if(uvs != null && uvs.size() > 0) {
+ VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
+ uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
+ geometry.getMesh().setBuffer(uvCoordsBuffer);
+ }//uvs might be null if the user assigned non existing UV coordinates group name to the mesh (this should be fixed in blender file)
} else {
LOGGER.log(Level.WARNING, "The texture could not be applied because JME only supports up to {0} different UV's.", TextureHelper.TEXCOORD_TYPES.length);
}
diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
index b7d6958ca..e406447eb 100644
--- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
+++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
@@ -158,6 +158,9 @@ public class CombinedTexture {
} else {
resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
}
+ if(resultUVS == null && LOGGER.isLoggable(Level.WARNING)) {
+ LOGGER.warning("The texture " + textureData.texture.getName() + " has assigned non existing UV coordinates group: " + textureData.uvCoordinatesName + ".");
+ }
masterUserUVSetName = textureData.uvCoordinatesName;
} else {
TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
From 06d6f0861668ae77d2d802e97deb48f481d1fe84 Mon Sep 17 00:00:00 2001
From: Dokthar
Date: Tue, 6 Oct 2015 19:54:40 +0200
Subject: [PATCH 80/94] GImpactCollisionShape : fix for #188, added a call to
updateBound() in native jni binding, just after creating the shape, (native
createShape() method)
---
.../com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp
index d3e0ba719..f416e46b4 100644
--- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp
+++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_collision_shapes_GImpactCollisionShape.cpp
@@ -51,6 +51,7 @@ extern "C" {
jmeClasses::initJavaClasses(env);
btTriangleIndexVertexArray* array = reinterpret_cast(meshId);
btGImpactMeshShape* shape = new btGImpactMeshShape(array);
+ shape->updateBound();
return reinterpret_cast(shape);
}
From cfdb9a87596cb5acd63570afffc0a824e0ba039b Mon Sep 17 00:00:00 2001
From: Dokthar
Date: Wed, 7 Oct 2015 22:25:36 +0200
Subject: [PATCH 81/94] Lights (see #362) : added light v. sphere intersection,
and implementations of intersectsSphere(), second attempt
---
.../java/com/jme3/light/AmbientLight.java | 6 +++
.../com/jme3/light/DefaultLightFilter.java | 7 ++--
.../java/com/jme3/light/DirectionalLight.java | 6 +++
.../src/main/java/com/jme3/light/Light.java | 15 +++++++
.../main/java/com/jme3/light/PointLight.java | 12 ++++++
.../main/java/com/jme3/light/SpotLight.java | 42 ++++++++++++++++++-
6 files changed, 83 insertions(+), 5 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
index 58676851c..a2dc1cd38 100644
--- a/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/AmbientLight.java
@@ -32,6 +32,7 @@
package com.jme3.light;
import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
@@ -62,6 +63,11 @@ public class AmbientLight extends Light {
return true;
}
+ @Override
+ public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+ return true;
+ }
+
@Override
public boolean intersectsFrustum(Camera camera, TempVars vars) {
return true;
diff --git a/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java b/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java
index c8456529d..5d07e1a8d 100644
--- a/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java
+++ b/jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 jMonkeyEngine
+ * Copyright (c) 2009-2015 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,8 +78,9 @@ public final class DefaultLightFilter implements LightFilter {
}
} else if (bv instanceof BoundingSphere) {
if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) {
- // Non-infinite bounding sphere... Not supported yet.
- throw new UnsupportedOperationException("Only AABB supported for now");
+ if (!light.intersectsSphere((BoundingSphere)bv, vars)) {
+ continue;
+ }
}
}
diff --git a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
index b8e1a1979..b1abb65cf 100644
--- a/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
@@ -32,6 +32,7 @@
package com.jme3.light;
import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
@@ -116,6 +117,11 @@ public class DirectionalLight extends Light {
return true;
}
+ @Override
+ public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+ return true;
+ }
+
@Override
public boolean intersectsFrustum(Camera camera, TempVars vars) {
return true;
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 bac775aeb..39a30980b 100644
--- a/jme3-core/src/main/java/com/jme3/light/Light.java
+++ b/jme3-core/src/main/java/com/jme3/light/Light.java
@@ -32,6 +32,7 @@
package com.jme3.light;
import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
import com.jme3.export.*;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.Camera;
@@ -196,6 +197,20 @@ public abstract class Light implements Savable, Cloneable {
*/
public abstract boolean intersectsBox(BoundingBox box, TempVars vars);
+ /**
+ * Determines if the light intersects with the given bounding sphere.
+ *
+ * For non-local lights, such as {@link DirectionalLight directional lights},
+ * {@link AmbientLight ambient lights}, or {@link PointLight point lights}
+ * without influence radius, this method should always return true.
+ *
+ * @param sphere The sphere to check intersection against.
+ * @param vars TempVars in case it is needed.
+ *
+ * @return True if the light intersects the sphere, false otherwise.
+ */
+ public abstract boolean intersectsSphere(BoundingSphere sphere, TempVars vars);
+
/**
* Determines if the light intersects with the given camera frustum.
*
diff --git a/jme3-core/src/main/java/com/jme3/light/PointLight.java b/jme3-core/src/main/java/com/jme3/light/PointLight.java
index 1f515e71c..1468d1ba1 100644
--- a/jme3-core/src/main/java/com/jme3/light/PointLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/PointLight.java
@@ -32,12 +32,14 @@
package com.jme3.light;
import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
import com.jme3.bounding.Intersection;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
+import com.jme3.math.FastMath;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
@@ -195,6 +197,16 @@ public class PointLight extends Light {
}
}
+ @Override
+ public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+ if (this.radius == 0) {
+ return true;
+ } else {
+ // Sphere v. sphere collision
+ return sphere.getCenter().subtract(position).lengthSquared() < FastMath.sqr(radius + sphere.getRadius());
+ }
+ }
+
@Override
public boolean intersectsFrustum(Camera camera, TempVars vars) {
if (this.radius == 0) {
diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
index de24280ab..444d58b3a 100644
--- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
@@ -32,6 +32,7 @@
package com.jme3.light;
import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
import com.jme3.export.*;
import com.jme3.math.ColorRGBA;
@@ -225,12 +226,49 @@ public class SpotLight extends Light {
return false;
}
+ @Override
+ public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+ if (this.spotRange > 0f) {
+ // Check spot range first.
+ // Sphere v. sphere collision
+ if (sphere.getCenter().subtract(position).lengthSquared() >= FastMath.sqr(spotRange + sphere.getRadius())) {
+ return false;
+ }
+ }
+
+ float otherRadiusSquared = FastMath.sqr(sphere.getRadius());
+ float otherRadius = sphere.getRadius();
+
+ // Check if sphere is within spot angle.
+ // Cone v. sphere collision.
+ Vector3f E = direction.mult(otherRadius * outerAngleSinRcp, vars.vect1);
+ Vector3f U = position.subtract(E, vars.vect2);
+ Vector3f D = sphere.getCenter().subtract(U, vars.vect3);
+
+ float dsqr = D.dot(D);
+ float e = direction.dot(D);
+
+ if (e > 0f && e * e >= dsqr * outerAngleCosSqr) {
+ D = sphere.getCenter().subtract(position, vars.vect3);
+ dsqr = D.dot(D);
+ e = -direction.dot(D);
+
+ if (e > 0f && e * e >= dsqr * outerAngleSinSqr) {
+ return dsqr <= otherRadiusSquared;
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@Override
public boolean intersectsFrustum(Camera cam, TempVars vars) {
if (spotRange == 0) {
// The algorithm below does not support infinite spot range.
- return true;
- }
+ return true;
+ }
Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange));
for (int i = 5; i >= 0; i--) {
//check origin against the plane
From 7d07cedc4ceaec2b3761c9670d5d3fde11701356 Mon Sep 17 00:00:00 2001
From: MeFisto94
Date: Sun, 6 Sep 2015 20:19:04 +0200
Subject: [PATCH 82/94] Fixed Issue #46 : The MaterialViewer will now simply
ignore not available textures instead of crashing
---
.../gde/materials/multiview/widgets/TexturePanel.java | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java
index b414a1126..0129535e4 100644
--- a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java
+++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/multiview/widgets/TexturePanel.java
@@ -10,15 +10,19 @@
*/
package com.jme3.gde.materials.multiview.widgets;
+import com.jme3.asset.AssetNotFoundException;
import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.core.properties.TexturePropertyEditor;
import com.jme3.gde.core.properties.preview.DDSPreview;
import com.jme3.gde.materials.MaterialProperty;
+import com.jme3.gde.materials.multiview.MaterialEditorTopComponent;
import com.jme3.texture.Texture;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.SwingUtilities;
import jme3tools.converters.ImageToAwt;
@@ -50,7 +54,7 @@ public class TexturePanel extends MaterialPropertyWidget {
exec.execute(new Runnable() {
public void run() {
-
+ try{
Texture tex = manager.loadTexture(textureName);
if (textureName.toLowerCase().endsWith(".dds")) {
if (ddsPreview == null) {
@@ -65,6 +69,9 @@ public class TexturePanel extends MaterialPropertyWidget {
}
});
}
+ } catch (AssetNotFoundException a) {
+ Logger.getLogger(MaterialEditorTopComponent.class.getName()).log(Level.WARNING, "Could not load texture {0}", textureName);
+ }
}
});
}
From 505aa23048cdc8eeb83eadb454d224f484aac69d Mon Sep 17 00:00:00 2001
From: Dokthar
Date: Wed, 14 Oct 2015 20:30:20 +0200
Subject: [PATCH 83/94] light : added unit tests for the new support of
bounding spheres intersections (for lightFilter)
---
.../main/java/com/jme3/light/SpotLight.java | 4 +-
.../java/com/jme3/light/LightFilterTest.java | 91 +++++++++++++++++++
2 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
index 444d58b3a..bd1c03c6e 100644
--- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
@@ -267,8 +267,8 @@ public class SpotLight extends Light {
public boolean intersectsFrustum(Camera cam, TempVars vars) {
if (spotRange == 0) {
// The algorithm below does not support infinite spot range.
- return true;
- }
+ return true;
+ }
Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange));
for (int i = 5; i >= 0; i--) {
//check origin against the plane
diff --git a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
index 0d1e71988..d4fc18db9 100644
--- a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
+++ b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
@@ -31,6 +31,7 @@
*/
package com.jme3.light;
+import com.jme3.bounding.BoundingSphere;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
@@ -81,12 +82,20 @@ public class LightFilterTest {
public void testAmbientFiltering() {
geom.addLight(new AmbientLight());
checkFilteredLights(1); // Ambient lights must never be filtered
+
+ // Test for bounding Sphere
+ geom.setModelBound(new BoundingSphere(0.5f, Vector3f.ZERO));
+ checkFilteredLights(1); // Ambient lights must never be filtered
}
@Test
public void testDirectionalFiltering() {
geom.addLight(new DirectionalLight(Vector3f.UNIT_Y));
checkFilteredLights(1); // Directional lights must never be filtered
+
+ // Test for bounding Sphere
+ geom.setModelBound(new BoundingSphere(0.5f, Vector3f.ZERO));
+ checkFilteredLights(1); // Directional lights must never be filtered
}
@Test
@@ -127,6 +136,44 @@ public class LightFilterTest {
// Rotate the camera so it is up, light is outside frustum.
cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y);
checkFilteredLights(0);
+
+ // ==================================
+ // Tests for bounding Sphere
+ geom.setLocalTranslation(0, 0, 0);
+
+ // Infinite point lights must never be filtered
+ pl.setRadius(0);
+ checkFilteredLights(1);
+
+ pl.setRadius(1f);
+ geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
+
+ // Put the light at the very close to the geom,
+ // the very edge of the sphere touches the other bounding sphere
+ // Still not considered an intersection though.
+ pl.setPosition(new Vector3f(0, 0, -2f));
+ checkFilteredLights(0);
+
+ // And more close - now its an intersection.
+ pl.setPosition(new Vector3f(0, 0, 0f));
+ checkFilteredLights(0);
+
+ // In this case its an intersection for pointLight v. box
+ // But not for pointLight v. sphere
+ // Vector3f(0, 0.5f, 0.5f).normalize().mult(2) ~ >= (0.0, 1.4142135, 1.4142135)
+ //pl.setPosition(new Vector3f(0, 0.5f, 0.5f).normalizeLocal().multLocal(2 + FastMath.ZERO_TOLERANCE));
+ pl.setPosition(new Vector3f(0f, 1.4142135f, 1.4142135f).multLocal(1+FastMath.ZERO_TOLERANCE));
+ checkFilteredLights(0);
+
+ // Make the distance a wee bit closer, now its an intersection
+ //pl.setPosition(new Vector3f(0, 0.5f, 0.5f).normalizeLocal().multLocal(2 - FastMath.ZERO_TOLERANCE));
+ pl.setPosition(new Vector3f(0f, 1.4142135f, 1.4142135f).multLocal(1-FastMath.ZERO_TOLERANCE));
+ checkFilteredLights(1);
+
+ // it's a point light, also test for the other corner
+ pl.setPosition(new Vector3f(0f, -1.4142135f, -1.4142135f).multLocal(1-FastMath.ZERO_TOLERANCE));
+ checkFilteredLights(0);
+
}
@Test
@@ -175,5 +222,49 @@ public class LightFilterTest {
// now, the spot will touch the box.
geom.setMesh(new Box(5, 1, 1));
checkFilteredLights(1);
+
+ // ==================================
+ // Tests for bounding sphere, with a radius of 1f (in the box geom)
+ sl.setPosition(Vector3f.ZERO);
+ sl.setDirection(Vector3f.UNIT_Z);
+ geom.setLocalTranslation(Vector3f.ZERO);
+ geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
+
+ // Infinit spot lights are only filtered
+ // if the geometry is outside the infinite cone.
+ sl.setSpotRange(0);
+ checkFilteredLights(1);
+
+ //the geommetry is outside the infinit cone (cone direction going away from the geom)
+ sl.setPosition(Vector3f.UNIT_Z.mult(1+FastMath.ZERO_TOLERANCE));
+ checkFilteredLights(0);
+
+ //place the spote ligth in the corner of the box geom, (in order to test bounding sphere)
+ sl.setDirection(new Vector3f(1, 1, 0).normalizeLocal());
+ geom.setLocalTranslation(0, 0, 10);
+ sl.setPosition(sl.getDirection().mult(-2f).add(geom.getLocalTranslation()));
+
+ // make it barely reach the sphere, incorect with a box
+ sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE);
+ checkFilteredLights(0);
+
+ // make it reach the sphere
+ sl.setSpotRange(1f + FastMath.ZERO_TOLERANCE);
+ checkFilteredLights(1);
+
+ // extent the range
+ sl.setPosition(Vector3f.ZERO);
+ sl.setDirection(Vector3f.UNIT_Z);
+ sl.setSpotRange(20);
+ checkFilteredLights(1);
+
+ // rotate the cone a bit so it no longer faces the geom
+ sl.setDirection(new Vector3f(0, 0.3f, 0.7f).normalizeLocal());
+ checkFilteredLights(0);
+
+ // Create sphere of size X=10 (double the radius)
+ // now, the spot will touch the sphere.
+ geom.setModelBound(new BoundingSphere(5f, Vector3f.ZERO));
+ checkFilteredLights(1);
}
}
From d48a1bb99838792285087fa71298801a9fc33c59 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Thu, 15 Oct 2015 09:46:35 +0100
Subject: [PATCH 84/94] Removed native library jemalloc.dll for LWJGL3 as this
will not be needed until 3.0.0b and after.
---
.../main/java/com/jme3/system/NativeLibraryLoader.java | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
index 53898883c..ab4f7a2c9 100644
--- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
+++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
@@ -31,11 +31,7 @@
*/
package com.jme3.system;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
@@ -148,8 +144,8 @@ public final class NativeLibraryLoader {
registerNativeLibrary("lwjgl3", Platform.Linux64, "native/linux/liblwjgl.so");
registerNativeLibrary("lwjgl3", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
registerNativeLibrary("lwjgl3", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
- registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll");
- registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll");
+ //registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll"); // These are introduced in LWJGL 3.0.0b
+ //registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll"); // These are introduced in LWJGL 3.0.0b
// OpenAL for LWJGL 3.x
// For OSX: Need to add lib prefix when extracting
From 4be09e3505b3fd07e93d747ac872a44e7155b775 Mon Sep 17 00:00:00 2001
From: Dokthar
Date: Thu, 15 Oct 2015 19:27:50 +0200
Subject: [PATCH 85/94] light : replaced duplicated code by methods from
Intersection
---
jme3-core/src/main/java/com/jme3/light/PointLight.java | 2 +-
jme3-core/src/main/java/com/jme3/light/SpotLight.java | 7 +++----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/light/PointLight.java b/jme3-core/src/main/java/com/jme3/light/PointLight.java
index 1468d1ba1..4b5224c30 100644
--- a/jme3-core/src/main/java/com/jme3/light/PointLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/PointLight.java
@@ -203,7 +203,7 @@ public class PointLight extends Light {
return true;
} else {
// Sphere v. sphere collision
- return sphere.getCenter().subtract(position).lengthSquared() < FastMath.sqr(radius + sphere.getRadius());
+ return Intersection.intersect(sphere, position, radius);
}
}
diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
index bd1c03c6e..bc1335b5b 100644
--- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java
+++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java
@@ -34,6 +34,7 @@ package com.jme3.light;
import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingSphere;
import com.jme3.bounding.BoundingVolume;
+import com.jme3.bounding.Intersection;
import com.jme3.export.*;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
@@ -189,9 +190,7 @@ public class SpotLight extends Light {
if (this.spotRange > 0f) {
// Check spot range first.
// Sphere v. box collision
- if (FastMath.abs(box.getCenter().x - position.x) >= spotRange + box.getXExtent()
- || FastMath.abs(box.getCenter().y - position.y) >= spotRange + box.getYExtent()
- || FastMath.abs(box.getCenter().z - position.z) >= spotRange + box.getZExtent()) {
+ if (!Intersection.intersect(box, position, spotRange)) {
return false;
}
}
@@ -231,7 +230,7 @@ public class SpotLight extends Light {
if (this.spotRange > 0f) {
// Check spot range first.
// Sphere v. sphere collision
- if (sphere.getCenter().subtract(position).lengthSquared() >= FastMath.sqr(spotRange + sphere.getRadius())) {
+ if (!Intersection.intersect(sphere, position, spotRange)) {
return false;
}
}
From 071ad5c6183f588bc8d1eeedd7ae97901c94938b Mon Sep 17 00:00:00 2001
From: Dokthar
Date: Fri, 16 Oct 2015 20:17:57 +0200
Subject: [PATCH 86/94] light : fixed pointLight v. bounding sphere unit test
---
.../java/com/jme3/light/LightFilterTest.java | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
index d4fc18db9..447682964 100644
--- a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
+++ b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java
@@ -139,25 +139,26 @@ public class LightFilterTest {
// ==================================
// Tests for bounding Sphere
- geom.setLocalTranslation(0, 0, 0);
-
+ geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
+ geom.setLocalTranslation(0, 0, 2);
+ pl.setPosition(new Vector3f(0, 0, 2f));
+
// Infinite point lights must never be filtered
pl.setRadius(0);
checkFilteredLights(1);
-
+
pl.setRadius(1f);
- geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
-
// Put the light at the very close to the geom,
// the very edge of the sphere touches the other bounding sphere
// Still not considered an intersection though.
- pl.setPosition(new Vector3f(0, 0, -2f));
+ pl.setPosition(new Vector3f(0, 0, 0));
checkFilteredLights(0);
// And more close - now its an intersection.
- pl.setPosition(new Vector3f(0, 0, 0f));
- checkFilteredLights(0);
-
+ pl.setPosition(new Vector3f(0, 0, 0f + FastMath.ZERO_TOLERANCE));
+ checkFilteredLights(1);
+
+ geom.setLocalTranslation(0, 0, 0);
// In this case its an intersection for pointLight v. box
// But not for pointLight v. sphere
// Vector3f(0, 0.5f, 0.5f).normalize().mult(2) ~ >= (0.0, 1.4142135, 1.4142135)
From 1bb3ee089a2102dfcf799137de69bb2b7a6b6d57 Mon Sep 17 00:00:00 2001
From: Brandon DeRosier
Date: Sat, 17 Oct 2015 22:34:22 -0400
Subject: [PATCH 87/94] Change duplicated docstring in
FlyByCamera.unregisterInput
---
jme3-core/src/main/java/com/jme3/input/FlyByCamera.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java
index d1dbe0aef..dd9f00dc1 100644
--- a/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java
+++ b/jme3-core/src/main/java/com/jme3/input/FlyByCamera.java
@@ -277,8 +277,7 @@ public class FlyByCamera implements AnalogListener, ActionListener {
}
/**
- * Registers the FlyByCamera to receive input events from the provided
- * Dispatcher.
+ * Unregisters the FlyByCamera from the event Dispatcher.
*/
public void unregisterInput(){
From 5e8f5e6a1f8f181b3d70a416a667659154091830 Mon Sep 17 00:00:00 2001
From: Daniel Johansson
Date: Wed, 21 Oct 2015 17:05:16 +0100
Subject: [PATCH 88/94] Updated lwjgl3 module to use LWJGL 3.0.0b #35 which is
the current stable build.
---
.../com/jme3/system/NativeLibraryLoader.java | 33 +++++++++++++-----
jme3-lwjgl3/build.gradle | 5 +--
jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar | Bin 0 -> 2632785 bytes
jme3-lwjgl3/lib/lwjgl-3.0.0b-35.jar | Bin 0 -> 1883204 bytes
.../java/com/jme3/audio/lwjgl/LwjglALC.java | 9 ++++-
.../com/jme3/system/lwjgl/LwjglContext.java | 11 +++---
6 files changed, 40 insertions(+), 18 deletions(-)
create mode 100644 jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar
create mode 100644 jme3-lwjgl3/lib/lwjgl-3.0.0b-35.jar
diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
index ab4f7a2c9..947129d30 100644
--- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
+++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
@@ -144,8 +144,22 @@ public final class NativeLibraryLoader {
registerNativeLibrary("lwjgl3", Platform.Linux64, "native/linux/liblwjgl.so");
registerNativeLibrary("lwjgl3", Platform.MacOSX32, "native/macosx/liblwjgl.dylib");
registerNativeLibrary("lwjgl3", Platform.MacOSX64, "native/macosx/liblwjgl.dylib");
- //registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll"); // These are introduced in LWJGL 3.0.0b
- //registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll"); // These are introduced in LWJGL 3.0.0b
+
+ // GLFW for LWJGL 3.x
+ registerNativeLibrary("glfw-lwjgl3", Platform.Windows32, "native/windows/glfw32.dll");
+ registerNativeLibrary("glfw-lwjgl3", Platform.Windows64, "native/windows/glfw.dll");
+ registerNativeLibrary("glfw-lwjgl3", Platform.Linux32, "native/linux/libglfw32.so");
+ registerNativeLibrary("glfw-lwjgl3", Platform.Linux64, "native/linux/libglfw.dll");
+ registerNativeLibrary("glfw-lwjgl3", Platform.MacOSX32, "native/macosx/libglfw.dylib");
+ registerNativeLibrary("glfw-lwjgl3", Platform.MacOSX64, "native/macosx/libglfw.dylib");
+
+ // jemalloc for LWJGL 3.x
+ registerNativeLibrary("jemalloc-lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll");
+ registerNativeLibrary("jemalloc-lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll");
+ registerNativeLibrary("jemalloc-lwjgl3", Platform.Linux32, "native/linux/libjemalloc32.so");
+ registerNativeLibrary("jemalloc-lwjgl3", Platform.Linux64, "native/linux/libjemalloc.so");
+ registerNativeLibrary("jemalloc-lwjgl3", Platform.MacOSX32, "native/macosx/libjemalloc.dylib");
+ registerNativeLibrary("jemalloc-lwjgl3", Platform.MacOSX64, "native/macosx/libjemalloc.dylib");
// OpenAL for LWJGL 3.x
// For OSX: Need to add lib prefix when extracting
@@ -475,7 +489,7 @@ public final class NativeLibraryLoader {
if (url == null) {
return;
}
-
+
String loadedAsFileName;
if (library.getExtractedAsName() != null) {
loadedAsFileName = library.getExtractedAsName();
@@ -522,7 +536,7 @@ public final class NativeLibraryLoader {
throw new UnsupportedOperationException("JVM is running under "
+ "reduced permissions. Cannot load native libraries.");
}
-
+
Platform platform = JmeSystem.getPlatform();
NativeLibrary library = nativeLibraryMap.get(new NativeLibrary.Key(name, platform));
@@ -540,27 +554,28 @@ public final class NativeLibraryLoader {
}
}
- String pathInJar = library.getPathInNativesJar();
-
+ final String pathInJar = library.getPathInNativesJar();
+
if (pathInJar == null) {
// This platform does not require the native library to be loaded.
return;
}
- String fileNameInJar;
+ final String fileNameInJar;
+
if (pathInJar.contains("/")) {
fileNameInJar = pathInJar.substring(pathInJar.lastIndexOf("/") + 1);
} else {
fileNameInJar = pathInJar;
}
-
+
URL url = Thread.currentThread().getContextClassLoader().getResource(pathInJar);
if (url == null) {
// Try the root of the classpath as well.
url = Thread.currentThread().getContextClassLoader().getResource(fileNameInJar);
}
-
+
if (url == null) {
// Attempt to load it as a system library.
String unmappedName = unmapLibraryName(fileNameInJar);
diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle
index e81175700..3ee3b0f65 100644
--- a/jme3-lwjgl3/build.gradle
+++ b/jme3-lwjgl3/build.gradle
@@ -11,8 +11,5 @@ repositories {
dependencies {
compile project(':jme3-core')
compile project(':jme3-desktop')
- compile 'org.lwjgl:lwjgl:3.0.0a'
- compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0a', classifier: 'natives-windows'
- compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0a', classifier: 'natives-linux'
- compile group: 'org.lwjgl', name: 'lwjgl-platform', version: '3.0.0a', classifier: 'natives-osx'
+ compile files('lib/lwjgl-3.0.0b-35.jar', 'lib/lwjgl-3.0.0b-35-natives.jar')
}
diff --git a/jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar b/jme3-lwjgl3/lib/lwjgl-3.0.0b-35-natives.jar
new file mode 100644
index 0000000000000000000000000000000000000000..79b12bc5d22c2ff860472581f678a6efd9d67b3c
GIT binary patch
literal 2632785
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