[SOLVED] Issue with Collisions on Models Imported by XmlImporter

Hey folks,



I can't get collisions to work on the models I import using XmlImporter and I'm just baffled.   :?  I've already spent way too much time on this problem, so I hope one of the experienced people here can point me to what I'm overlooking.



Here's example code that does not properly detect a collision:



Spatial sp = null;

String model = g.get(Graphic.MODEL);
URL u = JmeEasyButton.class.getResource(Constants.MODELS_LOCATION + model);
try {
    sp = (Spatial) XML_IMPORTER.load(u);
} catch (Throwable t) {
    String msg = "Unable to load the specified MODEL:  " + model;
    throw new RuntimeException(msg, t);
}

// Set up the BoundingVolume...
sp.setModelBound(new BoundingBox());
sp.updateModelBound();

sp.getLocalTranslation().set(new Vector3f());

// Calculate the Spatial's bottom using a Ray...
Vector3f origin = new Vector3f(0.0f, Float.MIN_VALUE, 0.0f);
Ray r = new Ray(origin, new Vector3f(0.0f, Float.MIN_VALUE + 1.0f, 0.0f));
PickResults pr = new BoundingPickResults();
pr.setCheckDistance(true);
sp.findPick(r, pr);

System.out.println("  > g.get(Entity.NAME)="+g.get(Entity.NAME));
System.out.println("  > pr.getNumber()="+pr.getNumber());

if (pr.getNumber() > 0) {
    PickData pd = pr.getPickData(0);
    float pointOfCollision = Float.MIN_VALUE + pd.getDistance();

    System.out.println("  > pointOfCollision="+pointOfCollision);
}



I know from the "System.out" statements that the PickResults contains zero results.  Also, in another place in my game I attempt to detect when the mouse moves over these obects via collisions -- that doesn't work either.

Lastly, if instead of loading a model I just create a simple sphere like this...


// This is just a placeholder until we get a model...
sp = new Sphere(name.toString(), 30, 30, scale.toGameUnits(1.5f));



all the picking/collision code works just fine.   :(

Any hints?  
haruspex said:

I know from the "System.out" statements that the PickResults contains zero results.  Also, in another place in my game I attempt to detect when the mouse moves over these obects via collisions -- that doesn't work either.


***** SOLUTION *****

It turns out that both my issues stemmed from the fact that the XmlImporter returns a Node (i.e. an aggregate of many Spatial objects, not a single Spatial object).

In establishing BoundingVolume, the updateModelBound() method works differently for Nodes than it does for simpal Spatials.  A Node object cannot accurately detect collisions until its updateWorldBound() method is invoked, whereas updateModelBound() is good enough for simple Spatials.

That was my first issue, as shown in the code above:  using findPick() on a Node before calling updateWorldBound().

My second issue -- detecting when the mouse moves over a Node -- was slightly different.  It turns out that when you use findPick() and you're looking for something that's a Node, the entries in your PickResults don't actually point to the Node you're looking for.  They will point to some Spatial within the Node.
haruspex said:
...

It turns out that both my issues stemmed from the fact that the XmlImporter returns a Node (i.e. an aggregate of many Spatial objects, not a single Spatial object).
...



For one thing, a Node is a single Spatial, but I see that what is happening that you don't want is you are getting a Node and its descendants.

XmlImporter will not return a Node unless that is what the root element in your model file is.  I often use XmlImporter to load custom classes from XML model files with no Node involvement.

If you want to import a single Geometry and your model file has more than that, then just edit the model file with a good editor (XML editor or not) and remove all the crap above and below the desired Geometry subclass element.