Desired deterministic movment of PxController - time stepping or something similiar...

( Yes, I am finally back, I had much to do, sorry community :D)

PhysX 3.3

Hello,

I want to move my PxBoxController when he hits a special sphere shape along a “path”.
The idea: Move the PxBoxController via the move(velocity,deltaTime,…) function, with
a precalculated velocity.
It should be simple calculated but the results must be determinstic and shouldn´t vary.
(The part of collision etc works perfect, the only problem is the mDeltaTime calculation of force.)

I know that my game is frame independent, and combining physics with apply forces to a kinematic object ( like the PxController) cant handle it right.
Appling forces to dynamic objects works perfect, all I need is to add the force.

But for kinematic objects (maybe espacially the PxController) cant handle it right, so I multipled
mDeltaTime for a much better result when the fps are changing, but all I get are different positions.

The goal is when I touch a special sphere ( from above) , I want to jump over it.
This must be deterministic, when its not, its possible to “cheat” because the player could jump
far or less away than it should.
(E.g. when he change windows or when he had a slow computer :D)
I dont know how to explain it better, but maybe this pic could help you:

External Media

Here are the “important” code snippets:

// Delta time calculation
unsigned long timeNow  = mTimer->getMicroseconds();
mTimeSinceLastFrame    = timeNow - mLastUpdateMs;
mLastUpdateMs		= timeNow;
mDeltaTime =  mTimeSinceLastFrame*0.001f; 

// This is the calculation of the jump for the PxBoxController, it has a smooth curve
float jumpGravity = -2;
float jumpForce = 40.f; 

mJumpTime += mDeltaTime*10; 
mVelocity.y = (jumpGravity*mJumpTime*mJumpTime + jumpForce);  

Vector3 dir = ... //Facing direction of my mesh, works   

mVelocity.x = dir.x;
mVelocity.z = dir.z;
mVelocity *= mDeltaTime; //Same delta time which is used for physic update ,  here are the bug
.
.
.
mController->move(mVelocity,0.01f,mDeltaTime,PxControllerFilters());

// Now the physic update, semi-fixed-style:
mStepSize = 0.01f;
mAccumulator += mDeltaTime;
if (mAccumulator > 0.05f) mAccumulator = 0.05f;

while (mAccumulator >= mStepSize)
{
	mAccumulator -= mStepSize;
	mScene->simulate(mStepSize);		
	mScene->fetchResults(true,&errorCode);
}

Again: The problem is that the player is “jumping” always to a new position, and not to a
position which is always the same, mostly the changes are 0 - 1 units (in global position) or
when the delta time is very very very high, he could jump more than 10+ units away from the desired
position. (I cant tell what the desired position is, - its calculated thru the gravity and jump force,- but this should alway be the same result.)
E.g: The PxController should move 20 units in his “face” direction, but he also moves up (jump) and falls down ( gravity) .

I also tried adding force for a little while (frame independent!) but this also leads to vary results.

My question is: How could I archieve my jumping movement which is always at changing frames deterministic and gives me the right result?!


I guess one way is to call from the “hidden” PxActor inside PxController the
setKinematicTarget(…) for position the PxController, but this shouldnt be the right way,
we lost information like the possible collisionFlags while he is moving. ( See PxController::move())

I want to get any collision information which could happen while
the PxController is “jumping over” it, and I dont want to use a separate movement update for it.
But maybe this could be a solution to the problem, but again, I dont want to use it unless
there is a efficent and easy way via the “force” calculation.

Hi,

thank you for the link - i´ve read it and googled it, and found a better way:
RK4 should be better than TCV - look at this for a basic implementation:

  • Here is a small flash presentation which shows the benifit of RK4 against other algorithms:
    Physics for Flash Games

But your sample code:
velocity *= mDeltaTime * (mDeltaTime / mPrevFrameDeltaTime);

Wont work corrctly, maybe its the way I calculate the mDelta time -
its only updated when the “main” loop are done, since I use a semi-fixed timestep
( for reasons, look at Fix Your Timestep! | Gaffer On Games )

Should be the “real” mDeltaTime calculated when the physics are updating?
Like, I calculate the “real” mDeltaTime direct inside the
while (mAccumulator >= mStepSize) loop to get the real mDeltaTime and mPrevFrameDeltaTime from
the physic update?

I´ve tested it with the “real” physic delta time, and the “main game loop” delta time (which
includes every possible delay…) but I wont get the same result.

Do you have a hint or something else?

UPDATE:

I hope the TCV is usabe for changing acceleration (like gravity…).
One of the questions are:
Is it okay to pass the (untouched) mDeltaTime for the elapsed (falling) time?
Like I did it here : mJumpTime += mDeltaTime*10;

