CollideWith optimization with CollisionResult allocation avoided

experimental
Bebul 10 years ago
parent b46973f33f
commit 75a801f0f7
  1. 45
      jme3-core/src/main/java/com/jme3/bounding/BoundingBox.java
  2. 42
      jme3-core/src/main/java/com/jme3/bounding/BoundingSphere.java
  3. 11
      jme3-core/src/main/java/com/jme3/bounding/BoundingVolume.java
  4. 77
      jme3-core/src/main/java/com/jme3/collision/DummyCollisionResults.java
  5. 8
      jme3-core/src/main/java/com/jme3/scene/Node.java

@ -761,6 +761,35 @@ public class BoundingBox extends BoundingVolume {
}
}
private int collideWithRay(Ray ray) {
TempVars vars = TempVars.get();
try {
Vector3f diff = vars.vect1.set(ray.origin).subtractLocal(center);
Vector3f direction = vars.vect2.set(ray.direction);
//float[] t = {0f, Float.POSITIVE_INFINITY};
float[] t = vars.fWdU; // use one of the tempvars arrays
t[0] = 0;
t[1] = Float.POSITIVE_INFINITY;
float saveT0 = t[0], saveT1 = t[1];
boolean notEntirelyClipped = clip(+direction.x, -diff.x - xExtent, t)
&& clip(-direction.x, +diff.x - xExtent, t)
&& 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);
if (notEntirelyClipped && (t[0] != saveT0 || t[1] != saveT1)) {
if (t[1] > t[0]) return 2;
else return 1;
}
return 0;
} finally {
vars.release();
}
}
public int collideWith(Collidable other, CollisionResults results) {
if (other instanceof Ray) {
Ray ray = (Ray) other;
@ -777,6 +806,22 @@ public class BoundingBox extends BoundingVolume {
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
}
}
@Override
public int collideWith(Collidable other) {
if (other instanceof Ray) {
Ray ray = (Ray) other;
return collideWithRay(ray);
} else if (other instanceof Triangle) {
Triangle t = (Triangle) other;
if (intersects(t.get1(), t.get2(), t.get3())) {
return 1;
}
return 0;
} else {
throw new UnsupportedCollisionException("With: " + other.getClass().getSimpleName());
}
}
/**
* C code ported from <a href="http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt">

@ -792,7 +792,35 @@ public class BoundingSphere extends BoundingVolume {
return 1;
}
}
private int collideWithRay(Ray ray) {
TempVars vars = TempVars.get();
Vector3f diff = vars.vect1.set(ray.getOrigin()).subtractLocal(
center);
float a = diff.dot(diff) - (getRadius() * getRadius());
float a1, discr;
if (a <= 0.0) {
// inside sphere
vars.release();
return 1;
}
a1 = ray.direction.dot(diff);
vars.release();
if (a1 >= 0.0) {
return 0;
}
discr = a1 * a1 - a;
if (discr < 0.0) {
return 0;
} else if (discr >= FastMath.ZERO_TOLERANCE) {
return 2;
}
return 1;
}
private int collideWithTri(Triangle tri, CollisionResults results) {
TempVars tvars = TempVars.get();
try {
@ -991,6 +1019,18 @@ public class BoundingSphere extends BoundingVolume {
}
}
@Override public int collideWith(Collidable other) {
if (other instanceof Ray) {
Ray ray = (Ray) other;
return collideWithRay(ray);
} else if (other instanceof Triangle){
return super.collideWith(other);
} else {
throw new UnsupportedCollisionException();
}
}
@Override
public boolean contains(Vector3f point) {
return center.distanceSquared(point) < (getRadius() * getRadius());

@ -32,10 +32,12 @@
package com.jme3.bounding;
import com.jme3.collision.Collidable;
import com.jme3.collision.CollisionResults;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.Savable;
import com.jme3.math.*;
import com.jme3.util.TempVars;
import java.io.IOException;
import java.nio.FloatBuffer;
@ -322,6 +324,15 @@ public abstract class BoundingVolume implements Savable, Cloneable, Collidable {
public void read(JmeImporter e) throws IOException {
center = (Vector3f) e.getCapsule(this).readSavable("center", Vector3f.ZERO.clone());
}
public int collideWith(Collidable other) {
TempVars tempVars = TempVars.get();
CollisionResults tempResults = tempVars.collisionResults;
tempResults.clear();
int retval = collideWith(other, tempResults);
tempVars.release();
return retval;
}
}

@ -1,77 +0,0 @@
/*
* Copyright (c) 2009-2014 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.collision;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* <code>DummyCollisionResults</code> is an empty "dummy" collection returned as a result of a
* collision detection operation done by {@link Collidable}.
* Its purpose is to avoid allocation of CollisionResults and its content,
* when collisionResults are out of our interest.
* Using the same API Collidable.collideWith() instead of possibly some new countCollideWith() implementation
* is chosen to keep the collision detection code "DRY", @see <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don't repeat yourself</a>
*
* @author Bebul
*/
public class DummyCollisionResults extends CollisionResults {
// the singleton for DummyCollisionResults is sufficient
private static DummyCollisionResults instance = null;
// exists only to defeat instantiation
protected DummyCollisionResults() {}
// classic singleton instance
public static DummyCollisionResults getInstance() {
if ( instance == null ) {
instance = new DummyCollisionResults();
}
return instance;
}
// Dummy implementation of CollisionResults
// All methods can be dummy except for iterator
@Override public void clear(){}
// even dummy iterator should return valid iterator
@Override public Iterator<CollisionResult> iterator() {
List<CollisionResult> dumbCompiler = Collections.emptyList();
return dumbCompiler.iterator();
}
@Override public void addCollision(CollisionResult result){}
@Override public int size(){ return 0; }
@Override public CollisionResult getClosestCollision(){ return null; }
@Override public CollisionResult getFarthestCollision(){ return null; }
@Override public CollisionResult getCollision(int index){ return null; }
@Override public CollisionResult getCollisionDirect(int index){ return null; }
}

@ -34,12 +34,12 @@ package com.jme3.scene;
import com.jme3.bounding.BoundingVolume;
import com.jme3.collision.Collidable;
import com.jme3.collision.CollisionResults;
import com.jme3.collision.DummyCollisionResults;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.Savable;
import com.jme3.material.Material;
import com.jme3.util.SafeArrayList;
import com.jme3.util.TempVars;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -499,10 +499,8 @@ public class Node extends Spatial implements Savable {
BoundingVolume bv = this.getWorldBound();
if (bv==null) return 0;
// use DummyCollisionResults to avoid allocation while making the call to any BoundingVolume.collideWith possible
// moreover, the DummyCollisionResults operations are empty, so faster
DummyCollisionResults dummyColRes = DummyCollisionResults.getInstance();
if (bv.collideWith(other, dummyColRes) == 0) return 0;
// collideWith without CollisionResults parameter used to avoid allocation when possible
if (bv.collideWith(other) == 0) return 0;
}
for (Spatial child : children.getArray()){
total += child.collideWith(other, results);

Loading…
Cancel
Save