Implemented a new TempVars system, temp vars can now be requested without conflict.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7692 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 14 years ago
parent dfeff3c6af
commit 413f2b1e48
  1. 10
      engine/src/bullet/com/jme3/bullet/control/KinematicRagdollControl.java
  2. 3
      engine/src/bullet/com/jme3/bullet/util/DebugShapeFactory.java
  3. 4
      engine/src/core/com/jme3/animation/Bone.java
  4. 4
      engine/src/core/com/jme3/animation/Skeleton.java
  5. 4
      engine/src/core/com/jme3/animation/SkeletonControl.java
  6. 179
      engine/src/core/com/jme3/bounding/BoundingBox.java
  7. 110
      engine/src/core/com/jme3/bounding/BoundingSphere.java
  8. 118
      engine/src/core/com/jme3/bounding/Intersection.java
  9. 136
      engine/src/core/com/jme3/collision/bih/BIHNode.java
  10. 151
      engine/src/core/com/jme3/collision/bih/BIHTree.java
  11. 26
      engine/src/core/com/jme3/effect/ParticleEmitter.java
  12. 13
      engine/src/core/com/jme3/math/Line.java
  13. 12
      engine/src/core/com/jme3/math/LineSegment.java
  14. 318
      engine/src/core/com/jme3/math/Matrix3f.java
  15. 9
      engine/src/core/com/jme3/math/Matrix4f.java
  16. 3
      engine/src/core/com/jme3/math/Quaternion.java
  17. 70
      engine/src/core/com/jme3/math/Ray.java
  18. 21
      engine/src/core/com/jme3/renderer/Camera.java
  19. 5
      engine/src/core/com/jme3/renderer/RenderManager.java
  20. 95
      engine/src/core/com/jme3/scene/Geometry.java
  21. 16
      engine/src/core/com/jme3/scene/Spatial.java
  22. 3
      engine/src/core/com/jme3/scene/control/CameraControl.java
  23. 8
      engine/src/core/com/jme3/scene/control/LightControl.java
  24. 10
      engine/src/core/com/jme3/scene/debug/SkeletonDebugger.java
  25. 33
      engine/src/core/com/jme3/scene/shape/Dome.java
  26. 113
      engine/src/core/com/jme3/scene/shape/Sphere.java
  27. 275
      engine/src/core/com/jme3/util/BufferUtils.java
  28. 181
      engine/src/core/com/jme3/util/TempVars.java
  29. 5
      engine/src/desktop-fx/com/jme3/water/WaterFilter.java
  30. 12
      engine/src/jbullet/com/jme3/bullet/control/KinematicRagdollControl.java
  31. 22
      engine/src/jbullet/com/jme3/bullet/util/DebugShapeFactory.java
  32. 81
      engine/src/test/jme3test/app/TestTempVars.java