So - the other question is how do I calculate the mDeltaTime?
For the whole update loop?
(PhysX and the whole updates etc are single threaded, so I dont have
a multithreaded game - no asynchron “run overs” are possible.)

One other thing is:
The “untouched” mDeltaTime is passed to the PxController::move(…) - so this wouldn change it?

Maybe I understood it wrong, but I guess I only need to multiply my mVelocity with the TCV -
which dont work ( results are almost the same with the “untocuhed” mDeltaTime).

Still I get an incredible movement when the game “freezes” or run slow - huge new velocity are result
and the PxController moves this distance.

— The nice thing is that this behavior is only on the PxController (maybe each kinematic object)-
the dynamic objects are easy to handle, just add the desired force and you are done.

Hi,

look at the code sample in the first post, its fixed timestep but I call it semi fixed, because
I cut it at some point, as a workaround for the “spiral of death” which is possible while using accumulated time.

It makes no sense for me to update the controller again, before I call simulate()

  • its not possible to insert the controller movement code before the loop, its too much code for it.
  • I could update the PxController before I run simulate(), but it shouldnt work
    (this happens 1x before the physics are done updating).
    Like this:

while (true)
{

mObjectManager->update(); //Here is the PxController going to update
mPhysic->update();

}

  • But nevermind, I´m doing it.

  • So, I update my PxController in the loop before the physic update, and like I said, it doesnt change anything and make no sense (but the PxController moves faster, and almost anything blow up).

I even testet it with different mDelta, from the “whole game update delta time” and with the
“physic deltaTime” - they lead to mixed results which is unusable like the “usally”
deltatime calculation for movement.

Hmm…

I´ve implemented the TCV as a test case:
Try it and you will see that TCV wont work correctly when mDeltaTime is changing.

This is a 1:1 port from the excel file created by Jonathan “lonesock” Dummer,
which was the first link in your post. I´ve found it somewhere on google.
(Of course, there is no graph…, but the algorithm is the same)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>      

#define USE_WITH_RANDOM_DELTA_TIME 1 // Set to 1 to get different results, 0 for exact results

void main(int argc, char* argv[])
{
	// This is the (unclean and simple) version of -> Time-Calculated-Verlet
	double velocity= 10; 
	double acceleration = -5; 
	double mDeltaTime = 0.5;
	if(USE_WITH_RANDOM_DELTA_TIME) srand (time(NULL));

	double elapsedTime = 0.f;
	double oldValue1 = 0;
	double oldValue2 = 0;
	double nextPos = 0;
	double exact = 0;

	oldValue1 = (velocity * elapsedTime) + (0.5 * acceleration * elapsedTime * elapsedTime);
	oldValue2 = oldValue1 - (velocity * mDeltaTime) + (0.5 * acceleration * mDeltaTime * mDeltaTime);
	exact = oldValue1;

	for (int i = 0; i < 35; i++)
	{
		if(USE_WITH_RANDOM_DELTA_TIME)	mDeltaTime = ((rand() % 100)+1)/100.0; // More zeros are leading to get more weird results
		elapsedTime += mDeltaTime;
		exact = (velocity*elapsedTime)+(0.5*acceleration*elapsedTime*elapsedTime);

		nextPos = (2*oldValue1) -oldValue2 + (acceleration*mDeltaTime*mDeltaTime);
		oldValue2 = oldValue1;
		oldValue1 = nextPos;

		printf("Exact: %f  calculated: %f\n",exact, nextPos);
	}

	getchar();
}

So I hope there is a solution to this problem.

And I dont want to use an infinity unefficently workaround way…
(Like creating a hidden actor which is an untouchable shape which moves like the
PxController should, and I set the hidden actor position as my PxController position…)

Or other weird solutions :D

Hi,

maybe its worth to say that the PxController is a PxExtension - so its independent from
the PxScene::simulate() and fetch() - it still can be updated via PxController::move() and
it collides with all PxShape´s even when the physic wasn´t updated.
(The PxScene is unimportant the PxController works independent from the PxScene…)

So - I guess this brings a new way to think about the solution.

Hi,

so, I dont know if this is the right way, but I have found a possible and simpel solution:
The mistake was mJumpTime += mDeltaTime*10; ← When I didnt pass the mDeltaTime, just only a constant,
everything works very well, the results are deterministic even with greatest delay or no fps something else, it works like I want it. Okay, maybe its not the right way to do it, but this is perfect for me.

Maybe its the right way …
(or not, because its linear, but this is the elapsed time, which should be linear, but its dependend how often the update() is called…)
but I pass the mDeltaTime to the PxController which do some stuff to make it right :D (or maybe not :D)