contactsProcess not called on every contact

technique

06-02-2012 21:24:14

Hi, i write a simple pinball game (as described here http://www.ogre3d.org/addonforums/viewtopic.php?f=4&t=29286).

I've registrated contact callbacks for the materialpair of balls und the rockers but a strange problem appears. the physics work very well but the contasctsProcess is not called every time. As you can see the right ball on top of the right blue rocker is called (see @ std::cout) but the contact of the left ball is only a few times called. the material and functions are the same - the determination is done by body comparison. the game is nearly done and i would be appreciated to get a hint whats may going wrong and how to fix it!

Ogre: v1-7-1
OgreNewt: 2.07.1
Newton: 2.24



rocker creation:

OgreNewt::CollisionPrimitives::ConvexHull* convx1 = new OgreNewt::CollisionPrimitives::ConvexHull(mWorld, mLeftRockerEntity);
OgreNewt::CollisionPrimitives::ConvexHull* convx2 = new OgreNewt::CollisionPrimitives::ConvexHull(mWorld, mRightRockerEntity);
mCollisionLeftRocker = OgreNewt::CollisionPtr(convx1);//Ogre::Vector3(0.95f, 0.125f, 0.375f), 1));
mCollisionRightRocker = OgreNewt::CollisionPtr(convx2);
mRightRockerBody = new OgreNewt::Body(mWorld, mCollisionLeftRocker);
mLeftRockerBody = new OgreNewt::Body(mWorld, mCollisionRightRocker);
mRightRockerBody->attachNode(mRightRockerNode);
mLeftRockerBody->attachNode(mLeftRockerNode);
mRightRockerBody->setPositionOrientation(Ogre::Vector3(1.75f, 0.5f, 0.f), Ogre::Quaternion::IDENTITY);
mLeftRockerBody->setPositionOrientation(Ogre::Vector3(-1.75f, 0.5f, 0.f), Ogre::Quaternion::IDENTITY);
mLeftRockerBody->setContinuousCollisionMode(1);
mRightRockerBody->setContinuousCollisionMode(1);
mLeftRockerBody->setCustomForceAndTorqueCallback<GamePingaball>(&GamePingaball::callbackFunction, this);
mRightRockerBody->setCustomForceAndTorqueCallback<GamePingaball>(&GamePingaball::callbackFunction, this);
Ogre::Vector3 centerOfMass, inertia;
convx1->calculateInertialMatrix(inertia, centerOfMass);
mLeftRockerBody->setMassMatrix(1000, inertia);
mRightRockerBody->setMassMatrix(1000, inertia);
mRightRockerBody->setCenterOfMass(centerOfMass);
mLeftRockerBody->setCenterOfMass(centerOfMass);
mLeftRockerJoint = new OgreNewt::Hinge(mLeftRockerBody, NULL, mLeftRockerBody->getPosition(), Ogre::Vector3::UNIT_Z);
mRightRockerJoint = new OgreNewt::Hinge(mRightRockerBody, NULL, mRightRockerBody->getPosition(), Ogre::Vector3::UNIT_Z);

mRockerBallCallback = new GamePingaballRockerBallCallback(this);
// Physik-Material erstellen
mBallMaterialID = new OgreNewt::MaterialID(mWorld);
mTargetMaterialID = new OgreNewt::MaterialID(mWorld);
mBallTargetMaterialPair = new OgreNewt::MaterialPair(mWorld, mBallMaterialID, mTargetMaterialID);
mRockerMaterialID = new OgreNewt::MaterialID(mWorld);
mRockerBallMaterialPair = new OgreNewt::MaterialPair(mWorld, mRockerMaterialID, mBallMaterialID);
mRockerBallMaterialPair->setContinuousCollisionMode(1);
mBallTargetMaterialPair->setContinuousCollisionMode(1);
mBallTargetMaterialPair->setContactCallback(this);
mRockerBallMaterialPair->setContactCallback(mRockerBallCallback);
mLeftRockerBody->setMaterialGroupID(mRockerMaterialID);
mRightRockerBody->setMaterialGroupID(mRockerMaterialID);
mRockerBallMaterialPair->setDefaultElasticity(.6f);


ball creation:

mSceneNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mEntity = mSceneManager->createEntity("ellipsoid.mesh");
mSceneNode->attachObject(mEntity);
mSceneNode->scale(0.35f, 0.35f, 0.35f);
// Szene Physik erstellen
OgreNewt::CollisionPrimitives::Ellipsoid* eps = new OgreNewt::CollisionPrimitives::Ellipsoid(mWorld, Ogre::Vector3(0.175, 0.175, 0.175), mID);
mCollisionObject = OgreNewt::CollisionPtr(eps);
mID++;
mCollisionBody = new OgreNewt::Body(mWorld, mCollisionObject);
Ogre::Vector3 centerOfMass;
eps->calculateInertialMatrix(mInertia, centerOfMass);
mCollisionBody->setMassMatrix(DEFAULT_WEIGHT, mInertia);
mCollisionBody->setCenterOfMass(centerOfMass);
mCollisionBody->attachNode(mSceneNode);
mCollisionBody->removeForceAndTorqueCallback();
mCollisionBody->setCustomForceAndTorqueCallback<GamePingaballBall>(&GamePingaballBall::callbackFunction, this);
mCollisionBody->setContinuousCollisionMode(1);
mCollisionBody->setMaterialGroupID(mMaterialID);


rocker callback:

void GamePingaball::callbackFunction(OgreNewt::Body* body, float timeStep, int threadIndex)
{
if(mLeftRockerBody == body)
{
Ogre::Real rotation = fmod(mLeftRockerRotation.x/* + 90.f*/, 360.f) - (mLeftRockerBody->getOrientation().getRoll().valueDegrees() + 180.f);
if(rotation > 180.f)
rotation = -(360.f - rotation);
else if(rotation < -180.f)
rotation = 360.f + rotation;
Ogre::Vector3 result(0, 0, rotation);
mLeftRockerBody->setOmega(result);
}
if(mRightRockerBody == body)
{
Ogre::Real rotation = fmod(mRightRockerRotation.x/* + 90.f*/, 360.f) - (mRightRockerBody->getOrientation().getRoll().valueDegrees() + 180.f);
if(rotation > 180.f)
rotation = -(360.f - rotation);
else if(rotation < -180.f)
rotation = 360.f + rotation;
Ogre::Vector3 result(0, 0, rotation);
mRightRockerBody->setOmega(result);
}
}


ball callback:

void GamePingaballBall::callbackFunction(OgreNewt::Body* body, float timeStep, int threadIndex)
{
Ogre::Vector3 inertia;
Ogre::Real mass;
body->getMassMatrix(mass, inertia);
Ogre::Vector3 force = Ogre::Vector3::ZERO;
force += Ogre::Vector3( 0, -9.81f, 0) * 100 * mass * timeStep;
body->addForce(force);
Ogre::Vector3 pos = body->getPosition();
pos.z = mRespawnPosition.z;
body->setPositionOrientation(pos, body->getOrientation());
}


ball - rocker contact process:

void GamePingaballRockerBallCallback::contactsProcess(OgreNewt::ContactJoint &contactJoint, Ogre::Real timeStep, int threadIndex)
{
OgreNewt::World::get()->criticalSectionLock();
mContactProcessQueue.push(std::pair<OgreNewt::Body*, OgreNewt::Body*>(contactJoint.getBody0(), contactJoint.getBody1()));
OgreNewt::World::get()->criticalSectionUnlock();
}

void GamePingaballRockerBallCallback::update(float timeSinceLastFrame)
{
OgreNewt::World::get()->criticalSectionLock();
while(!mContactProcessQueue.empty())
{
OgreNewt::Body* body0, *body1;
body0 = mContactProcessQueue.back().first;
body1 = mContactProcessQueue.back().second;
mContactProcessQueue.pop();
if(body0 == mGame->mLeftRockerBody)
{
if(mGame->getBall(body1))
{
mGame->getBall(body1)->setPlayer(1);
}
}
else if(body1 == mGame->mLeftRockerBody)
{
if(mGame->getBall(body0))
{
mGame->getBall(body0)->setPlayer(1);
}
}
if(body0 == mGame->mRightRockerBody)
{
if(mGame->getBall(body1))
{
mGame->getBall(body1)->setPlayer(2);
}
}
else if(body1 == mGame->mRightRockerBody)
{
if(mGame->getBall(body0))
{
mGame->getBall(body0)->setPlayer(2);
}
}
}
OgreNewt::World::get()->criticalSectionUnlock();
}


thank you for your time in reading my question!