@ -165,7 +165,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
return; return;
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Quaternion tmpRot1 = vars.quat1; Quaternion tmpRot1 = vars.quat1;
Quaternion tmpRot2 = vars.quat2; Quaternion tmpRot2 = vars.quat2;
@ -264,7 +264,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
} }
assert vars.unlock(); vars.release();
} }
@ -682,7 +682,6 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
baseRigidBody.setKinematic(mode == Mode.Kinetmatic); baseRigidBody.setKinematic(mode == Mode.Kinetmatic);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
link.rigidBody.setKinematic(mode == Mode.Kinetmatic); link.rigidBody.setKinematic(mode == Mode.Kinetmatic);
if (mode == Mode.Ragdoll) { if (mode == Mode.Ragdoll) {
@ -693,7 +692,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
assert vars.unlock(); vars.release();
for (Bone bone : skeleton.getRoots()) { for (Bone bone : skeleton.getRoots()) {
RagdollUtils.setUserControl(bone, mode == Mode.Ragdoll); RagdollUtils.setUserControl(bone, mode == Mode.Ragdoll);
@ -718,7 +717,6 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
@ -737,7 +735,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
link.startBlendingRot.set(q2); link.startBlendingRot.set(q2);
link.rigidBody.setKinematic(true); link.rigidBody.setKinematic(true);
} }
assert vars.unlock(); vars.release();
for (Bone bone : skeleton.getRoots()) { for (Bone bone : skeleton.getRoots()) {
RagdollUtils.setUserControl(bone, false); RagdollUtils.setUserControl(bone, false);

@ -80,14 +80,13 @@ public class DebugShapeFactory {
// apply rotation // apply rotation
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Matrix3f tempRot = vars.tempMat3; Matrix3f tempRot = vars.tempMat3;
tempRot.set(geometry.getLocalRotation()); tempRot.set(geometry.getLocalRotation());
childCollisionShape.rotation.mult(tempRot, tempRot); childCollisionShape.rotation.mult(tempRot, tempRot);
geometry.setLocalRotation(tempRot); geometry.setLocalRotation(tempRot);
assert vars.unlock(); vars.release();
node.attachChild(geometry); node.attachChild(geometry);
} }

@ -524,7 +524,7 @@ public final class Bone implements Savable {
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock(); // assert vars.lock();
Vector3f tmpV = vars.vect1; Vector3f tmpV = vars.vect1;
Vector3f tmpV2 = vars.vect2; Vector3f tmpV2 = vars.vect2;
@ -545,7 +545,7 @@ public final class Bone implements Savable {
} }
assert vars.unlock(); vars.release();
} }
/** /**

@ -54,7 +54,6 @@ public final class Skeleton implements Savable {
private Bone[] rootBones; private Bone[] rootBones;
private Bone[] boneList; private Bone[] boneList;
/** /**
* Contains the skinning matrices, multiplying it by a vertex effected by a bone * Contains the skinning matrices, multiplying it by a vertex effected by a bone
* will cause it to go to the animated position. * will cause it to go to the animated position.
@ -251,11 +250,10 @@ public final class Skeleton implements Savable {
*/ */
public Matrix4f[] computeSkinningMatrices() { public Matrix4f[] computeSkinningMatrices() {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
for (int i = 0; i < boneList.length; i++) { for (int i = 0; i < boneList.length; i++) {
boneList[i].getOffsetTransform(skinningMatrixes[i], vars.quat1, vars.vect1, vars.vect2, vars.tempMat3); boneList[i].getOffsetTransform(skinningMatrixes[i], vars.quat1, vars.vect1, vars.vect2, vars.tempMat3);
} }
assert vars.unlock(); vars.release();
return skinningMatrixes; return skinningMatrixes;
} }

@ -227,7 +227,7 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
int idxWeights = 0; int idxWeights = 0;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
float[] posBuf = vars.skinPositions; float[] posBuf = vars.skinPositions;
float[] normBuf = vars.skinNormals; float[] normBuf = vars.skinNormals;
@ -284,7 +284,7 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
fnb.put(normBuf, 0, bufLength); fnb.put(normBuf, 0, bufLength);
} }
assert vars.unlock(); vars.release();
vb.updateData(fvb); vb.updateData(fvb);
nb.updateData(fnb); nb.updateData(fnb);

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.bounding; package com.jme3.bounding;
import com.jme3.collision.Collidable; import com.jme3.collision.Collidable;
@ -90,14 +89,14 @@ public class BoundingBox extends BoundingVolume {
this.zExtent = z; this.zExtent = z;
} }
public BoundingBox(BoundingBox source){ public BoundingBox(BoundingBox source) {
this.center.set(source.center); this.center.set(source.center);
this.xExtent = source.xExtent; this.xExtent = source.xExtent;
this.yExtent = source.yExtent; this.yExtent = source.yExtent;
this.zExtent = source.zExtent; this.zExtent = source.zExtent;
} }
public BoundingBox(Vector3f min, Vector3f max){ public BoundingBox(Vector3f min, Vector3f max) {
setMinMax(min, max); setMinMax(min, max);
} }
@ -130,7 +129,7 @@ public class BoundingBox extends BoundingVolume {
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f min = vars.vect1.set(new Vector3f(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)); Vector3f min = vars.vect1.set(new Vector3f(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY));
Vector3f max = vars.vect2.set(new Vector3f(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY)); Vector3f max = vars.vect2.set(new Vector3f(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY));
@ -151,7 +150,7 @@ public class BoundingBox extends BoundingVolume {
yExtent = max.y - center.y; yExtent = max.y - center.y;
zExtent = max.z - center.z; zExtent = max.z - center.z;
assert vars.unlock(); vars.release();
} }
public void computeFromTris(int[] indices, Mesh mesh, int start, int end) { public void computeFromTris(int[] indices, Mesh mesh, int start, int end) {
@ -160,7 +159,7 @@ public class BoundingBox extends BoundingVolume {
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f vect1 = vars.vect1; Vector3f vect1 = vars.vect1;
Vector3f vect2 = vars.vect2; Vector3f vect2 = vars.vect2;
Triangle triangle = vars.triangle; Triangle triangle = vars.triangle;
@ -186,23 +185,29 @@ public class BoundingBox extends BoundingVolume {
yExtent = max.y - center.y; yExtent = max.y - center.y;
zExtent = max.z - center.z; zExtent = max.z - center.z;
assert vars.unlock(); vars.release();
} }
public static final void checkMinMax(Vector3f min, Vector3f max, Vector3f point) { public static final void checkMinMax(Vector3f min, Vector3f max, Vector3f point) {
if (point.x < min.x) if (point.x < min.x) {
min.x = point.x; min.x = point.x;
if (point.x > max.x) }
if (point.x > max.x) {
max.x = point.x; max.x = point.x;
if (point.y < min.y) }
if (point.y < min.y) {
min.y = point.y; min.y = point.y;
if (point.y > max.y) }
if (point.y > max.y) {
max.y = point.y; max.y = point.y;
if (point.z < min.z) }
if (point.z < min.z) {
min.z = point.z; min.z = point.z;
if (point.z > max.z) }
if (point.z > max.z) {
max.z = point.z; max.z = point.z;
} }
}
/** /**
* <code>containAABB</code> creates a minimum-volume axis-aligned bounding * <code>containAABB</code> creates a minimum-volume axis-aligned bounding
@ -213,15 +218,18 @@ public class BoundingBox extends BoundingVolume {
* the list of points. * the list of points.
*/ */
public void containAABB(FloatBuffer points) { public void containAABB(FloatBuffer points) {
if (points == null) if (points == null) {
return; return;
}
points.rewind(); points.rewind();
if (points.remaining() <= 2) // we need at least a 3 float vector if (points.remaining() <= 2) // we need at least a 3 float vector
{
return; return;
}
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
BufferUtils.populateFromBuffer(vars.vect1, points, 0); BufferUtils.populateFromBuffer(vars.vect1, points, 0);
float minX = vars.vect1.x, minY = vars.vect1.y, minZ = vars.vect1.z; float minX = vars.vect1.x, minY = vars.vect1.y, minZ = vars.vect1.z;
float maxX = vars.vect1.x, maxY = vars.vect1.y, maxZ = vars.vect1.z; float maxX = vars.vect1.x, maxY = vars.vect1.y, maxZ = vars.vect1.z;
@ -229,23 +237,26 @@ public class BoundingBox extends BoundingVolume {
for (int i = 1, len = points.remaining() / 3; i < len; i++) { for (int i = 1, len = points.remaining() / 3; i < len; i++) {
BufferUtils.populateFromBuffer(vars.vect1, points, i); BufferUtils.populateFromBuffer(vars.vect1, points, i);
if (vars.vect1.x < minX) if (vars.vect1.x < minX) {
minX = vars.vect1.x; minX = vars.vect1.x;
else if (vars.vect1.x > maxX) } else if (vars.vect1.x > maxX) {
maxX = vars.vect1.x; maxX = vars.vect1.x;
}
if (vars.vect1.y < minY) if (vars.vect1.y < minY) {
minY = vars.vect1.y; minY = vars.vect1.y;
else if (vars.vect1.y > maxY) } else if (vars.vect1.y > maxY) {
maxY = vars.vect1.y; maxY = vars.vect1.y;
}
if (vars.vect1.z < minZ) if (vars.vect1.z < minZ) {
minZ = vars.vect1.z; minZ = vars.vect1.z;
else if (vars.vect1.z > maxZ) } else if (vars.vect1.z > maxZ) {
maxZ = vars.vect1.z; maxZ = vars.vect1.z;
} }
}
assert vars.unlock(); vars.release();
center.set(minX + maxX, minY + maxY, minZ + maxZ); center.set(minX + maxX, minY + maxY, minZ + maxZ);
center.multLocal(0.5f); center.multLocal(0.5f);
@ -278,7 +289,7 @@ public class BoundingBox extends BoundingVolume {
box.center.addLocal(trans.getTranslation()); box.center.addLocal(trans.getTranslation());
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Matrix3f transMatrix = vars.tempMat3; Matrix3f transMatrix = vars.tempMat3;
transMatrix.set(trans.getRotation()); transMatrix.set(trans.getRotation());
// Make the rotation matrix all positive to get the maximum x/y/z extent // Make the rotation matrix all positive to get the maximum x/y/z extent
@ -292,12 +303,12 @@ public class BoundingBox extends BoundingVolume {
box.yExtent = FastMath.abs(vars.vect2.getY()); box.yExtent = FastMath.abs(vars.vect2.getY());
box.zExtent = FastMath.abs(vars.vect2.getZ()); box.zExtent = FastMath.abs(vars.vect2.getZ());
assert vars.unlock(); vars.release();
return box; return box;
} }
public BoundingVolume transform(Matrix4f trans, BoundingVolume store){ public BoundingVolume transform(Matrix4f trans, BoundingVolume store) {
BoundingBox box; BoundingBox box;
if (store == null || store.getType() != Type.AABB) { if (store == null || store.getType() != Type.AABB) {
box = new BoundingBox(); box = new BoundingBox();
@ -305,7 +316,7 @@ public class BoundingBox extends BoundingVolume {
box = (BoundingBox) store; box = (BoundingBox) store;
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
float w = trans.multProj(center, box.center); float w = trans.multProj(center, box.center);
box.center.divideLocal(w); box.center.divideLocal(w);
@ -324,7 +335,7 @@ public class BoundingBox extends BoundingVolume {
box.yExtent = FastMath.abs(vars.vect1.getY()); box.yExtent = FastMath.abs(vars.vect1.getY());
box.zExtent = FastMath.abs(vars.vect1.getZ()); box.zExtent = FastMath.abs(vars.vect1.getZ());
assert vars.unlock(); vars.release();
return box; return box;
} }
@ -471,7 +482,6 @@ public class BoundingBox extends BoundingVolume {
// zExtent = max.z - center.z; // zExtent = max.z - center.z;
// return this; // return this;
// } // }
/** /**
* <code>merge</code> combines this bounding box with another box which is * <code>merge</code> combines this bounding box with another box which is
* defined by the center, x, y, z extents. * defined by the center, x, y, z extents.
@ -492,26 +502,32 @@ public class BoundingBox extends BoundingVolume {
float boxZ, BoundingBox rVal) { float boxZ, BoundingBox rVal) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
vars.vect1.x = center.x - xExtent; vars.vect1.x = center.x - xExtent;
if (vars.vect1.x > boxCenter.x - boxX) if (vars.vect1.x > boxCenter.x - boxX) {
vars.vect1.x = boxCenter.x - boxX; vars.vect1.x = boxCenter.x - boxX;
}
vars.vect1.y = center.y - yExtent; vars.vect1.y = center.y - yExtent;
if (vars.vect1.y > boxCenter.y - boxY) if (vars.vect1.y > boxCenter.y - boxY) {
vars.vect1.y = boxCenter.y - boxY; vars.vect1.y = boxCenter.y - boxY;
}
vars.vect1.z = center.z - zExtent; vars.vect1.z = center.z - zExtent;
if (vars.vect1.z > boxCenter.z - boxZ) if (vars.vect1.z > boxCenter.z - boxZ) {
vars.vect1.z = boxCenter.z - boxZ; vars.vect1.z = boxCenter.z - boxZ;
}
vars.vect2.x = center.x + xExtent; vars.vect2.x = center.x + xExtent;
if (vars.vect2.x < boxCenter.x + boxX) if (vars.vect2.x < boxCenter.x + boxX) {
vars.vect2.x = boxCenter.x + boxX; vars.vect2.x = boxCenter.x + boxX;
}
vars.vect2.y = center.y + yExtent; vars.vect2.y = center.y + yExtent;
if (vars.vect2.y < boxCenter.y + boxY) if (vars.vect2.y < boxCenter.y + boxY) {
vars.vect2.y = boxCenter.y + boxY; vars.vect2.y = boxCenter.y + boxY;
}
vars.vect2.z = center.z + zExtent; vars.vect2.z = center.z + zExtent;
if (vars.vect2.z < boxCenter.z + boxZ) if (vars.vect2.z < boxCenter.z + boxZ) {
vars.vect2.z = boxCenter.z + boxZ; vars.vect2.z = boxCenter.z + boxZ;
}
center.set(vars.vect2).addLocal(vars.vect1).multLocal(0.5f); center.set(vars.vect2).addLocal(vars.vect1).multLocal(0.5f);
@ -519,7 +535,7 @@ public class BoundingBox extends BoundingVolume {
yExtent = vars.vect2.y - center.y; yExtent = vars.vect2.y - center.y;
zExtent = vars.vect2.z - center.z; zExtent = vars.vect2.z - center.z;
assert vars.unlock(); vars.release();
return rVal; return rVal;
} }
@ -585,8 +601,9 @@ public class BoundingBox extends BoundingVolume {
&& FastMath.abs(center.y - bs.center.y) < bs.getRadius() && FastMath.abs(center.y - bs.center.y) < bs.getRadius()
+ yExtent + yExtent
&& FastMath.abs(center.z - bs.center.z) < bs.getRadius() && FastMath.abs(center.z - bs.center.z) < bs.getRadius()
+ zExtent) + zExtent) {
return true; return true;
}
return false; return false;
} }
@ -602,17 +619,18 @@ public class BoundingBox extends BoundingVolume {
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center); assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center);
if (center.x + xExtent < bb.center.x - bb.xExtent if (center.x + xExtent < bb.center.x - bb.xExtent
|| center.x - xExtent > bb.center.x + bb.xExtent) || center.x - xExtent > bb.center.x + bb.xExtent) {
return false; return false;
else if (center.y + yExtent < bb.center.y - bb.yExtent } else if (center.y + yExtent < bb.center.y - bb.yExtent
|| center.y - yExtent > bb.center.y + bb.yExtent) || center.y - yExtent > bb.center.y + bb.yExtent) {
return false; return false;
else if (center.z + zExtent < bb.center.z - bb.zExtent } else if (center.z + zExtent < bb.center.z - bb.zExtent
|| center.z - zExtent > bb.center.z + bb.zExtent) || center.z - zExtent > bb.center.z + bb.zExtent) {
return false; return false;
else } else {
return true; return true;
} }
}
/** /**
* determines if this bounding box intersects with a given oriented bounding * determines if this bounding box intersects with a given oriented bounding
@ -623,7 +641,6 @@ public class BoundingBox extends BoundingVolume {
// public boolean intersectsOrientedBoundingBox(OrientedBoundingBox obb) { // public boolean intersectsOrientedBoundingBox(OrientedBoundingBox obb) {
// return obb.intersectsBoundingBox(this); // return obb.intersectsBoundingBox(this);
// } // }
/** /**
* determines if this bounding box intersects with a given ray object. If an * determines if this bounding box intersects with a given ray object. If an
* intersection has occurred, true is returned, otherwise false is returned. * intersection has occurred, true is returned, otherwise false is returned.
@ -636,7 +653,7 @@ public class BoundingBox extends BoundingVolume {
float rhs; float rhs;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = ray.origin.subtract(getCenter(vars.vect2), vars.vect1); Vector3f diff = ray.origin.subtract(getCenter(vars.vect2), vars.vect1);
final float[] fWdU = vars.fWdU; final float[] fWdU = vars.fWdU;
@ -650,7 +667,7 @@ public class BoundingBox extends BoundingVolume {
fDdU[0] = diff.dot(Vector3f.UNIT_X); fDdU[0] = diff.dot(Vector3f.UNIT_X);
fADdU[0] = FastMath.abs(fDdU[0]); fADdU[0] = FastMath.abs(fDdU[0]);
if (fADdU[0] > xExtent && fDdU[0] * fWdU[0] >= 0.0) { if (fADdU[0] > xExtent && fDdU[0] * fWdU[0] >= 0.0) {
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -659,7 +676,7 @@ public class BoundingBox extends BoundingVolume {
fDdU[1] = diff.dot(Vector3f.UNIT_Y); fDdU[1] = diff.dot(Vector3f.UNIT_Y);
fADdU[1] = FastMath.abs(fDdU[1]); fADdU[1] = FastMath.abs(fDdU[1]);
if (fADdU[1] > yExtent && fDdU[1] * fWdU[1] >= 0.0) { if (fADdU[1] > yExtent && fDdU[1] * fWdU[1] >= 0.0) {
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -668,7 +685,7 @@ public class BoundingBox extends BoundingVolume {
fDdU[2] = diff.dot(Vector3f.UNIT_Z); fDdU[2] = diff.dot(Vector3f.UNIT_Z);
fADdU[2] = FastMath.abs(fDdU[2]); fADdU[2] = FastMath.abs(fDdU[2]);
if (fADdU[2] > zExtent && fDdU[2] * fWdU[2] >= 0.0) { if (fADdU[2] > zExtent && fDdU[2] * fWdU[2] >= 0.0) {
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -677,25 +694,25 @@ public class BoundingBox extends BoundingVolume {
fAWxDdU[0] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_X)); fAWxDdU[0] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_X));
rhs = yExtent * fAWdU[2] + zExtent * fAWdU[1]; rhs = yExtent * fAWdU[2] + zExtent * fAWdU[1];
if (fAWxDdU[0] > rhs) { if (fAWxDdU[0] > rhs) {
assert vars.unlock(); vars.release();
return false; return false;
} }
fAWxDdU[1] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_Y)); fAWxDdU[1] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_Y));
rhs = xExtent * fAWdU[2] + zExtent * fAWdU[0]; rhs = xExtent * fAWdU[2] + zExtent * fAWdU[0];
if (fAWxDdU[1] > rhs) { if (fAWxDdU[1] > rhs) {
assert vars.unlock(); vars.release();
return false; return false;
} }
fAWxDdU[2] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_Z)); fAWxDdU[2] = FastMath.abs(wCrossD.dot(Vector3f.UNIT_Z));
rhs = xExtent * fAWdU[1] + yExtent * fAWdU[0]; rhs = xExtent * fAWdU[1] + yExtent * fAWdU[0];
if (fAWxDdU[2] > rhs) { if (fAWxDdU[2] > rhs) {
assert vars.unlock(); vars.release();
return false; return false;
} }
assert vars.unlock(); vars.release();
return true; return true;
} }
@ -704,11 +721,11 @@ public class BoundingBox extends BoundingVolume {
*/ */
private int collideWithRay(Ray ray, CollisionResults results) { private int collideWithRay(Ray ray, CollisionResults results) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = vars.vect1.set(ray.origin).subtractLocal(center); Vector3f diff = vars.vect1.set(ray.origin).subtractLocal(center);
Vector3f direction = vars.vect2.set(ray.direction); Vector3f direction = vars.vect2.set(ray.direction);
float[] t = { 0f, Float.POSITIVE_INFINITY }; float[] t = {0f, Float.POSITIVE_INFINITY};
float saveT0 = t[0], saveT1 = t[1]; float saveT0 = t[0], saveT1 = t[1];
boolean notEntirelyClipped = clip(+direction.x, -diff.x - xExtent, t) boolean notEntirelyClipped = clip(+direction.x, -diff.x - xExtent, t)
@ -717,12 +734,12 @@ public class BoundingBox extends BoundingVolume {
&& clip(-direction.y, +diff.y - yExtent, t) && clip(-direction.y, +diff.y - yExtent, t)
&& clip(+direction.z, -diff.z - zExtent, t) && clip(+direction.z, -diff.z - zExtent, t)
&& clip(-direction.z, +diff.z - zExtent, t); && clip(-direction.z, +diff.z - zExtent, t);
assert vars.unlock(); vars.release();
if (notEntirelyClipped && (t[0] != saveT0 || t[1] != saveT1)) { if (notEntirelyClipped && (t[0] != saveT0 || t[1] != saveT1)) {
if (t[1] > t[0]) { if (t[1] > t[0]) {
float[] distances = t; float[] distances = t;
Vector3f[] points = new Vector3f[] { Vector3f[] points = new Vector3f[]{
new Vector3f(ray.direction).multLocal(distances[0]).addLocal(ray.origin), new Vector3f(ray.direction).multLocal(distances[0]).addLocal(ray.origin),
new Vector3f(ray.direction).multLocal(distances[1]).addLocal(ray.origin) new Vector3f(ray.direction).multLocal(distances[1]).addLocal(ray.origin)
}; };
@ -742,20 +759,20 @@ public class BoundingBox extends BoundingVolume {
return 0; return 0;
} }
public int collideWith(Collidable other, CollisionResults results){ public int collideWith(Collidable other, CollisionResults results) {
if (other instanceof Ray){ if (other instanceof Ray) {
Ray ray = (Ray) other; Ray ray = (Ray) other;
return collideWithRay(ray, results); return collideWithRay(ray, results);
}else if (other instanceof Triangle){ } else if (other instanceof Triangle) {
Triangle t = (Triangle) other; Triangle t = (Triangle) other;
if (intersects(t.get1(), t.get2(), t.get3())){ if (intersects(t.get1(), t.get2(), t.get3())) {
CollisionResult r = new CollisionResult(); CollisionResult r = new CollisionResult();
results.addCollision(r); results.addCollision(r);
return 1; return 1;
} }
return 0; return 0;
}else{ } else {
throw new UnsupportedCollisionException("With: "+other.getClass().getSimpleName()); throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
} }
} }
@ -768,7 +785,7 @@ public class BoundingBox extends BoundingVolume {
* @return True if the bounding box intersects the triangle, false * @return True if the bounding box intersects the triangle, false
* otherwise. * otherwise.
*/ */
public boolean intersects(Vector3f v1, Vector3f v2, Vector3f v3){ public boolean intersects(Vector3f v1, Vector3f v2, Vector3f v3) {
return Intersection.intersect(this, v1, v2, v3); return Intersection.intersect(this, v1, v2, v3);
} }
@ -844,16 +861,20 @@ public class BoundingBox extends BoundingVolume {
// plane. Otherwise 'false' is returned in which case the line segment // plane. Otherwise 'false' is returned in which case the line segment
// is entirely clipped. // is entirely clipped.
if (denom > 0.0f) { if (denom > 0.0f) {
if (numer > denom * t[1]) if (numer > denom * t[1]) {
return false; return false;
if (numer > denom * t[0]) }
if (numer > denom * t[0]) {
t[0] = numer / denom; t[0] = numer / denom;
}
return true; return true;
} else if (denom < 0.0f) { } else if (denom < 0.0f) {
if (numer > denom * t[0]) if (numer > denom * t[0]) {
return false; return false;
if (numer > denom * t[1]) }
if (numer > denom * t[1]) {
t[1] = numer / denom; t[1] = numer / denom;
}
return true; return true;
} else { } else {
return numer <= 0.0; return numer <= 0.0;
@ -875,40 +896,43 @@ public class BoundingBox extends BoundingVolume {
return store; return store;
} }
public float getXExtent(){ public float getXExtent() {
return xExtent; return xExtent;
} }
public float getYExtent(){ public float getYExtent() {
return yExtent; return yExtent;
} }
public float getZExtent(){ public float getZExtent() {
return zExtent; return zExtent;
} }
public void setXExtent(float xExtent) { public void setXExtent(float xExtent) {
if (xExtent < 0) if (xExtent < 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
}
this.xExtent = xExtent; this.xExtent = xExtent;
} }
public void setYExtent(float yExtent) { public void setYExtent(float yExtent) {
if (yExtent < 0) if (yExtent < 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
}
this.yExtent = yExtent; this.yExtent = yExtent;
} }
public void setZExtent(float zExtent) { public void setZExtent(float zExtent) {
if (zExtent < 0) if (zExtent < 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
}
this.zExtent = zExtent; this.zExtent = zExtent;
} }
public Vector3f getMin(Vector3f store){ public Vector3f getMin(Vector3f store) {
if (store == null) { if (store == null) {
store = new Vector3f(); store = new Vector3f();
} }
@ -916,7 +940,7 @@ public class BoundingBox extends BoundingVolume {
return store; return store;
} }
public Vector3f getMax(Vector3f store){ public Vector3f getMax(Vector3f store) {
if (store == null) { if (store == null) {
store = new Vector3f(); store = new Vector3f();
} }
@ -924,7 +948,7 @@ public class BoundingBox extends BoundingVolume {
return store; return store;
} }
public void setMinMax(Vector3f min, Vector3f max){ public void setMinMax(Vector3f min, Vector3f max) {
this.center.set(max).addLocal(min).multLocal(0.5f); this.center.set(max).addLocal(min).multLocal(0.5f);
xExtent = FastMath.abs(max.x - center.x); xExtent = FastMath.abs(max.x - center.x);
yExtent = FastMath.abs(max.y - center.y); yExtent = FastMath.abs(max.y - center.y);
@ -951,7 +975,6 @@ public class BoundingBox extends BoundingVolume {
@Override @Override
public float getVolume() { public float getVolume() {
return (8*xExtent*yExtent*zExtent); return (8 * xExtent * yExtent * zExtent);
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.bounding; package com.jme3.bounding;
import com.jme3.collision.Collidable; import com.jme3.collision.Collidable;
@ -69,9 +68,7 @@ public class BoundingSphere extends BoundingVolume {
private static final Logger logger = private static final Logger logger =
Logger.getLogger(BoundingSphere.class.getName()); Logger.getLogger(BoundingSphere.class.getName());
float radius; float radius;
private static final float RADIUS_EPSILON = 1f + 0.00001f; private static final float RADIUS_EPSILON = 1f + 0.00001f;
/** /**
@ -190,8 +187,9 @@ public class BoundingSphere extends BoundingVolume {
* The points to calculate the minimum bounds from. * The points to calculate the minimum bounds from.
*/ */
public void calcWelzl(FloatBuffer points) { public void calcWelzl(FloatBuffer points) {
if (center == null) if (center == null) {
center = new Vector3f(); center = new Vector3f();
}
FloatBuffer buf = BufferUtils.createFloatBuffer(points.limit()); FloatBuffer buf = BufferUtils.createFloatBuffer(points.limit());
points.rewind(); points.rewind();
buf.put(points); buf.put(points);
@ -216,7 +214,7 @@ public class BoundingSphere extends BoundingVolume {
*/ */
private void recurseMini(FloatBuffer points, int p, int b, int ap) { private void recurseMini(FloatBuffer points, int p, int b, int ap) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f tempA = vars.vect1; Vector3f tempA = vars.vect1;
Vector3f tempB = vars.vect2; Vector3f tempB = vars.vect2;
Vector3f tempC = vars.vect3; Vector3f tempC = vars.vect3;
@ -229,30 +227,30 @@ public class BoundingSphere extends BoundingVolume {
break; break;
case 1: case 1:
this.radius = 1f - RADIUS_EPSILON; this.radius = 1f - RADIUS_EPSILON;
BufferUtils.populateFromBuffer(center, points, ap-1); BufferUtils.populateFromBuffer(center, points, ap - 1);
break; break;
case 2: case 2:
BufferUtils.populateFromBuffer(tempA, points, ap-1); BufferUtils.populateFromBuffer(tempA, points, ap - 1);
BufferUtils.populateFromBuffer(tempB, points, ap-2); BufferUtils.populateFromBuffer(tempB, points, ap - 2);
setSphere(tempA, tempB); setSphere(tempA, tempB);
break; break;
case 3: case 3:
BufferUtils.populateFromBuffer(tempA, points, ap-1); BufferUtils.populateFromBuffer(tempA, points, ap - 1);
BufferUtils.populateFromBuffer(tempB, points, ap-2); BufferUtils.populateFromBuffer(tempB, points, ap - 2);
BufferUtils.populateFromBuffer(tempC, points, ap-3); BufferUtils.populateFromBuffer(tempC, points, ap - 3);
setSphere(tempA, tempB, tempC); setSphere(tempA, tempB, tempC);
break; break;
case 4: case 4:
BufferUtils.populateFromBuffer(tempA, points, ap-1); BufferUtils.populateFromBuffer(tempA, points, ap - 1);
BufferUtils.populateFromBuffer(tempB, points, ap-2); BufferUtils.populateFromBuffer(tempB, points, ap - 2);
BufferUtils.populateFromBuffer(tempC, points, ap-3); BufferUtils.populateFromBuffer(tempC, points, ap - 3);
BufferUtils.populateFromBuffer(tempD, points, ap-4); BufferUtils.populateFromBuffer(tempD, points, ap - 4);
setSphere(tempA, tempB, tempC, tempD); setSphere(tempA, tempB, tempC, tempD);
assert vars.unlock(); vars.release();
return; return;
} }
for (int i = 0; i < p; i++) { for (int i = 0; i < p; i++) {
BufferUtils.populateFromBuffer(tempA, points, i+ap); BufferUtils.populateFromBuffer(tempA, points, i + ap);
if (tempA.distanceSquared(center) - (radius * radius) > RADIUS_EPSILON - 1f) { if (tempA.distanceSquared(center) - (radius * radius) > RADIUS_EPSILON - 1f) {
for (int j = i; j > 0; j--) { for (int j = i; j > 0; j--) {
BufferUtils.populateFromBuffer(tempB, points, j + ap); BufferUtils.populateFromBuffer(tempB, points, j + ap);
@ -260,12 +258,12 @@ public class BoundingSphere extends BoundingVolume {
BufferUtils.setInBuffer(tempC, points, j + ap); BufferUtils.setInBuffer(tempC, points, j + ap);
BufferUtils.setInBuffer(tempB, points, j - 1 + ap); BufferUtils.setInBuffer(tempB, points, j - 1 + ap);
} }
assert vars.unlock(); vars.release();
recurseMini(points, i, b + 1, ap + 1); recurseMini(points, i, b + 1, ap + 1);
assert vars.lock();
} }
} }
assert vars.unlock(); vars.release();
} }
/** /**
@ -327,9 +325,7 @@ public class BoundingSphere extends BoundingVolume {
radius = 0; radius = 0;
} else { } else {
Vector3f o = acrossB.cross(a).multLocal(b.lengthSquared()) Vector3f o = acrossB.cross(a).multLocal(b.lengthSquared()).addLocal(b.cross(acrossB).multLocal(a.lengthSquared())).divideLocal(Denominator);
.addLocal(b.cross(acrossB).multLocal(a.lengthSquared()))
.divideLocal(Denominator);
radius = o.length() * RADIUS_EPSILON; radius = o.length() * RADIUS_EPSILON;
O.add(o, center); O.add(o, center);
} }
@ -418,7 +414,7 @@ public class BoundingSphere extends BoundingVolume {
} }
trans.mult(center, sphere.center); trans.mult(center, sphere.center);
Vector3f axes = new Vector3f(1,1,1); Vector3f axes = new Vector3f(1, 1, 1);
trans.mult(axes, axes); trans.mult(axes, axes);
float ax = getMaxAxis(axes); float ax = getMaxAxis(axes);
sphere.radius = FastMath.abs(ax * radius) + RADIUS_EPSILON - 1f; sphere.radius = FastMath.abs(ax * radius) + RADIUS_EPSILON - 1f;
@ -431,13 +427,15 @@ public class BoundingSphere extends BoundingVolume {
float z = FastMath.abs(scale.z); float z = FastMath.abs(scale.z);
if (x >= y) { if (x >= y) {
if (x >= z) if (x >= z) {
return x; return x;
}
return z; return z;
} }
if (y >= z) if (y >= z) {
return y; return y;
}
return z; return z;
} }
@ -475,7 +473,7 @@ public class BoundingSphere extends BoundingVolume {
return this; return this;
} }
switch(volume.getType()) { switch (volume.getType()) {
case Sphere: { case Sphere: {
BoundingSphere sphere = (BoundingSphere) volume; BoundingSphere sphere = (BoundingSphere) volume;
@ -531,12 +529,12 @@ public class BoundingSphere extends BoundingVolume {
case AABB: { case AABB: {
BoundingBox box = (BoundingBox) volume; BoundingBox box = (BoundingBox) volume;
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f radVect = TempVars.get().vect1; Vector3f radVect = vars.vect1;
radVect.set(box.xExtent, box.yExtent, box.zExtent); radVect.set(box.xExtent, box.yExtent, box.zExtent);
Vector3f temp_center = box.center; Vector3f temp_center = box.center;
float len = radVect.length(); float len = radVect.length();
assert TempVars.get().unlock(); vars.release();
return merge(len, temp_center, this); return merge(len, temp_center, this);
} }
@ -585,11 +583,10 @@ public class BoundingSphere extends BoundingVolume {
// //
// return this; // return this;
// } // }
private BoundingVolume merge(float temp_radius, Vector3f temp_center, private BoundingVolume merge(float temp_radius, Vector3f temp_center,
BoundingSphere rVal) { BoundingSphere rVal) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = temp_center.subtract(center, vars.vect1); Vector3f diff = temp_center.subtract(center, vars.vect1);
float lengthSquared = diff.lengthSquared(); float lengthSquared = diff.lengthSquared();
float radiusDiff = temp_radius - radius; float radiusDiff = temp_radius - radius;
@ -598,25 +595,25 @@ public class BoundingSphere extends BoundingVolume {
if (fRDiffSqr >= lengthSquared) { if (fRDiffSqr >= lengthSquared) {
if (radiusDiff <= 0.0f) { if (radiusDiff <= 0.0f) {
assert vars.unlock(); vars.release();
return this; return this;
} }
Vector3f rCenter = rVal.center; Vector3f rCenter = rVal.center;
if ( rCenter == null ) { if (rCenter == null) {
rVal.setCenter( rCenter = new Vector3f() ); rVal.setCenter(rCenter = new Vector3f());
} }
rCenter.set(temp_center); rCenter.set(temp_center);
rVal.setRadius(temp_radius); rVal.setRadius(temp_radius);
assert vars.unlock(); vars.release();
return rVal; return rVal;
} }
float length = (float) Math.sqrt(lengthSquared); float length = (float) Math.sqrt(lengthSquared);
Vector3f rCenter = rVal.center; Vector3f rCenter = rVal.center;
if ( rCenter == null ) { if (rCenter == null) {
rVal.setCenter( rCenter = new Vector3f() ); rVal.setCenter(rCenter = new Vector3f());
} }
if (length > RADIUS_EPSILON) { if (length > RADIUS_EPSILON) {
float coeff = (length + radiusDiff) / (2.0f * length); float coeff = (length + radiusDiff) / (2.0f * length);
@ -626,7 +623,7 @@ public class BoundingSphere extends BoundingVolume {
} }
rVal.setRadius(0.5f * (length + radius + temp_radius)); rVal.setRadius(0.5f * (length + radius + temp_radius));
assert vars.unlock(); vars.release();
return rVal; return rVal;
} }
@ -685,11 +682,11 @@ public class BoundingSphere extends BoundingVolume {
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center); assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = center.subtract(bs.center, vars.vect1); Vector3f diff = center.subtract(bs.center, vars.vect1);
float rsum = getRadius() + bs.getRadius(); float rsum = getRadius() + bs.getRadius();
boolean eq = (diff.dot(diff) <= rsum * rsum); boolean eq = (diff.dot(diff) <= rsum * rsum);
assert vars.unlock(); vars.release();
return eq; return eq;
} }
@ -706,8 +703,9 @@ public class BoundingSphere extends BoundingVolume {
&& FastMath.abs(bb.center.y - center.y) < getRadius() && FastMath.abs(bb.center.y - center.y) < getRadius()
+ bb.yExtent + bb.yExtent
&& FastMath.abs(bb.center.z - center.z) < getRadius() && FastMath.abs(bb.center.z - center.z) < getRadius()
+ bb.zExtent) + bb.zExtent) {
return true; return true;
}
return false; return false;
} }
@ -730,9 +728,8 @@ public class BoundingSphere extends BoundingVolume {
assert Vector3f.isValidVector(center); assert Vector3f.isValidVector(center);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = vars.vect1.set(ray.getOrigin()) Vector3f diff = vars.vect1.set(ray.getOrigin()).subtractLocal(center);
.subtractLocal(center);
float radiusSquared = getRadius() * getRadius(); float radiusSquared = getRadius() * getRadius();
float a = diff.dot(diff) - radiusSquared; float a = diff.dot(diff) - radiusSquared;
if (a <= 0.0) { if (a <= 0.0) {
@ -742,11 +739,11 @@ public class BoundingSphere extends BoundingVolume {
// outside sphere // outside sphere
float b = ray.getDirection().dot(diff); float b = ray.getDirection().dot(diff);
assert vars.unlock(); vars.release();
if (b >= 0.0) { if (b >= 0.0) {
return false; return false;
} }
return b*b >= a; return b * b >= a;
} }
/* /*
@ -756,10 +753,10 @@ public class BoundingSphere extends BoundingVolume {
*/ */
public int collideWithRay(Ray ray, CollisionResults results) { public int collideWithRay(Ray ray, CollisionResults results) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = vars.vect1.set(ray.getOrigin()).subtractLocal( Vector3f diff = vars.vect1.set(ray.getOrigin()).subtractLocal(
center); center);
float a = diff.dot(diff) - (getRadius()*getRadius()); float a = diff.dot(diff) - (getRadius() * getRadius());
float a1, discr, root; float a1, discr, root;
if (a <= 0.0) { if (a <= 0.0) {
// inside sphere // inside sphere
@ -776,16 +773,15 @@ public class BoundingSphere extends BoundingVolume {
} }
a1 = ray.direction.dot(diff); a1 = ray.direction.dot(diff);
assert vars.unlock(); vars.release();
if (a1 >= 0.0) { if (a1 >= 0.0) {
return 0; return 0;
} }
discr = a1*a1 - a; discr = a1 * a1 - a;
if (discr < 0.0) if (discr < 0.0) {
return 0; return 0;
} else if (discr >= FastMath.ZERO_TOLERANCE) {
else if (discr >= FastMath.ZERO_TOLERANCE) {
root = FastMath.sqrt(discr); root = FastMath.sqrt(discr);
float dist = -a1 - root; float dist = -a1 - root;
Vector3f point = new Vector3f(ray.direction).multLocal(dist).addLocal(ray.origin); Vector3f point = new Vector3f(ray.direction).multLocal(dist).addLocal(ray.origin);
@ -803,11 +799,11 @@ public class BoundingSphere extends BoundingVolume {
} }
} }
public int collideWith(Collidable other, CollisionResults results){ public int collideWith(Collidable other, CollisionResults results) {
if (other instanceof Ray){ if (other instanceof Ray) {
Ray ray = (Ray) other; Ray ray = (Ray) other;
return collideWithRay(ray, results); return collideWithRay(ray, results);
}else{ } else {
throw new UnsupportedCollisionException(); throw new UnsupportedCollisionException();
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.bounding; package com.jme3.bounding;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
@ -47,16 +46,23 @@ import static java.lang.Math.max;
*/ */
public class Intersection { public class Intersection {
private static final void findMinMax(float x0, float x1, float x2, Vector3f minMax){ private static final void findMinMax(float x0, float x1, float x2, Vector3f minMax) {
minMax.set(x0, x0, 0); minMax.set(x0, x0, 0);
if (x1 < minMax.x) minMax.setX(x1); if (x1 < minMax.x) {
if (x1 > minMax.y) minMax.setY(x1); minMax.setX(x1);
if (x2 < minMax.x) minMax.setX(x2); }
if (x2 > minMax.y) minMax.setY(x2); if (x1 > minMax.y) {
minMax.setY(x1);
}
if (x2 < minMax.x) {
minMax.setX(x2);
}
if (x2 > minMax.y) {
minMax.setY(x2);
}
} }
// private boolean axisTest(float a, float b, float fa, float fb, Vector3f v0, Vector3f v1, ) // private boolean axisTest(float a, float b, float fa, float fb, Vector3f v0, Vector3f v1, )
// private boolean axisTestX01(float a, float b, float fa, float fb, // private boolean axisTestX01(float a, float b, float fa, float fb,
// Vector3f center, Vector3f ext, // Vector3f center, Vector3f ext,
// Vector3f v1, Vector3f v2, Vector3f v3){ // Vector3f v1, Vector3f v2, Vector3f v3){
@ -73,8 +79,7 @@ public class Intersection {
// if(min > rad || max < -rad) // if(min > rad || max < -rad)
// return false; // return false;
// } // }
public static boolean intersect(BoundingBox bbox, Vector3f v1, Vector3f v2, Vector3f v3) {
public static boolean intersect(BoundingBox bbox, Vector3f v1, Vector3f v2, Vector3f v3){
// use separating axis theorem to test overlap between triangle and box // use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions: // need to test for overlap in these directions:
// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
@ -84,7 +89,7 @@ public class Intersection {
// this gives 3x3=9 more tests // this gives 3x3=9 more tests
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f tmp0 = vars.vect1, Vector3f tmp0 = vars.vect1,
tmp1 = vars.vect2, tmp1 = vars.vect2,
@ -124,33 +129,33 @@ public class Intersection {
//AXISTEST_X01(e0[Z], e0[Y], fez, fey); //AXISTEST_X01(e0[Z], e0[Y], fez, fey);
p0 = e0.z * tmp0.y - e0.y * tmp0.z; p0 = e0.z * tmp0.y - e0.y * tmp0.z;
p2 = e0.z * tmp2.y - e0.y * tmp2.z; p2 = e0.z * tmp2.y - e0.y * tmp2.z;
min = min(p0,p2); min = min(p0, p2);
max = max(p0,p2); max = max(p0, p2);
rad = fez * extent.y + fey * extent.z; rad = fez * extent.y + fey * extent.z;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// AXISTEST_Y02(e0[Z], e0[X], fez, fex); // AXISTEST_Y02(e0[Z], e0[X], fez, fex);
p0 = -e0.z * tmp0.x + e0.x * tmp0.z; p0 = -e0.z * tmp0.x + e0.x * tmp0.z;
p2 = -e0.z * tmp2.x + e0.x * tmp2.z; p2 = -e0.z * tmp2.x + e0.x * tmp2.z;
min = min(p0,p2); min = min(p0, p2);
max = max(p0,p2); max = max(p0, p2);
rad = fez * extent.x + fex * extent.z; rad = fez * extent.x + fex * extent.z;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// AXISTEST_Z12(e0[Y], e0[X], fey, fex); // AXISTEST_Z12(e0[Y], e0[X], fey, fex);
p1 = e0.y * tmp1.x - e0.x * tmp1.y; p1 = e0.y * tmp1.x - e0.x * tmp1.y;
p2 = e0.y * tmp2.x - e0.x * tmp2.y; p2 = e0.y * tmp2.x - e0.x * tmp2.y;
min = min(p1,p2); min = min(p1, p2);
max = max(p1,p2); max = max(p1, p2);
rad = fey * extent.x + fex * extent.y; rad = fey * extent.x + fex * extent.y;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -161,33 +166,33 @@ public class Intersection {
// AXISTEST_X01(e1[Z], e1[Y], fez, fey); // AXISTEST_X01(e1[Z], e1[Y], fez, fey);
p0 = e1.z * tmp0.y - e1.y * tmp0.z; p0 = e1.z * tmp0.y - e1.y * tmp0.z;
p2 = e1.z * tmp2.y - e1.y * tmp2.z; p2 = e1.z * tmp2.y - e1.y * tmp2.z;
min = min(p0,p2); min = min(p0, p2);
max = max(p0,p2); max = max(p0, p2);
rad = fez * extent.y + fey * extent.z; rad = fez * extent.y + fey * extent.z;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// AXISTEST_Y02(e1[Z], e1[X], fez, fex); // AXISTEST_Y02(e1[Z], e1[X], fez, fex);
p0 = -e1.z * tmp0.x + e1.x * tmp0.z; p0 = -e1.z * tmp0.x + e1.x * tmp0.z;
p2 = -e1.z * tmp2.x + e1.x * tmp2.z; p2 = -e1.z * tmp2.x + e1.x * tmp2.z;
min = min(p0,p2); min = min(p0, p2);
max = max(p0,p2); max = max(p0, p2);
rad = fez * extent.x + fex * extent.z; rad = fez * extent.x + fex * extent.z;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// AXISTEST_Z0(e1[Y], e1[X], fey, fex); // AXISTEST_Z0(e1[Y], e1[X], fey, fex);
p0 = e1.y * tmp0.x - e1.x * tmp0.y; p0 = e1.y * tmp0.x - e1.x * tmp0.y;
p1 = e1.y * tmp1.x - e1.x * tmp1.y; p1 = e1.y * tmp1.x - e1.x * tmp1.y;
min = min(p0,p1); min = min(p0, p1);
max = max(p0,p1); max = max(p0, p1);
rad = fey * extent.x + fex * extent.y; rad = fey * extent.x + fex * extent.y;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// //
@ -198,33 +203,33 @@ public class Intersection {
// AXISTEST_X2(e2[Z], e2[Y], fez, fey); // AXISTEST_X2(e2[Z], e2[Y], fez, fey);
p0 = e2.z * tmp0.y - e2.y * tmp0.z; p0 = e2.z * tmp0.y - e2.y * tmp0.z;
p1 = e2.z * tmp1.y - e2.y * tmp1.z; p1 = e2.z * tmp1.y - e2.y * tmp1.z;
min = min(p0,p1); min = min(p0, p1);
max = max(p0,p1); max = max(p0, p1);
rad = fez * extent.y + fey * extent.z; rad = fez * extent.y + fey * extent.z;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// AXISTEST_Y1(e2[Z], e2[X], fez, fex); // AXISTEST_Y1(e2[Z], e2[X], fez, fex);
p0 = -e2.z * tmp0.x + e2.x * tmp0.z; p0 = -e2.z * tmp0.x + e2.x * tmp0.z;
p1 = -e2.z * tmp1.x + e2.x * tmp1.z; p1 = -e2.z * tmp1.x + e2.x * tmp1.z;
min = min(p0,p1); min = min(p0, p1);
max = max(p0,p1); max = max(p0, p1);
rad = fez * extent.x + fex * extent.y; rad = fez * extent.x + fex * extent.y;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// AXISTEST_Z12(e2[Y], e2[X], fey, fex); // AXISTEST_Z12(e2[Y], e2[X], fey, fex);
p1 = e2.y * tmp1.x - e2.x * tmp1.y; p1 = e2.y * tmp1.x - e2.x * tmp1.y;
p2 = e2.y * tmp2.x - e2.x * tmp2.y; p2 = e2.y * tmp2.x - e2.x * tmp2.y;
min = min(p1,p2); min = min(p1, p2);
max = max(p1,p2); max = max(p1, p2);
rad = fey * extent.x + fex * extent.y; rad = fey * extent.x + fex * extent.y;
if (min > rad || max < -rad){ if (min > rad || max < -rad) {
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -239,22 +244,22 @@ public class Intersection {
// test in X-direction // test in X-direction
findMinMax(tmp0.x, tmp1.x, tmp2.x, minMax); findMinMax(tmp0.x, tmp1.x, tmp2.x, minMax);
if(minMax.x > extent.x || minMax.y < -extent.x){ if (minMax.x > extent.x || minMax.y < -extent.x) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// test in Y-direction // test in Y-direction
findMinMax(tmp0.y, tmp1.y, tmp2.y, minMax); findMinMax(tmp0.y, tmp1.y, tmp2.y, minMax);
if(minMax.x > extent.y || minMax.y < -extent.y){ if (minMax.x > extent.y || minMax.y < -extent.y) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// test in Z-direction // test in Z-direction
findMinMax(tmp0.z, tmp1.z, tmp2.z, minMax); findMinMax(tmp0.z, tmp1.z, tmp2.z, minMax);
if(minMax.x > extent.z || minMax.y < -extent.z){ if (minMax.x > extent.z || minMax.y < -extent.z) {
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -265,17 +270,16 @@ public class Intersection {
// e0.cross(e1, normal); // e0.cross(e1, normal);
Plane p = vars.plane; Plane p = vars.plane;
p.setPlanePoints(v1,v2,v3); p.setPlanePoints(v1, v2, v3);
if (bbox.whichSide(p) == Plane.Side.Negative){ if (bbox.whichSide(p) == Plane.Side.Negative) {
assert vars.unlock(); vars.release();
return false; return false;
} }
// //
// if(!planeBoxOverlap(normal,v0,boxhalfsize)) return false; // if(!planeBoxOverlap(normal,v0,boxhalfsize)) return false;
assert vars.unlock(); vars.release();
return true; /* box and triangle overlaps */ return true; /* box and triangle overlaps */
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.collision.bih; package com.jme3.collision.bih;
import com.jme3.bounding.BoundingBox; import com.jme3.bounding.BoundingBox;
@ -62,24 +61,23 @@ import static java.lang.Math.max;
public final class BIHNode implements Savable { public final class BIHNode implements Savable {
private int leftIndex, rightIndex; private int leftIndex, rightIndex;
private BIHNode left; private BIHNode left;
private BIHNode right; private BIHNode right;
private float leftPlane; private float leftPlane;
private float rightPlane; private float rightPlane;
private int axis; private int axis;
public BIHNode(int l, int r){ public BIHNode(int l, int r) {
leftIndex = l; leftIndex = l;
rightIndex = r; rightIndex = r;
axis = 3; // indicates leaf axis = 3; // indicates leaf
} }
public BIHNode(int axis){ public BIHNode(int axis) {
this.axis = axis; this.axis = axis;
} }
public BIHNode(){ public BIHNode() {
} }
public BIHNode getLeftChild() { public BIHNode getLeftChild() {
@ -146,53 +144,55 @@ public final class BIHNode implements Savable {
this.min = min; this.min = min;
this.max = max; this.max = max;
} }
} }
public final int intersectWhere(Collidable col, public final int intersectWhere(Collidable col,
BoundingBox box, BoundingBox box,
Matrix4f worldMatrix, Matrix4f worldMatrix,
BIHTree tree, BIHTree tree,
CollisionResults results){ CollisionResults results) {
ArrayList<BIHStackData> stack = TempVars.get().bihStack; TempVars vars = TempVars.get();
ArrayList<BIHStackData> stack = vars.bihStack;
stack.clear(); stack.clear();
float[] minExts = { box.getCenter().x - box.getXExtent(), float[] minExts = {box.getCenter().x - box.getXExtent(),
box.getCenter().y - box.getYExtent(), box.getCenter().y - box.getYExtent(),
box.getCenter().z - box.getZExtent() }; box.getCenter().z - box.getZExtent()};
float[] maxExts = { box.getCenter().x + box.getXExtent(), float[] maxExts = {box.getCenter().x + box.getXExtent(),
box.getCenter().y + box.getYExtent(), box.getCenter().y + box.getYExtent(),
box.getCenter().z + box.getZExtent() }; box.getCenter().z + box.getZExtent()};
stack.add(new BIHStackData(this, 0,0)); stack.add(new BIHStackData(this, 0, 0));
Triangle t = new Triangle(); Triangle t = new Triangle();
int cols = 0; int cols = 0;
stackloop: while (stack.size() > 0){ stackloop:
BIHNode node = stack.remove(stack.size()-1).node; while (stack.size() > 0) {
BIHNode node = stack.remove(stack.size() - 1).node;
while (node.axis != 3){ while (node.axis != 3) {
int a = node.axis; int a = node.axis;
float maxExt = maxExts[a]; float maxExt = maxExts[a];
float minExt = minExts[a]; float minExt = minExts[a];
if (node.leftPlane < node.rightPlane){ if (node.leftPlane < node.rightPlane) {
// means there's a gap in the middle // means there's a gap in the middle
// if the box is in that gap, we stop there // if the box is in that gap, we stop there
if (minExt > node.leftPlane if (minExt > node.leftPlane
&& maxExt < node.rightPlane) && maxExt < node.rightPlane) {
continue stackloop; continue stackloop;
} }
}
if (maxExt < node.rightPlane){ if (maxExt < node.rightPlane) {
node = node.left; node = node.left;
}else if (minExt > node.leftPlane){ } else if (minExt > node.leftPlane) {
node = node.right; node = node.right;
}else{ } else {
stack.add(new BIHStackData(node.right, 0, 0)); stack.add(new BIHStackData(node.right, 0, 0));
node = node.left; node = node.left;
} }
@ -207,9 +207,9 @@ public final class BIHNode implements Savable {
// } // }
} }
for (int i = node.leftIndex; i <= node.rightIndex; i++){ for (int i = node.leftIndex; i <= node.rightIndex; i++) {
tree.getTriangle(i, t.get1(), t.get2(), t.get3()); tree.getTriangle(i, t.get1(), t.get2(), t.get3());
if (worldMatrix != null){ if (worldMatrix != null) {
worldMatrix.mult(t.get1(), t.get1()); worldMatrix.mult(t.get1(), t.get1());
worldMatrix.mult(t.get2(), t.get2()); worldMatrix.mult(t.get2(), t.get2());
worldMatrix.mult(t.get3(), t.get3()); worldMatrix.mult(t.get3(), t.get3());
@ -217,11 +217,11 @@ public final class BIHNode implements Savable {
int added = col.collideWith(t, results); int added = col.collideWith(t, results);
if (added > 0){ if (added > 0) {
int index = tree.getTriangleIndex(i); int index = tree.getTriangleIndex(i);
int start = results.size() - added; int start = results.size() - added;
for (int j = start; j < results.size(); j++){ for (int j = start; j < results.size(); j++) {
CollisionResult cr = results.getCollisionDirect(j); CollisionResult cr = results.getCollisionDirect(j);
cr.setTriangleIndex(index); cr.setTriangleIndex(index);
} }
@ -230,7 +230,7 @@ public final class BIHNode implements Savable {
} }
} }
} }
vars.release();
return cols; return cols;
} }
@ -239,7 +239,7 @@ public final class BIHNode implements Savable {
BIHTree tree, BIHTree tree,
float sceneMin, float sceneMin,
float sceneMax, float sceneMax,
CollisionResults results){ CollisionResults results) {
float tHit = Float.POSITIVE_INFINITY; float tHit = Float.POSITIVE_INFINITY;
Vector3f v1 = new Vector3f(), Vector3f v1 = new Vector3f(),
@ -248,15 +248,18 @@ public final class BIHNode implements Savable {
int cols = 0; int cols = 0;
ArrayList<BIHStackData> stack = TempVars.get().bihStack; TempVars vars = TempVars.get();
ArrayList<BIHStackData> stack = vars.bihStack;
stack.clear(); stack.clear();
stack.add(new BIHStackData(this, 0, 0)); stack.add(new BIHStackData(this, 0, 0));
stackloop: while (stack.size() > 0){ stackloop:
while (stack.size() > 0) {
BIHStackData data = stack.remove(stack.size()-1); BIHStackData data = stack.remove(stack.size() - 1);
BIHNode node = data.node; BIHNode node = data.node;
leafloop: while (node.axis != 3){ // while node is not a leaf leafloop:
while (node.axis != 3) { // while node is not a leaf
BIHNode nearNode, farNode; BIHNode nearNode, farNode;
nearNode = node.left; nearNode = node.left;
farNode = node.right; farNode = node.right;
@ -266,29 +269,27 @@ public final class BIHNode implements Savable {
} }
// a leaf // a leaf
for (int i = node.leftIndex; i <= node.rightIndex; i++){ for (int i = node.leftIndex; i <= node.rightIndex; i++) {
tree.getTriangle(i, v1,v2,v3); tree.getTriangle(i, v1, v2, v3);
if (worldMatrix != null){ if (worldMatrix != null) {
worldMatrix.mult(v1, v1); worldMatrix.mult(v1, v1);
worldMatrix.mult(v2, v2); worldMatrix.mult(v2, v2);
worldMatrix.mult(v3, v3); worldMatrix.mult(v3, v3);
} }
float t = r.intersects(v1,v2,v3); float t = r.intersects(v1, v2, v3);
if (t < tHit){ if (t < tHit) {
tHit = t; tHit = t;
Vector3f contactPoint = new Vector3f(r.direction) Vector3f contactPoint = new Vector3f(r.direction).multLocal(tHit).addLocal(r.origin);
.multLocal(tHit)
.addLocal(r.origin);
CollisionResult cr = new CollisionResult(contactPoint, tHit); CollisionResult cr = new CollisionResult(contactPoint, tHit);
cr.setTriangleIndex(tree.getTriangleIndex(i)); cr.setTriangleIndex(tree.getTriangleIndex(i));
results.addCollision(cr); results.addCollision(cr);
cols ++; cols++;
} }
} }
} }
vars.release();
return cols; return cols;
} }
@ -297,9 +298,10 @@ public final class BIHNode implements Savable {
BIHTree tree, BIHTree tree,
float sceneMin, float sceneMin,
float sceneMax, float sceneMax,
CollisionResults results){ CollisionResults results) {
ArrayList<BIHStackData> stack = TempVars.get().bihStack; TempVars vars = TempVars.get();
ArrayList<BIHStackData> stack = vars.bihStack;
stack.clear(); stack.clear();
// float tHit = Float.POSITIVE_INFINITY; // float tHit = Float.POSITIVE_INFINITY;
@ -315,13 +317,13 @@ public final class BIHNode implements Savable {
inv.multNormal(r.getDirection(), r.getDirection()); inv.multNormal(r.getDirection(), r.getDirection());
// inv.multNormalAcross(r.getDirection(), r.getDirection()); // inv.multNormalAcross(r.getDirection(), r.getDirection());
float[] origins = { r.getOrigin().x, float[] origins = {r.getOrigin().x,
r.getOrigin().y, r.getOrigin().y,
r.getOrigin().z }; r.getOrigin().z};
float[] invDirections = { 1f / r.getDirection().x, float[] invDirections = {1f / r.getDirection().x,
1f / r.getDirection().y, 1f / r.getDirection().y,
1f / r.getDirection().z }; 1f / r.getDirection().z};
r.getDirection().normalizeLocal(); r.getDirection().normalizeLocal();
@ -331,17 +333,20 @@ public final class BIHNode implements Savable {
int cols = 0; int cols = 0;
stack.add(new BIHStackData(this, sceneMin, sceneMax)); stack.add(new BIHStackData(this, sceneMin, sceneMax));
stackloop: while (stack.size() > 0){ stackloop:
while (stack.size() > 0) {
BIHStackData data = stack.remove(stack.size()-1); BIHStackData data = stack.remove(stack.size() - 1);
BIHNode node = data.node; BIHNode node = data.node;
float tMin = data.min, float tMin = data.min,
tMax = data.max; tMax = data.max;
if (tMax < tMin) if (tMax < tMin) {
continue; continue;
}
leafloop: while (node.axis != 3){ // while node is not a leaf leafloop:
while (node.axis != 3) { // while node is not a leaf
int a = node.axis; int a = node.axis;
// find the origin and direction value for the given axis // find the origin and direction value for the given axis
@ -356,7 +361,7 @@ public final class BIHNode implements Savable {
nearNode = node.left; nearNode = node.left;
farNode = node.right; farNode = node.right;
if (invDirection < 0){ if (invDirection < 0) {
float tmpSplit = tNearSplit; float tmpSplit = tNearSplit;
tNearSplit = tFarSplit; tNearSplit = tFarSplit;
tFarSplit = tmpSplit; tFarSplit = tmpSplit;
@ -366,17 +371,17 @@ public final class BIHNode implements Savable {
farNode = tmpNode; farNode = tmpNode;
} }
if (tMin > tNearSplit && tMax < tFarSplit){ if (tMin > tNearSplit && tMax < tFarSplit) {
continue stackloop; continue stackloop;
} }
if (tMin > tNearSplit){ if (tMin > tNearSplit) {
tMin = max(tMin, tFarSplit); tMin = max(tMin, tFarSplit);
node = farNode; node = farNode;
}else if (tMax < tFarSplit){ } else if (tMax < tFarSplit) {
tMax = min(tMax, tNearSplit); tMax = min(tMax, tNearSplit);
node = nearNode; node = nearNode;
}else{ } else {
stack.add(new BIHStackData(farNode, max(tMin, tFarSplit), tMax)); stack.add(new BIHStackData(farNode, max(tMin, tFarSplit), tMax));
tMax = min(tMax, tNearSplit); tMax = min(tMax, tNearSplit);
node = nearNode; node = nearNode;
@ -391,38 +396,35 @@ public final class BIHNode implements Savable {
// } // }
// a leaf // a leaf
for (int i = node.leftIndex; i <= node.rightIndex; i++){ for (int i = node.leftIndex; i <= node.rightIndex; i++) {
tree.getTriangle(i, v1,v2,v3); tree.getTriangle(i, v1, v2, v3);
float t = r.intersects(v1,v2,v3); float t = r.intersects(v1, v2, v3);
if (!Float.isInfinite(t)){ if (!Float.isInfinite(t)) {
if (worldMatrix != null) { if (worldMatrix != null) {
worldMatrix.mult(v1, v1); worldMatrix.mult(v1, v1);
worldMatrix.mult(v2, v2); worldMatrix.mult(v2, v2);
worldMatrix.mult(v3, v3); worldMatrix.mult(v3, v3);
float t_world = new Ray(o,d).intersects(v1,v2,v3); float t_world = new Ray(o, d).intersects(v1, v2, v3);
t = t_world; t = t_world;
} }
Vector3f contactNormal = Triangle.computeTriangleNormal(v1, v2, v3, null); Vector3f contactNormal = Triangle.computeTriangleNormal(v1, v2, v3, null);
Vector3f contactPoint = new Vector3f(d) Vector3f contactPoint = new Vector3f(d).multLocal(t).addLocal(o);
.multLocal(t)
.addLocal(o);
float worldSpaceDist = o.distance(contactPoint); float worldSpaceDist = o.distance(contactPoint);
CollisionResult cr = new CollisionResult(contactPoint, worldSpaceDist); CollisionResult cr = new CollisionResult(contactPoint, worldSpaceDist);
cr.setContactNormal(contactNormal); cr.setContactNormal(contactNormal);
cr.setTriangleIndex(tree.getTriangleIndex(i)); cr.setTriangleIndex(tree.getTriangleIndex(i));
results.addCollision(cr); results.addCollision(cr);
cols ++; cols++;
} }
} }
} }
vars.release();
r.setOrigin(o); r.setOrigin(o);
r.setDirection(d); r.setDirection(d);
return cols; return cols;
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.collision.bih; package com.jme3.collision.bih;
import com.jme3.scene.mesh.VirtualIndexBuffer; import com.jme3.scene.mesh.VirtualIndexBuffer;
@ -64,18 +63,14 @@ public class BIHTree implements CollisionData {
public static final int MAX_TREE_DEPTH = 100; public static final int MAX_TREE_DEPTH = 100;
public static final int MAX_TRIS_PER_NODE = 21; public static final int MAX_TRIS_PER_NODE = 21;
private Mesh mesh; private Mesh mesh;
private BIHNode root; private BIHNode root;
private int maxTrisPerNode; private int maxTrisPerNode;
private int numTris; private int numTris;
private float[] pointData; private float[] pointData;
private int[] triIndices; private int[] triIndices;
private transient CollisionResults boundResults = new CollisionResults(); private transient CollisionResults boundResults = new CollisionResults();
private transient float[] bihSwapTmp; private transient float[] bihSwapTmp;
private static final TriangleAxisComparator[] comparators = new TriangleAxisComparator[3]; private static final TriangleAxisComparator[] comparators = new TriangleAxisComparator[3];
static { static {
@ -84,45 +79,47 @@ public class BIHTree implements CollisionData {
comparators[2] = new TriangleAxisComparator(2); comparators[2] = new TriangleAxisComparator(2);
} }
private void initTriList(FloatBuffer vb, IndexBuffer ib){ private void initTriList(FloatBuffer vb, IndexBuffer ib) {
pointData = new float[numTris * 3 * 3]; pointData = new float[numTris * 3 * 3];
int p = 0; int p = 0;
for (int i = 0; i < numTris*3; i+=3){ for (int i = 0; i < numTris * 3; i += 3) {
int vert = ib.get(i)*3; int vert = ib.get(i) * 3;
pointData[p++] = vb.get(vert++); pointData[p++] = vb.get(vert++);
pointData[p++] = vb.get(vert++); pointData[p++] = vb.get(vert++);
pointData[p++] = vb.get(vert); pointData[p++] = vb.get(vert);
vert = ib.get(i+1)*3; vert = ib.get(i + 1) * 3;
pointData[p++] = vb.get(vert++); pointData[p++] = vb.get(vert++);
pointData[p++] = vb.get(vert++); pointData[p++] = vb.get(vert++);
pointData[p++] = vb.get(vert); pointData[p++] = vb.get(vert);
vert = ib.get(i+2)*3; vert = ib.get(i + 2) * 3;
pointData[p++] = vb.get(vert++); pointData[p++] = vb.get(vert++);
pointData[p++] = vb.get(vert++); pointData[p++] = vb.get(vert++);
pointData[p++] = vb.get(vert); pointData[p++] = vb.get(vert);
} }
triIndices = new int[numTris]; triIndices = new int[numTris];
for (int i = 0; i < numTris; i++) for (int i = 0; i < numTris; i++) {
triIndices[i] = i; triIndices[i] = i;
} }
}
public BIHTree(Mesh mesh, int maxTrisPerNode){ public BIHTree(Mesh mesh, int maxTrisPerNode) {
this.mesh = mesh; this.mesh = mesh;
this.maxTrisPerNode = maxTrisPerNode; this.maxTrisPerNode = maxTrisPerNode;
if (maxTrisPerNode < 1 || mesh == null) if (maxTrisPerNode < 1 || mesh == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
}
bihSwapTmp = new float[9]; bihSwapTmp = new float[9];
FloatBuffer vb = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); FloatBuffer vb = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
IndexBuffer ib = mesh.getIndexBuffer(); IndexBuffer ib = mesh.getIndexBuffer();
if (ib == null){ if (ib == null) {
ib = new VirtualIndexBuffer(mesh.getVertexCount(), mesh.getMode()); ib = new VirtualIndexBuffer(mesh.getVertexCount(), mesh.getMode());
}else if (mesh.getMode() != Mode.Triangles){ } else if (mesh.getMode() != Mode.Triangles) {
ib = new WrappedIndexBuffer(mesh); ib = new WrappedIndexBuffer(mesh);
} }
@ -130,21 +127,21 @@ public class BIHTree implements CollisionData {
initTriList(vb, ib); initTriList(vb, ib);
} }
public BIHTree(Mesh mesh){ public BIHTree(Mesh mesh) {
this(mesh, MAX_TRIS_PER_NODE); this(mesh, MAX_TRIS_PER_NODE);
} }
public BIHTree(){ public BIHTree() {
} }
public void construct(){ public void construct() {
BoundingBox sceneBbox = createBox(0, numTris-1); BoundingBox sceneBbox = createBox(0, numTris - 1);
root = createNode(0, numTris-1, sceneBbox, 0); root = createNode(0, numTris - 1, sceneBbox, 0);
} }
private BoundingBox createBox(int l, int r) { private BoundingBox createBox(int l, int r) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f min = vars.vect1.set(new Vector3f(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)); Vector3f min = vars.vect1.set(new Vector3f(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY));
Vector3f max = vars.vect2.set(new Vector3f(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY)); Vector3f max = vars.vect2.set(new Vector3f(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY));
@ -153,65 +150,67 @@ public class BIHTree implements CollisionData {
v3 = vars.vect5; v3 = vars.vect5;
for (int i = l; i <= r; i++) { for (int i = l; i <= r; i++) {
getTriangle(i, v1,v2,v3); getTriangle(i, v1, v2, v3);
BoundingBox.checkMinMax(min, max, v1); BoundingBox.checkMinMax(min, max, v1);
BoundingBox.checkMinMax(min, max, v2); BoundingBox.checkMinMax(min, max, v2);
BoundingBox.checkMinMax(min, max, v3); BoundingBox.checkMinMax(min, max, v3);
} }
BoundingBox bbox = new BoundingBox(min,max); BoundingBox bbox = new BoundingBox(min, max);
assert vars.unlock(); vars.release();
return bbox; return bbox;
} }
int getTriangleIndex(int triIndex){ int getTriangleIndex(int triIndex) {
return triIndices[triIndex]; return triIndices[triIndex];
} }
private int sortTriangles(int l, int r, float split, int axis){ private int sortTriangles(int l, int r, float split, int axis) {
int pivot = l; int pivot = l;
int j = r; int j = r;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f v1 = vars.vect1, Vector3f v1 = vars.vect1,
v2 = vars.vect2, v2 = vars.vect2,
v3 = vars.vect3; v3 = vars.vect3;
while (pivot <= j){ while (pivot <= j) {
getTriangle(pivot, v1, v2, v3); getTriangle(pivot, v1, v2, v3);
v1.addLocal(v2).addLocal(v3).multLocal(FastMath.ONE_THIRD); v1.addLocal(v2).addLocal(v3).multLocal(FastMath.ONE_THIRD);
if (v1.get(axis) > split){ if (v1.get(axis) > split) {
swapTriangles(pivot, j); swapTriangles(pivot, j);
--j; --j;
}else{ } else {
++pivot; ++pivot;
} }
} }
assert vars.unlock(); vars.release();
pivot = (pivot == l && j < pivot) ? j : pivot; pivot = (pivot == l && j < pivot) ? j : pivot;
return pivot; return pivot;
} }
private void setMinMax(BoundingBox bbox, boolean doMin, int axis, float value){ private void setMinMax(BoundingBox bbox, boolean doMin, int axis, float value) {
Vector3f min = bbox.getMin(null); Vector3f min = bbox.getMin(null);
Vector3f max = bbox.getMax(null); Vector3f max = bbox.getMax(null);
if (doMin) if (doMin) {
min.set(axis, value); min.set(axis, value);
else } else {
max.set(axis, value); max.set(axis, value);
}
bbox.setMinMax(min, max); bbox.setMinMax(min, max);
} }
private float getMinMax(BoundingBox bbox, boolean doMin, int axis){ private float getMinMax(BoundingBox bbox, boolean doMin, int axis) {
if (doMin) if (doMin) {
return bbox.getMin(null).get(axis); return bbox.getMin(null).get(axis);
else } else {
return bbox.getMax(null).get(axis); return bbox.getMax(null).get(axis);
} }
}
// private BIHNode createNode2(int l, int r, BoundingBox nodeBbox, int depth){ // private BIHNode createNode2(int l, int r, BoundingBox nodeBbox, int depth){
// if ((r - l) < maxTrisPerNode || depth > 100) // if ((r - l) < maxTrisPerNode || depth > 100)
@ -290,9 +289,8 @@ public class BIHTree implements CollisionData {
// //
// return node; // return node;
// } // }
private BIHNode createNode(int l, int r, BoundingBox nodeBbox, int depth) { private BIHNode createNode(int l, int r, BoundingBox nodeBbox, int depth) {
if ((r - l) < maxTrisPerNode || depth > MAX_TREE_DEPTH){ if ((r - l) < maxTrisPerNode || depth > MAX_TREE_DEPTH) {
return new BIHNode(l, r); return new BIHNode(l, r);
} }
@ -303,38 +301,42 @@ public class BIHTree implements CollisionData {
exteriorExt.subtractLocal(interiorExt); exteriorExt.subtractLocal(interiorExt);
int axis = 0; int axis = 0;
if (exteriorExt.x > exteriorExt.y){ if (exteriorExt.x > exteriorExt.y) {
if (exteriorExt.x > exteriorExt.z) if (exteriorExt.x > exteriorExt.z) {
axis = 0; axis = 0;
else } else {
axis = 2; axis = 2;
}else{ }
if (exteriorExt.y > exteriorExt.z) } else {
if (exteriorExt.y > exteriorExt.z) {
axis = 1; axis = 1;
else } else {
axis = 2; axis = 2;
} }
if (exteriorExt.equals(Vector3f.ZERO)) }
if (exteriorExt.equals(Vector3f.ZERO)) {
axis = 0; axis = 0;
}
// Arrays.sort(tris, l, r, comparators[axis]); // Arrays.sort(tris, l, r, comparators[axis]);
float split = currentBox.getCenter().get(axis); float split = currentBox.getCenter().get(axis);
int pivot = sortTriangles(l, r, split, axis); int pivot = sortTriangles(l, r, split, axis);
if (pivot == l || pivot == r) if (pivot == l || pivot == r) {
pivot = (r + l) / 2; pivot = (r + l) / 2;
}
//If one of the partitions is empty, continue with recursion: same level but different bbox //If one of the partitions is empty, continue with recursion: same level but different bbox
if (pivot < l){ if (pivot < l) {
//Only right //Only right
BoundingBox rbbox = new BoundingBox(currentBox); BoundingBox rbbox = new BoundingBox(currentBox);
setMinMax(rbbox, true, axis, split); setMinMax(rbbox, true, axis, split);
return createNode(l, r, rbbox, depth+1); return createNode(l, r, rbbox, depth + 1);
}else if (pivot > r){ } else if (pivot > r) {
//Only left //Only left
BoundingBox lbbox = new BoundingBox(currentBox); BoundingBox lbbox = new BoundingBox(currentBox);
setMinMax(lbbox, false, axis, split); setMinMax(lbbox, false, axis, split);
return createNode(l, r, lbbox, depth+1); return createNode(l, r, lbbox, depth + 1);
}else{ } else {
//Build the node //Build the node
BIHNode node = new BIHNode(axis); BIHNode node = new BIHNode(axis);
@ -343,21 +345,21 @@ public class BIHTree implements CollisionData {
setMinMax(lbbox, false, axis, split); setMinMax(lbbox, false, axis, split);
//The left node right border is the plane most right //The left node right border is the plane most right
node.setLeftPlane( getMinMax(createBox(l, max(l, pivot - 1)), false, axis) ); node.setLeftPlane(getMinMax(createBox(l, max(l, pivot - 1)), false, axis));
node.setLeftChild( createNode(l, max(l, pivot - 1), lbbox, depth+1) ); //Recursive call node.setLeftChild(createNode(l, max(l, pivot - 1), lbbox, depth + 1)); //Recursive call
//Right Child //Right Child
BoundingBox rbbox = new BoundingBox(currentBox); BoundingBox rbbox = new BoundingBox(currentBox);
setMinMax(rbbox, true, axis, split); setMinMax(rbbox, true, axis, split);
//The right node left border is the plane most left //The right node left border is the plane most left
node.setRightPlane( getMinMax(createBox(pivot, r), true, axis) ); node.setRightPlane(getMinMax(createBox(pivot, r), true, axis));
node.setRightChild( createNode(pivot, r, rbbox, depth+1) ); //Recursive call node.setRightChild(createNode(pivot, r, rbbox, depth + 1)); //Recursive call
return node; return node;
} }
} }
public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3){ public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3) {
int pointIndex = index * 9; int pointIndex = index * 9;
v1.x = pointData[pointIndex++]; v1.x = pointData[pointIndex++];
@ -373,7 +375,7 @@ public class BIHTree implements CollisionData {
v3.z = pointData[pointIndex++]; v3.z = pointData[pointIndex++];
} }
public void swapTriangles(int index1, int index2){ public void swapTriangles(int index1, int index2) {
int p1 = index1 * 9; int p1 = index1 * 9;
int p2 = index2 * 9; int p2 = index2 * 9;
@ -395,23 +397,25 @@ public class BIHTree implements CollisionData {
private int collideWithRay(Ray r, private int collideWithRay(Ray r,
Matrix4f worldMatrix, Matrix4f worldMatrix,
BoundingVolume worldBound, BoundingVolume worldBound,
CollisionResults results){ CollisionResults results) {
boundResults.clear(); boundResults.clear();
worldBound.collideWith(r, boundResults); worldBound.collideWith(r, boundResults);
if (boundResults.size() > 0){ if (boundResults.size() > 0) {
float tMin = boundResults.getClosestCollision().getDistance(); float tMin = boundResults.getClosestCollision().getDistance();
float tMax = boundResults.getFarthestCollision().getDistance(); float tMax = boundResults.getFarthestCollision().getDistance();
if (tMax <= 0) if (tMax <= 0) {
tMax = Float.POSITIVE_INFINITY; tMax = Float.POSITIVE_INFINITY;
else if (tMin == tMax) } else if (tMin == tMax) {
tMin = 0; tMin = 0;
}
if (tMin <= 0) if (tMin <= 0) {
tMin = 0; tMin = 0;
}
if (r.getLimit() < Float.POSITIVE_INFINITY){ if (r.getLimit() < Float.POSITIVE_INFINITY) {
tMax = Math.min(tMax, r.getLimit()); tMax = Math.min(tMax, r.getLimit());
} }
@ -423,16 +427,16 @@ public class BIHTree implements CollisionData {
private int collideWithBoundingVolume(BoundingVolume bv, private int collideWithBoundingVolume(BoundingVolume bv,
Matrix4f worldMatrix, Matrix4f worldMatrix,
CollisionResults results){ CollisionResults results) {
BoundingBox bbox; BoundingBox bbox;
if (bv instanceof BoundingSphere){ if (bv instanceof BoundingSphere) {
BoundingSphere sphere = (BoundingSphere) bv; BoundingSphere sphere = (BoundingSphere) bv;
bbox = new BoundingBox(bv.getCenter().clone(), sphere.getRadius(), bbox = new BoundingBox(bv.getCenter().clone(), sphere.getRadius(),
sphere.getRadius(), sphere.getRadius(),
sphere.getRadius()); sphere.getRadius());
}else if (bv instanceof BoundingBox){ } else if (bv instanceof BoundingBox) {
bbox = new BoundingBox( (BoundingBox) bv ); bbox = new BoundingBox((BoundingBox) bv);
}else{ } else {
throw new UnsupportedCollisionException(); throw new UnsupportedCollisionException();
} }
@ -443,15 +447,15 @@ public class BIHTree implements CollisionData {
public int collideWith(Collidable other, public int collideWith(Collidable other,
Matrix4f worldMatrix, Matrix4f worldMatrix,
BoundingVolume worldBound, BoundingVolume worldBound,
CollisionResults results){ CollisionResults results) {
if (other instanceof Ray){ if (other instanceof Ray) {
Ray ray = (Ray) other; Ray ray = (Ray) other;
return collideWithRay(ray, worldMatrix, worldBound, results); return collideWithRay(ray, worldMatrix, worldBound, results);
}else if (other instanceof BoundingVolume){ } else if (other instanceof BoundingVolume) {
BoundingVolume bv = (BoundingVolume) other; BoundingVolume bv = (BoundingVolume) other;
return collideWithBoundingVolume(bv, worldMatrix, results); return collideWithBoundingVolume(bv, worldMatrix, results);
}else{ } else {
throw new UnsupportedCollisionException(); throw new UnsupportedCollisionException();
} }
} }
@ -473,5 +477,4 @@ public class BIHTree implements CollisionData {
pointData = ic.readFloatArray("points", null); pointData = ic.readFloatArray("points", null);
triIndices = ic.readIntArray("indices", null); triIndices = ic.readIntArray("indices", null);
} }
} }

@ -75,7 +75,6 @@ public class ParticleEmitter extends Geometry {
private static final EmitterShape DEFAULT_SHAPE = new EmitterPointShape(Vector3f.ZERO); private static final EmitterShape DEFAULT_SHAPE = new EmitterPointShape(Vector3f.ZERO);
private static final ParticleInfluencer DEFAULT_INFLUENCER = new DefaultParticleInfluencer(); private static final ParticleInfluencer DEFAULT_INFLUENCER = new DefaultParticleInfluencer();
private ParticleEmitterControl control = new ParticleEmitterControl(); private ParticleEmitterControl control = new ParticleEmitterControl();
private EmitterShape shape = DEFAULT_SHAPE; private EmitterShape shape = DEFAULT_SHAPE;
private ParticleMesh particleMesh; private ParticleMesh particleMesh;
@ -110,7 +109,7 @@ public class ParticleEmitter extends Geometry {
private class ParticleEmitterControl implements Control { private class ParticleEmitterControl implements Control {
public Control cloneForSpatial(Spatial spatial) { public Control cloneForSpatial(Spatial spatial) {
return ((ParticleEmitter)spatial).control; return ((ParticleEmitter) spatial).control;
} }
public void setSpatial(Spatial spatial) { public void setSpatial(Spatial spatial) {
@ -139,7 +138,6 @@ public class ParticleEmitter extends Geometry {
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
// the data is not written here // the data is not written here
} }
} }
@Override @Override
@ -199,7 +197,6 @@ public class ParticleEmitter extends Geometry {
this.shape = shape; this.shape = shape;
} }
public EmitterShape getShape() { public EmitterShape getShape() {
return shape; return shape;
} }
@ -838,7 +835,7 @@ public class ParticleEmitter extends Geometry {
this.getWorldTransform(); this.getWorldTransform();
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
BoundingBox bbox = (BoundingBox) this.getMesh().getBound(); BoundingBox bbox = (BoundingBox) this.getMesh().getBound();
@ -862,7 +859,7 @@ public class ParticleEmitter extends Geometry {
bbox.setMinMax(min, max); bbox.setMinMax(min, max);
this.setBoundRefresh(); this.setBoundRefresh();
assert vars.unlock(); vars.release();
} }
/** /**
@ -909,7 +906,7 @@ public class ParticleEmitter extends Geometry {
this.getWorldTransform(); this.getWorldTransform();
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f min = vars.vect1.set(Vector3f.POSITIVE_INFINITY); Vector3f min = vars.vect1.set(Vector3f.POSITIVE_INFINITY);
Vector3f max = vars.vect2.set(Vector3f.NEGATIVE_INFINITY); Vector3f max = vars.vect2.set(Vector3f.NEGATIVE_INFINITY);
@ -979,7 +976,7 @@ public class ParticleEmitter extends Geometry {
bbox.setMinMax(min, max); bbox.setMinMax(min, max);
this.setBoundRefresh(); this.setBoundRefresh();
assert vars.unlock(); vars.release();
} }
/** /**
@ -1033,14 +1030,15 @@ public class ParticleEmitter extends Geometry {
} }
Matrix3f inverseRotation = Matrix3f.IDENTITY; Matrix3f inverseRotation = Matrix3f.IDENTITY;
TempVars vars = null;
if (!worldSpace) { if (!worldSpace) {
TempVars vars = TempVars.get(); vars = TempVars.get();
assert vars.lock();
inverseRotation = this.getWorldRotation().toRotationMatrix(vars.tempMat3).invertLocal(); inverseRotation = this.getWorldRotation().toRotationMatrix(vars.tempMat3).invertLocal();
} }
particleMesh.updateParticleData(particles, cam, inverseRotation); particleMesh.updateParticleData(particles, cam, inverseRotation);
if (!worldSpace) { if (!worldSpace) {
assert TempVars.get().unlock(); vars.release();
} }
} }
@ -1123,9 +1121,9 @@ public class ParticleEmitter extends Geometry {
// compatibility before the control inside particle emitter // compatibility before the control inside particle emitter
// was changed: // was changed:
// find it in the controls and take it out, then add the proper one in // find it in the controls and take it out, then add the proper one in
for (int i = 0; i < controls.size(); i++){ for (int i = 0; i < controls.size(); i++) {
Object obj = controls.get(i); Object obj = controls.get(i);
if (obj instanceof ParticleEmitter){ if (obj instanceof ParticleEmitter) {
controls.remove(i); controls.remove(i);
// now add the proper one in // now add the proper one in
controls.add(control); controls.add(control);
@ -1134,7 +1132,7 @@ public class ParticleEmitter extends Geometry {
} }
// compatability before gravity was not a vector but a float // compatability before gravity was not a vector but a float
if (gravity == null){ if (gravity == null) {
gravity = new Vector3f(); gravity = new Vector3f();
gravity.y = ic.readFloat("gravity", 0); gravity.y = ic.readFloat("gravity", 0);
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.math; package com.jme3.math;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
@ -113,7 +112,7 @@ public class Line implements Savable, Cloneable {
public float distanceSquared(Vector3f point) { public float distanceSquared(Vector3f point) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f compVec1 = vars.vect1; Vector3f compVec1 = vars.vect1;
Vector3f compVec2 = vars.vect2; Vector3f compVec2 = vars.vect2;
@ -122,7 +121,7 @@ public class Line implements Savable, Cloneable {
origin.add(direction.mult(lineParameter, compVec2), compVec2); origin.add(direction.mult(lineParameter, compVec2), compVec2);
compVec2.subtract(point, compVec1); compVec2.subtract(point, compVec1);
float len = compVec1.lengthSquared(); float len = compVec1.lengthSquared();
assert vars.unlock(); vars.release();
return len; return len;
} }
@ -136,7 +135,7 @@ public class Line implements Savable, Cloneable {
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f compVec1 = vars.vect1; Vector3f compVec1 = vars.vect1;
Vector3f compVec2 = vars.vect2; Vector3f compVec2 = vars.vect2;
Matrix3f compMat1 = vars.tempMat3; Matrix3f compMat1 = vars.tempMat3;
@ -185,7 +184,7 @@ public class Line implements Savable, Cloneable {
compEigen1.calculateEigen(compMat1); compEigen1.calculateEigen(compMat1);
direction = compEigen1.getEigenVector(0); direction = compEigen1.getEigenVector(0);
assert vars.unlock(); vars.release();
} }
/** /**
@ -224,8 +223,8 @@ public class Line implements Savable, Cloneable {
public void read(JmeImporter e) throws IOException { public void read(JmeImporter e) throws IOException {
InputCapsule capsule = e.getCapsule(this); InputCapsule capsule = e.getCapsule(this);
origin = (Vector3f)capsule.readSavable("origin", Vector3f.ZERO.clone()); origin = (Vector3f) capsule.readSavable("origin", Vector3f.ZERO.clone());
direction = (Vector3f)capsule.readSavable("direction", Vector3f.ZERO.clone()); direction = (Vector3f) capsule.readSavable("direction", Vector3f.ZERO.clone());
} }
@Override @Override

@ -110,8 +110,8 @@ public class LineSegment implements Cloneable, Savable {
} }
public float distanceSquared(Vector3f point) { public float distanceSquared(Vector3f point) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f compVec1 = TempVars.get().vect1; Vector3f compVec1 = vars.vect1;
point.subtract(origin, compVec1); point.subtract(origin, compVec1);
float segmentParameter = direction.dot(compVec1); float segmentParameter = direction.dot(compVec1);
@ -129,20 +129,20 @@ public class LineSegment implements Cloneable, Savable {
compVec1.subtractLocal(point); compVec1.subtractLocal(point);
float len = compVec1.lengthSquared(); float len = compVec1.lengthSquared();
assert TempVars.get().unlock(); vars.release();
return len; return len;
} }
public float distanceSquared(LineSegment test) { public float distanceSquared(LineSegment test) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f compVec1 = TempVars.get().vect1; Vector3f compVec1 = vars.vect1;
origin.subtract(test.getOrigin(), compVec1); origin.subtract(test.getOrigin(), compVec1);
float negativeDirectionDot = -(direction.dot(test.getDirection())); float negativeDirectionDot = -(direction.dot(test.getDirection()));
float diffThisDot = compVec1.dot(direction); float diffThisDot = compVec1.dot(direction);
float diffTestDot = -(compVec1.dot(test.getDirection())); float diffTestDot = -(compVec1.dot(test.getDirection()));
float lengthOfDiff = compVec1.lengthSquared(); float lengthOfDiff = compVec1.lengthSquared();
assert TempVars.get().unlock(); vars.release();
float determinant = FastMath.abs(1.0f - negativeDirectionDot float determinant = FastMath.abs(1.0f - negativeDirectionDot
* negativeDirectionDot); * negativeDirectionDot);
float s0, s1, squareDistance, extentDeterminant0, extentDeterminant1, tempS0, tempS1; float s0, s1, squareDistance, extentDeterminant0, extentDeterminant1, tempS0, tempS1;

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.math; package com.jme3.math;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
@ -55,12 +54,10 @@ import java.util.logging.Logger;
public final class Matrix3f implements Savable, Cloneable { public final class Matrix3f implements Savable, Cloneable {
private static final Logger logger = Logger.getLogger(Matrix3f.class.getName()); private static final Logger logger = Logger.getLogger(Matrix3f.class.getName());
protected float m00, m01, m02; protected float m00, m01, m02;
protected float m10, m11, m12; protected float m10, m11, m12;
protected float m20, m21, m22; protected float m20, m21, m22;
public static final Matrix3f ZERO = new Matrix3f(0, 0, 0, 0, 0, 0, 0, 0, 0);
public static final Matrix3f ZERO = new Matrix3f(0,0,0,0,0,0,0,0,0);
public static final Matrix3f IDENTITY = new Matrix3f(); public static final Matrix3f IDENTITY = new Matrix3f();
/** /**
@ -176,21 +173,30 @@ public final class Matrix3f implements Savable, Cloneable {
switch (i) { switch (i) {
case 0: case 0:
switch (j) { switch (j) {
case 0: return m00; case 0:
case 1: return m01; return m00;
case 2: return m02; case 1:
return m01;
case 2:
return m02;
} }
case 1: case 1:
switch (j) { switch (j) {
case 0: return m10; case 0:
case 1: return m11; return m10;
case 2: return m12; case 1:
return m11;
case 2:
return m12;
} }
case 2: case 2:
switch (j) { switch (j) {
case 0: return m20; case 0:
case 1: return m21; return m20;
case 2: return m22; case 1:
return m21;
case 2:
return m22;
} }
} }
@ -220,8 +226,7 @@ public final class Matrix3f implements Savable, Cloneable {
data[6] = m20; data[6] = m20;
data[7] = m21; data[7] = m21;
data[8] = m22; data[8] = m22;
} } else {
else {
data[0] = m00; data[0] = m00;
data[1] = m10; data[1] = m10;
data[2] = m20; data[2] = m20;
@ -232,8 +237,7 @@ public final class Matrix3f implements Savable, Cloneable {
data[7] = m12; data[7] = m12;
data[8] = m22; data[8] = m22;
} }
} } else if (data.length == 16) {
else if (data.length == 16) {
if (rowMajor) { if (rowMajor) {
data[0] = m00; data[0] = m00;
data[1] = m01; data[1] = m01;
@ -244,8 +248,7 @@ public final class Matrix3f implements Savable, Cloneable {
data[8] = m20; data[8] = m20;
data[9] = m21; data[9] = m21;
data[10] = m22; data[10] = m22;
} } else {
else {
data[0] = m00; data[0] = m00;
data[1] = m10; data[1] = m10;
data[2] = m20; data[2] = m20;
@ -256,8 +259,7 @@ public final class Matrix3f implements Savable, Cloneable {
data[9] = m12; data[9] = m12;
data[10] = m22; data[10] = m22;
} }
} } else {
else {
throw new IndexOutOfBoundsException("Array size must be 9 or 16 in Matrix3f.get()."); throw new IndexOutOfBoundsException("Array size must be 9 or 16 in Matrix3f.get().");
} }
} }
@ -286,7 +288,9 @@ public final class Matrix3f implements Savable, Cloneable {
* @return the column specified by the index. * @return the column specified by the index.
*/ */
public Vector3f getColumn(int i, Vector3f store) { public Vector3f getColumn(int i, Vector3f store) {
if (store == null) store = new Vector3f(); if (store == null) {
store = new Vector3f();
}
switch (i) { switch (i) {
case 0: case 0:
store.x = m00; store.x = m00;
@ -334,7 +338,9 @@ public final class Matrix3f implements Savable, Cloneable {
* @return the row specified by the index. * @return the row specified by the index.
*/ */
public Vector3f getRow(int i, Vector3f store) { public Vector3f getRow(int i, Vector3f store) {
if (store == null) store = new Vector3f(); if (store == null) {
store = new Vector3f();
}
switch (i) { switch (i) {
case 0: case 0:
store.x = m00; store.x = m00;
@ -396,17 +402,17 @@ public final class Matrix3f implements Savable, Cloneable {
// } // }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
fillFloatArray(vars.matrixWrite, columnMajor); fillFloatArray(vars.matrixWrite, columnMajor);
fb.put(vars.matrixWrite, 0, 9); fb.put(vars.matrixWrite, 0, 9);
assert vars.unlock(); vars.release();
return fb; return fb;
} }
public void fillFloatArray(float[] f, boolean columnMajor){ public void fillFloatArray(float[] f, boolean columnMajor) {
if (columnMajor) { if (columnMajor) {
f[ 0] = m00; f[ 0] = m00;
f[ 1] = m10; f[ 1] = m10;
@ -417,7 +423,7 @@ public final class Matrix3f implements Savable, Cloneable {
f[ 6] = m02; f[ 6] = m02;
f[ 7] = m12; f[ 7] = m12;
f[ 8] = m22; f[ 8] = m22;
}else{ } else {
f[ 0] = m00; f[ 0] = m00;
f[ 1] = m01; f[ 1] = m01;
f[ 2] = m02; f[ 2] = m02;
@ -470,7 +476,6 @@ public final class Matrix3f implements Savable, Cloneable {
return this; return this;
} }
/** /**
* *
* <code>setRow</code> sets a particular row of this matrix to that * <code>setRow</code> sets a particular row of this matrix to that
@ -529,21 +534,39 @@ public final class Matrix3f implements Savable, Cloneable {
switch (i) { switch (i) {
case 0: case 0:
switch (j) { switch (j) {
case 0: m00 = value; return this; case 0:
case 1: m01 = value; return this; m00 = value;
case 2: m02 = value; return this; return this;
case 1:
m01 = value;
return this;
case 2:
m02 = value;
return this;
} }
case 1: case 1:
switch (j) { switch (j) {
case 0: m10 = value; return this; case 0:
case 1: m11 = value; return this; m10 = value;
case 2: m12 = value; return this; return this;
case 1:
m11 = value;
return this;
case 2:
m12 = value;
return this;
} }
case 2: case 2:
switch (j) { switch (j) {
case 0: m20 = value; return this; case 0:
case 1: m21 = value; return this; m20 = value;
case 2: m22 = value; return this; return this;
case 1:
m21 = value;
return this;
case 2:
m22 = value;
return this;
} }
} }
@ -563,8 +586,10 @@ public final class Matrix3f implements Savable, Cloneable {
* @return this * @return this
*/ */
public Matrix3f set(float[][] matrix) { public Matrix3f set(float[][] matrix) {
if (matrix.length != 3 || matrix[0].length != 3) { throw new IllegalArgumentException( if (matrix.length != 3 || matrix[0].length != 3) {
"Array must be of size 9."); } throw new IllegalArgumentException(
"Array must be of size 9.");
}
m00 = matrix[0][0]; m00 = matrix[0][0];
m01 = matrix[0][1]; m01 = matrix[0][1];
@ -626,8 +651,10 @@ public final class Matrix3f implements Savable, Cloneable {
* @return this * @return this
*/ */
public Matrix3f set(float[] matrix, boolean rowMajor) { public Matrix3f set(float[] matrix, boolean rowMajor) {
if (matrix.length != 9) throw new IllegalArgumentException( if (matrix.length != 9) {
throw new IllegalArgumentException(
"Array must be of size 9."); "Array must be of size 9.");
}
if (rowMajor) { if (rowMajor) {
m00 = matrix[0]; m00 = matrix[0];
@ -681,10 +708,9 @@ public final class Matrix3f implements Savable, Cloneable {
* @return true if this matrix is identity * @return true if this matrix is identity
*/ */
public boolean isIdentity() { public boolean isIdentity() {
return return (m00 == 1 && m01 == 0 && m02 == 0)
(m00 == 1 && m01 == 0 && m02 == 0) && && (m10 == 0 && m11 == 1 && m12 == 0)
(m10 == 0 && m11 == 1 && m12 == 0) && && (m20 == 0 && m21 == 0 && m22 == 1);
(m20 == 0 && m21 == 0 && m22 == 1);
} }
/** /**
@ -714,26 +740,26 @@ public final class Matrix3f implements Savable, Cloneable {
public void fromAngleNormalAxis(float angle, Vector3f axis) { public void fromAngleNormalAxis(float angle, Vector3f axis) {
float fCos = FastMath.cos(angle); float fCos = FastMath.cos(angle);
float fSin = FastMath.sin(angle); float fSin = FastMath.sin(angle);
float fOneMinusCos = ((float)1.0)-fCos; float fOneMinusCos = ((float) 1.0) - fCos;
float fX2 = axis.x*axis.x; float fX2 = axis.x * axis.x;
float fY2 = axis.y*axis.y; float fY2 = axis.y * axis.y;
float fZ2 = axis.z*axis.z; float fZ2 = axis.z * axis.z;
float fXYM = axis.x*axis.y*fOneMinusCos; float fXYM = axis.x * axis.y * fOneMinusCos;
float fXZM = axis.x*axis.z*fOneMinusCos; float fXZM = axis.x * axis.z * fOneMinusCos;
float fYZM = axis.y*axis.z*fOneMinusCos; float fYZM = axis.y * axis.z * fOneMinusCos;
float fXSin = axis.x*fSin; float fXSin = axis.x * fSin;
float fYSin = axis.y*fSin; float fYSin = axis.y * fSin;
float fZSin = axis.z*fSin; float fZSin = axis.z * fSin;
m00 = fX2*fOneMinusCos+fCos; m00 = fX2 * fOneMinusCos + fCos;
m01 = fXYM-fZSin; m01 = fXYM - fZSin;
m02 = fXZM+fYSin; m02 = fXZM + fYSin;
m10 = fXYM+fZSin; m10 = fXYM + fZSin;
m11 = fY2*fOneMinusCos+fCos; m11 = fY2 * fOneMinusCos + fCos;
m12 = fYZM-fXSin; m12 = fYZM - fXSin;
m20 = fXZM-fYSin; m20 = fXZM - fYSin;
m21 = fYZM+fXSin; m21 = fYZM + fXSin;
m22 = fZ2*fOneMinusCos+fCos; m22 = fZ2 * fOneMinusCos + fCos;
} }
/** /**
@ -766,7 +792,9 @@ public final class Matrix3f implements Savable, Cloneable {
float temp10, temp11, temp12; float temp10, temp11, temp12;
float temp20, temp21, temp22; float temp20, temp21, temp22;
if (product == null) product = new Matrix3f(); if (product == null) {
product = new Matrix3f();
}
temp00 = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20; temp00 = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20;
temp01 = m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21; temp01 = m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21;
temp02 = m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22; temp02 = m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22;
@ -862,7 +890,9 @@ public final class Matrix3f implements Savable, Cloneable {
* @return The passed vector after multiplication * @return The passed vector after multiplication
*/ */
public Vector3f multLocal(Vector3f vec) { public Vector3f multLocal(Vector3f vec) {
if (vec == null) return null; if (vec == null) {
return null;
}
float x = vec.x; float x = vec.x;
float y = vec.y; float y = vec.y;
vec.x = m00 * x + m01 * y + m02 * vec.z; vec.x = m00 * x + m01 * y + m02 * vec.z;
@ -925,23 +955,26 @@ public final class Matrix3f implements Savable, Cloneable {
* @return The store * @return The store
*/ */
public Matrix3f invert(Matrix3f store) { public Matrix3f invert(Matrix3f store) {
if (store == null) store = new Matrix3f(); if (store == null) {
store = new Matrix3f();
}
float det = determinant(); float det = determinant();
if ( FastMath.abs(det) <= FastMath.FLT_EPSILON ) if (FastMath.abs(det) <= FastMath.FLT_EPSILON) {
return store.zero(); return store.zero();
}
store.m00 = m11 * m22 - m12 * m21;
store.m01 = m02 * m21 - m01 * m22;
store.m02 = m01 * m12 - m02 * m11;
store.m10 = m12 * m20 - m10 * m22;
store.m11 = m00 * m22 - m02 * m20;
store.m12 = m02 * m10 - m00 * m12;
store.m20 = m10 * m21 - m11 * m20;
store.m21 = m01 * m20 - m00 * m21;
store.m22 = m00 * m11 - m01 * m10;
store.m00 = m11*m22 - m12*m21; store.multLocal(1f / det);
store.m01 = m02*m21 - m01*m22;
store.m02 = m01*m12 - m02*m11;
store.m10 = m12*m20 - m10*m22;
store.m11 = m00*m22 - m02*m20;
store.m12 = m02*m10 - m00*m12;
store.m20 = m10*m21 - m11*m20;
store.m21 = m01*m20 - m00*m21;
store.m22 = m00*m11 - m01*m10;
store.multLocal(1f/det);
return store; return store;
} }
@ -952,18 +985,19 @@ public final class Matrix3f implements Savable, Cloneable {
*/ */
public Matrix3f invertLocal() { public Matrix3f invertLocal() {
float det = determinant(); float det = determinant();
if ( FastMath.abs(det) <= FastMath.FLT_EPSILON ) if (FastMath.abs(det) <= FastMath.FLT_EPSILON) {
return zero(); return zero();
}
float f00 = m11*m22 - m12*m21; float f00 = m11 * m22 - m12 * m21;
float f01 = m02*m21 - m01*m22; float f01 = m02 * m21 - m01 * m22;
float f02 = m01*m12 - m02*m11; float f02 = m01 * m12 - m02 * m11;
float f10 = m12*m20 - m10*m22; float f10 = m12 * m20 - m10 * m22;
float f11 = m00*m22 - m02*m20; float f11 = m00 * m22 - m02 * m20;
float f12 = m02*m10 - m00*m12; float f12 = m02 * m10 - m00 * m12;
float f20 = m10*m21 - m11*m20; float f20 = m10 * m21 - m11 * m20;
float f21 = m01*m20 - m00*m21; float f21 = m01 * m20 - m00 * m21;
float f22 = m00*m11 - m01*m10; float f22 = m00 * m11 - m01 * m10;
m00 = f00; m00 = f00;
m01 = f01; m01 = f01;
@ -975,7 +1009,7 @@ public final class Matrix3f implements Savable, Cloneable {
m21 = f21; m21 = f21;
m22 = f22; m22 = f22;
multLocal(1f/det); multLocal(1f / det);
return this; return this;
} }
@ -996,17 +1030,19 @@ public final class Matrix3f implements Savable, Cloneable {
* @return store * @return store
*/ */
public Matrix3f adjoint(Matrix3f store) { public Matrix3f adjoint(Matrix3f store) {
if (store == null) store = new Matrix3f(); if (store == null) {
store = new Matrix3f();
store.m00 = m11*m22 - m12*m21; }
store.m01 = m02*m21 - m01*m22;
store.m02 = m01*m12 - m02*m11; store.m00 = m11 * m22 - m12 * m21;
store.m10 = m12*m20 - m10*m22; store.m01 = m02 * m21 - m01 * m22;
store.m11 = m00*m22 - m02*m20; store.m02 = m01 * m12 - m02 * m11;
store.m12 = m02*m10 - m00*m12; store.m10 = m12 * m20 - m10 * m22;
store.m20 = m10*m21 - m11*m20; store.m11 = m00 * m22 - m02 * m20;
store.m21 = m01*m20 - m00*m21; store.m12 = m02 * m10 - m00 * m12;
store.m22 = m00*m11 - m01*m10; store.m20 = m10 * m21 - m11 * m20;
store.m21 = m01 * m20 - m00 * m21;
store.m22 = m00 * m11 - m01 * m10;
return store; return store;
} }
@ -1017,10 +1053,10 @@ public final class Matrix3f implements Savable, Cloneable {
* @return the determinate * @return the determinate
*/ */
public float determinant() { public float determinant() {
float fCo00 = m11*m22 - m12*m21; float fCo00 = m11 * m22 - m12 * m21;
float fCo10 = m12*m20 - m10*m22; float fCo10 = m12 * m20 - m10 * m22;
float fCo20 = m10*m21 - m11*m20; float fCo20 = m10 * m21 - m11 * m20;
float fDet = m00*fCo00 + m01*fCo10 + m02*fCo20; float fDet = m00 * fCo00 + m01 * fCo10 + m02 * fCo20;
return fDet; return fDet;
} }
@ -1138,17 +1174,35 @@ public final class Matrix3f implements Savable, Cloneable {
} }
Matrix3f comp = (Matrix3f) o; Matrix3f comp = (Matrix3f) o;
if (Float.compare(m00,comp.m00) != 0) return false; if (Float.compare(m00, comp.m00) != 0) {
if (Float.compare(m01,comp.m01) != 0) return false; return false;
if (Float.compare(m02,comp.m02) != 0) return false; }
if (Float.compare(m01, comp.m01) != 0) {
return false;
}
if (Float.compare(m02, comp.m02) != 0) {
return false;
}
if (Float.compare(m10,comp.m10) != 0) return false; if (Float.compare(m10, comp.m10) != 0) {
if (Float.compare(m11,comp.m11) != 0) return false; return false;
if (Float.compare(m12,comp.m12) != 0) return false; }
if (Float.compare(m11, comp.m11) != 0) {
return false;
}
if (Float.compare(m12, comp.m12) != 0) {
return false;
}
if (Float.compare(m20,comp.m20) != 0) return false; if (Float.compare(m20, comp.m20) != 0) {
if (Float.compare(m21,comp.m21) != 0) return false; return false;
if (Float.compare(m22,comp.m22) != 0) return false; }
if (Float.compare(m21, comp.m21) != 0) {
return false;
}
if (Float.compare(m22, comp.m22) != 0) {
return false;
}
return true; return true;
} }
@ -1290,18 +1344,36 @@ public final class Matrix3f implements Savable, Cloneable {
} }
static boolean equalIdentity(Matrix3f mat) { static boolean equalIdentity(Matrix3f mat) {
if (Math.abs(mat.m00 - 1) > 1e-4) return false; if (Math.abs(mat.m00 - 1) > 1e-4) {
if (Math.abs(mat.m11 - 1) > 1e-4) return false; return false;
if (Math.abs(mat.m22 - 1) > 1e-4) return false; }
if (Math.abs(mat.m11 - 1) > 1e-4) {
return false;
}
if (Math.abs(mat.m22 - 1) > 1e-4) {
return false;
}
if (Math.abs(mat.m01) > 1e-4) return false; if (Math.abs(mat.m01) > 1e-4) {
if (Math.abs(mat.m02) > 1e-4) return false; return false;
}
if (Math.abs(mat.m02) > 1e-4) {
return false;
}
if (Math.abs(mat.m10) > 1e-4) return false; if (Math.abs(mat.m10) > 1e-4) {
if (Math.abs(mat.m12) > 1e-4) return false; return false;
}
if (Math.abs(mat.m12) > 1e-4) {
return false;
}
if (Math.abs(mat.m20) > 1e-4) return false; if (Math.abs(mat.m20) > 1e-4) {
if (Math.abs(mat.m21) > 1e-4) return false; return false;
}
if (Math.abs(mat.m21) > 1e-4) {
return false;
}
return true; return true;
} }

@ -159,7 +159,6 @@ public final class Matrix4f implements Savable, Cloneable {
loadIdentity(); loadIdentity();
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f f = vars.vect1.set(direction); Vector3f f = vars.vect1.set(direction);
Vector3f s = vars.vect2.set(f).crossLocal(up); Vector3f s = vars.vect2.set(f).crossLocal(up);
@ -192,14 +191,14 @@ public final class Matrix4f implements Savable, Cloneable {
// m22 = -direction.z; // m22 = -direction.z;
// //
Matrix4f transMatrix = TempVars.get().tempMat4; Matrix4f transMatrix = vars.tempMat4;
transMatrix.loadIdentity(); transMatrix.loadIdentity();
transMatrix.m03 = -location.x; transMatrix.m03 = -location.x;
transMatrix.m13 = -location.y; transMatrix.m13 = -location.y;
transMatrix.m23 = -location.z; transMatrix.m23 = -location.z;
this.multLocal(transMatrix); this.multLocal(transMatrix);
assert TempVars.get().unlock(); vars.release();
// transMatrix.multLocal(this); // transMatrix.multLocal(this);
@ -746,12 +745,12 @@ public final class Matrix4f implements Savable, Cloneable {
// } // }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
fillFloatArray(vars.matrixWrite, columnMajor); fillFloatArray(vars.matrixWrite, columnMajor);
fb.put(vars.matrixWrite, 0, 16); fb.put(vars.matrixWrite, 0, 16);
assert vars.unlock(); vars.release();
return fb; return fb;
} }

@ -1276,12 +1276,11 @@ public final class Quaternion implements Savable, Cloneable {
*/ */
public void lookAt(Vector3f direction, Vector3f up) { public void lookAt(Vector3f direction, Vector3f up) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
vars.vect3.set(direction).normalizeLocal(); vars.vect3.set(direction).normalizeLocal();
vars.vect1.set(up).crossLocal(direction).normalizeLocal(); vars.vect1.set(up).crossLocal(direction).normalizeLocal();
vars.vect2.set(direction).crossLocal(vars.vect1).normalizeLocal(); vars.vect2.set(direction).crossLocal(vars.vect1).normalizeLocal();
fromAxes(vars.vect1, vars.vect2, vars.vect3); fromAxes(vars.vect1, vars.vect2, vars.vect3);
assert vars.unlock(); vars.release();
} }
public void write(JmeExporter e) throws IOException { public void write(JmeExporter e) throws IOException {

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.math; package com.jme3.math;
import com.jme3.bounding.BoundingVolume; import com.jme3.bounding.BoundingVolume;
@ -45,7 +44,6 @@ import com.jme3.export.Savable;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.io.IOException; import java.io.IOException;
/** /**
* <code>Ray</code> defines a line segment which has an origin and a direction. * <code>Ray</code> defines a line segment which has an origin and a direction.
* That is, a point and an infinite ray is cast from this point. The ray is * That is, a point and an infinite ray is cast from this point. The ray is
@ -57,19 +55,16 @@ import java.io.IOException;
public final class Ray implements Savable, Cloneable, Collidable { public final class Ray implements Savable, Cloneable, Collidable {
//todo: merge with Line? //todo: merge with Line?
/** The ray's begining point. */ /** The ray's begining point. */
public Vector3f origin; public Vector3f origin;
/** The direction of the ray. */ /** The direction of the ray. */
public Vector3f direction; public Vector3f direction;
public float limit = Float.POSITIVE_INFINITY; public float limit = Float.POSITIVE_INFINITY;
// protected static final Vector3f tempVa=new Vector3f(); // protected static final Vector3f tempVa=new Vector3f();
// protected static final Vector3f tempVb=new Vector3f(); // protected static final Vector3f tempVb=new Vector3f();
// protected static final Vector3f tempVc=new Vector3f(); // protected static final Vector3f tempVc=new Vector3f();
// protected static final Vector3f tempVd=new Vector3f(); // protected static final Vector3f tempVd=new Vector3f();
/** /**
* Constructor instantiates a new <code>Ray</code> object. As default, the * Constructor instantiates a new <code>Ray</code> object. As default, the
* origin is (0,0,0) and the direction is (0,0,0). * origin is (0,0,0) and the direction is (0,0,0).
@ -99,7 +94,6 @@ public final class Ray implements Savable, Cloneable, Collidable {
// public boolean intersect(Triangle t) { // public boolean intersect(Triangle t) {
// return intersect(t.get(0), t.get(1), t.get(2)); // return intersect(t.get(0), t.get(1), t.get(2));
// } // }
/** /**
* <code>intersect</code> determines if the Ray intersects a triangle * <code>intersect</code> determines if the Ray intersects a triangle
* defined by the specified points. * defined by the specified points.
@ -115,7 +109,6 @@ public final class Ray implements Savable, Cloneable, Collidable {
// public boolean intersect(Vector3f v0,Vector3f v1,Vector3f v2){ // public boolean intersect(Vector3f v0,Vector3f v1,Vector3f v2){
// return intersectWhere(v0, v1, v2, null); // return intersectWhere(v0, v1, v2, null);
// } // }
/** /**
* <code>intersectWhere</code> determines if the Ray intersects a triangle. It then * <code>intersectWhere</code> determines if the Ray intersects a triangle. It then
* stores the point of intersection in the given loc vector * stores the point of intersection in the given loc vector
@ -147,7 +140,7 @@ public final class Ray implements Savable, Cloneable, Collidable {
*/ */
public boolean intersectWhere(Vector3f v0, Vector3f v1, Vector3f v2, public boolean intersectWhere(Vector3f v0, Vector3f v1, Vector3f v2,
Vector3f loc) { Vector3f loc) {
return intersects(v0, v1, v2, loc, false, false ); return intersects(v0, v1, v2, loc, false, false);
} }
/** /**
@ -187,7 +180,7 @@ public final class Ray implements Savable, Cloneable, Collidable {
*/ */
public boolean intersectWherePlanar(Vector3f v0, Vector3f v1, Vector3f v2, public boolean intersectWherePlanar(Vector3f v0, Vector3f v1, Vector3f v2,
Vector3f loc) { Vector3f loc) {
return intersects(v0, v1, v2, loc, true, false ); return intersects(v0, v1, v2, loc, true, false);
} }
/** /**
@ -206,10 +199,9 @@ public final class Ray implements Savable, Cloneable, Collidable {
* @param quad * @param quad
* @return true if ray intersects triangle * @return true if ray intersects triangle
*/ */
private boolean intersects( Vector3f v0, Vector3f v1, Vector3f v2, private boolean intersects(Vector3f v0, Vector3f v1, Vector3f v2,
Vector3f store, boolean doPlanar, boolean quad ) { Vector3f store, boolean doPlanar, boolean quad) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f tempVa = vars.vect1, Vector3f tempVa = vars.vect1,
tempVb = vars.vect2, tempVb = vars.vect2,
@ -230,7 +222,7 @@ public final class Ray implements Savable, Cloneable, Collidable {
dirDotNorm = -dirDotNorm; dirDotNorm = -dirDotNorm;
} else { } else {
// ray and triangle/quad are parallel // ray and triangle/quad are parallel
assert vars.unlock(); vars.release();
return false; return false;
} }
@ -240,16 +232,17 @@ public final class Ray implements Savable, Cloneable, Collidable {
* direction.dot(edge1.crossLocal(diff)); * direction.dot(edge1.crossLocal(diff));
if (dirDotEdge1xDiff >= 0.0f) { if (dirDotEdge1xDiff >= 0.0f) {
if ( !quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm ) { if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) {
float diffDotNorm = -sign * diff.dot(norm); float diffDotNorm = -sign * diff.dot(norm);
if (diffDotNorm >= 0.0f) { if (diffDotNorm >= 0.0f) {
// this method always returns // this method always returns
assert vars.unlock(); vars.release();
// ray intersects triangle // ray intersects triangle
// if storage vector is null, just return true, // if storage vector is null, just return true,
if (store == null) if (store == null) {
return true; return true;
}
// else fill in. // else fill in.
float inv = 1f / dirDotNorm; float inv = 1f / dirDotNorm;
@ -273,11 +266,11 @@ public final class Ray implements Savable, Cloneable, Collidable {
} }
} }
} }
assert vars.unlock(); vars.release();
return false; return false;
} }
public float intersects(Vector3f v0, Vector3f v1, Vector3f v2){ public float intersects(Vector3f v0, Vector3f v1, Vector3f v2) {
float edge1X = v1.x - v0.x; float edge1X = v1.x - v0.x;
float edge1Y = v1.y - v0.y; float edge1Y = v1.y - v0.y;
float edge1Z = v1.z - v0.z; float edge1Z = v1.z - v0.z;
@ -365,7 +358,7 @@ public final class Ray implements Savable, Cloneable, Collidable {
*/ */
public boolean intersectWherePlanarQuad(Vector3f v0, Vector3f v1, Vector3f v2, public boolean intersectWherePlanarQuad(Vector3f v0, Vector3f v1, Vector3f v2,
Vector3f loc) { Vector3f loc) {
return intersects( v0, v1, v2, loc, true, true ); return intersects(v0, v1, v2, loc, true, true);
} }
/** /**
@ -377,57 +370,57 @@ public final class Ray implements Savable, Cloneable, Collidable {
public boolean intersectsWherePlane(Plane p, Vector3f loc) { public boolean intersectsWherePlane(Plane p, Vector3f loc) {
float denominator = p.getNormal().dot(direction); float denominator = p.getNormal().dot(direction);
if (denominator > -FastMath.FLT_EPSILON && denominator < FastMath.FLT_EPSILON) if (denominator > -FastMath.FLT_EPSILON && denominator < FastMath.FLT_EPSILON) {
return false; // coplanar return false; // coplanar
}
float numerator = -(p.getNormal().dot(origin) - p.getConstant()); float numerator = -(p.getNormal().dot(origin) - p.getConstant());
float ratio = numerator / denominator; float ratio = numerator / denominator;
if (ratio < FastMath.FLT_EPSILON) if (ratio < FastMath.FLT_EPSILON) {
return false; // intersects behind origin return false; // intersects behind origin
}
loc.set(direction).multLocal(ratio).addLocal(origin); loc.set(direction).multLocal(ratio).addLocal(origin);
return true; return true;
} }
public int collideWith(Collidable other, CollisionResults results){ public int collideWith(Collidable other, CollisionResults results) {
if (other instanceof BoundingVolume){ if (other instanceof BoundingVolume) {
BoundingVolume bv = (BoundingVolume) other; BoundingVolume bv = (BoundingVolume) other;
return bv.collideWith(this, results); return bv.collideWith(this, results);
}else if (other instanceof AbstractTriangle){ } else if (other instanceof AbstractTriangle) {
AbstractTriangle tri = (AbstractTriangle) other; AbstractTriangle tri = (AbstractTriangle) other;
float d = intersects(tri.get1(), tri.get2(), tri.get3()); float d = intersects(tri.get1(), tri.get2(), tri.get3());
if (Float.isInfinite(d) || Float.isNaN(d)) if (Float.isInfinite(d) || Float.isNaN(d)) {
return 0; return 0;
}
Vector3f point = new Vector3f(direction).multLocal(d).addLocal(origin); Vector3f point = new Vector3f(direction).multLocal(d).addLocal(origin);
results.addCollision(new CollisionResult(point, d)); results.addCollision(new CollisionResult(point, d));
return 1; return 1;
}else{ } else {
throw new UnsupportedCollisionException(); throw new UnsupportedCollisionException();
} }
} }
public float distanceSquared(Vector3f point) { public float distanceSquared(Vector3f point) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f tempVa = vars.vect1, Vector3f tempVa = vars.vect1,
tempVb = vars.vect2; tempVb = vars.vect2;
point.subtract(origin, tempVa); point.subtract(origin, tempVa);
float rayParam = direction.dot(tempVa); float rayParam = direction.dot(tempVa);
if (rayParam > 0){ if (rayParam > 0) {
origin.add(direction.mult(rayParam, tempVb), tempVb); origin.add(direction.mult(rayParam, tempVb), tempVb);
}else{ } else {
tempVb.set(origin); tempVb.set(origin);
rayParam = 0.0f; rayParam = 0.0f;
} }
tempVb.subtract(point, tempVa); tempVb.subtract(point, tempVa);
float len = tempVa.lengthSquared(); float len = tempVa.lengthSquared();
assert vars.unlock(); vars.release();
return len; return len;
} }
@ -457,7 +450,7 @@ public final class Ray implements Savable, Cloneable, Collidable {
* *
* @return the limit or the ray, aka the length. * @return the limit or the ray, aka the length.
*/ */
public float getLimit(){ public float getLimit() {
return limit; return limit;
} }
@ -466,7 +459,7 @@ public final class Ray implements Savable, Cloneable, Collidable {
* @param limit the limit of the ray. * @param limit the limit of the ray.
* @see Ray#getLimit() * @see Ray#getLimit()
*/ */
public void setLimit(float limit){ public void setLimit(float limit) {
this.limit = limit; this.limit = limit;
} }
@ -499,8 +492,8 @@ public final class Ray implements Savable, Cloneable, Collidable {
direction.set(source.getDirection()); direction.set(source.getDirection());
} }
public String toString(){ public String toString() {
return getClass().getSimpleName()+" [Origin: "+origin+", Direction: "+direction+"]"; return getClass().getSimpleName() + " [Origin: " + origin + ", Direction: " + direction + "]";
} }
public void write(JmeExporter e) throws IOException { public void write(JmeExporter e) throws IOException {
@ -511,8 +504,8 @@ public final class Ray implements Savable, Cloneable, Collidable {
public void read(JmeImporter e) throws IOException { public void read(JmeImporter e) throws IOException {
InputCapsule capsule = e.getCapsule(this); InputCapsule capsule = e.getCapsule(this);
origin = (Vector3f)capsule.readSavable("origin", Vector3f.ZERO.clone()); origin = (Vector3f) capsule.readSavable("origin", Vector3f.ZERO.clone());
direction = (Vector3f)capsule.readSavable("direction", Vector3f.ZERO.clone()); direction = (Vector3f) capsule.readSavable("direction", Vector3f.ZERO.clone());
} }
@Override @Override
@ -527,4 +520,3 @@ public final class Ray implements Savable, Cloneable, Collidable {
} }
} }
} }

@ -98,7 +98,6 @@ public class Camera implements Savable, Cloneable {
*/ */
Intersects; Intersects;
} }
/** /**
* LEFT_PLANE represents the left plane of the camera frustum. * LEFT_PLANE represents the left plane of the camera frustum.
*/ */
@ -131,7 +130,6 @@ public class Camera implements Savable, Cloneable {
* MAX_WORLD_PLANES holds the maximum planes allowed by the system. * MAX_WORLD_PLANES holds the maximum planes allowed by the system.
*/ */
private static final int MAX_WORLD_PLANES = 6; private static final int MAX_WORLD_PLANES = 6;
/** /**
* Camera's location * Camera's location
*/ */
@ -164,14 +162,12 @@ public class Camera implements Savable, Cloneable {
* Distance from camera to bottom frustum plane. * Distance from camera to bottom frustum plane.
*/ */
protected float frustumBottom; protected float frustumBottom;
//Temporary values computed in onFrustumChange that are needed if a //Temporary values computed in onFrustumChange that are needed if a
//call is made to onFrameChange. //call is made to onFrameChange.
protected float[] coeffLeft; protected float[] coeffLeft;
protected float[] coeffRight; protected float[] coeffRight;
protected float[] coeffBottom; protected float[] coeffBottom;
protected float[] coeffTop; protected float[] coeffTop;
//view port coordinates //view port coordinates
/** /**
* Percent value on display where horizontal viewing starts for this camera. * Percent value on display where horizontal viewing starts for this camera.
@ -197,13 +193,11 @@ public class Camera implements Savable, Cloneable {
* Array holding the planes that this camera will check for culling. * Array holding the planes that this camera will check for culling.
*/ */
protected Plane[] worldPlane; protected Plane[] worldPlane;
/** /**
* A mask value set during contains() that allows fast culling of a Node's * A mask value set during contains() that allows fast culling of a Node's
* children. * children.
*/ */
private int planeState; private int planeState;
protected int width; protected int width;
protected int height; protected int height;
protected boolean viewportChanged = true; protected boolean viewportChanged = true;
@ -758,10 +752,9 @@ public class Camera implements Savable, Cloneable {
*/ */
public void lookAt(Vector3f pos, Vector3f worldUpVector) { public void lookAt(Vector3f pos, Vector3f worldUpVector) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock(); Vector3f newDirection = vars.vect1;
Vector3f newDirection = TempVars.get().vect1; Vector3f newUp = vars.vect2;
Vector3f newUp = TempVars.get().vect2; Vector3f newLeft = vars.vect3;
Vector3f newLeft = TempVars.get().vect3;
newDirection.set(pos).subtractLocal(location).normalizeLocal(); newDirection.set(pos).subtractLocal(location).normalizeLocal();
@ -783,7 +776,7 @@ public class Camera implements Savable, Cloneable {
this.rotation.fromAxes(newLeft, newUp, newDirection); this.rotation.fromAxes(newLeft, newUp, newDirection);
this.rotation.normalizeLocal(); this.rotation.normalizeLocal();
assert vars.unlock(); vars.release();
onFrameChange(); onFrameChange();
} }
@ -1285,15 +1278,15 @@ public class Camera implements Savable, Cloneable {
store = new Vector3f(); store = new Vector3f();
} }
// assert TempVars.get().lock(); // TempVars vars = vars.lock();
// Quaternion tmp_quat = TempVars.get().quat1; // Quaternion tmp_quat = vars.quat1;
// tmp_quat.set( worldPosition.x, worldPosition.y, worldPosition.z, 1 ); // tmp_quat.set( worldPosition.x, worldPosition.y, worldPosition.z, 1 );
// viewProjectionMatrix.mult(tmp_quat, tmp_quat); // viewProjectionMatrix.mult(tmp_quat, tmp_quat);
// tmp_quat.multLocal( 1.0f / tmp_quat.getW() ); // tmp_quat.multLocal( 1.0f / tmp_quat.getW() );
// store.x = ( ( tmp_quat.getX() + 1 ) * ( viewPortRight - viewPortLeft ) / 2 + viewPortLeft ) * getWidth(); // store.x = ( ( tmp_quat.getX() + 1 ) * ( viewPortRight - viewPortLeft ) / 2 + viewPortLeft ) * getWidth();
// store.y = ( ( tmp_quat.getY() + 1 ) * ( viewPortTop - viewPortBottom ) / 2 + viewPortBottom ) * getHeight(); // store.y = ( ( tmp_quat.getY() + 1 ) * ( viewPortTop - viewPortBottom ) / 2 + viewPortBottom ) * getHeight();
// store.z = ( tmp_quat.getZ() + 1 ) / 2; // store.z = ( tmp_quat.getZ() + 1 ) / 2;
// assert TempVars.get().unlock(); // vars.release();
float w = viewProjectionMatrix.multProj(worldPosition, store); float w = viewProjectionMatrix.multProj(worldPosition, store);
store.divideLocal(w); store.divideLocal(w);

@ -75,7 +75,6 @@ import java.util.logging.Logger;
public class RenderManager { public class RenderManager {
private static final Logger logger = Logger.getLogger(RenderManager.class.getName()); private static final Logger logger = Logger.getLogger(RenderManager.class.getName());
private Renderer renderer; private Renderer renderer;
private Timer timer; private Timer timer;
private ArrayList<ViewPort> preViewPorts = new ArrayList<ViewPort>(); private ArrayList<ViewPort> preViewPorts = new ArrayList<ViewPort>();
@ -344,7 +343,6 @@ public class RenderManager {
public void updateUniformBindings(List<Uniform> params) { public void updateUniformBindings(List<Uniform> params) {
// assums worldMatrix is properly set. // assums worldMatrix is properly set.
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Matrix4f tempMat4 = vars.tempMat4; Matrix4f tempMat4 = vars.tempMat4;
Matrix3f tempMat3 = vars.tempMat3; Matrix3f tempMat3 = vars.tempMat3;
@ -465,7 +463,7 @@ public class RenderManager {
} }
} }
assert vars.unlock(); vars.release();
} }
/** /**
@ -1167,5 +1165,4 @@ public class RenderManager {
renderViewPort(postViewPorts.get(i), tpf); renderViewPort(postViewPorts.get(i), tpf);
} }
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.scene; package com.jme3.scene;
import com.jme3.asset.AssetNotFoundException; import com.jme3.asset.AssetNotFoundException;
@ -60,24 +59,19 @@ import java.util.logging.Logger;
public class Geometry extends Spatial { public class Geometry extends Spatial {
private static final Logger logger = Logger.getLogger(Geometry.class.getName()); private static final Logger logger = Logger.getLogger(Geometry.class.getName());
protected Mesh mesh; protected Mesh mesh;
protected transient int lodLevel = 0; protected transient int lodLevel = 0;
protected Material material; protected Material material;
/** /**
* When true, the geometry's transform will not be applied. * When true, the geometry's transform will not be applied.
*/ */
protected boolean ignoreTransform = false; protected boolean ignoreTransform = false;
protected transient Matrix4f cachedWorldMat = new Matrix4f(); protected transient Matrix4f cachedWorldMat = new Matrix4f();
/** /**
* Serialization only. Do not use. * Serialization only. Do not use.
*/ */
public Geometry(){ public Geometry() {
} }
/** /**
@ -87,7 +81,7 @@ public class Geometry extends Spatial {
* *
* @param name The name of this geometry * @param name The name of this geometry
*/ */
public Geometry(String name){ public Geometry(String name) {
super(name); super(name);
} }
@ -99,10 +93,11 @@ public class Geometry extends Spatial {
* @param name The name of this geometry * @param name The name of this geometry
* @param mesh The mesh data for this geometry * @param mesh The mesh data for this geometry
*/ */
public Geometry(String name, Mesh mesh){ public Geometry(String name, Mesh mesh) {
this(name); this(name);
if (mesh == null) if (mesh == null) {
throw new NullPointerException(); throw new NullPointerException();
}
this.mesh = mesh; this.mesh = mesh;
} }
@ -132,12 +127,14 @@ public class Geometry extends Spatial {
* @param lod The lod level to set * @param lod The lod level to set
*/ */
@Override @Override
public void setLodLevel(int lod){ public void setLodLevel(int lod) {
if (mesh.getNumLodLevels() == 0) if (mesh.getNumLodLevels() == 0) {
throw new IllegalStateException("LOD levels are not set on this mesh"); throw new IllegalStateException("LOD levels are not set on this mesh");
}
if (lod < 0 || lod >= mesh.getNumLodLevels()) if (lod < 0 || lod >= mesh.getNumLodLevels()) {
throw new IllegalArgumentException("LOD level is out of range: "+lod); throw new IllegalArgumentException("LOD level is out of range: " + lod);
}
lodLevel = lod; lodLevel = lod;
} }
@ -147,7 +144,7 @@ public class Geometry extends Spatial {
* *
* @return the LOD level set * @return the LOD level set
*/ */
public int getLodLevel(){ public int getLodLevel() {
return lodLevel; return lodLevel;
} }
@ -158,7 +155,7 @@ public class Geometry extends Spatial {
* *
* @see Mesh#getVertexCount() * @see Mesh#getVertexCount()
*/ */
public int getVertexCount(){ public int getVertexCount() {
return mesh.getVertexCount(); return mesh.getVertexCount();
} }
@ -169,7 +166,7 @@ public class Geometry extends Spatial {
* *
* @see Mesh#getTriangleCount() * @see Mesh#getTriangleCount()
*/ */
public int getTriangleCount(){ public int getTriangleCount() {
return mesh.getTriangleCount(); return mesh.getTriangleCount();
} }
@ -180,9 +177,10 @@ public class Geometry extends Spatial {
* *
* @throws IllegalArgumentException If mesh is null * @throws IllegalArgumentException If mesh is null
*/ */
public void setMesh(Mesh mesh){ public void setMesh(Mesh mesh) {
if (mesh == null) if (mesh == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
}
this.mesh = mesh; this.mesh = mesh;
setBoundRefresh(); setBoundRefresh();
@ -195,7 +193,7 @@ public class Geometry extends Spatial {
* *
* @see #setMesh(com.jme3.scene.Mesh) * @see #setMesh(com.jme3.scene.Mesh)
*/ */
public Mesh getMesh(){ public Mesh getMesh() {
return mesh; return mesh;
} }
@ -205,7 +203,7 @@ public class Geometry extends Spatial {
* @param material the material to use for this geometry * @param material the material to use for this geometry
*/ */
@Override @Override
public void setMaterial(Material material){ public void setMaterial(Material material) {
this.material = material; this.material = material;
} }
@ -216,14 +214,14 @@ public class Geometry extends Spatial {
* *
* @see #setMaterial(com.jme3.material.Material) * @see #setMaterial(com.jme3.material.Material)
*/ */
public Material getMaterial(){ public Material getMaterial() {
return material; return material;
} }
/** /**
* @return The bounding volume of the mesh, in model space. * @return The bounding volume of the mesh, in model space.
*/ */
public BoundingVolume getModelBound(){ public BoundingVolume getModelBound() {
return mesh.getBound(); return mesh.getBound();
} }
@ -246,22 +244,23 @@ public class Geometry extends Spatial {
@Override @Override
protected void updateWorldBound() { protected void updateWorldBound() {
super.updateWorldBound(); super.updateWorldBound();
if (mesh == null) if (mesh == null) {
throw new NullPointerException("Geometry: "+getName()+" has null mesh"); throw new NullPointerException("Geometry: " + getName() + " has null mesh");
}
if (mesh.getBound() != null) { if (mesh.getBound() != null) {
if (ignoreTransform){ if (ignoreTransform) {
// we do not transform the model bound by the world transform, // we do not transform the model bound by the world transform,
// just use the model bound as-is // just use the model bound as-is
worldBound = mesh.getBound().clone(worldBound); worldBound = mesh.getBound().clone(worldBound);
}else{ } else {
worldBound = mesh.getBound().transform(worldTransform, worldBound); worldBound = mesh.getBound().transform(worldTransform, worldBound);
} }
} }
} }
@Override @Override
protected void updateWorldTransforms(){ protected void updateWorldTransforms() {
super.updateWorldTransforms(); super.updateWorldTransforms();
computeWorldMatrix(); computeWorldMatrix();
@ -274,7 +273,7 @@ public class Geometry extends Spatial {
* Recomputes the matrix returned by {@link Geometry#getWorldMatrix() }. * Recomputes the matrix returned by {@link Geometry#getWorldMatrix() }.
* This will require a localized transform update for this geometry. * This will require a localized transform update for this geometry.
*/ */
public void computeWorldMatrix(){ public void computeWorldMatrix() {
// Force a local update of the geometry's transform // Force a local update of the geometry's transform
checkDoTransformUpdate(); checkDoTransformUpdate();
@ -283,12 +282,12 @@ public class Geometry extends Spatial {
cachedWorldMat.setRotationQuaternion(worldTransform.getRotation()); cachedWorldMat.setRotationQuaternion(worldTransform.getRotation());
cachedWorldMat.setTranslation(worldTransform.getTranslation()); cachedWorldMat.setTranslation(worldTransform.getTranslation());
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Matrix4f scaleMat = TempVars.get().tempMat4; Matrix4f scaleMat = vars.tempMat4;
scaleMat.loadIdentity(); scaleMat.loadIdentity();
scaleMat.scale(worldTransform.getScale()); scaleMat.scale(worldTransform.getScale());
cachedWorldMat.multLocal(scaleMat); cachedWorldMat.multLocal(scaleMat);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -300,7 +299,7 @@ public class Geometry extends Spatial {
* *
* @return Matrix to transform from local space to world space * @return Matrix to transform from local space to world space
*/ */
public Matrix4f getWorldMatrix(){ public Matrix4f getWorldMatrix() {
return cachedWorldMat; return cachedWorldMat;
} }
@ -319,7 +318,7 @@ public class Geometry extends Spatial {
updateModelBound(); updateModelBound();
} }
public int collideWith(Collidable other, CollisionResults results){ public int collideWith(Collidable other, CollisionResults results) {
// Force bound to update // Force bound to update
checkDoBoundUpdate(); checkDoBoundUpdate();
// Update transform, and compute cached world matrix // Update transform, and compute cached world matrix
@ -327,13 +326,13 @@ public class Geometry extends Spatial {
assert (refreshFlags & (RF_BOUND | RF_TRANSFORM)) == 0; assert (refreshFlags & (RF_BOUND | RF_TRANSFORM)) == 0;
if (mesh != null){ if (mesh != null) {
// NOTE: BIHTree in mesh already checks collision with the // NOTE: BIHTree in mesh already checks collision with the
// mesh's bound // mesh's bound
int prevSize = results.size(); int prevSize = results.size();
int added = mesh.collideWith(other, cachedWorldMat, worldBound, results); int added = mesh.collideWith(other, cachedWorldMat, worldBound, results);
int newSize = results.size(); int newSize = results.size();
for (int i = prevSize; i < newSize; i++){ for (int i = prevSize; i < newSize; i++) {
results.getCollisionDirect(i).setGeometry(this); results.getCollisionDirect(i).setGeometry(this);
} }
return added; return added;
@ -358,17 +357,18 @@ public class Geometry extends Spatial {
* and normals are deep copied. * and normals are deep copied.
*/ */
@Override @Override
public Geometry clone(boolean cloneMaterial){ public Geometry clone(boolean cloneMaterial) {
Geometry geomClone = (Geometry) super.clone(cloneMaterial); Geometry geomClone = (Geometry) super.clone(cloneMaterial);
geomClone.cachedWorldMat = cachedWorldMat.clone(); geomClone.cachedWorldMat = cachedWorldMat.clone();
if (material != null){ if (material != null) {
if (cloneMaterial) if (cloneMaterial) {
geomClone.material = material.clone(); geomClone.material = material.clone();
else } else {
geomClone.material = material; geomClone.material = material;
} }
}
if (mesh != null && mesh.getBuffer(Type.BindPosePosition) != null){ if (mesh != null && mesh.getBuffer(Type.BindPosePosition) != null) {
geomClone.mesh = mesh.cloneForAnim(); geomClone.mesh = mesh.cloneForAnim();
} }
@ -383,7 +383,7 @@ public class Geometry extends Spatial {
* and normals are deep copied. * and normals are deep copied.
*/ */
@Override @Override
public Geometry clone(){ public Geometry clone() {
return clone(true); return clone(true);
} }
@ -393,7 +393,7 @@ public class Geometry extends Spatial {
* with the vertexbuffer data duplicated. * with the vertexbuffer data duplicated.
*/ */
@Override @Override
public Spatial deepClone(){ public Spatial deepClone() {
Geometry geomClone = clone(true); Geometry geomClone = clone(true);
geomClone.mesh = mesh.deepClone(); geomClone.mesh = mesh.deepClone();
return geomClone; return geomClone;
@ -404,7 +404,7 @@ public class Geometry extends Spatial {
super.write(ex); super.write(ex);
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(mesh, "mesh", null); oc.write(mesh, "mesh", null);
if (material != null){ if (material != null) {
oc.write(material.getAssetName(), "materialName", null); oc.write(material.getAssetName(), "materialName", null);
} }
oc.write(material, "material", null); oc.write(material, "material", null);
@ -419,22 +419,21 @@ public class Geometry extends Spatial {
material = null; material = null;
String matName = ic.readString("materialName", null); String matName = ic.readString("materialName", null);
if (matName != null){ if (matName != null) {
// Material name is set, // Material name is set,
// Attempt to load material via J3M // Attempt to load material via J3M
try { try {
material = im.getAssetManager().loadMaterial(matName); material = im.getAssetManager().loadMaterial(matName);
} catch (AssetNotFoundException ex){ } catch (AssetNotFoundException ex) {
// Cannot find J3M file. // Cannot find J3M file.
logger.log(Level.FINE, "Could not load J3M file {0} for Geometry.", logger.log(Level.FINE, "Could not load J3M file {0} for Geometry.",
matName); matName);
} }
} }
// If material is NULL, try to load it from the geometry // If material is NULL, try to load it from the geometry
if (material == null){ if (material == null) {
material = (Material) ic.readSavable("material", null); material = (Material) ic.readSavable("material", null);
} }
ignoreTransform = ic.readBoolean("ignoreTransform", false); ignoreTransform = ic.readBoolean("ignoreTransform", false);
} }
} }

@ -340,7 +340,6 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
*/ */
public void rotateUpTo(Vector3f newUp) { public void rotateUpTo(Vector3f newUp) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f compVecA = vars.vect1; Vector3f compVecA = vars.vect1;
Quaternion q = vars.quat1; Quaternion q = vars.quat1;
@ -360,7 +359,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
q.fromAngleNormalAxis(angle, rotAxis); q.fromAngleNormalAxis(angle, rotAxis);
q.mult(rot, rot); q.mult(rot, rot);
assert vars.unlock(); vars.release();
setTransformRefresh(); setTransformRefresh();
} }
@ -382,9 +381,9 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
Vector3f worldTranslation = getWorldTranslation(); Vector3f worldTranslation = getWorldTranslation();
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f compVecA = vars.vect4; Vector3f compVecA = vars.vect4;
assert vars.unlock(); vars.release();
compVecA.set(position).subtractLocal(worldTranslation); compVecA.set(position).subtractLocal(worldTranslation);
getLocalRotation().lookAt(compVecA, upVector); getLocalRotation().lookAt(compVecA, upVector);
@ -448,7 +447,6 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
refreshFlags &= ~RF_TRANSFORM; refreshFlags &= ~RF_TRANSFORM;
} else { } else {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Spatial[] stack = vars.spatialStack; Spatial[] stack = vars.spatialStack;
Spatial rootNode = this; Spatial rootNode = this;
@ -472,7 +470,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
i++; i++;
} }
assert vars.unlock(); vars.release();
for (int j = i; j >= 0; j--) { for (int j = i; j >= 0; j--) {
rootNode = stack[j]; rootNode = stack[j];
@ -978,11 +976,11 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
* @return The spatial on which this method is called, e.g <code>this</code>. * @return The spatial on which this method is called, e.g <code>this</code>.
*/ */
public Spatial rotate(float yaw, float roll, float pitch) { public Spatial rotate(float yaw, float roll, float pitch) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Quaternion q = TempVars.get().quat1; Quaternion q = vars.quat1;
q.fromAngles(yaw, roll, pitch); q.fromAngles(yaw, roll, pitch);
rotate(q); rotate(q);
assert TempVars.get().unlock(); vars.release();
return this; return this;
} }

@ -116,7 +116,6 @@ public class CameraControl extends AbstractControl {
// set the localtransform, so that the worldtransform would be equal to the camera's transform. // set the localtransform, so that the worldtransform would be equal to the camera's transform.
// Location: // Location:
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f vecDiff = vars.vect1.set(camera.getLocation()).subtractLocal(spatial.getWorldTranslation()); Vector3f vecDiff = vars.vect1.set(camera.getLocation()).subtractLocal(spatial.getWorldTranslation());
spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation()));
@ -124,7 +123,7 @@ public class CameraControl extends AbstractControl {
// Rotation: // Rotation:
Quaternion worldDiff = vars.quat1.set(camera.getRotation()).subtractLocal(spatial.getWorldRotation()); Quaternion worldDiff = vars.quat1.set(camera.getRotation()).subtractLocal(spatial.getWorldRotation());
spatial.setLocalRotation(worldDiff.addLocal(spatial.getLocalRotation())); spatial.setLocalRotation(worldDiff.addLocal(spatial.getLocalRotation()));
assert vars.unlock(); vars.release();
break; break;
} }
} }

@ -126,12 +126,11 @@ public class LightControl extends AbstractControl {
((PointLight) light).setPosition(spatial.getWorldTranslation()); ((PointLight) light).setPosition(spatial.getWorldTranslation());
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
if (light instanceof DirectionalLight) { if (light instanceof DirectionalLight) {
((DirectionalLight) light).setDirection(vars.vect1.set(spatial.getWorldTranslation()).multLocal(-1.0f)); ((DirectionalLight) light).setDirection(vars.vect1.set(spatial.getWorldTranslation()).multLocal(-1.0f));
} }
assert vars.unlock(); vars.release();
//TODO add code for Spot light here when it's done //TODO add code for Spot light here when it's done
// if( light instanceof SpotLight){ // if( light instanceof SpotLight){
// ((SpotLight)light).setPosition(spatial.getWorldTranslation()); // ((SpotLight)light).setPosition(spatial.getWorldTranslation());
@ -142,15 +141,12 @@ public class LightControl extends AbstractControl {
private void lightToSpatial(Light light) { private void lightToSpatial(Light light) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
if (light instanceof PointLight) { if (light instanceof PointLight) {
PointLight pLight = (PointLight) light; PointLight pLight = (PointLight) light;
Vector3f vecDiff = vars.vect1.set(pLight.getPosition()).subtractLocal(spatial.getWorldTranslation()); Vector3f vecDiff = vars.vect1.set(pLight.getPosition()).subtractLocal(spatial.getWorldTranslation());
spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation()));
assert vars.unlock();
} }
if (light instanceof DirectionalLight) { if (light instanceof DirectionalLight) {
@ -159,7 +155,7 @@ public class LightControl extends AbstractControl {
Vector3f vecDiff = vars.vect1.subtractLocal(spatial.getWorldTranslation()); Vector3f vecDiff = vars.vect1.subtractLocal(spatial.getWorldTranslation());
spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation())); spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation()));
} }
assert vars.unlock(); vars.release();
//TODO add code for Spot light here when it's done //TODO add code for Spot light here when it's done

@ -67,4 +67,14 @@ public class SkeletonDebugger extends Node {
wires.updateGeometry(); wires.updateGeometry();
points.updateGeometry(); points.updateGeometry();
} }
public SkeletonPoints getPoints() {
return points;
}
public SkeletonWire getWires() {
return wires;
}
} }

@ -29,11 +29,9 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// $Id: Dome.java 4131 2009-03-19 20:15:28Z blaine.dev $ // $Id: Dome.java 4131 2009-03-19 20:15:28Z blaine.dev $
package com.jme3.scene.shape; package com.jme3.scene.shape;
import com.jme3.scene.*; import com.jme3.scene.*;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
@ -58,15 +56,11 @@ import java.nio.ShortBuffer;
public class Dome extends Mesh { public class Dome extends Mesh {
private int planes; private int planes;
private int radialSamples; private int radialSamples;
/** The radius of the dome */ /** The radius of the dome */
private float radius; private float radius;
/** The center of the dome */ /** The center of the dome */
private Vector3f center; private Vector3f center;
private boolean outsideView = true; private boolean outsideView = true;
/** /**
@ -220,7 +214,6 @@ public class Dome extends Mesh {
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f tempVc = vars.vect3; Vector3f tempVc = vars.vect3;
Vector3f tempVb = vars.vect2; Vector3f tempVb = vars.vect2;
Vector3f tempVa = vars.vect1; Vector3f tempVa = vars.vect1;
@ -251,10 +244,11 @@ public class Dome extends Mesh {
BufferUtils.populateFromBuffer(tempVa, vb, i); BufferUtils.populateFromBuffer(tempVa, vb, i);
kNormal = tempVa.subtractLocal(center); kNormal = tempVa.subtractLocal(center);
kNormal.normalizeLocal(); kNormal.normalizeLocal();
if (outsideView) if (outsideView) {
nb.put(kNormal.x).put(kNormal.y).put(kNormal.z); nb.put(kNormal.x).put(kNormal.y).put(kNormal.z);
else } else {
nb.put(-kNormal.x).put(-kNormal.y).put(-kNormal.z); nb.put(-kNormal.x).put(-kNormal.y).put(-kNormal.z);
}
tb.put(fRadialFraction).put(fYFraction); tb.put(fRadialFraction).put(fYFraction);
} }
@ -263,7 +257,7 @@ public class Dome extends Mesh {
tb.put(1.0f).put(fYFraction); tb.put(1.0f).put(fYFraction);
} }
assert vars.unlock(); vars.release();
// pole // pole
vb.put(center.x).put(center.y + radius).put(center.z); vb.put(center.x).put(center.y + radius).put(center.z);
@ -282,21 +276,21 @@ public class Dome extends Mesh {
int bottomPlaneStart = ((plane - 1) * (radialSamples + 1)); int bottomPlaneStart = ((plane - 1) * (radialSamples + 1));
int topPlaneStart = (plane * (radialSamples + 1)); int topPlaneStart = (plane * (radialSamples + 1));
for (int sample = 0; sample < radialSamples; sample++, index += 6) { for (int sample = 0; sample < radialSamples; sample++, index += 6) {
ib.put((short)(bottomPlaneStart + sample)); ib.put((short) (bottomPlaneStart + sample));
ib.put((short)(topPlaneStart + sample)); ib.put((short) (topPlaneStart + sample));
ib.put((short)(bottomPlaneStart + sample + 1)); ib.put((short) (bottomPlaneStart + sample + 1));
ib.put((short)(bottomPlaneStart + sample + 1)); ib.put((short) (bottomPlaneStart + sample + 1));
ib.put((short)(topPlaneStart + sample)); ib.put((short) (topPlaneStart + sample));
ib.put((short)(topPlaneStart + sample + 1)); ib.put((short) (topPlaneStart + sample + 1));
} }
} }
// pole triangles // pole triangles
int bottomPlaneStart = (planes - 2) * (radialSamples + 1); int bottomPlaneStart = (planes - 2) * (radialSamples + 1);
for (int samples = 0; samples < radialSamples; samples++, index += 3) { for (int samples = 0; samples < radialSamples; samples++, index += 3) {
ib.put((short)(bottomPlaneStart + samples)); ib.put((short) (bottomPlaneStart + samples));
ib.put((short)(vertCount - 1)); ib.put((short) (vertCount - 1));
ib.put((short)(bottomPlaneStart + samples + 1)); ib.put((short) (bottomPlaneStart + samples + 1));
} }
updateBound(); updateBound();
@ -321,5 +315,4 @@ public class Dome extends Mesh {
capsule.write(radius, "radius", 0); capsule.write(radius, "radius", 0);
capsule.write(center, "center", Vector3f.ZERO); capsule.write(center, "center", Vector3f.ZERO);
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// $Id: Sphere.java 4163 2009-03-25 01:14:55Z matt.yellen $ // $Id: Sphere.java 4163 2009-03-25 01:14:55Z matt.yellen $
package com.jme3.scene.shape; package com.jme3.scene.shape;
@ -47,7 +46,6 @@ import java.io.IOException;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
/** /**
* <code>Sphere</code> represents a 3D object with all points equidistance * <code>Sphere</code> represents a 3D object with all points equidistance
* from a center point. * from a center point.
@ -58,6 +56,7 @@ import java.nio.ShortBuffer;
public class Sphere extends Mesh { public class Sphere extends Mesh {
public enum TextureMode { public enum TextureMode {
/** /**
* Wrap texture radially and along z-axis * Wrap texture radially and along z-axis
*/ */
@ -72,28 +71,20 @@ public class Sphere extends Mesh {
*/ */
Polar Polar
} }
protected int vertCount; protected int vertCount;
protected int triCount; protected int triCount;
protected int zSamples; protected int zSamples;
protected int radialSamples; protected int radialSamples;
protected boolean useEvenSlices; protected boolean useEvenSlices;
protected boolean interior; protected boolean interior;
/** the distance from the center point each point falls on */ /** the distance from the center point each point falls on */
public float radius; public float radius;
protected TextureMode textureMode = TextureMode.Original; protected TextureMode textureMode = TextureMode.Original;
/** /**
* Serialization only. Do not use. * Serialization only. Do not use.
*/ */
public Sphere(){ public Sphere() {
} }
/** /**
@ -185,7 +176,6 @@ public class Sphere extends Mesh {
afCos[radialSamples] = afCos[0]; afCos[radialSamples] = afCos[0];
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Vector3f tempVa = vars.vect1; Vector3f tempVa = vars.vect1;
Vector3f tempVb = vars.vect2; Vector3f tempVb = vars.vect2;
Vector3f tempVc = vars.vect3; Vector3f tempVc = vars.vect3;
@ -195,11 +185,11 @@ public class Sphere extends Mesh {
for (int iZ = 1; iZ < (zSamples - 1); iZ++) { for (int iZ = 1; iZ < (zSamples - 1); iZ++) {
float fAFraction = FastMath.HALF_PI * (-1.0f + fZFactor * iZ); // in (-pi/2, pi/2) float fAFraction = FastMath.HALF_PI * (-1.0f + fZFactor * iZ); // in (-pi/2, pi/2)
float fZFraction; float fZFraction;
if (useEvenSlices) if (useEvenSlices) {
fZFraction = -1.0f + fZFactor * iZ; // in (-1, 1) fZFraction = -1.0f + fZFactor * iZ; // in (-1, 1)
else } else {
fZFraction = FastMath.sin(fAFraction); // in (-1,1) fZFraction = FastMath.sin(fAFraction); // in (-1,1)
}
float fZ = radius * fZFraction; float fZ = radius * fZFraction;
// compute center of slice // compute center of slice
@ -225,21 +215,22 @@ public class Sphere extends Mesh {
kNormal = tempVa; kNormal = tempVa;
kNormal.normalizeLocal(); kNormal.normalizeLocal();
if (!interior) // allow interior texture vs. exterior if (!interior) // allow interior texture vs. exterior
{
normBuf.put(kNormal.x).put(kNormal.y).put( normBuf.put(kNormal.x).put(kNormal.y).put(
kNormal.z); kNormal.z);
else } else {
normBuf.put(-kNormal.x).put(-kNormal.y).put( normBuf.put(-kNormal.x).put(-kNormal.y).put(
-kNormal.z); -kNormal.z);
}
if (textureMode == TextureMode.Original) if (textureMode == TextureMode.Original) {
texBuf.put(fRadialFraction).put( texBuf.put(fRadialFraction).put(
0.5f * (fZFraction + 1.0f)); 0.5f * (fZFraction + 1.0f));
else if (textureMode == TextureMode.Projected) } else if (textureMode == TextureMode.Projected) {
texBuf.put(fRadialFraction).put( texBuf.put(fRadialFraction).put(
FastMath.INV_PI FastMath.INV_PI
* (FastMath.HALF_PI + FastMath * (FastMath.HALF_PI + FastMath.asin(fZFraction)));
.asin(fZFraction))); } else if (textureMode == TextureMode.Polar) {
else if (textureMode == TextureMode.Polar) {
float r = (FastMath.HALF_PI - FastMath.abs(fAFraction)) / FastMath.PI; float r = (FastMath.HALF_PI - FastMath.abs(fAFraction)) / FastMath.PI;
float u = r * afCos[iR] + 0.5f; float u = r * afCos[iR] + 0.5f;
float v = r * afSin[iR] + 0.5f; float v = r * afSin[iR] + 0.5f;
@ -252,43 +243,41 @@ public class Sphere extends Mesh {
BufferUtils.copyInternalVector3(posBuf, iSave, i); BufferUtils.copyInternalVector3(posBuf, iSave, i);
BufferUtils.copyInternalVector3(normBuf, iSave, i); BufferUtils.copyInternalVector3(normBuf, iSave, i);
if (textureMode == TextureMode.Original) if (textureMode == TextureMode.Original) {
texBuf.put(1.0f).put( texBuf.put(1.0f).put(
0.5f * (fZFraction + 1.0f)); 0.5f * (fZFraction + 1.0f));
else if (textureMode == TextureMode.Projected) } else if (textureMode == TextureMode.Projected) {
texBuf.put(1.0f) texBuf.put(1.0f).put(
.put(
FastMath.INV_PI FastMath.INV_PI
* (FastMath.HALF_PI + FastMath * (FastMath.HALF_PI + FastMath.asin(fZFraction)));
.asin(fZFraction))); } else if (textureMode == TextureMode.Polar) {
else if (textureMode == TextureMode.Polar) {
float r = (FastMath.HALF_PI - FastMath.abs(fAFraction)) / FastMath.PI; float r = (FastMath.HALF_PI - FastMath.abs(fAFraction)) / FastMath.PI;
texBuf.put(r+0.5f).put(0.5f); texBuf.put(r + 0.5f).put(0.5f);
} }
i++; i++;
} }
assert vars.unlock(); vars.release();
// south pole // south pole
posBuf.position(i * 3); posBuf.position(i * 3);
posBuf.put(0f).put(0f).put(-radius); posBuf.put(0f).put(0f).put(-radius);
normBuf.position(i * 3); normBuf.position(i * 3);
if (!interior) if (!interior) {
normBuf.put(0).put(0).put(-1); // allow for inner normBuf.put(0).put(0).put(-1); // allow for inner
// texture orientation } // texture orientation
// later. // later.
else else {
normBuf.put(0).put(0).put(1); normBuf.put(0).put(0).put(1);
}
texBuf.position(i * 2); texBuf.position(i * 2);
if (textureMode == TextureMode.Polar) { if (textureMode == TextureMode.Polar) {
texBuf.put(0.5f).put(0.5f); texBuf.put(0.5f).put(0.5f);
} } else {
else {
texBuf.put(0.5f).put(0.0f); texBuf.put(0.5f).put(0.0f);
} }
@ -297,10 +286,11 @@ public class Sphere extends Mesh {
// north pole // north pole
posBuf.put(0).put(0).put(radius); posBuf.put(0).put(0).put(radius);
if (!interior) if (!interior) {
normBuf.put(0).put(0).put(1); normBuf.put(0).put(0).put(1);
else } else {
normBuf.put(0).put(0).put(-1); normBuf.put(0).put(0).put(-1);
}
if (textureMode == TextureMode.Polar) { if (textureMode == TextureMode.Polar) {
texBuf.put(0.5f).put(0.5f); texBuf.put(0.5f).put(0.5f);
@ -331,19 +321,19 @@ public class Sphere extends Mesh {
int i3 = i2 + 1; int i3 = i2 + 1;
for (int i = 0; i < radialSamples; i++, index += 6) { for (int i = 0; i < radialSamples; i++, index += 6) {
if (!interior) { if (!interior) {
idxBuf.put((short)i0++); idxBuf.put((short) i0++);
idxBuf.put((short)i1); idxBuf.put((short) i1);
idxBuf.put((short)i2); idxBuf.put((short) i2);
idxBuf.put((short)i1++); idxBuf.put((short) i1++);
idxBuf.put((short)i3++); idxBuf.put((short) i3++);
idxBuf.put((short)i2++); idxBuf.put((short) i2++);
} else { // inside view } else { // inside view
idxBuf.put((short)i0++); idxBuf.put((short) i0++);
idxBuf.put((short)i2); idxBuf.put((short) i2);
idxBuf.put((short)i1); idxBuf.put((short) i1);
idxBuf.put((short)i1++); idxBuf.put((short) i1++);
idxBuf.put((short)i2++); idxBuf.put((short) i2++);
idxBuf.put((short)i3++); idxBuf.put((short) i3++);
} }
} }
} }
@ -351,13 +341,13 @@ public class Sphere extends Mesh {
// south pole triangles // south pole triangles
for (int i = 0; i < radialSamples; i++, index += 3) { for (int i = 0; i < radialSamples; i++, index += 3) {
if (!interior) { if (!interior) {
idxBuf.put((short)i); idxBuf.put((short) i);
idxBuf.put((short)(vertCount - 2)); idxBuf.put((short) (vertCount - 2));
idxBuf.put((short)(i + 1)); idxBuf.put((short) (i + 1));
} else { // inside view } else { // inside view
idxBuf.put((short)i); idxBuf.put((short) i);
idxBuf.put((short)(i + 1)); idxBuf.put((short) (i + 1));
idxBuf.put((short)(vertCount - 2)); idxBuf.put((short) (vertCount - 2));
} }
} }
@ -365,13 +355,13 @@ public class Sphere extends Mesh {
int iOffset = (zSamples - 3) * (radialSamples + 1); int iOffset = (zSamples - 3) * (radialSamples + 1);
for (int i = 0; i < radialSamples; i++, index += 3) { for (int i = 0; i < radialSamples; i++, index += 3) {
if (!interior) { if (!interior) {
idxBuf.put((short)(i + iOffset)); idxBuf.put((short) (i + iOffset));
idxBuf.put((short)(i + 1 + iOffset)); idxBuf.put((short) (i + 1 + iOffset));
idxBuf.put((short)(vertCount - 1)); idxBuf.put((short) (vertCount - 1));
} else { // inside view } else { // inside view
idxBuf.put((short)(i + iOffset)); idxBuf.put((short) (i + iOffset));
idxBuf.put((short)(vertCount - 1)); idxBuf.put((short) (vertCount - 1));
idxBuf.put((short)(i + 1 + iOffset)); idxBuf.put((short) (i + 1 + iOffset));
} }
} }
} }
@ -427,5 +417,4 @@ public class Sphere extends Mesh {
capsule.write(textureMode, "textureMode", TextureMode.Original); capsule.write(textureMode, "textureMode", TextureMode.Original);
capsule.write(interior, "interior", false); capsule.write(interior, "interior", false);
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.util; package com.jme3.util;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
@ -48,7 +47,6 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
/** /**
* <code>BufferUtils</code> is a helper class for generating nio buffers from * <code>BufferUtils</code> is a helper class for generating nio buffers from
* jME data classes such as Vectors and ColorRGBA. * jME data classes such as Vectors and ColorRGBA.
@ -62,14 +60,12 @@ public final class BufferUtils {
// private static final Vector2f _tempVec2 = new Vector2f(); // private static final Vector2f _tempVec2 = new Vector2f();
// private static final Vector3f _tempVec3 = new Vector3f(); // private static final Vector3f _tempVec3 = new Vector3f();
// private static final ColorRGBA _tempColor = new ColorRGBA(); // private static final ColorRGBA _tempColor = new ColorRGBA();
//// -- TRACKER HASH -- //// //// -- TRACKER HASH -- ////
private static final Map<Buffer, Object> trackingHash = Collections.synchronizedMap(new WeakHashMap<Buffer, Object>()); private static final Map<Buffer, Object> trackingHash = Collections.synchronizedMap(new WeakHashMap<Buffer, Object>());
private static final Object ref = new Object(); private static final Object ref = new Object();
private static final boolean trackDirectMemory = false; private static final boolean trackDirectMemory = false;
//// -- GENERIC CLONE -- //// //// -- GENERIC CLONE -- ////
/** /**
* Creates a clone of the given buffer. The clone's capacity is * Creates a clone of the given buffer. The clone's capacity is
* equal to the given buffer's limit. * equal to the given buffer's limit.
@ -77,25 +73,23 @@ public final class BufferUtils {
* @param buf The buffer to clone * @param buf The buffer to clone
* @return The cloned buffer * @return The cloned buffer
*/ */
public static Buffer clone(Buffer buf){ public static Buffer clone(Buffer buf) {
if (buf instanceof FloatBuffer){ if (buf instanceof FloatBuffer) {
return clone( (FloatBuffer) buf ); return clone((FloatBuffer) buf);
}else if (buf instanceof ShortBuffer){ } else if (buf instanceof ShortBuffer) {
return clone( (ShortBuffer) buf ); return clone((ShortBuffer) buf);
}else if (buf instanceof ByteBuffer){ } else if (buf instanceof ByteBuffer) {
return clone( (ByteBuffer) buf ); return clone((ByteBuffer) buf);
}else if (buf instanceof IntBuffer){ } else if (buf instanceof IntBuffer) {
return clone( (IntBuffer) buf ); return clone((IntBuffer) buf);
}else if (buf instanceof DoubleBuffer){ } else if (buf instanceof DoubleBuffer) {
return clone( (DoubleBuffer) buf ); return clone((DoubleBuffer) buf);
}else{ } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
//// -- VECTOR3F METHODS -- //// //// -- VECTOR3F METHODS -- ////
/** /**
* Generate a new FloatBuffer using the given array of Vector3f objects. * Generate a new FloatBuffer using the given array of Vector3f objects.
* The FloatBuffer will be 3 * data.length long and contain the vector data * The FloatBuffer will be 3 * data.length long and contain the vector data
@ -103,15 +97,18 @@ public final class BufferUtils {
* *
* @param data array of Vector3f objects to place into a new FloatBuffer * @param data array of Vector3f objects to place into a new FloatBuffer
*/ */
public static FloatBuffer createFloatBuffer(Vector3f ... data) { public static FloatBuffer createFloatBuffer(Vector3f... data) {
if (data == null) return null; if (data == null) {
return null;
}
FloatBuffer buff = createFloatBuffer(3 * data.length); FloatBuffer buff = createFloatBuffer(3 * data.length);
for (int x = 0; x < data.length; x++) { for (int x = 0; x < data.length; x++) {
if (data[x] != null) if (data[x] != null) {
buff.put(data[x].x).put(data[x].y).put(data[x].z); buff.put(data[x].x).put(data[x].y).put(data[x].z);
else } else {
buff.put(0).put(0).put(0); buff.put(0).put(0).put(0);
} }
}
buff.flip(); buff.flip();
return buff; return buff;
} }
@ -122,16 +119,18 @@ public final class BufferUtils {
* *
* @param data array of Quaternion objects to place into a new FloatBuffer * @param data array of Quaternion objects to place into a new FloatBuffer
*/ */
public static FloatBuffer createFloatBuffer(Quaternion ... data) { public static FloatBuffer createFloatBuffer(Quaternion... data) {
if (data == null) return null; if (data == null) {
return null;
}
FloatBuffer buff = createFloatBuffer(4 * data.length); FloatBuffer buff = createFloatBuffer(4 * data.length);
for (int x = 0; x < data.length; x++) { for (int x = 0; x < data.length; x++) {
if (data[x] != null) if (data[x] != null) {
buff.put(data[x].getX()).put(data[x].getY()) buff.put(data[x].getX()).put(data[x].getY()).put(data[x].getZ()).put(data[x].getW());
.put(data[x].getZ()).put(data[x].getW()); } else {
else
buff.put(0).put(0).put(0); buff.put(0).put(0).put(0);
} }
}
buff.flip(); buff.flip();
return buff; return buff;
} }
@ -140,8 +139,10 @@ public final class BufferUtils {
* Generate a new FloatBuffer using the given array of float primitives. * Generate a new FloatBuffer using the given array of float primitives.
* @param data array of float primitives to place into a new FloatBuffer * @param data array of float primitives to place into a new FloatBuffer
*/ */
public static FloatBuffer createFloatBuffer(float ... data) { public static FloatBuffer createFloatBuffer(float... data) {
if (data == null) return null; if (data == null) {
return null;
}
FloatBuffer buff = createFloatBuffer(data.length); FloatBuffer buff = createFloatBuffer(data.length);
buff.clear(); buff.clear();
buff.put(data); buff.put(data);
@ -197,7 +198,7 @@ public final class BufferUtils {
*/ */
public static void setInBuffer(ColorRGBA color, FloatBuffer buf, public static void setInBuffer(ColorRGBA color, FloatBuffer buf,
int index) { int index) {
buf.position(index*4); buf.position(index * 4);
buf.put(color.r); buf.put(color.r);
buf.put(color.g); buf.put(color.g);
buf.put(color.b); buf.put(color.b);
@ -217,7 +218,7 @@ public final class BufferUtils {
*/ */
public static void setInBuffer(Quaternion quat, FloatBuffer buf, public static void setInBuffer(Quaternion quat, FloatBuffer buf,
int index) { int index) {
buf.position(index*4); buf.position(index * 4);
buf.put(quat.getX()); buf.put(quat.getX());
buf.put(quat.getY()); buf.put(quat.getY());
buf.put(quat.getZ()); buf.put(quat.getZ());
@ -236,10 +237,10 @@ public final class BufferUtils {
* the postion to place the data; in terms of vectors not floats * the postion to place the data; in terms of vectors not floats
*/ */
public static void setInBuffer(Vector3f vector, FloatBuffer buf, int index) { public static void setInBuffer(Vector3f vector, FloatBuffer buf, int index) {
if(buf == null) { if (buf == null) {
return; return;
} }
if(vector == null) { if (vector == null) {
buf.put(index * 3, 0); buf.put(index * 3, 0);
buf.put((index * 3) + 1, 0); buf.put((index * 3) + 1, 0);
buf.put((index * 3) + 2, 0); buf.put((index * 3) + 2, 0);
@ -263,9 +264,9 @@ public final class BufferUtils {
* the buf * the buf
*/ */
public static void populateFromBuffer(Vector3f vector, FloatBuffer buf, int index) { public static void populateFromBuffer(Vector3f vector, FloatBuffer buf, int index) {
vector.x = buf.get(index*3); vector.x = buf.get(index * 3);
vector.y = buf.get(index*3+1); vector.y = buf.get(index * 3 + 1);
vector.z = buf.get(index*3+2); vector.z = buf.get(index * 3 + 2);
} }
/** /**
@ -298,7 +299,7 @@ public final class BufferUtils {
* the index to copy the vector to * the index to copy the vector to
*/ */
public static void copyInternalVector3(FloatBuffer buf, int fromPos, int toPos) { public static void copyInternalVector3(FloatBuffer buf, int fromPos, int toPos) {
copyInternal(buf, fromPos*3, toPos*3, 3); copyInternal(buf, fromPos * 3, toPos * 3, 3);
} }
/** /**
@ -311,12 +312,12 @@ public final class BufferUtils {
* to normalize * to normalize
*/ */
public static void normalizeVector3(FloatBuffer buf, int index) { public static void normalizeVector3(FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f tempVec3 = TempVars.get().vect1; Vector3f tempVec3 = vars.vect1;
populateFromBuffer(tempVec3, buf, index); populateFromBuffer(tempVec3, buf, index);
tempVec3.normalizeLocal(); tempVec3.normalizeLocal();
setInBuffer(tempVec3, buf, index); setInBuffer(tempVec3, buf, index);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -331,12 +332,12 @@ public final class BufferUtils {
* to add to * to add to
*/ */
public static void addInBuffer(Vector3f toAdd, FloatBuffer buf, int index) { public static void addInBuffer(Vector3f toAdd, FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f tempVec3 = TempVars.get().vect1; Vector3f tempVec3 = vars.vect1;
populateFromBuffer(tempVec3, buf, index); populateFromBuffer(tempVec3, buf, index);
tempVec3.addLocal(toAdd); tempVec3.addLocal(toAdd);
setInBuffer(tempVec3, buf, index); setInBuffer(tempVec3, buf, index);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -351,12 +352,12 @@ public final class BufferUtils {
* to multiply * to multiply
*/ */
public static void multInBuffer(Vector3f toMult, FloatBuffer buf, int index) { public static void multInBuffer(Vector3f toMult, FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f tempVec3 = TempVars.get().vect1; Vector3f tempVec3 = vars.vect1;
populateFromBuffer(tempVec3, buf, index); populateFromBuffer(tempVec3, buf, index);
tempVec3.multLocal(toMult); tempVec3.multLocal(toMult);
setInBuffer(tempVec3, buf, index); setInBuffer(tempVec3, buf, index);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -373,16 +374,15 @@ public final class BufferUtils {
* @return * @return
*/ */
public static boolean equals(Vector3f check, FloatBuffer buf, int index) { public static boolean equals(Vector3f check, FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector3f tempVec3 = TempVars.get().vect1; Vector3f tempVec3 = vars.vect1;
populateFromBuffer(tempVec3, buf, index); populateFromBuffer(tempVec3, buf, index);
boolean eq = tempVec3.equals(check); boolean eq = tempVec3.equals(check);
assert TempVars.get().unlock(); vars.release();
return eq; return eq;
} }
// // -- VECTOR2F METHODS -- //// // // -- VECTOR2F METHODS -- ////
/** /**
* Generate a new FloatBuffer using the given array of Vector2f objects. * Generate a new FloatBuffer using the given array of Vector2f objects.
* The FloatBuffer will be 2 * data.length long and contain the vector data * The FloatBuffer will be 2 * data.length long and contain the vector data
@ -390,15 +390,18 @@ public final class BufferUtils {
* *
* @param data array of Vector2f objects to place into a new FloatBuffer * @param data array of Vector2f objects to place into a new FloatBuffer
*/ */
public static FloatBuffer createFloatBuffer(Vector2f ... data) { public static FloatBuffer createFloatBuffer(Vector2f... data) {
if (data == null) return null; if (data == null) {
return null;
}
FloatBuffer buff = createFloatBuffer(2 * data.length); FloatBuffer buff = createFloatBuffer(2 * data.length);
for (int x = 0; x < data.length; x++) { for (int x = 0; x < data.length; x++) {
if (data[x] != null) if (data[x] != null) {
buff.put(data[x].x).put(data[x].y); buff.put(data[x].x).put(data[x].y);
else } else {
buff.put(0).put(0); buff.put(0).put(0);
} }
}
buff.flip(); buff.flip();
return buff; return buff;
} }
@ -467,8 +470,8 @@ public final class BufferUtils {
* the buf * the buf
*/ */
public static void populateFromBuffer(Vector2f vector, FloatBuffer buf, int index) { public static void populateFromBuffer(Vector2f vector, FloatBuffer buf, int index) {
vector.x = buf.get(index*2); vector.x = buf.get(index * 2);
vector.y = buf.get(index*2+1); vector.y = buf.get(index * 2 + 1);
} }
/** /**
@ -501,7 +504,7 @@ public final class BufferUtils {
* the index to copy the vector to * the index to copy the vector to
*/ */
public static void copyInternalVector2(FloatBuffer buf, int fromPos, int toPos) { public static void copyInternalVector2(FloatBuffer buf, int fromPos, int toPos) {
copyInternal(buf, fromPos*2, toPos*2, 2); copyInternal(buf, fromPos * 2, toPos * 2, 2);
} }
/** /**
@ -514,12 +517,12 @@ public final class BufferUtils {
* to normalize * to normalize
*/ */
public static void normalizeVector2(FloatBuffer buf, int index) { public static void normalizeVector2(FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector2f tempVec2 = TempVars.get().vect2d; Vector2f tempVec2 = vars.vect2d;
populateFromBuffer(tempVec2, buf, index); populateFromBuffer(tempVec2, buf, index);
tempVec2.normalizeLocal(); tempVec2.normalizeLocal();
setInBuffer(tempVec2, buf, index); setInBuffer(tempVec2, buf, index);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -534,12 +537,12 @@ public final class BufferUtils {
* to add to * to add to
*/ */
public static void addInBuffer(Vector2f toAdd, FloatBuffer buf, int index) { public static void addInBuffer(Vector2f toAdd, FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector2f tempVec2 = TempVars.get().vect2d; Vector2f tempVec2 = vars.vect2d;
populateFromBuffer(tempVec2, buf, index); populateFromBuffer(tempVec2, buf, index);
tempVec2.addLocal(toAdd); tempVec2.addLocal(toAdd);
setInBuffer(tempVec2, buf, index); setInBuffer(tempVec2, buf, index);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -554,12 +557,12 @@ public final class BufferUtils {
* to multiply * to multiply
*/ */
public static void multInBuffer(Vector2f toMult, FloatBuffer buf, int index) { public static void multInBuffer(Vector2f toMult, FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector2f tempVec2 = TempVars.get().vect2d; Vector2f tempVec2 = vars.vect2d;
populateFromBuffer(tempVec2, buf, index); populateFromBuffer(tempVec2, buf, index);
tempVec2.multLocal(toMult); tempVec2.multLocal(toMult);
setInBuffer(tempVec2, buf, index); setInBuffer(tempVec2, buf, index);
assert TempVars.get().unlock(); vars.release();
} }
/** /**
@ -576,17 +579,15 @@ public final class BufferUtils {
* @return * @return
*/ */
public static boolean equals(Vector2f check, FloatBuffer buf, int index) { public static boolean equals(Vector2f check, FloatBuffer buf, int index) {
assert TempVars.get().lock(); TempVars vars = TempVars.get();
Vector2f tempVec2 = TempVars.get().vect2d; Vector2f tempVec2 = vars.vect2d;
populateFromBuffer(tempVec2, buf, index); populateFromBuffer(tempVec2, buf, index);
boolean eq = tempVec2.equals(check); boolean eq = tempVec2.equals(check);
assert TempVars.get().unlock(); vars.release();
return eq; return eq;
} }
//// -- INT METHODS -- //// //// -- INT METHODS -- ////
/** /**
* Generate a new IntBuffer using the given array of ints. The IntBuffer * Generate a new IntBuffer using the given array of ints. The IntBuffer
* will be data.length long and contain the int data as data[0], data[1]... * will be data.length long and contain the int data as data[0], data[1]...
@ -596,7 +597,9 @@ public final class BufferUtils {
* array of ints to place into a new IntBuffer * array of ints to place into a new IntBuffer
*/ */
public static IntBuffer createIntBuffer(int... data) { public static IntBuffer createIntBuffer(int... data) {
if (data == null) return null; if (data == null) {
return null;
}
IntBuffer buff = createIntBuffer(data.length); IntBuffer buff = createIntBuffer(data.length);
buff.clear(); buff.clear();
buff.put(data); buff.put(data);
@ -613,7 +616,9 @@ public final class BufferUtils {
* @return a new int array populated from the IntBuffer * @return a new int array populated from the IntBuffer
*/ */
public static int[] getIntArray(IntBuffer buff) { public static int[] getIntArray(IntBuffer buff) {
if (buff == null) return null; if (buff == null) {
return null;
}
buff.clear(); buff.clear();
int[] inds = new int[buff.limit()]; int[] inds = new int[buff.limit()];
for (int x = 0; x < inds.length; x++) { for (int x = 0; x < inds.length; x++) {
@ -631,7 +636,9 @@ public final class BufferUtils {
* @return a new float array populated from the FloatBuffer * @return a new float array populated from the FloatBuffer
*/ */
public static float[] getFloatArray(FloatBuffer buff) { public static float[] getFloatArray(FloatBuffer buff) {
if (buff == null) return null; if (buff == null) {
return null;
}
buff.clear(); buff.clear();
float[] inds = new float[buff.limit()]; float[] inds = new float[buff.limit()];
for (int x = 0; x < inds.length; x++) { for (int x = 0; x < inds.length; x++) {
@ -640,9 +647,7 @@ public final class BufferUtils {
return inds; return inds;
} }
//// -- GENERAL DOUBLE ROUTINES -- //// //// -- GENERAL DOUBLE ROUTINES -- ////
/** /**
* Create a new DoubleBuffer of the specified size. * Create a new DoubleBuffer of the specified size.
* *
@ -691,13 +696,15 @@ public final class BufferUtils {
* @return the copy * @return the copy
*/ */
public static DoubleBuffer clone(DoubleBuffer buf) { public static DoubleBuffer clone(DoubleBuffer buf) {
if (buf == null) return null; if (buf == null) {
return null;
}
buf.rewind(); buf.rewind();
DoubleBuffer copy; DoubleBuffer copy;
if (buf.isDirect()){ if (buf.isDirect()) {
copy = createDoubleBuffer(buf.limit()); copy = createDoubleBuffer(buf.limit());
}else{ } else {
copy = DoubleBuffer.allocate(buf.limit()); copy = DoubleBuffer.allocate(buf.limit());
} }
copy.put(buf); copy.put(buf);
@ -705,10 +712,7 @@ public final class BufferUtils {
return copy; return copy;
} }
//// -- GENERAL FLOAT ROUTINES -- //// //// -- GENERAL FLOAT ROUTINES -- ////
/** /**
* Create a new FloatBuffer of the specified size. * Create a new FloatBuffer of the specified size.
* *
@ -756,13 +760,15 @@ public final class BufferUtils {
* @return the copy * @return the copy
*/ */
public static FloatBuffer clone(FloatBuffer buf) { public static FloatBuffer clone(FloatBuffer buf) {
if (buf == null) return null; if (buf == null) {
return null;
}
buf.rewind(); buf.rewind();
FloatBuffer copy; FloatBuffer copy;
if (buf.isDirect()){ if (buf.isDirect()) {
copy = createFloatBuffer(buf.limit()); copy = createFloatBuffer(buf.limit());
}else{ } else {
copy = FloatBuffer.allocate(buf.limit()); copy = FloatBuffer.allocate(buf.limit());
} }
copy.put(buf); copy.put(buf);
@ -770,9 +776,7 @@ public final class BufferUtils {
return copy; return copy;
} }
//// -- GENERAL INT ROUTINES -- //// //// -- GENERAL INT ROUTINES -- ////
/** /**
* Create a new IntBuffer of the specified size. * Create a new IntBuffer of the specified size.
* *
@ -821,13 +825,15 @@ public final class BufferUtils {
* @return the copy * @return the copy
*/ */
public static IntBuffer clone(IntBuffer buf) { public static IntBuffer clone(IntBuffer buf) {
if (buf == null) return null; if (buf == null) {
return null;
}
buf.rewind(); buf.rewind();
IntBuffer copy; IntBuffer copy;
if (buf.isDirect()){ if (buf.isDirect()) {
copy = createIntBuffer(buf.limit()); copy = createIntBuffer(buf.limit());
}else{ } else {
copy = IntBuffer.allocate(buf.limit()); copy = IntBuffer.allocate(buf.limit());
} }
copy.put(buf); copy.put(buf);
@ -835,9 +841,7 @@ public final class BufferUtils {
return copy; return copy;
} }
//// -- GENERAL BYTE ROUTINES -- //// //// -- GENERAL BYTE ROUTINES -- ////
/** /**
* Create a new ByteBuffer of the specified size. * Create a new ByteBuffer of the specified size.
* *
@ -875,14 +879,14 @@ public final class BufferUtils {
return buf; return buf;
} }
public static ByteBuffer createByteBuffer(byte ... data){ public static ByteBuffer createByteBuffer(byte... data) {
ByteBuffer bb = createByteBuffer(data.length); ByteBuffer bb = createByteBuffer(data.length);
bb.put(data); bb.put(data);
bb.flip(); bb.flip();
return bb; return bb;
} }
public static ByteBuffer createByteBuffer(String data){ public static ByteBuffer createByteBuffer(String data) {
byte[] bytes = data.getBytes(); byte[] bytes = data.getBytes();
ByteBuffer bb = createByteBuffer(bytes.length); ByteBuffer bb = createByteBuffer(bytes.length);
bb.put(bytes); bb.put(bytes);
@ -901,13 +905,15 @@ public final class BufferUtils {
* @return the copy * @return the copy
*/ */
public static ByteBuffer clone(ByteBuffer buf) { public static ByteBuffer clone(ByteBuffer buf) {
if (buf == null) return null; if (buf == null) {
return null;
}
buf.rewind(); buf.rewind();
ByteBuffer copy; ByteBuffer copy;
if (buf.isDirect()){ if (buf.isDirect()) {
copy = createByteBuffer(buf.limit()); copy = createByteBuffer(buf.limit());
}else{ } else {
copy = ByteBuffer.allocate(buf.limit()); copy = ByteBuffer.allocate(buf.limit());
} }
copy.put(buf); copy.put(buf);
@ -915,9 +921,7 @@ public final class BufferUtils {
return copy; return copy;
} }
//// -- GENERAL SHORT ROUTINES -- //// //// -- GENERAL SHORT ROUTINES -- ////
/** /**
* Create a new ShortBuffer of the specified size. * Create a new ShortBuffer of the specified size.
* *
@ -956,7 +960,9 @@ public final class BufferUtils {
} }
public static ShortBuffer createShortBuffer(short... data) { public static ShortBuffer createShortBuffer(short... data) {
if (data == null) return null; if (data == null) {
return null;
}
ShortBuffer buff = createShortBuffer(data.length); ShortBuffer buff = createShortBuffer(data.length);
buff.clear(); buff.clear();
buff.put(data); buff.put(data);
@ -975,13 +981,15 @@ public final class BufferUtils {
* @return the copy * @return the copy
*/ */
public static ShortBuffer clone(ShortBuffer buf) { public static ShortBuffer clone(ShortBuffer buf) {
if (buf == null) return null; if (buf == null) {
return null;
}
buf.rewind(); buf.rewind();
ShortBuffer copy; ShortBuffer copy;
if (buf.isDirect()){ if (buf.isDirect()) {
copy = createShortBuffer(buf.limit()); copy = createShortBuffer(buf.limit());
}else{ } else {
copy = ShortBuffer.allocate(buf.limit()); copy = ShortBuffer.allocate(buf.limit());
} }
copy.put(buf); copy.put(buf);
@ -997,42 +1005,42 @@ public final class BufferUtils {
* @return a buffer large enough to receive at least the <code>required</code> number of entries, same position as * @return a buffer large enough to receive at least the <code>required</code> number of entries, same position as
* the input buffer, not null * the input buffer, not null
*/ */
public static FloatBuffer ensureLargeEnough( FloatBuffer buffer, int required ) { public static FloatBuffer ensureLargeEnough(FloatBuffer buffer, int required) {
if ( buffer == null || ( buffer.remaining() < required ) ) { if (buffer == null || (buffer.remaining() < required)) {
int position = ( buffer != null ? buffer.position() : 0 ); int position = (buffer != null ? buffer.position() : 0);
FloatBuffer newVerts = createFloatBuffer( position + required ); FloatBuffer newVerts = createFloatBuffer(position + required);
if ( buffer != null ) { if (buffer != null) {
buffer.rewind(); buffer.rewind();
newVerts.put( buffer ); newVerts.put(buffer);
newVerts.position( position ); newVerts.position(position);
} }
buffer = newVerts; buffer = newVerts;
} }
return buffer; return buffer;
} }
public static ShortBuffer ensureLargeEnough( ShortBuffer buffer, int required ) { public static ShortBuffer ensureLargeEnough(ShortBuffer buffer, int required) {
if ( buffer == null || ( buffer.remaining() < required ) ) { if (buffer == null || (buffer.remaining() < required)) {
int position = ( buffer != null ? buffer.position() : 0 ); int position = (buffer != null ? buffer.position() : 0);
ShortBuffer newVerts = createShortBuffer( position + required ); ShortBuffer newVerts = createShortBuffer(position + required);
if ( buffer != null ) { if (buffer != null) {
buffer.rewind(); buffer.rewind();
newVerts.put( buffer ); newVerts.put(buffer);
newVerts.position( position ); newVerts.position(position);
} }
buffer = newVerts; buffer = newVerts;
} }
return buffer; return buffer;
} }
public static ByteBuffer ensureLargeEnough( ByteBuffer buffer, int required ) { public static ByteBuffer ensureLargeEnough(ByteBuffer buffer, int required) {
if ( buffer == null || ( buffer.remaining() < required ) ) { if (buffer == null || (buffer.remaining() < required)) {
int position = ( buffer != null ? buffer.position() : 0 ); int position = (buffer != null ? buffer.position() : 0);
ByteBuffer newVerts = createByteBuffer( position + required ); ByteBuffer newVerts = createByteBuffer(position + required);
if ( buffer != null ) { if (buffer != null) {
buffer.rewind(); buffer.rewind();
newVerts.put( buffer ); newVerts.put(buffer);
newVerts.position( position ); newVerts.position(position);
} }
buffer = newVerts; buffer = newVerts;
} }
@ -1068,25 +1076,20 @@ public final class BufferUtils {
dBufs++; dBufs++;
} }
} }
long heapMem = Runtime.getRuntime().totalMemory() - long heapMem = Runtime.getRuntime().totalMemory()
Runtime.getRuntime().freeMemory(); - Runtime.getRuntime().freeMemory();
boolean printStout = store == null; boolean printStout = store == null;
if (store == null) { if (store == null) {
store = new StringBuilder(); store = new StringBuilder();
} }
store.append("Existing buffers: ").append(bufs.size()).append("\n"); store.append("Existing buffers: ").append(bufs.size()).append("\n");
store.append("(b: ").append(bBufs).append(" f: ").append(fBufs) store.append("(b: ").append(bBufs).append(" f: ").append(fBufs).append(" i: ").append(iBufs).append(" s: ").append(sBufs).append(" d: ").append(dBufs).append(")").append("\n");
.append(" i: ").append(iBufs).append(" s: ").append(sBufs) store.append("Total heap memory held: ").append(heapMem / 1024).append("kb\n");
.append(" d: ").append(dBufs).append(")").append("\n"); store.append("Total direct memory held: ").append(totalHeld / 1024).append("kb\n");
store.append("Total heap memory held: ").append(heapMem/1024).append("kb\n"); store.append("(b: ").append(bBufsM / 1024).append("kb f: ").append(fBufsM / 1024).append("kb i: ").append(iBufsM / 1024).append("kb s: ").append(sBufsM / 1024).append("kb d: ").append(dBufsM / 1024).append("kb)").append("\n");
store.append("Total direct memory held: ").append(totalHeld/1024).append("kb\n");
store.append("(b: ").append(bBufsM/1024).append("kb f: ").append(fBufsM/1024)
.append("kb i: ").append(iBufsM/1024).append("kb s: ").append(sBufsM/1024)
.append("kb d: ").append(dBufsM/1024).append("kb)").append("\n");
if (printStout) { if (printStout) {
System.out.println(store.toString()); System.out.println(store.toString());
} }
} }
} }

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.util; package com.jme3.util;
import com.jme3.collision.bih.BIHNode.BIHStackData; import com.jme3.collision.bih.BIHNode.BIHStackData;
@ -45,94 +44,148 @@ import com.jme3.scene.Spatial;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* Temporary variables assigned to each thread. Engine classes may access * Temporary variables assigned to each thread. Engine classes may access
* these temp variables with TempVars.get(). A method using temp vars with this * these temp variables with TempVars.get().
* class is not allowed to make calls to other methods using the class otherwise * This returns an available instance of the TempVar class ensuring this particular instance is never used elsewhere in the mean time.
* memory corruption will occur. A locking mechanism may be implemented
* in the future to prevent the occurance of such situation.
*/ */
public class TempVars { public class TempVars {
private static final ThreadLocal<TempVars> varsLocal private static final Logger log = Logger.getLogger(TempVars.class.getName());
= new ThreadLocal<TempVars>(){ //default array size
private static final int arraySize = 30;
//one array per thread
private static final ThreadLocal<TempVars[]> varsLocal = new ThreadLocal<TempVars[]>() {
@Override @Override
public TempVars initialValue(){ public TempVars[] initialValue() {
return new TempVars(); TempVars[] l = new TempVars[arraySize];
//the array is initialized with one instance (should be enough in most cases)
l[0] = new TempVars();
return l;
} }
}; };
//the current index in the stack
private static int stackLevel = 0;
//number of instanced TempVar, just to raise a warning if too much are instanced
private static int instanceCount = 1;
public static TempVars get(){ /**
return varsLocal.get(); * Returns an available instance of the TempVar class
} * Warning, you have to release the instance once used by calling the release() method
* @return a TempVar instance
private TempVars(){ */
} public static TempVars get() {
private boolean locked = false; TempVars vars = null;
private StackTraceElement[] lockerStack; TempVars[] array = varsLocal.get();
//if the stack level is > 0 it means we have some instances in the array, we can return one of them
public final boolean lock(){ if (stackLevel >= 0) {
if (locked){ //getting the lastTempVar instance
System.err.println("INTERNAL ERROR"); vars = array[stackLevel];
System.err.println("Offending trace: "); //removing the reference to it in the array so if it's never released it will be garbage collected.
array[stackLevel] = null;
StackTraceElement[] stack = new Throwable().getStackTrace(); //decreasing the stack level since we have one less instance
for (int i = 1; i < stack.length; i++){ stackLevel--;
System.err.println("\tat "+stack[i].toString());
//In some cases (when lauching jme threads from another thread), the instance at 0 can be null
//so we check that to avoid NPE
if (vars==null){
vars = new TempVars();
//increasing the count to keep track
instanceCount++;
} }
} else {
System.err.println("Attempted to aquire TempVars lock owned by"); //if the stack level is <0 it means the stack is empty, we have to create a new instance
for (int i = 1; i < lockerStack.length; i++){ //there
System.err.println("\tat "+lockerStack[i].toString()); vars = new TempVars();
//increasing the count to keep track
instanceCount++;
//raising a warning if the instance count is to high, because it might be due to bad usage
if (instanceCount == array.length) {
log.log(Level.WARNING, "TempVars has been requested {0} times, maybe you forgot to call release()?", instanceCount);
} }
System.exit(1);
return false;
} }
return vars;
lockerStack = new Throwable().getStackTrace();
locked = true;
return true;
} }
public final boolean unlock(){ private TempVars() {
if (!locked){
System.err.println("INTERNAL ERROR");
System.err.println("Attempted to release non-existent lock: ");
StackTraceElement[] stack = new Throwable().getStackTrace();
for (int i = 1; i < stack.length; i++){
System.err.println("\tat "+stack[i].toString());
} }
// private boolean locked = false;
System.exit(1); // private StackTraceElement[] lockerStack;
return false;
// public final boolean lock() {
// if (locked) {
// System.err.println("INTERNAL ERROR");
// System.err.println("Offending trace: ");
//
// StackTraceElement[] stack = new Throwable().getStackTrace();
// for (int i = 1; i < stack.length; i++) {
// System.err.println("\tat " + stack[i].toString());
// }
//
// System.err.println("Attempted to aquire TempVars lock owned by");
// for (int i = 1; i < lockerStack.length; i++) {
// System.err.println("\tat " + lockerStack[i].toString());
// }
// System.exit(1);
// return false;
// }
//
// lockerStack = new Throwable().getStackTrace();
// locked = true;
// return true;
// }
//
// public final boolean unlock() {
// if (!locked) {
// System.err.println("INTERNAL ERROR");
// System.err.println("Attempted to release non-existent lock: ");
//
// StackTraceElement[] stack = new Throwable().getStackTrace();
// for (int i = 1; i < stack.length; i++) {
// System.err.println("\tat " + stack[i].toString());
// }
//
// System.exit(1);
// return false;
// }
//
// lockerStack = null;
// locked = false;
// return true;
// }
/**
* Release this instance of TempVar, allowing it to be reused later.
*/
public final void release() {
//we only keep as much instances as we can,
//but if too much are instanced, we just don't readd them, they'll be garbage collected
//This can happen only in case of recursive calls that are instancing the TempVar
if (stackLevel < arraySize - 1) {
stackLevel++;
varsLocal.get()[stackLevel] = this;
} }
lockerStack = null;
locked = false;
return true;
} }
/** /**
* For interfacing with OpenGL in Renderer. * For interfacing with OpenGL in Renderer.
*/ */
public final IntBuffer intBuffer1 = BufferUtils.createIntBuffer(1); public final IntBuffer intBuffer1 = BufferUtils.createIntBuffer(1);
public final IntBuffer intBuffer16 = BufferUtils.createIntBuffer(16); public final IntBuffer intBuffer16 = BufferUtils.createIntBuffer(16);
public final FloatBuffer floatBuffer16 = BufferUtils.createFloatBuffer(16); public final FloatBuffer floatBuffer16 = BufferUtils.createFloatBuffer(16);
/** /**
* Skinning buffers * Skinning buffers
*/ */
public final float[] skinPositions = new float[512 * 3]; public final float[] skinPositions = new float[512 * 3];
public final float[] skinNormals = new float[512 * 3]; public final float[] skinNormals = new float[512 * 3];
/** /**
* Fetching triangle from mesh * Fetching triangle from mesh
*/ */
public final Triangle triangle = new Triangle(); public final Triangle triangle = new Triangle();
/** /**
* General vectors. * General vectors.
*/ */
@ -143,42 +196,36 @@ public class TempVars {
public final Vector3f vect5 = new Vector3f(); public final Vector3f vect5 = new Vector3f();
public final Vector3f vect6 = new Vector3f(); public final Vector3f vect6 = new Vector3f();
public final Vector3f vect7 = new Vector3f(); public final Vector3f vect7 = new Vector3f();
//seems the maximum number of vector used is 7 in com.jme3.bounding.java
public final Vector3f vect8 = new Vector3f(); public final Vector3f vect8 = new Vector3f();
public final Vector3f vect9 = new Vector3f(); public final Vector3f vect9 = new Vector3f();
public final Vector3f vect10 = new Vector3f(); public final Vector3f vect10 = new Vector3f();
public final Vector3f[] tri = {new Vector3f(),
public final Vector3f[] tri = { new Vector3f(),
new Vector3f(), new Vector3f(),
new Vector3f() }; new Vector3f()};
/** /**
* 2D vector * 2D vector
*/ */
public final Vector2f vect2d = new Vector2f(); public final Vector2f vect2d = new Vector2f();
public final Vector2f vect2d2 = new Vector2f(); public final Vector2f vect2d2 = new Vector2f();
/** /**
* General matrices. * General matrices.
*/ */
public final Matrix3f tempMat3 = new Matrix3f(); public final Matrix3f tempMat3 = new Matrix3f();
public final Matrix4f tempMat4 = new Matrix4f(); public final Matrix4f tempMat4 = new Matrix4f();
/** /**
* General quaternions. * General quaternions.
*/ */
public final Quaternion quat1 = new Quaternion(); public final Quaternion quat1 = new Quaternion();
public final Quaternion quat2 = new Quaternion(); public final Quaternion quat2 = new Quaternion();
/** /**
* Eigen * Eigen
*/ */
public final Eigen3f eigen = new Eigen3f(); public final Eigen3f eigen = new Eigen3f();
/** /**
* Plane * Plane
*/ */
public final Plane plane = new Plane(); public final Plane plane = new Plane();
/** /**
* BoundingBox ray collision * BoundingBox ray collision
*/ */
@ -187,18 +234,14 @@ public class TempVars {
public final float[] fDdU = new float[3]; public final float[] fDdU = new float[3];
public final float[] fADdU = new float[3]; public final float[] fADdU = new float[3];
public final float[] fAWxDdU = new float[3]; public final float[] fAWxDdU = new float[3];
/** /**
* Maximum tree depth .. 32 levels?? * Maximum tree depth .. 32 levels??
*/ */
public final Spatial[] spatialStack = new Spatial[32]; public final Spatial[] spatialStack = new Spatial[32];
public final float[] matrixWrite = new float[16]; public final float[] matrixWrite = new float[16];
/** /**
* BIHTree * BIHTree
*/ */
public final float[] bihSwapTmp = new float[9]; public final float[] bihSwapTmp = new float[9];
public final ArrayList<BIHStackData> bihStack = new ArrayList<BIHStackData>(); public final ArrayList<BIHStackData> bihStack = new ArrayList<BIHStackData>();
} }

@ -109,7 +109,6 @@ public class WaterFilter extends Filter {
private boolean useCaustics = true; private boolean useCaustics = true;
private boolean useRefraction = true; private boolean useRefraction = true;
private float time = 0; private float time = 0;
private float savedTpf = 0;
private float reflectionDisplace = 30; private float reflectionDisplace = 30;
private float foamIntensity = 0.5f; private float foamIntensity = 0.5f;
private boolean underWater; private boolean underWater;
@ -168,7 +167,7 @@ public class WaterFilter extends Filter {
sceneCam.getFrustumTop(), sceneCam.getFrustumTop(),
sceneCam.getFrustumBottom()); sceneCam.getFrustumBottom());
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
vars.vect1.set(sceneCam.getLocation()).addLocal(sceneCam.getUp()); vars.vect1.set(sceneCam.getLocation()).addLocal(sceneCam.getUp());
float planeDistance = plane.pseudoDistance(vars.vect1); float planeDistance = plane.pseudoDistance(vars.vect1);
@ -176,8 +175,8 @@ public class WaterFilter extends Filter {
vars.vect3.set(vars.vect1.subtractLocal(vars.vect2)).subtractLocal(loc).normalizeLocal().negateLocal(); vars.vect3.set(vars.vect1.subtractLocal(vars.vect2)).subtractLocal(loc).normalizeLocal().negateLocal();
reflectionCam.lookAt(targetLocation, vars.vect3); reflectionCam.lookAt(targetLocation, vars.vect3);
vars.release();
assert vars.unlock();
if (inv) { if (inv) {
reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal()); reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal());
} }

@ -165,7 +165,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
return; return;
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Quaternion tmpRot1 = vars.quat1; Quaternion tmpRot1 = vars.quat1;
Quaternion tmpRot2 = vars.quat2; Quaternion tmpRot2 = vars.quat2;
@ -264,7 +264,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
} }
assert vars.unlock(); vars.release();
} }
@ -682,7 +682,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
baseRigidBody.setKinematic(mode == Mode.Kinetmatic); baseRigidBody.setKinematic(mode == Mode.Kinetmatic);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
link.rigidBody.setKinematic(mode == Mode.Kinetmatic); link.rigidBody.setKinematic(mode == Mode.Kinetmatic);
if (mode == Mode.Ragdoll) { if (mode == Mode.Ragdoll) {
@ -693,7 +693,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
assert vars.unlock(); vars.release();
for (Bone bone : skeleton.getRoots()) { for (Bone bone : skeleton.getRoots()) {
RagdollUtils.setUserControl(bone, mode == Mode.Ragdoll); RagdollUtils.setUserControl(bone, mode == Mode.Ragdoll);
@ -716,9 +716,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
animControl.setEnabled(true); animControl.setEnabled(true);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
@ -737,7 +735,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
link.startBlendingRot.set(q2); link.startBlendingRot.set(q2);
link.rigidBody.setKinematic(true); link.rigidBody.setKinematic(true);
} }
assert vars.unlock(); vars.release();
for (Bone bone : skeleton.getRoots()) { for (Bone bone : skeleton.getRoots()) {
RagdollUtils.setUserControl(bone, false); RagdollUtils.setUserControl(bone, false);

@ -90,14 +90,14 @@ public class DebugShapeFactory {
// apply rotation // apply rotation
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
Matrix3f tempRot = vars.tempMat3; Matrix3f tempRot = vars.tempMat3;
tempRot.set(geometry.getLocalRotation()); tempRot.set(geometry.getLocalRotation());
childCollisionShape.rotation.mult(tempRot, tempRot); childCollisionShape.rotation.mult(tempRot, tempRot);
geometry.setLocalRotation(tempRot); geometry.setLocalRotation(tempRot);
assert vars.unlock(); vars.release();
node.attachChild(geometry); node.attachChild(geometry);
} }
@ -120,17 +120,15 @@ public class DebugShapeFactory {
return geom; return geom;
} }
public static Mesh getDebugMesh(CollisionShape shape){ public static Mesh getDebugMesh(CollisionShape shape) {
Mesh mesh=null; Mesh mesh = null;
if(shape.getCShape() instanceof ConvexShape){ if (shape.getCShape() instanceof ConvexShape) {
mesh=new Mesh(); mesh = new Mesh();
mesh.setBuffer(Type.Position, 3, getVertices((ConvexShape)shape.getCShape())); mesh.setBuffer(Type.Position, 3, getVertices((ConvexShape) shape.getCShape()));
mesh.getFloatBuffer(Type.Position).clear(); mesh.getFloatBuffer(Type.Position).clear();
} } else if (shape.getCShape() instanceof ConcaveShape) {
else if(shape.getCShape() instanceof ConcaveShape) mesh = new Mesh();
{ mesh.setBuffer(Type.Position, 3, getVertices((ConcaveShape) shape.getCShape()));
mesh=new Mesh();
mesh.setBuffer(Type.Position, 3, getVertices((ConcaveShape)shape.getCShape()));
mesh.getFloatBuffer(Type.Position).clear(); mesh.getFloatBuffer(Type.Position).clear();
} }
return mesh; return mesh;

@ -29,51 +29,82 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package jme3test.app; package jme3test.app;
import com.jme3.util.TempVars; import com.jme3.util.TempVars;
import java.util.Date;
import java.util.Iterator;
public class TestTempVars { public class TestTempVars {
public static void methodThatUsesTempVars(){
TempVars vars = TempVars.get();
assert vars.lock();
{
vars.vect1.set(123,999,-55);
}
assert vars.unlock();
}
public static void main(String[] args){ public static void main(String[] args) {
System.err.println("NOTE: This test simulates a data corruption attempt\n" +
" in the engine. If assertions are enabled (-ea VM flag), the \n" + Date d,d2;
"data corruption will be detected and displayed below."); System.err.println("NOTE: This test simulates a data corruption attempt\n"
+ " in the engine. If assertions are enabled (-ea VM flag), the \n"
+ "data corruption will be detected and displayed below.");
//get the vars
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
assert vars.lock();
{
// do something with temporary vars // do something with temporary vars
vars.vect1.addLocal(vars.vect2); vars.vect1.addLocal(vars.vect2);
//release the vars
vars.release();
//Perf tests
//100 million calls
d = new Date();
for (int i = 0; i < 100000000; i++) {
methodThatUsesTempVars();
} }
assert vars.unlock(); d2 = new Date();
System.out.println("100 million calls : " +(d2.getTime() - d.getTime())+" ms");
//recursive Method
d = new Date();
recursiveMethod();
d2 = new Date();
System.out.println("100 recursive calls : " +(d2.getTime() - d.getTime())+" ms");
assert vars.lock(); d = new Date();
{ for (int i = 0; i < 1000000; i++) {
// set a value methodThatUsesTempVarsWithNoRelease();
vars.vect1.set(1,1,1); }
d2 = new Date();
System.out.println("1 million calls with no release : " +(d2.getTime() - d.getTime())+" ms");
// method that currupts the value }
methodThatUsesTempVars(); static int recurse = 0;
public static void recursiveMethod(){
TempVars vars = TempVars.get();
vars.vect1.set(123, 999, -55);
recurse++;
if(recurse<100){
recursiveMethod();
}
// read the value vars.release();
System.out.println(vars.vect1);
} }
assert vars.unlock();
public static void methodThatUsesTempVars() {
TempVars vars = TempVars.get();
{
vars.vect1.set(123, 999, -55);
}
vars.release();
}
public static void methodThatUsesTempVarsWithNoRelease() {
TempVars vars = TempVars.get();
{
vars.vect1.set(123, 999, -55);
} }
}
} }

Loading…
Cancel
Save