ComplexCollisionShape made of Complex collision shapes

There are several ways of looking at the problem I am having. One is to say that I am letting users load custom vehicle models created from multiple 3D models. For instance, the wheels are 1 model, the body could be made from multiple different parts, the driver is another custom 3d model. How to I add the collision shapes of these models to the vehicleControl?

I’ve tried creating a compound collision shape from the model (or a hullcollisionshape) and adding it to the compioundCollisionShape of the vehicle which already exists, but I get the error that

CompoundCollisionShapes cannot have CompoundCollisionShapes as children!

Currently I am using the Ninja model as an example “driver” that a user could design to look like themselves, then load into the game.

The code below shows a collision shape when I turn on the debug shapes of the ninja, but it doesn’t collide with objects in the world. This type of RigidBody code isn’t correct for adding to a vehicle, but it code works fine for objects I load into the world and is the only way I can get the debugShape to show up for the Ninja.

[java] public void addModel(PhysicsSpace physicsSpace, Node vehicleNode, AssetManager assetManager, Node Collidables, CompoundCollisionShape compoundShape) {

    /** Load a OGREMesh model (OgreXML + material + texture from test_data) */
    System.out.println("Creating a ORGEmesh Model at path "+pathToNinjaFile);
    Spatial modelObject = assetManager.loadModel(pathToNinjaFile);
 
    modelObject.setLocalTranslation(this.worldX, this.worldY, this.worldZ);

            
    //scale the model to user specs, default to 100%
    modelObject.scale(scale);

    //Set up physics for this model
    RigidBodyControl model_phy = new RigidBodyControl(10);

    /** Add physical brick to physics space. */
    modelObject.addControl(model_phy);
    physicsSpace.add(model_phy);
    Collidables.attachChild(modelObject);


   vehicleNode.attachChild(modelObject); //Makes the model visible

}//End addModel

Any help would be appreciated!

Is this really needed? Are the wheels/driver/etc possibilities actually different enough that they need a different collision shape?

That is just a simple example. In fact, the vehicle is completely designed by the user. It can literally be anything. The reason is that this isn’t a regular game, it is a robotics simulator, simulating actual hardware.

I already have it working with native jmonkey shapes, boxes, cylinders, etc. My problem is that if the users need to create a more photorealistic model of a sensor on the robot. They could design the part in CAD/Blender and they would bring in each piece of the vehicle separately. The reason is that each piece has its own mass, which would allow me to calculate the COG of the vehicle with all parts added (I calculate this and change the location of the compoundcollisionshape to change the COG of the vehicle). Each part also needs its own location and rotation relative to the robot. This is required for being able to accurately simulate from the location of that particular sensor.

TLDR; Yes, it has to be this way.

If there isn’t a way to add a complex collision shape as a child, then is there at least some way to make a simple collision shape based on the length height and width of a model’s mesh?

For instance, could a box or capsule could be used based on the size of the model’s mesh? How could I get the extremes of a model’s mesh?

@morrowsend said: If there isn't a way to add a complex collision shape as a child, then is there at least some way to make a simple collision shape based on the length height and width of a model's mesh?

For instance, could a box or capsule could be used based on the size of the model’s mesh? How could I get the extremes of a model’s mesh?

You mean like this?
http://hub.jmonkeyengine.org/javadoc/com/jme3/scene/Mesh.html#getBound()

Thanks! This put me on the right track for sure! Since I can’t have a perfect mesh, the extents of the bounding box will do nicely for a general Box collision shape encompassing the models.

Well you could try to use the gimpact shapes, assumingt that for a robot simulation there wont be many physic objects the additional precessing need might be worth it.

I can’t always assume that I will be able to cast the model (a Spatial) as a Geometry to create the mesh. For instance, it won’t work on the Ninja.

Also, since I won’t necessarily know what the mesh(s) might be named (since the user created it/them) I don’t know how I can find the geometry looking at all the children. I can’t, for example, use the findGeom(Spatial, String meshName) like in the Fancycar demo. Is there another way?

You could always loop over the children checking if they are a geometry.

I didn’t know it was possible to tell if a child was a geometry on its own. Once you said that, I looked on the forum and found some code from this link: http://hub.jmonkeyengine.org/forum/topic/batchnode-modification-proposal/ I would have assumed that a Spatial that is loaded would not be able to have the specific type of objects the children were (I thought they were all Spatials that the developer would have to cast into whatever they wanted.) I will have to take a closer look at this.

[java]
Spatial s;
if (s instanceof Geometry) {
do stuff to (Geometry)s
} else if (s instanceof Node) {
do stuff to (Node)s;
}
[/java]

For example if its a node you could recurse and call the same method for every child…

OK, so I have this working, however when I scale my Spatial (model) then create a GImpactCollisionShape from the mesh, it isn’t scaled. Even when i specifically scale the geometry first as shown below. Any ideas?

[java]public void addModel(){

/* Using GImpactCollisionShape which is mesh-accurate but CPU intensive */
Geometry modelGeom = getGeometry(modelObject);
modelGeom.scale(scale);
GImpactCollisionShape colShape = new GImpactCollisionShape(modelGeom.getMesh());
vehicleNode.attachChild(modelObject); //Makes the model visible
//Vector3f collisionLocation = new Vector3f(this.worldX, this.worldY, this.worldZ);
compoundShape.addChildShape(colShape, Vector3f.UNIT_Y, rotMatrix);
}

protected Geometry getGeometry(Spatial n) {
Spatial s = ((Node)n).getChild(0);
System.out.println(“getting root child”);
while (s instanceof Node) {
s = ((Node)s).getChild(0); // descend into the child node
System.out.println(“getting next child”);
}
if (s instanceof Geometry) {
System.out.println(“Found Geometry”);
return (Geometry)s;
} else{
System.out.println(“I Dunno…”);}
return null;
}[/java]

Some shapes do not support scaling, not sure if the gimpact is affected by this.

Sorry for the late reply, but I found it yesterday. I should have posted it then. You have to explicitly scale the GImpactShape as well as the Spatial. That way the physics will match the graphics.: eg
[java]colShape.setScale (New Vector3f (scale, scale, scale)); [/java]

Actually, I’ve found that once you scale the GImpactCollisionShape, it no longer collides with anything. That’s weird. I suppose I’ll have to mention to my users that they must make models 1:1 scale I suppose.