Extension of CollisionShapeFactory

For my own use, I extended CollisionShapeFactory, so you can create Individual MeshCollisionShapes, BoxCollisionShapes, and two short-cut methods, for the lazy one out there! :smiley:



Here's the code:

(Btw… already tested it, TestQ3 is still working  :D)


import com.jme3.bounding.BoundingBox;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.CompoundCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;

/**
 *
 * @author normenhansen, tim8dev
 */
public class CollisionShapeFactory {

    private static CompoundCollisionShape createCompoundShape(
            Node rootNode, CompoundCollisionShape shape, boolean meshAccurate) {
        for (Spatial spatial : rootNode.getChildren()) {
            if (spatial instanceof Node) {
                createCompoundShape((Node) spatial, shape, meshAccurate);
            } else if (spatial instanceof Geometry) {
                shape.addChildShape(
                        meshAccurate?
                            createSingleMeshShape((Geometry) spatial) :
                            createSingleBoxShape(spatial),
                        spatial.getWorldTranslation(),
                        spatial.getWorldRotation().toRotationMatrix());
            }
        }
        return shape;
    }

    public static CompoundCollisionShape createMeshCompoundShape(Node rootNode){
        rootNode.updateGeometricState();
        return createCompoundShape(rootNode, new CompoundCollisionShape(), true);
    }

    public static CompoundCollisionShape createBoxCompoundShape(Node rootNode) {
        rootNode.updateGeometricState();
        return createCompoundShape(rootNode, new CompoundCollisionShape(), false);
    }

    public static CollisionShape createMeshShape(Spatial spatial) {
        if(spatial instanceof Geometry)
            return createSingleMeshShape((Geometry) spatial);
        else if (spatial instanceof Node)
            return createMeshCompoundShape((Node) spatial);
        else
            throw new IllegalArgumentException("Supplied spatial must either be Node or Geometry!");
    }

    public static CollisionShape createBoxShape(Spatial spatial) {
        if(spatial instanceof Geometry)
            return createSingleBoxShape((Geometry) spatial);
        else if (spatial instanceof Node)
            return createBoxCompoundShape((Node) spatial);
        else
            throw new IllegalArgumentException("Supplied spatial must either be Node or Geometry!");

    }

    public static MeshCollisionShape createSingleMeshShape(Geometry geom) {
        Mesh mesh = geom.getMesh();
        if (mesh != null) {
            MeshCollisionShape mColl = new MeshCollisionShape(mesh);
            mColl.setScale(geom.getWorldScale());
            return mColl;
        } else {
            return null;
        }
    }

    public static BoxCollisionShape createSingleBoxShape(Spatial spatial) {
        spatial.setModelBound(new BoundingBox());
        spatial.updateGeometricState();
        spatial.updateModelBound();
        BoxCollisionShape shape = new BoxCollisionShape(
                ((BoundingBox) spatial.getWorldBound()).getExtent(new Vector3f()));
        return shape;
    }
}

Cool, thanks!

I will move this thread to the contrib depot. Already some nice stuff there for jme3 physics, keep 'em coming :smiley:

Before you contribute…

I've added some Methods for DynamicMeshShapes (GImpactShape),

btw… you can make compoundshapes out of them, can't you? (didn't tested it yet  )



import com.jme3.bounding.BoundingBox;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.CompoundCollisionShape;
import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;

/**
 *
 * @author normenhansen, tim8dev
 */
public class CollisionShapeFactory {
    private static CompoundCollisionShape createCompoundShape(
            Node rootNode, CompoundCollisionShape shape, boolean meshAccurate, boolean dynamic) {
        for (Spatial spatial : rootNode.getChildren()) {
            if (spatial instanceof Node) {
                createCompoundShape((Node) spatial, shape, meshAccurate);
            } else if (spatial instanceof Geometry) {
                if(meshAccurate) {
                    CollisionShape childShape = dynamic ?
                            createSingleMeshShape((Geometry) spatial) :
                            createSingleDynamicMeshShape((Geometry) spatial);
                    if(childShape != null)
                        shape.addChildShape(childShape,
                            spatial.getWorldTranslation(),
                            spatial.getWorldRotation().toRotationMatrix());
                } else {
                    shape.addChildShape(createSingleBoxShape(spatial),
                            spatial.getWorldTranslation(),
                            spatial.getWorldRotation().toRotationMatrix());
                }
            }
        }
        return shape;
    }

    public static CompoundCollisionShape createCompoundShape(
            Node rootNode, CompoundCollisionShape shape, boolean meshAccurate) {
        return createCompoundShape(rootNode, shape, meshAccurate, false);
    }

    public static CompoundCollisionShape createMeshCompoundShape(Node rootNode){
        rootNode.updateGeometricState();
        return createCompoundShape(rootNode, new CompoundCollisionShape(), true);
    }


    public static CompoundCollisionShape createBoxCompoundShape(Node rootNode) {
        rootNode.updateGeometricState();
        return createCompoundShape(rootNode, new CompoundCollisionShape(), false);
    }

    public static CollisionShape createMeshShape(Spatial spatial) {
        if(spatial instanceof Geometry)
            return createSingleMeshShape((Geometry) spatial);
        else if (spatial instanceof Node)
            return createMeshCompoundShape((Node) spatial);
        else
            throw new IllegalArgumentException("Supplied spatial must either be Node or Geometry!");
    }

    public static CollisionShape createDynamicMeshShape(Spatial spatial) {
        if(spatial instanceof Geometry)
            return createSingleDynamicMeshShape((Geometry) spatial);
        else if (spatial instanceof Node)
            return createDynamicMeshCompoundShape((Node) spatial);
        else
            throw new IllegalArgumentException("Supplied spatial must either be Node or Geometry!");

    }

    public static CollisionShape createBoxShape(Spatial spatial) {
        if(spatial instanceof Geometry)
            return createSingleBoxShape((Geometry) spatial);
        else if (spatial instanceof Node)
            return createBoxCompoundShape((Node) spatial);
        else
            throw new IllegalArgumentException("Supplied spatial must either be Node or Geometry!");
    }

    public static MeshCollisionShape createSingleMeshShape(Geometry geom) {
        Mesh mesh = geom.getMesh();
        if (mesh != null) {
            MeshCollisionShape mColl = new MeshCollisionShape(mesh);
            mColl.setScale(geom.getWorldScale());
            return mColl;
        } else {
            return null;
        }
    }

    public static BoxCollisionShape createSingleBoxShape(Spatial spatial) {
        spatial.setModelBound(new BoundingBox());
        spatial.updateGeometricState();
        spatial.updateModelBound();
        BoxCollisionShape shape = new BoxCollisionShape(
                ((BoundingBox) spatial.getWorldBound()).getExtent(new Vector3f()));
        return shape;
    }

    public static GImpactCollisionShape createSingleDynamicMeshShape(Geometry geom) {
        Mesh mesh = geom.getMesh();
        if(mesh != null) {
            GImpactCollisionShape dynamicShape = new GImpactCollisionShape(mesh);
            dynamicShape.setScale(geom.getWorldScale());
            return dynamicShape;
        } else {
            return null;
        }
    }
}

Right now we are all collecting and testing more than committing I suppose, so take your time testing and extending :wink:

added to svn