PhysX - Scene scaling, object size, timestep and gravity inconsistency.

Started by
29 comments, last by N01 10 years, 7 months ago
I guess the ultimate point of these snippets is to keep the physics timestep fixed while graphics run at higher fps interpolating frame results. There are obviously
better solutions than this piece of code and those will be more relevant at later development stages... Since your graphics run at constant 30fps, you could perhaps replace that code with just simulate(1.0f/30.0f) and fetchResults(true) and keep looking until you find the actual problem. fetchResults can be called right after simulate as long as that first parameter remains true. I suppose it's also possible to "hack" some speed by making that dt > 1/30 (or even better call twice those functions), did you try the direct approach?
Advertisement

dt always means delta-time, which is the time spent last frame

so, each time you accumulated more than mStepSize time, you integrate (or simulate if you will)

it's hard to say why your scene is slow, since if you provided real time to the function, it would just integrate each and every time forever

you are missing a while loop though

while (mAccumulator >= mStepSize)
{
mAccumulator -= mStepSize;
mScene->simulate(mStepSize);

}

throw that boolean return value to the fishes

anyways, the fix might just be to reduce mStepSize and all will be well

I guess the ultimate point of these snippets is to keep the physics timestep fixed while graphics run at higher fps interpolating frame results. There are obviously
better solutions than this piece of code and those will be more relevant at later development stages... Since your graphics run at constant 30fps, you could perhaps replace that code with just simulate(1.0f/30.0f) and fetchResults(true) and keep looking until you find the actual problem. fetchResults can be called right after simulate as long as that first parameter remains true. I suppose it's also possible to "hack" some speed by making that dt > 1/30 (or even better call twice those functions), did you try the direct approach?

well, actually, my graphics run at 60 FPS in a separate thread, and logics\physics are at 30 FPS. yes, i've tried simplifying time-step function to just "simulate(1.0f/30.0f) and fetchResults(true)", it didn't make any difference. as i already said, making dt bigger, doesn't really matter. i also tried calling functions multiple times. yes, it does speed things up. in order to get something resembling normal speed, i need to call them 3-4 times. it works, but it doesn't seem like a proper solution. and it's probably expensive as hell.

dt always means delta-time, which is the time spent last frame

so, each time you accumulated more than mStepSize time, you integrate (or simulate if you will)

it's hard to say why your scene is slow, since if you provided real time to the function, it would just integrate each and every time forever

you are missing a while loop though

while (mAccumulator >= mStepSize)
{
mAccumulator -= mStepSize;
mScene->simulate(mStepSize);

}

throw that boolean return value to the fishes

anyways, the fix might just be to reduce mStepSize and all will be well

yep, i knew what dt means, that's why in my code(post #6) it's deltaTime. but i have no idea, how it is calculated properly, to fit timestep.

i've added a while cycle, removing "if" statement. so it looks like that:


