[Git] Still collision ocurring after translating actor

Karan

16-09-2009 15:32:17

I'm using yesterday's commit.

The situation is: The ball (OGRE3DBody) lies on the ground, creates contact reports all the time (I'm using NxOgre::Callback), but they're ignored based on game state. Then I translate the ball somwhere into midair with setGlobalPosition() and suspend it there using putToSleep(). And I change the game state, so that future collisions are handled (gameplay-wise). But in the next simulation step the ContactCallback is still called - the ball supposedly still has contact with the ground. That messes up the gameplay. Why is that? The PhysX docs say that moving a dynamic actor is ok, so there shouldn't be another collision, should there?

I thought about changing the game state after the next simulation step after I translate the ball, but unfortunately I don't know when the next simulation step actually happens because of NxOgre's accumulative timer (In debug mode it's in the next frame, in release mode about 15 frames later because of the much higher framerate).

Any ideas?

betajaen

16-09-2009 16:03:40

Hmm. Just to be clear, are you saying your callback is roughly written as:

void callback(Actor* actor)
{
actor->setGlobalPosition(Vec3(1,2,3));
}


What happens if you don't put the ball asleep once you've translated it? Does the contact get called again?

Karan

16-09-2009 18:56:39

Not exactly, but similar. The callback (onContact(const NxOgre::ContactPair& contactPair)) starts a timer (Ogre::Timer). Based on that timer, a few seconds later a FrameListener calls
frameRenderingQueued(const FrameEvent &evt) {
...
mPhysicsTimeController->advance(evt.timeSinceLastFrame*mSimulationSpeed);

// simplified - actually this method calls another method that calls another method which has these lines
if (mTimerActive && mTimer.getMilliseconds() > 3000)
mBallBody->setGlobalPosition(NxOgre::Vec3(position);
...
}


Not putting the ball asleep doesn't change anything, the callback still gets called.

betajaen

16-09-2009 19:27:53

I suspect then it's the action of translating the Actor causing PhysX to not realise that the ball is not there and still in contact with the ground. Sounds silly, I know. I believe it's part of the "optimisation"; the ball didn't technically move (in the traditional sense) so it has no reason to think that it's no longer touching the ground.

I have two ideas;

1. Make it believe you moved, and set the angular/linear velocity to a very tiny amount Vec3(1E-5,0,0) after teleportation.

2. Deleting the ball and re-creating. Don't delete it within the callback, use your timer.

Karan

16-09-2009 21:17:27

I had another idea: I added another state variable and changed when which contacts are ignored - now ground collisions are ignored until the player touches the translated ball. There maybe a rare edge case where it doesn't work when the player touches the ball right after teleportation...but I think I can ignore that (it's more likely the ball gets teleported into the player and then it hardly matters anyway).

BTW your first idea doesn't work because the ball needs to be "asleep" after teleportation.

Edit: Found another edge case which is much more likely to happen...I think I'll do the recreating.

betajaen

16-09-2009 21:29:41

Shame, I liked my idea. ;)

Anyway. Glad it works for you. PhysX is really a strange beast, and I wonder why these sorts of behaviour aren't better documented.

Karan

16-09-2009 22:15:34

Yeah, it's a bit strange...but Nvidia doesn't seem to working on improving PhysX, do they? Just some rare bugfix releases...
I might switch to Bullet for my next project as they're quite catching up feature-wise (soft bodies, SPH fluids, GPU-support) and because it also runs on Mac (and open source is nice too).

And btw recreating the ball works fine now :)

betajaen

16-09-2009 23:17:49

From what I read and heard; the commercial users get to work with a major release or two ahead of us. But we've had 2.8.1 for a while, shame really.