Inconsistency in collision detection

Started by Tishu, September 12, 2011, 01:06:20 PM

Previous topic - Next topic

Tishu

Hello

I am using collision detection from a plane to a point using the calcMinDistance method. I use the following code:


public double checkLeftGearCollisionDz(double modelDz)
{
final SimpleVector uiDz = new SimpleVector(0, -1, 0);
final float minDist = ground.calcMinDistance(leftGear.getTransformedCenter(), uiDz);
if(!(minDist == Object3D.COLLISION_NONE) && minDist > modelDz) // values are <0
{
return 0;
//return minDist < 0.5 ? 0 : minDist*modelDz;
}
return Object3D.COLLISION_NONE;
}


I place my plane a bit over the ground, and it falls nicely on it. Collision works fine, as I can see in the figues I write in the logs. Then I start rolling forward, and at some point it will fail. The values I pass to the collision detection are consistent though:


Z before(22996): 4.150430202484131
dZ tentative(22996): -0.11481471204757691
actual dZ(22996): 0.0

Z before(22996): 4.150430202484131
dZ tentative(22996): -0.10089619320631027
actual dZ(22996): 0.0

Z before(22996): 4.150430202484131
dZ tentative(22996): -0.12035272479057313
actual dZ(22996): 0.0

Z before(22996): 4.150430202484131
dZ tentative(22996): -0.10804409158229827
actual dZ(22996): -0.10804409158229827


Z before is the position of the plane before calcMinDistance. This remains constant. On each frame I try to move the plane by dZ tentative and check if this makes it collide with the ground. If yes, I use 0 for actual dZ.
On the last frame, my Z before has not changed, the dZ tentative is a value I have tried before, but calcMinDistance returns Object3D.COLLISION_NONE and actual dZ is non zero -> the plane goes trough the ground.

I have taken a look at this thread
http://www.jpct.net/forum2/index.php/topic,1376.msg9655.html#msg9655
I increased the value of collideOffset to 500 with no success (even tried 5000, made no difference)

I also saw this one
http://www.jpct.net/forum2/index.php/topic,335.msg1825.html#msg1825
And I tried using an octree:


final Object3D world = loadGround(is, 1);
world.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
final OcTree o = new OcTree(world, 100, OcTree.MODE_OPTIMIZED);
o.setCollisionUse(OcTree.COLLISION_USE);
world.setOcTree(o);     
world.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);
r.ground = world;


Tried difference values for the maxPoly. I get a StackOverFlowException for values <100, and no difference in collision detection for values >100.

It seems to me that there is an area in the ground where collision just won't happen.

Thx
Nicolas

EgonOlsen

What is modelDz? I'm a bit puzzled about this "minDist > modelDz"-condition...have you checked the actual return value of calcMinDistance in the case that has the problem? I would be interested if the method itself returns "no collision" or if you "invent" this with this condition in your code!?

Tishu

It does return COLLISION_NONE.

modelDz is how much the model would like the plane to move. I check how much I can move in that direction (minDist, which should rather be called maxDz), and I can move less that what the model wants to move, I stay still Z-axis wise.

I really think there is like  a "hole" in the ground, as no matter how I approach it, it goes trough the floor at the same place.

Thx
Nic

Tishu

To illustrate this, rolling always is fine until I get to the point on the picture below. I can see the end of a face (with the texture being discontinuous) and when I get to the next one, I fall through it.


Tishu

#4
It seems that the sign of the return value of calcMinDistance is dictated by the direction of the normal of my plane. I fixed the normals in Blender and it works good now.

Thx
Nic

Edit: Correction before I'm told off by EgonOlsen :), if does not just dictate the sign of the return value, it seems to dictate the direction where it moves for collision detection, hence sometimes I got COLLISION_NONE as it was moving in the opposite direction

EgonOlsen

 ??? I'm not doing anything with the normals from any model in jPCT. Or was culling disabled on the model? In that case, you will create holes for the collision detection on all faces that would otherwise be culled, because collision detection doesn't happen on back faces.

Tishu

That makes completely sense - culling was disabled. I've reenabled it now after sorting the normals. All behave well.

Thx
Nic

Tishu

Actually I still think the behaviour is weird. I've turned culling back off:


plane.setCulling(Object3D.CULLING_DISABLED);
ground.setCulling(Object3D.CULLING_DISABLED);
sky.setCulling(Object3D.CULLING_DISABLED);


Now the code works fine when I check if the plane can move downwards (y and z are flipped):


final SimpleVector uiDz = new SimpleVector(0, 1, 0);
final float minDist = ground.calcMinDistance(plane.getTransformedCenter(), uiDz);


minDist takes correct values. Now I want to know if the plane has gone underground, I assume I just have to flip the "direction" vector.


final SimpleVector uiDz = new SimpleVector(0, -1, 0);
final float minDist = ground.calcMinDistance(plane.getTransformedCenter(), uiDz);


Issue is this always returns COLLISION_NONE, even when I go trough the ground.

Nic

EgonOlsen

I can't see anything weird here...unless i misunderstood something. You can't check for collisions with the backfaces of polygons in jPCT, not matter if you enable or disable culling.

Tishu

Ok sorry I just misunderstood the following (or rather misread)

QuoteOr was culling disabled on the model? In that case, you will create holes for the collision detection on all faces that would otherwise be culled, because collision detection doesn't happen on back faces.

Thx
Nicolas

Tishu

Any chance we get that supported in a future version? I agree it should be disabled by default, but could be useful in some cases to be able to enable it.

Nic

EgonOlsen

Not very likely. The algorithms used for collision detection can't handle this case ATM and franky speaking, i don't much need to change them just for that. If you want to detect this case, you have other options. For example, you could offset plane.getTransformedCenter() by some value like (0,-5,0), so it's above the ground for sure and then do a collision detection with (0,1,0). If the result is lower than your offset (in this case 5), the plane is below the ground....something like that.

K24A3

#12
I'm  having a bit of difficulty placing an Object3D (an MD2 character) on the ground. I got it working, but the character ends up too high off the ground, so I hack the offset by 20.

The ground is an Object3D plane created with Primitives and modified by a VertexController
terrain = Primitives.getPlane(50, 50);
terrain.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);


On every frame I call this function:


private void ObjectToGround(Object3D object)
{
SimpleVector sv = new SimpleVector();

// Get object position
sv = object.getTranslation();

// Determine height above terrain
float terrHeight = terrain.calcMinDistance(sv, new SimpleVector(0,1,0));
if(terrHeight == Object3D.COLLISION_NONE)
{
//Log.v(TAG, "COLLISION_NONE" );
}
else
{
//sv.scalarMul(terrHeight); // object goes underground
terrHeight -= 20; // Hack offset
sv.set(0, terrHeight, 0);
character.translate(sv);

}
}



My question is, how do you determine the height or bottom of the 3D Object and place it on the ground properly without hacking the value?


Do I need to use the ellipse method?

Or scale the value returned by calcMinDistance() to the world scale?


EgonOlsen

None of the collision detection method has any information about the size of the object that collides. If you don't want to use magic numbers for this, you might want to get the bounding box from the Mesh and calculate the needed values from that.

K24A3

I see, ok I may just stay with magic numbers if that's the normal way of doing it.