void update() {
        float deltaTime = (clock() - mLastTime) * mStepSize;
        mAccumulator  += deltaTime;
        mLastTime = clock();

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

i moved mLastTime = clock(); before simulation, and now it's super fast(5x speed. speed is normal, if i multiply deltaTime by 0.2f). i can just multiply deltaTime, but i'd like to figure out the reason.

and if i use fetchResults(false), speed is normal. but calling it with a false argument seems a bit undetermined.

*changed last bit of post a lot.

The clock() function gives you the ticks elapsed since the program was launch. PhysX expects its delta times in seconds. Try dividing your clock values by CLOCKS_PER_SEC and working in seconds rather than ticks.

ok, CLOCKS_PER_SEC is just 1000 for visual studio, i already tried dividing it by 1000.

if deltaTime = (clock() - mLastTime)/CLOCKS_PER_SEC, it's slow-mo. about 1/4 to 1/5 speed. so it still requires multiplying with magic number.

if i additionally multiply it with stepSize, it's super slow-mo. about 1fps.

Physx...you might find yourself in trouble....there are not many(almost none) tutorials,or documentations for it

I don't quite understand what you mean - in my opinion/experience the documentation is extremely accurate, clear and complete. And the SDK comes with a bunch of samples, as well as tutorial/guides in the documentation. I'm not sure how anyone could ask for more, to be honest.

As for solving this problem - I'd recommend using the PhysX Visual Debugger - it's extremely useful generally, and only takes a couple of lines to set up the communication in your code. Then when you simulate, you can inspect pretty much everything, including the scene timestep, gravity, objects etc. If you're unsure whether things are moving as they should, set up a little test scenario in your game where you drop a sphere, and in the debugger check that it falls the correct distance in a given time period - distance = vel * time + 0.5 * gravity * time^2

If you can't figure things out from that, you could even attach the pvd capture to a post here...

I don't quite understand what you mean - in my opinion/experience the documentation is extremely accurate, clear and complete. And the SDK comes with a bunch of samples, as well as tutorial/guides in the documentation. I'm not sure how anyone could ask for more, to be honest.

As for solving this problem - I'd recommend using the PhysX Visual Debugger - it's extremely useful generally, and only takes a couple of lines to set up the communication in your code. Then when you simulate, you can inspect pretty much everything, including the scene timestep, gravity, objects etc. If you're unsure whether things are moving as they should, set up a little test scenario in your game where you drop a sphere, and in the debugger check that it falls the correct distance in a given time period - distance = vel * time + 0.5 * gravity * time^2

If you can't figure things out from that, you could even attach the pvd capture to a post here...

literally 1st post mentions i'm using PVD. and later i mention that objects in PVD output look fine, parameters are intact. bearing that in mind, how do you think can it lead me to an explanation of the fact that i need to pre-multiply delta-time by some factor to get rid of slow-mo? if you didn't bother to read at least most of the thread and last OP's post, then why do you reply?

it works, so i moved on to other things, but i'm still a bit bothered on where does this speed factor comes from.

[spoiler]and on documentation\samples quality....

in post #10 there's a snippet from documentation, for time-stepping. it's doesn't function correctly, at least in a normal application with a basic setup. it's taken out of context of their samples framework. and there's no explanation on how it supposed to work. doc only does general time-stepping explanation, but you need to know exactly what API expects you to do.

and when it comes to convex hull creation, it uses PxToolkit::MemoryOutputStream and PxToolkit::MemoryInputData. does it explain, wtf are those and wtf is PxToolkit? no. do you need to use them? no. you can use PxDefaultMemoryOutputStream and PxDefaultMemoryInputData. how do you supposed to know that? you supposed to guess, that there are classes, that do exactly the same thing in the library itself and not to link to that useless PxTollkit library exclusively for those two, despite documentation shows you example of doing that.

also, searching through documentation by "gpuDispatcher" i failed to find, where exactly it explains, how do you check, if GPU acceleration is available. it does show some intialization routine in a Scene initialization example, but it doesn't explain it. then it does it again in Particles and states as a sufficient initialization code. so i guess, you need to assume that if cudaContextManager is not NULL, you have it running?

that's my problem with this documentation. it's a bit non-deterministic and scattered. that's just problems i came up from the top of my head, from my experience. it's not really bad, but it's not well-written, you can't just highlight the stuff you need, because information is really scattered and it has some bugs. it doesn't cover it all. no one would complain if it was complemented with decent samples, but...

when you suggest PhysX SDK samples as a source of information, i start to question your sanity. take a look at their hello world. what do you expect to see? i don't know, maybe basic initialization, creation of a basic rigid body and a plane and timestep, proper shutdown. this all could fit into a single, very small and clean cpp file. instead of that, they implemented really poorly written cross-platform framework only for samples, so none of the samples source files contatins anything useful or anything you would expect to see. it's all scattered through a pile of include files, within a confusing mess of classes and functions. most of the time it is really problematic to navigate from a sample code through this framework to find the actual code that is executed and you need to do it constantly, while trying to keep a picture of all that in your head, reconstructing how sample would look, if it wasn't written by lunatic.[/spoiler]


literally 1st post mentions i'm using PVD. and later i mention that objects in PVD output look fine, parameters are intact. bearing that in mind, how do you think can it lead me to an explanation of the fact that i need to pre-multiply delta-time by some factor to get rid of slow-mo? if you didn't bother to read at least most of the thread and last OP's post, then why do you reply?

I replied because I thought, and think, that my suggestion should help - rather than vaguely say "it looks like it's in slow motion" - do some basic numerical comparisons of simulation against theory. I can't see any mention of you doing that. PVD is useful for that.

I missed one sentence where you mention PVD out of 15 detailed posts. I'd say that's not unreasonable (though I agree it's in the original post!). Still doesn't invalidate my suggestion though.

It seems like you code by copy and paste, and if A/B doesn't work you just try B/A instead. That doesn't really work for physics stuff, in my experience.

I replied because I thought, and think, that my suggestion should help - rather than vaguely say "it looks like it's in slow motion" - do some basic numerical comparisons of simulation against theory. I can't see any mention of you doing that. PVD is useful for that.

I missed one sentence where you mention PVD out of 15 detailed posts. I'd say that's not unreasonable (though I agree it's in the original post!). Still doesn't invalidate my suggestion though.

It seems like you code by copy and paste, and if A/B doesn't work you just try B/A instead. That doesn't really work for physics stuff, in my experience.

i mention PVD twice in my 1st post, 1st time as an item in a list. and then in post 6 i mention again, that i do test with PVD. that's why i assumed, that you didn't read this thread at all.

copy paste exactly what? the only thing i copy-pasted(and openly stated that) was time-stepping function from documentation. it was in attempts to find a reason for my original problem with objects falling through stuff, by minimizing deviations from basic documentation code. and i couldn't tweak it in a sensible way, because it lacks any description. as soon as i've got some hints on how it should work from someone, who has more experience with PhysX, i fixed it and cleaned it up. you know something more sensible to do?

other sections of code are also based on documentation code with only necessary alternations. i always do it like that, when i gradually figure out something. i see no point in wrapping it up yet, because i tweak it a lot.

about simulation numbers. ok, i spawned a unit sphere with a density of 1 at some height, and using PVD i measured that without any deltaTime scaling(so everything is slow-mo), gravity of -9.8f and stepSize of 1/30 it touched the ground in 2.5 seconds, falling 132 units from starting point. well, it's velocity wasn't constant, but i'm not sure how else can you measure it.


about simulation numbers. ok, i spawned a unit sphere with a density of 1 at some height, and using PVD i measured that without any deltaTime scaling(so everything is slow-mo), gravity of -9.8f and stepSize of 1/30 it touched the ground in 2.5 seconds, falling 132 units from starting point. well, it's velocity wasn't constant, but i'm not sure how else can you measure it.

Do you mean that in 2.5 seconds (that is: 2.5 seconds of simulation time), your sphere, starting at rest, has fallen 132m? If so, that's much further than expected - you'd expect 0.5 * 9.81 * 2.5 * 2.5 which is about 30.7m. That would suggest your simulation is running faster than normal... so I'm not sure I've interpreted your numbers right.

In post 13 your loop multiplies by mStepSize, which is definitely wrong - but then you correct it in post 15. But it's still not quite clear what your latest version looks like.

In any case I'd expect this to work:


void update() {
        clock_t c = clock();
        float deltaTime = (c - mLastTime) / CLOCKS_PER_SEC;
        mAccumulator  += deltaTime;
        mLastTime = c;

        while(mAccumulator > mStepSize) {
            mAccumulator -= mStepSize;
            mScene->simulate(mStepSize);
            mScene->fetchResults(true);
        }
        // Ideally call something like sleepInSeconds(mAccumulator) here
}

I've replaced two calls to clock with one. I wonder - with your current code, assuming your scene is really simple, that update loop may spend a lot of time just spinning round, whilst it waits for the accumulator to accumulate, in which case each time it will lose a little bit of time - maybe that's where your slowdown is coming from?

This topic is closed to new replies.

Advertisement