Frame Rate Independence

chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Frame Rate Independence

Post by chunky »

Abaraba: OK, one last attempt before I quit responding to this.

1) Have. You. Tried. Dividing. Your. First. Parameter. By. 1000.0f? If so, what results did you see?. It's a total of eight characters to add to your code and a recompile.

2) You need to show some actual code here. Spark, I, Erwin, all have working code that displays framerate-independance. That your code doesn't implies that your code is doing something different to mine. Therefore I need to see your code before I can help with more than wild guesses

Gary (-;
stenyak
Posts: 29
Joined: Fri Aug 12, 2005 4:59 pm

Re: Frame Rate Independence

Post by stenyak »

Erwin Coumans wrote:Fast-forward or a slow motion is already possible with the current stepSimulation interface. Slow motion is automatically handled by interpolation. Fast-forward can be done by calling the stepSimulation multiple times, or by using a large time step in combination with a very large allowed number of internal substeps (second argument).

If you really want to manage the call to each single internal simulation substep, similar to Open Dynamics Engine, you can pass in 0 as second argument.
Hi, thanks for the reply.

I don't want to use variable step times. Instead, i want to:
-Increase or decrease simulation frequency (or accuracy/precission) at will at runtime (in order to debug and watch the difference visually, on the fly, allowing me to fine-tune the fixed step time that will be used eventually).
-Be able to run the simulation at any speed. That means i may want to run my, say, 250Hz simulation at 0.5x wall-clock speed, or maybe 2x wall-clock speed, or maybe full speed (for a graphics-less computation of data, or whatever). I should be able to change this simulation speed at run time.

I'm not sure why i would need interpolation?
Also, i'm not sure why i don't need to specify the third parameter, if the documentation says it specifies the size of the "internal step".
Finally, what is this "internal clock" mentioned in the docs? Does it have anything to do with a wall-clock?

Thanks for your patience!
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Frame Rate Independence

Post by chunky »

I'm not sure why i would need interpolation?
Because if the time between two frames is less than the time between two fixed simulation steps, your bodies will appear jerky.

More generally, because render frames won't appear on whole number boundaries of your fixed simulation step time, you need to move bodies very slightly to make up for the difference.
Also, i'm not sure why i don't need to specify the third parameter, if the documentation says it specifies the size of the "internal step".
Because there's a default value of 1/60th of a second. Yay C++.
Finally, what is this "internal clock" mentioned in the docs? Does it have anything to do with a wall-clock?
Bullet keeps track of how much time you have passed it via the first parameter, and uses this to decide how much to interpolate by.

Gary (-;
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Frame Rate Independence

Post by sparkprime »

stenyak wrote:...
I know it's getting busy in here but make sure you read my post since I just showed how to do all those things that you want to do.
stenyak
Posts: 29
Joined: Fri Aug 12, 2005 4:59 pm

Re: Frame Rate Independence

Post by stenyak »

sparkprime wrote:I've had no success at all with 60hz, I think a large number of people will need to use 100hz or more. When you have worked on commercial games, how many have used bullet for dynamics (not just collisions) and what have they clocked the simulation to?
In the field of vehicle simulators (which is what i'm coding), it's not uncommon to step the physics engine at 250, 333 or even 500Hz. This explains why interpolation rarely comes into play in physics, and is in fact not desirable, even though it can help with the user/ai inputs. (but that's offtopic)
sparkprime wrote:for all A,X:
stepSimulation(A,0,X) == stepSimulation(A,X,A) == stepSimulation(X*A,1,A)

There is actually no reason for the special max_steps==0 behaviour at all. I don't like it when a function provides wildly different behaviours depending on its arguments anyway.
Ok, so in theory those 3 are the same, but in practice they're not?
What exacly is X and A? Which one relates to the frequency (250Hz or whatever) of the physics engine if i am to run it in real time? Which of the 3 should be used? I can't get a clear idea by reading your code examples.
sparkprime wrote:I may need even more in the future, when I use bullet in a background thread for instance.
I'm running Bullet on its own thread (dedicated solely to physics)... does that change how the stepSimulation method is used? (regardless of how i code the interaction between physics engine and the rest of subsystems of the simulation)
sparkprime wrote:
Erwin Coumans wrote: What suggestions do you have to document this interface better?
I would prefer a different interface entirely because this is not a simple thing and attempting to "encode" it into a single call does not make it simple. In fact I think it does more damage than exposing a more broken-down API. I'm happy to put a patch together sometime in the next few weeks. There are also some issues to do with interpolation and btMotionState in the tracker, I could fix them at the same time. I already have hacked workarounds in my own copy of the tree. I believe it will be be less buggy, faster, more intuitive, more newbie-friendly, more powerful, and backwards compatible :)
I concur; using default values for parameters can be consfusing at times. For example, stepSimulation is supposed to be used a lot of times a second, however the third parameter is intented to be changed only once during the program life.

Thanks again for the help.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Frame Rate Independence

Post by sparkprime »

stenyak wrote:In the field of vehicle simulators (which is what i'm coding), it's not uncommon to step the physics engine at 250, 333 or even 500Hz. This explains why interpolation rarely comes into play in physics, and is in fact not desirable, ...
So you would also want control over interpolation.
sparkprime wrote:for all A,X:
stepSimulation(A,0,X) == stepSimulation(A,X,A) == stepSimulation(X*A,1,A)
Ok, so in theory those 3 are the same, but in practice they're not?
Both theory and practice as far as I can tell.
What exacly is X and A?
X and A are just numbers, it's an equation, whatever you put in those variables it will be the same.
Which one relates to the frequency (250Hz or whatever) of the physics engine if i am to run it in real time?
The 3rd parameter of stepSimulation is the internal step except in the first case where it's the first parameter. See what I mean about complicated? :)

I used A in both cases actually.
Which of the 3 should be used
It doesn't make any difference as far as I know.
I can't get a clear idea by reading your code examples.
That was kinda my point :p But hopefully it will become clear if you study what they each mean. They all do one internal tick of A seconds with no interpolation. X is always unused.
sparkprime wrote:I may need even more in the future, when I use bullet in a background thread for instance.
I'm running Bullet on its own thread (dedicated solely to physics)... does that change how the stepSimulation method is used? (regardless of how i code the interaction between physics engine and the rest of subsystems of the simulation)
This is a difficult question. You will need to synchronize with the frame to some extent because otherwise you will just call stepSimulation in a tight loop, and the majority of these calls will do nothing. If you give more information about how you are synchronising physics with everything else then I could probably answer. The issue is that your game loop will no longer look like the standard single threaded game loop, it will instead have a physics loop and a graphics loop.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Frame Rate Independence

Post by Erwin Coumans »

From this discussion, one option is to break the current API.

We could remove the optional 3rd parameter (internal fixed timestep), and make it a separate API call 'configureInternalSimulationSubsteps'.
This would configure wether to use internal substeps or not, the value of the internal fixed timestep and clamping value for maximum number of internal simulation substeps.
Obviously, users can still abuse the API, similar to what sparkprime did, by calling this 'configureInternalSimulationSubsteps' API each frame with a variable timestep.

The only argument to stepSimulation remains delta time, usually the amount of wall clock 'seconds' since last call to stepSimulation.

I wonder if changing the API makes it more clear. Rather then creating a patch, what is your suggestion sparkprime? Others?
Thanks,
Erwin
stenyak
Posts: 29
Joined: Fri Aug 12, 2005 4:59 pm

Re: Frame Rate Independence

Post by stenyak »

sparkprime wrote:So you would also want control over interpolation.
Well, yes, i guess i want to control the absence of it :-)
sparkprime wrote:
Ok, so in theory those 3 are the same, but in practice they're not?
Both theory and practice as far as I can tell.
[...]
Which one relates to the frequency (250Hz or whatever) of the physics engine if i am to run it in real time?
The 3rd parameter of stepSimulation is the internal step except in the first case where it's the first parameter. See what I mean about complicated? :)
If the third parameter is the real timestep duration, then those 3 calls are not the same: the one with the smaller 3rd parameter is more accurate and will eat more cpu as a penalty, am i wrong?
sparkprime wrote:
I'm running Bullet on its own thread (dedicated solely to physics)... does that change how the stepSimulation method is used? (regardless of how i code the interaction between physics engine and the rest of subsystems of the simulation)
This is a difficult question. You will need to synchronize with the frame to some extent because otherwise you will just call stepSimulation in a tight loop, and the majority of these calls will do nothing. If you give more information about how you are synchronising physics with everything else then I could probably answer. The issue is that your game loop will no longer look like the standard single threaded game loop, it will instead have a physics loop and a graphics loop.
The synchronizing issues are not what concern me, but rather things inherent to simply running bullet physics in a thread that is not the main one of the program. You can never be too cautious about these issues, specially if i'm not an expert in multithreading...

[as for the sync issues, i've done some tests (not with bullet but with a placeholder fake physics engine) using double and triple buffers for the subsets of data needed by each of the simulation subsystems: input/output (forces and torques for forcefeedback and 6DOF chairs), graphics (positions, rotations, velocities for motion blur), sound (position, velocity for doppler...), net, AI, and other subsystems, etc. My initial tests seemed to work fine in a multithreaded environment (each subsystem running its own thread at its own Hz), so i'll try it again once i get the major subsystems working with the actual libraries]
Erwin Coumans wrote:From this discussion, one option is to break the current API.
We could remove the optional 3rd parameter (internal fixed timestep), and make it a separate API call 'configureInternalSimulationSubsteps'.
This would configure wether to use internal substeps or not, the value of the internal fixed timestep and clamping value for maximum number of internal simulation substeps.
Obviously, users can still abuse the API, similar to what sparkprime did, by calling this 'configureInternalSimulationSubsteps' API each frame with a variable timestep.
I'm not an expert in APIs, but if breaking API is a no-no at the moment, i suggest creating some wrapper methods around the existing one. Obviously, since i come from the ODE community, my suggestion is to create a simple computeThisMuchTimeAtOnce(TimeDuration td); function, that uses the versatile one under the hood. Or even simpler, document how this wrapping can be done manually (put the method implementation in the relevant wiki/doxygen page; i guess it's just one line).
In any case, i feel like current stepSimulation() method is a bit too C-ish compared to the rest of the Bullet API. At first sight, and still not understanding current API completely, i suggest to create two basic methods:
computeThisMuchTimeAtOnce (TimeDuration td);
interpolateThisMuchTimeIntoTheFuture (TimeDuration td); (shouldn't it be called extrapolation instead, if we're guessing values outside the range of known ones?)
And then, maybe, code some wrappers around them, so that newbies have an easy time coding helloWorld.
Just my 0.02€ :)
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Frame Rate Independence

Post by chunky »

Parameters two and three to stepSimulation are tethered and important. Taking the stance that one is going to only be set once per application instance implies that the other is only going to be set once per application instance.

What most people do, I imagine, is end up wrapping stepSimulation into their own function. For sheer irrelevance factor, here's mine:

Code: Select all

int TWPhysics::tick(float delta) {
	// Bullet is smart. It uses fixed ticks, and interpolates the rest.
	//  Pass any old numbers to this function and it'll behave properly
	if(NULL != mWorld) {
		return mWorld->stepSimulation(delta, 20, 1.0/180.0);
	}
	return -1;
}
The only parameter that ever changes is delta. If you were going to modify the API, I would suggest something akin to this [which obviously leaves space for future expansion, and borrows the idea from btRigidBodyConstructionInfo]:

Code: Select all

class btSimulationParameters {
public:
    btSimulationParameters() :
        maxSubSteps(1),
        fixedTimeStep(btScalar(1.0)/btScalar(60.0))
    { }
    btScalar maxSubSteps;
    btScalar fixedTimeStep; 
};

btSimulationParameters p; // These are our stepping parameters
p.maxSubSteps = 5;
btDynamicsWorld *w; // Create a world
w->setSimulationParameters(p);

// And then to actually step the world, you only need to call:
w->advanceSimulation(delta);
Note that I also suggested advanceSimulation instead of stepSimulation - this way, stepSimulation can remain for people who desire per-call control over the extra parameters.

It would also be newbie-friendly, you wouldn't need to create a btSimulationParameters instance until you'd progressed to the point where you would need it.

That's just the ideas off the top of my head

Gary (-;
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Frame Rate Independence

Post by sparkprime »

erwin: I'm just going to add one more parameter to your suggestion based on what people have said:

Code: Select all

void configureInternalSimulationSubsteps(time_step, max_steps, use_interpolation);
int stepSimulation(delta_time);
Personally I would break the new function out into its parts:

Code: Select all

void setTimeStep(btScalar);
void setMaxSteps(unsigned int);
void setUseInterpolation(bool);
void setUseFixedStep(bool);
unsigned int stepSimulation(btScalar delta_time);
And also getters of course. Don't forget the getters :)

That's similar to what I originally proposed except not quite as powerful, and I propose not breaking backwards compatability, but introducing a new interface and marking the old one as deprecated:

Code: Select all

unsigned int stepSimulation(btScalar,int,btScalar); // deprecated

void setTimeStep(btScalar);
unsigned int externalStep(btScalar delta_time); // as you suggested it
unsigned int internalStep(void); // just uses the timestep provided by the setter
unsigned void clearForces(void);  // could be called endExternalStep()
unsigned void synchroniseMotionStates(btScalar time_left);
Now, beginners can just call externalStep(delta_time) and it will just work with sensible defaults. I suggest higher than 60hz since it is more likely to work first time then. Performance issues come second.

However advanced users can now easliy make their own physics loops that call internalStep directly, control motion state stuff (making concurrency more easy) and also interpolation can be disabled by passing a 0 as the time_left parameter of synchroniseMotionStates.

Many of these functions already exist anyway :) But they're not quite clean enough yet, though.

it should be clear how externalStep is implemented just by calling the other listed functions.

Internal step callbacks are no-longer needed either. I've always considered them a work-around for an insufficiently powerful API.
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Frame Rate Independence

Post by chunky »

void setTimeStep(btScalar);
Why? Isn't that just the same as the parameter you end up passing to stepSimulation every time? Also, {set,get} methods imply it's pretty constant, which this one very much isn't.

Gary (-;
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Frame Rate Independence

Post by sparkprime »

This is the value that would default to 60hz (or preferably higher in my opinion), it is "pretty much constant" in the sense that it can be tweaked at runtime for the purposes of experimentation but should otherwise be left constant :)

It is the same as the 3rd parameter but I'd rather it not were done that way for reasons already discussed.
stenyak
Posts: 29
Joined: Fri Aug 12, 2005 4:59 pm

Re: Frame Rate Independence

Post by stenyak »

I'm left wondering 2 things:
a) Why is maxSubSteps ever needed, shouldn't it be automatically calculated?
b) Does interpolation ever change the actual properties of world objects, or is it just some helper feature for people who use graphics engines?

