many thanks for your wonderful project.
I am currently trying to use BulletOde to add collision support for convex shapes to my application, but have run into some difficulies with that : eg. my usually well-behaved stack of Jenga blocks is exploding like popcorn in a microwave, single Jenga blocks are gaining momentum and rolling across the tabletop when they should just rest in place, and I get displays of collision points in far outside the geoms involved.
To investigate this, I have made some simple tests (without using my own framework to avoid introducing errors from there):
I create a large tabletop using an ode box primitive (object1 o1) and a small box by adding the 8 corner points to a convex shape (object2 o2).
I manually position o2 so that is just intersects the top surface of o1 and then call dCollide directly on the two geoms.
The result is just 1 contact point, which I think would need to be in the center of contact area to avoid generating torque for o2.
If o2 is centered on top of o1, the results are as expected, but as o2 moves away from the center of o1 towards the edge of the "table", the difference between the expected and reported contact position get larger. This effect seems very small if o1 and o2 have similar scale, but increases dramatically if that is not the case.
If the scale ratio is large enough (75:1) the system can even miss the collision entirely if o2 isn't close to the center of the table o1.
Example 1:
Ratio 2.5:1
o1 Tabletop length/width/height 5.0/5.0/2.0
o1 Position 0.0, 0.0, -1.0
o2 ConvexBox x: (-1)...(1) y: (-1)...(1) z: (-0.1)...(0.1)
o2 Position (2.0, 0.0, 0.05)
1 Collisions detected @ (1.42857 , 1.04305e-007 , -0.0250005) Normal : (0 , 1.78803e-006 , -1) Depth : 0.050001
Deviation from expected collision point (x-axis only) (2.0 - 1.42857) = 0.571429 ~ 57% relative to o2's size
Example 2:
Ratio 75:1
o1 Tabletop length/width/height 150.0/150.0/2.0
o1 Position 0.0, 0.0, -1.0
o2 ConvexBox x: (-1)...(1) y: (-1)...(1) z: (-0.1)...(0.1)
o2 Position (48.75, 0.0, 0.05)
0 Collisions detected. !!!
This is the code that I used for the tests:
Code: Select all
#include "ode/ode.h"
#include "CollisionShapes/ConvexHullShape.h"
#include "BulletOdeCollide.h"
#include <iostream>
#include <fstream>
#include <sstream>
void buildBox(std::stringstream& LOG, ConvexHullShape* hullShape, float x_min, float x_max, float y_min, float y_max, float z_min, float z_max)
{
hullShape->AddPoint(SimdPoint3(x_min, y_min, z_min));
hullShape->AddPoint(SimdPoint3(x_min, y_min, z_max));
hullShape->AddPoint(SimdPoint3(x_min, y_max, z_min));
hullShape->AddPoint(SimdPoint3(x_min, y_max, z_max));
hullShape->AddPoint(SimdPoint3(x_max, y_min, z_min));
hullShape->AddPoint(SimdPoint3(x_max, y_min, z_max));
hullShape->AddPoint(SimdPoint3(x_max, y_max, z_min));
hullShape->AddPoint(SimdPoint3(x_max, y_max, z_max));
//hullShape->SetMargin(0.04f);
hullShape->SetMargin(1e-6f);
hullShape->setLocalScaling(SimdVector3(1.f, 1.f, 1.f));
LOG << "o2 ConvexBox x:(" << x_min << ")...(" << x_max <<
") y:(" << y_min << ")...(" << y_max <<
") z:(" << z_min << ")...(" << z_max << ")";
}
void collideLOG(std::stringstream& LOG, dGeomID o1, dGeomID o2, float cboxhsize)
{
dContactGeom contactGeom[1024];
int numc = dCollide(o1, o2, 128, contactGeom, sizeof(dContactGeom));
LOG << std::endl;
LOG << "Geom 1 Pos: (" <<
dGeomGetPosition(o1)[0] << " , " <<
dGeomGetPosition(o1)[1] << " , " <<
dGeomGetPosition(o1)[2] << ") ";
LOG << "Geom 2 Pos: (" <<
dGeomGetPosition(o2)[0] << " , " <<
dGeomGetPosition(o2)[1] << " , " <<
dGeomGetPosition(o2)[2] << ")" << std::endl;
LOG << numc << " Collisions detected." ;
if (numc > 0)
LOG << " Contact diff.%: " << ((dGeomGetPosition(o2)[0] - contactGeom[0].pos[0]) / cboxhsize * 100.f )<< std::endl;
else
LOG << std::endl;
for (int i = 0; i < numc; ++i) {
LOG << "Col " << (i+1) << ": (" <<
contactGeom[i].pos[0] << " , " <<
contactGeom[i].pos[1] << " , " <<
contactGeom[i].pos[2] << ")" <<
" Normal : (" <<
contactGeom[i].normal[0] << " , " <<
contactGeom[i].normal[1] << " , " <<
contactGeom[i].normal[2] << ")" <<
" Depth : " <<
contactGeom[i].depth << std::endl;
}
}
void BulletOdeTest()
{
// setup logging
std::stringstream LOG;
LOG.precision(6);
LOG.width(0);
LOG.fill(' ');
// create world
dSpaceID World = dSimpleSpaceCreate(0);
const dQuaternion identity = {1.f, 0.f, 0.f, 0.f};
// setup object parameters
// EDIT HERE
const float o1length = 150.0f;
const float o1width = 150.0f;
const float o1height = 2.0f;
const float cboxhsize = 1.0f;
const float cboxhheight = 0.1f;
const float startpos = 0.f;
// create object 1
LOG << "o1 Box l:" << o1length << " w: " << o1width << " h: " << o1height << " ";
dGeomID o1 = dCreateBox(World, o1length, o1width, o1height);
dGeomSetPosition(o1, startpos, 0.0f, -(o1height / 2.f));
dGeomSetQuaternion(o1, identity);
// create object 2
ConvexHullShape* hullShape = new ConvexHullShape(0,0);
buildBox(LOG, hullShape, -cboxhsize, +cboxhsize, -cboxhsize, +cboxhsize, -cboxhheight, +cboxhheight);
dGeomID o2 = dCreateConvex(World,hullShape);
dGeomSetQuaternion(o2, identity);
// move object 2 across o1's surface
for (float pos = startpos; pos < startpos + (o1length / 2.f); pos += (o1length / 40.f)) {
dGeomSetPosition(o2, pos, 0.f, cboxhheight / 2.f);
collideLOG(LOG, o1, o2, cboxhsize);
}
std::ofstream LOGFILE;
LOGFILE.open("logfile.txt");
LOGFILE << LOG.str();
LOGFILE.close();
std::cout << LOG.str();
}
int main(int argc, char* argv[])
{
BulletOdeTest();
return 0;
}
Thanks in advance,
Jan