Collision between two complex objects?

Started by Tishu, September 05, 2011, 07:57:16 PM

Previous topic - Next topic

Tishu

Hello

I have been reading the documentation on collisions, as well as existing resource on this forum, but could not find my answer. I am trying to detect collisions between a complex object (a plane) and the ground which can be considered as a plane (it is actually an assembly of several planes grouped into one Object3D loaded via the 3DS loader).

From what I have read, if I do not want to consider the plane as an ellipsoid (I need to be accurate for example for the landing gear, the wings etc - I have tried the Ellipsoid but this did not provide accurate enough results), I need to set the ground to COLLISION_OTHERS and check collisions from it calling "checkCollision". I have now two options (let's say two as Spherical and Ellipsoid are roughly the same here).

- If I check for collisions using a casted ray from the ground, my understanding is that this does not return the new translation vector which is collision free. This is no good to me as the plane needs to "fit" the ground on landing.
- If I check for collisions using an Ellipsoid, I will need to "wrap" the ground into an Ellipsoid. Problem is that the ground is huge compared to the plane and this would not be accurate enough.

What I would be looking for really is to calculate collisions between two complex Object3D. Is this possible with the current JPCT framework and have I missed something? Or should I look for another collision detector framwork?

Thanks in advance.
Nicolas

EgonOlsen

You could use the calcMinDistance method. It's basically the same as the ray-polygon-collision detection but it returns the distance instead of the hit object. You can use that distance to calculate the translation vector on your own.

Tishu

Thanks for your quick reply. Much appreciated. This seems to be what I am looking for. I am now trying to make it work in practice, and am having a few problems. The values returned by this method do not make sense to me, I must be doing something wrong. As per the below picture, I have a plane (black), the translation vector for the next frame (red) and the ground (blue).



I have enabled COLLISION_CHECK_OTHER on the ground, with collision improvement. To check collision, I use the following code:


public float checkCollision(SimpleVector sv)
{
// sv is the opposite the plane movement
final int id = ground.checkForCollision(sv, 10);
if(id != Object3D.NO_OBJECT)
{
return ground.calcMinDistance(ground.getTransformedCenter(), sv);
}
return Object3D.NO_OBJECT;
}


In this scenario, the collision is never detected (id is always Object3D.NO_OBJECT even if I fly trough the sea). Also when I check values for the min distance, it varies between 1E12 (max float I guess) and figures between 50 and 200 depending on the areas I fly over but not depending on my altitude. I would like to remind that the ground is a set of Object3D laoded via 3DS and regrouped via the following code, but should still behave as an atomic object right?


private static Object3D loadModel(InputStream file, float scale) {
Object3D[] model = Loader.load3DS(file, scale);
        Object3D o3d = new Object3D(0);
        Object3D temp = null;
        for (int i = 0; i < model.length; i++) {
temp = model[i];
temp.setCenter(SimpleVector.ORIGIN);
temp.rotateX((float)( -.5*Math.PI));
temp.rotateMesh();
temp.setRotationMatrix(new Matrix());
o3d = Object3D.mergeObjects(o3d, temp);
o3d.build();
}
        return o3d;
}


Thanks for you patience
Nicolas

EgonOlsen

Remove the checkForCollision-calls. They are not needed here. Just use the calcMinDistance with sv being a unit vector (i.e. normalize it). If the result isn't Object3D.COLLISION_NONE, multiply it with the normalized sv to get the actual translation vector.
In your picture, it looks like as if the translation vector of the plane is in parallel to the plane...in that case, no collision will be detection.

Tishu

I agree that on my picture there is no collision - it was more to show a generic case. But even when I fly trough the object representing the water, I do not get a collision.

I have tried your suggestion. I changed the collision detection method to:


public float checkCollision(SimpleVector sv)
{
sv = sv.normalize();
final float minDist = ground.calcMinDistance(ground.getTransformedCenter(), sv);
if(!(minDist == Object3D.COLLISION_NONE))
{
Log.e("Collision", Float.toString(minDist));
}
return null;
}


Collision is almost never triggered when I fly trough the plane, but is sometimes randomely triggered for some minDist figures around 50.

I strongly suspect that I am doing something wrong, perhaps with the coordinates system, but could not find anything obvious. I have even changed the translation vector sv to always point straight up towards the plane.

Would you mind if I sent you my two models? Without textures, but they should still load properly. I load them via the code pasted a few messages above. For the plane, I do not set any collision attributes. For the ground, I set


ground.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
ground.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);


Many thanks
Nicolas

EgonOlsen

If you want me to look at it, please send me a test case that i can compile and execute without having to write my own one.

EgonOlsen

While looking at the code: Why are you calculating the distance between the ground and the...ground?


ground.calcMinDistance(ground.getTransformedCenter(), sv);

Tishu

This might be why! Perhaps I misunderstood the arguments of this method:


public float calcMinDistance(SimpleVector org, SimpleVector dr)
Returns the minimal distance to some polygon of the object from a particular position vector looking into a specific direction.

org - a SimpleVector containing the position vector
dr - a SimpleVector containing the direction vector


I assumed that org was the initial position of the ground, and from there it tried to move dr. If it hit any other polygon of the world, that's a collision.

I agree that in this case it does not make much sense passing the first argument, but what should it be then?

EDIT: Or should I calculate the distance from the center of the plane? In that case, how do I know whether it is the wing or the landing gear that has hit the ground?

Thx

EgonOlsen

It's the position in world space from which sv starts.

Tishu

I tried to use plane.getTransformedCenter as you recommended and I agree the figures I see make much more sense. I am not sure I understand why however.

If org is the position in world space from where the translation starts, it seems correct to me to start translating the ground from where it is (ground.getTransformedCenter()) with a vector which is opposite to the plane's movement. This is equivalent as moving the plane towards the ground with its own motion vector.

Moreover, if I calculate such distance from the plane center, this does not allow me to do what I was initially trying to do which is to find out which part of the plane hits the ground.

EgonOlsen

The thing is, that you can't calculate a distance between the ground and the ground. The transformed center of the ground lies within the ground itself...you won't get a reasonable result out of this no matter what value sv has.
If you want to check different parts of the plane against the ground, you can do that. You don't have to use the center, it can be any other position vector. You can either place dummy objects at the points of the plane that you want to check and make them child objects of the plane or use the plane's vertices directly. You can obtain a PolygonManager from any Object3D, which has a method to transform any vertex of it into world space. The remaining problem is to find out which vertices of the plane you want to use...i guess that this will be a little bit of trial and error work...

Tishu

That you very much for your help. It made it a lot clearer to me.

I have now pretty much worked how the transformed center of the plane collides with the ground in my code, it will be possible for me to finish the job with the few tips on your last message.

Regards,
Nicolas