Assuming that maxSubSteps is not necessary, and that interpolation is just an add-on feature that has nothing to do with the physics simulation, then i think sparkprime suggestion is on the right track, with some small modifications:

Code: Select all

unsigned int stepSimulation(btScalar,int,btScalar); // deprecated
void setTimeStep(btScalar seconds);  //defaults to 1/100, aka 100Hz.
unsigned int stepSimulation();  //compute an step
unsigned int stepSimulation(unsigned btScalar seconds);  //batch computing of steps. remaining times are logged so that we stay real-time (see example below).
Example:

Code: Select all

setTimeStep(1/10); //we want our simulation to run unbelievably unfrequently, 10Hz for this example.
stepSimulation(); //we just computed 0.1 seconds (1 step). This is the behaviour ODE users (me :) ) expect.
stepSimulation(0); //do nothing (0 steps).
stepSimulation(2);  //we just computed two seconds (20 steps).
stepSimulation(1.05); //we compute a second (10 steps). We have 0.05s left to compute in future batch calls.
stepSimulation(0.03); //nothing gets computed (0 steps). We have another 0.03s left to compute in future batch calls, totalling 0.08s.
stepSimulation(0.02); //we have 0.05 + 0.03 + 0.02 = 0.10s to compute, which is >= our timeStep, so we compute 1 step.
Obviously, batch-mode calls and single-step calls will usually not be mixed.
If the new stepSimulation batch-mode overlaps with the deprecated function, then simply rename the new method (for example advanceSimulation, as suggested).

