HullShapeOptimizer

As Bullet need quite long to create HullCollisionShapes out of normal rendering models, I searched for ways to do the complex part of the calculation before it runs.

So I searchd for implemented algorithms in java tha optimize a pointcloud to a efficient hull and found this one here:
http://www.cs.ubc.ca/~lloyd/java/quickhull3d.html

I wrote a small wrapper for this to use in conjunction with a HullCollisionShape, and it is quite fast, in fact it is way faster than the bullet internal optimisation.
I used it in my testcase for a car chassis
(http://www.dexsoft-games.com/models/viper.html)
prior needed 5 seconds to generate the hullshape,
now its less than 100ms, for no toher ingame difference this is a great result. And I thought others might want to know about this.

If there is any interest/chance that this could get into the contributions/physicutils I would clean it up (add missing methods, docu, port to float for performance as jme only uses float anyway ect) and integrate it a bit more. The license of the used library should be compatible with jme. (see below)

Basically the jar just needs to be put into the buildpath, and then this small snippet:

[java]
/**
*
* @param mesh
* The to calculate the Optimized Shape for
* @param precision
* Sets an explicit distance tolerance for convexity tests. If AUTOMATIC_TOLERANCE (-1) is specified , then the tolerance will be computed automatically from the point data.
*
* @see #getDistanceTolerance
*
* @return
*/
private float[] getOptimizeHullPoints(final Mesh mesh, final float precision) {
final FloatBuffer vertices = mesh.getFloatBuffer(Type.Position);
vertices.rewind();
final int components = mesh.getVertexCount() * 3;
final double[] pointsArray = new double[components];
for (int i = 0; i < components; i += 3) {
pointsArray[i] = vertices.get();
pointsArray[i + 1] = vertices.get();
pointsArray[i + 2] = vertices.get();
}
final QuickHull3D quickHull = new QuickHull3D();
quickHull.setExplicitDistanceTolerance(precision);
quickHull.build(pointsArray);
final double[] output = new double[quickHull.getNumVertices() * 3];
quickHull.getVertices(output);
final float[] floatOutput = new float[output.length];
for (int i = 0; i < floatOutput.length; i++) {
floatOutput[i] = (float) output[i];
}
System.out.println("Reduced from " + mesh.getVertexCount() + " to " + quickHull.getNumVertices());
return floatOutput;
}

[/java]

/**
  * Copyright John E. Lloyd, 2004. All rights reserved. Permission to use,
  * copy, modify and redistribute is granted, provided that this copyright
  * notice is retained and the author is given credit whenever appropriate.
  *
  * This  software is distributed "as is", without any warranty, including 
  * any implied warranty of merchantability or fitness for a particular
  * use. The author assumes no responsibility for, and shall not be liable
  * for, any special, indirect, or consequential damages, or any damages
  * whatsoever, arising out of or in connection with the use of this
  * software.
  */
6 Likes

Hehe, cool, thanks.

Maybe you want to contribute to bullet directly, too? :wink:

@EmpirePhoenix: Bullet already includes convex hull:
http://bulletphysics.org/Bullet/BulletFull/classbtShapeHull.html
http://bulletphysics.org/Bullet/BulletFull/classHullLibrary.html

@Momoko_Fan said: @EmpirePhoenix: Bullet already includes convex hull: http://bulletphysics.org/Bullet/BulletFull/classbtShapeHull.html http://bulletphysics.org/Bullet/BulletFull/classHullLibrary.html

What he says is that now he can make these faster from a jme mesh because he optimizes the vertices for it before he creates the hull, if I got him right.

@normen said: What he says is that now he can make these faster from a jme mesh because he optimizes the vertices for it before he creates the hull, if I got him right.
The bullet class I mentioned is used exactly for that purpose.
@Momoko_Fan said: The bullet class I mentioned is used exactly for that purpose.

And it apparently takes 5s to boil down the vertices as opposed to 100ms with Empires code…?

@normen said: And it apparently takes 5s to boil down the vertices as opposed to 100ms with Empires code..?
Because he didn't use btConvexHull (utility class) to generate the point cloud, he fed his mesh directly into btConvexHullShape without any preprocessing.
@Momoko_Fan said: Because he didn't use btConvexHull (utility class) to generate the point cloud, he fed his mesh directly into btConvexHullShape without any preprocessing.
Ah right, I would have thought the ConvexHullShape uses that. But I guess since feed it the points directly it even recalcs it on every vertex. Still having this one the java side could reduce the data copying for large meshes (which this is apparently for).
@normen said: Ah right, I would have thought the ConvexHullShape uses that. But I guess since feed it the points directly it even recalcs it on every vertex. Still having this one the java side could reduce the data copying for large meshes (which this is apparently for).
I think we should expose btConvexHull on the Java side, its algorithm is superior to quickhull3d. This will let you retrieve the point cloud and persist it with your J3O file so you don't have to recalculate it at runtime.
@Momoko_Fan said: I think we should expose btConvexHull on the Java side, its algorithm is superior to quickhull3d. This will let you retrieve the point cloud and persist it with your J3O file so you don't have to recalculate it at runtime.

Yes but you still have to copy over the whole mesh before you get the points if you use bullet for this. Storage wise its always just saving the points you supply, also right now.

As long as there is stuff like this:

void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)

in the native code, without any comment on what it actually does, I prefer a clean documented pure java solution every time.

1 Like

I’m not dead!

Edit : sorry about that, go on with your conversation

2 Likes

Can’t wait for Halloween :slight_smile: I’m gonna scare me some kids (And I don’t even have to dress up)

Another reason for a pure java solution would be the compability with jbullet, as else you are forced to native ones.