Inconsistency in collision detection

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

Previous topic - Next topic

K24A3

I'm attempting to use the bounding box to get the magic number but not sure how to calculate it.

// Get mesh
Mesh mesh = object.getMesh();
      
// Get Bounding Box
float[] fBounds = mesh.getBoundingBox();   


The fBounds[2] value is -135f, and the fBounds[3] value is 87f. Object3D.getCenter() is 0,0,0

The magic value is supposed to be -35 (where the lowest polygon touches the terrain). How do I get -35 from -135f and 87f?


// I use this code to calculate and translate the object to the ground
sv = object.getTranslation();
float terrHeight = terrain.calcMinDistance(sv, new SimpleVector(0,1,0));
terrHeight += magicNumber;
sv.set(0, terrHeight, 0);
object.translate(sv);   

EgonOlsen

Hard to tell from your code because your translations add up. You'll end up in a situation, where -calcMinDistance equals your magic number, won't you? I used to do this different: I use a fixed height which is guaranteed to be always above the ground, calculate the distance and apply the offset to that value. Personally, i can understand this approach much better than yours. I'm not even sure if yours works at all...then again, i'm feeling a little sick today, so my thinking is slow... ;)

K24A3

QuoteI use a fixed height which is guaranteed to be always above the ground, calculate the distance and apply the offset to that value.

That is how I am doing it but I needed to manually supply the offset. The problem is that I have multiple instances of the object with different scales, so the offset is different each time.


private void ObjectToGround(Object3D object, float nYOffset)
{
if(terrain==null) return;

SimpleVector sv = new SimpleVector();

// Make sure object is above the terrain
object.translate(0, -200, 0);

// Get object position
sv.set(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" );
// Drop back down
object.translate(0, 200, 0);
}
else
{
Log.v(TAG, "COLLISION terrHeight = "+terrHeight );
if(terrHeight>1000)  {object.translate(0, 200, 0); return;}
terrHeight += nYOffset;
sv.set(0, terrHeight, 0);
object.translate(sv);
}
}


And here's my current attempt to automatically get the offset, assuming calcMinDistance is based on the center of the object rather than the bounding box.

private void ObjectToGroundAuto(Object3D object)
{
if(terrain==null) return;

float fAutoOffset  = 0;


// Get mesh
Mesh mesh = object.getMesh();

// Get Bounding Box
float[] fBounds = mesh.getBoundingBox();

// Get the middle of the bounds
float fMid = fBounds[3] - fBounds[2];


fAutoOffset = fMid / 2; //(fMid * object.getScale()); // Always 1.0

Log.v(TAG,"fBounds2 = "+fBounds[2]+"  fBounds3 = "+fBounds[3]+" fMid="+fMid+" fAutoOffset="+fAutoOffset+" scale="+object.getScale());

Log.v(TAG,"Center = "+object.getCenter()); // Always 0,0,0 if calcCenter() is not called.

// Ground 
ObjectToGround(object, -fAutoOffset);
}


Are you able to show the code in the function calcMinDistance()? I'd like to see how the starting point of the object is calculated.

EgonOlsen

The starting point is the center in world space. However, you don't have to use this variant. You can use the methods in World if you want to set the starting point yourself. Keep in mind that scaling doesn't affect the bounding box, i.e. you have to apply a scale to the values yourself to get the actual values in world space.

K24A3

Sorry I meant the starting point of the collision detection, does calcMinDistance start measuring from the exact center of the object? Or does it start from the closest polygon?

EgonOlsen


K24A3

Ok so theoretically if the center is 0,0,0,  the lower value of the meshes bounding box should be the offset. I tried that but I'm still needing a corrective offset.

I can't seem to figure out a trending value to use. I'm guessing that calcBoundingBox() is not calculating the boundary exactly at the lowest vertex for performance reasons perhaps.


OBJECT 1
--------
Scale = 40f
Center = 0,0,0
LowerBoundingBox = -77
UpperBoundingBox = 50
Wants Offset = -10
Mesh BoundingBox 0 = -62.069466 1=51.452503 2=-33.44815 3=9.098154 4=-78.36731 5=49.07093

Scale = 80f
Center = 0,0,0
LowerBoundingBox = -67
UpperBoundingBox = 18
Wants Offset = -20
Mesh BoundingBox 0 = -124.13893 1=102.90501 2=-66.8963 3=18.196308 4=-156.73462 5=98.14186



OBJECT 2
--------
Scale = 95f
Center = 0,0,0
LowerBoundingBox = -550
UpperBoundingBox = -9
Wants Offset = 10
Mesh BoundingBox 0 = -80.026985 1=96.586525 2=-550.9481 3=-9.235985 4=-89.274704 5=144.33151

Scale = 35f
Center = 0,0,0
LowerBoundingBox = -202
UpperBoundingBox = -3.4
Wants Offset = 5
Mesh BoundingBox 0 = -29.483627 1=35.58451 2=-202.98088 3=-3.4027314 4=-32.890682 5=53.17477



By the way, there is no scaling being done loading the 3D file, there are no axis rotations (all objects point up natively), there are no animations.

obj = Object3D.mergeAll(Loader.load3DS(myContext.getResources().openRawResource(R.raw.obj7), 40f));
//obj.calcCenter();
//obj.getMesh().compress();
obj.calcBoundingBox();
obj.setTexture("obj7tex");
obj.setSpecularLighting(true);
obj.compile();
//obj.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
world.addObject(obj);
obj.translate(mainArea.getRandomPos());
ObjectToGroundAuto(obj);

The offset seems to follow the scale so I may just calculate the offset manually at scale 100f, then scale that master offset in ratio when scaling the cloned objects.

EgonOlsen

#22
The center is (0,0,0) only because you don't calculate it. It will be calculated anyway when the object is rendered for the first time, so your distance calculations work with a different center than (0,0,0). Maybe you should calculate the center before...just call build() on the object after loading and remove all other calcXXX-methods, because build() already calls them. The bounding box actually calculates the exact, axis-aligned bounds in object space.

K24A3

#23
It appears to be working now after your suggestions, all three different objects completely sit flush on the ground. The offset is incorrect if I clone and rescale the objects, but I can take care of that  (I'll just scale the offset accordingly).

Here's the code if anyone is wandering:

Mesh mesh = object.getMesh();
float[] fBounds = mesh.getBoundingBox();      
fAutoOffset = -fBounds[3];
ObjectToGround(object, fAutoOffset);


Appreciate the help, thanks :)