I'm not sure how interpolation fits in the api, and also isn't clearForces() done automatically after each step?
chunky
Posts: 145
Joined: Tue Oct 30, 2007 9:23 pm

Re: Frame Rate Independence

Post by chunky »

a) Why is maxSubSteps ever needed, shouldn't it be automatically calculated?
Because then when you accidentally passes milliseconds instead of seconds, or your laptop goes to sleep in the middle of simulation, the whole app doesn't lock up for 5 minutes
b) Does interpolation ever change the actual properties of world objects, or is it just some helper feature for people who use graphics engines?
It's just for visible output [or whatever else you do using a motionstate]
stepSimulation();
Ew, no. stepSimulation needs to take *something* as a value, else you get framerate-dependance.

Gary (-;
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Frame Rate Independence

Post by Erwin Coumans »

This is the value that would default to 60hz (or preferably higher in my opinion), it is "pretty much constant" in the sense that it can be tweaked at runtime for the purposes of experimentation but should otherwise be left constant
Re-using the name 'setTimeStep(btScalar)' for 3rd argument is confusing: the third argument is the internal fixed simulation substep.
a) Why is maxSubSteps ever needed, shouldn't it be automatically calculated?
It is needed and can't be calculated. It clamps the maximum number of internal substeps, to avoid the simulation grinding to a halt.
b) Does interpolation ever change the actual properties of world objects, or is it just some helper feature for people who use graphics engines?
It is just a helper to interpolate the world transform for people who use graphics engines, using a MotionState derived class. It doesn't change the actual property of rigid bodies.

Reading your feedback, I prefer chunky's btSimulationParameters to keep the API clean and simple, and name it btSteppingInfo. We can keep using "stepSimulation", removing the last 2 arguments and breaking backwards compatibility. I rather not introduce additional APIs to step the simulation, to avoid confusion which one to use. The naming of btSteppingInfo should make it clear what the current stepping strategy is. We already have "getSolverInfo" and "getDispatchInfo" so we could add "getSteppingInfo".

If we want to keep backwards compatibility, I rather have 2 versions of "stepSimulation", one accepting only one argument (delta time), and a deprecated one that accepts 3 arguments (the current API).

What do you think?
Erwin