I'm now using this exact piece of code. substepping turns substeps ON/OFF, and substeps is the max number of substeps to compute. I believe the 2 systems are equivalente, but please point out if you find any bug.
IMPORTANT: i'm not reading the world state when X steps pass, but when X seconds pass. That is, i use a timer between pause and pause. Therefore, it's not guaranteed that 300 steps will be computed during one second at 300Hz. However, this happens almost always with the first case, and almost never in the rest of cases (which is why it's taking me so long to edit the results in the post, because i have to make several runs before i get a consistent one...).
Code: Select all
const bool substepping = true;
const int substeps = 100;
if (substepping)
{
int countInc = dynamicsWorld->stepSimulation(dt.total_microseconds()/1000000.,substeps,1./getFrequency());
count += countInc;
lasttime += period * countInc;
}
else
{
while (dt > halfperiod) //TODO: merge this loop with the parent, so that the thread can be pauses if physics get under realtime.
{
++count;
dynamicsWorld->stepSimulation(1./getFrequency(),0);
dt -= period;
lasttime += period;
}
}
And the positions are retrieved with this code:
Code: Select all
btTransform trans;
fallRigidBody->getMotionState()->getWorldTransform(trans);
std::cout<<"<< Finished "<<count<<" steps at "<<getFrequency()<< " Hz. Final position: "<< trans.getOrigin().getY() << std::endl;
These are the results:
no substepping wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.95
<< Finished 100 steps at 100 Hz. Final position: 44.85
<< Finished 60 steps at 60 Hz. Final position: 44.75
<< Finished 30 steps at 30 Hz. Final position: 44.5
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.8999
<< Finished 100 steps at 100 Hz. Final position: 29.7
<< Finished 60 steps at 60 Hz. Final position: 29.5
<< Finished 30 steps at 30 Hz. Final position: 29
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.84998
<< Finished 100 steps at 100 Hz. Final position: 4.54993
<< Finished 60 steps at 60 Hz. Final position: 4.25001
<< Finished 30 steps at 30 Hz. Final position: 3.49999
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999991
<< Finished 60 steps at 60 Hz. Final position: 0.99899
<< Finished 30 steps at 30 Hz. Final position: 0.995528
max 10000 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.9581
<< Finished 100 steps at 100 Hz. Final position: 44.9038
<< Finished 60 steps at 60 Hz. Final position: 44.764
<< Finished 30 steps at 30 Hz. Final position: 44.7664
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.9785
<< Finished 100 steps at 100 Hz. Final position: 29.7678
<< Finished 60 steps at 60 Hz. Final position: 29.6784
<< Finished 30 steps at 30 Hz. Final position: 29.167
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.86899
<< Finished 100 steps at 100 Hz. Final position: 4.67576
<< Finished 60 steps at 60 Hz. Final position: 4.5475
<< Finished 30 steps at 30 Hz. Final position: 4.16572
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999989
<< Finished 60 steps at 60 Hz. Final position: 0.998869
<< Finished 30 steps at 30 Hz. Final position: 0.994024
max 100 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.9819
<< Finished 100 steps at 100 Hz. Final position: 44.888
<< Finished 60 steps at 60 Hz. Final position: 44.7536
<< Finished 30 steps at 30 Hz. Final position: 44.6459
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.9117
<< Finished 100 steps at 100 Hz. Final position: 29.7587
<< Finished 60 steps at 60 Hz. Final position: 29.5242
<< Finished 30 steps at 30 Hz. Final position: 29.0363
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.91648
<< Finished 100 steps at 100 Hz. Final position: 4.685
<< Finished 60 steps at 60 Hz. Final position: 4.3828
<< Finished 30 steps at 30 Hz. Final position: 3.71284
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999991
<< Finished 60 steps at 60 Hz. Final position: 0.998838
<< Finished 30 steps at 30 Hz. Final position: 0.994509
max 25 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.9613
<< Finished 100 steps at 100 Hz. Final position: 44.8854
<< Finished 60 steps at 60 Hz. Final position: 44.8123
<< Finished 30 steps at 30 Hz. Final position: 44.8477
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.9041
<< Finished 100 steps at 100 Hz. Final position: 29.8604
<< Finished 60 steps at 60 Hz. Final position: 29.6729
<< Finished 30 steps at 30 Hz. Final position: 29.4106
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.90391
<< Finished 100 steps at 100 Hz. Final position: 4.77254
<< Finished 60 steps at 60 Hz. Final position: 4.70113
<< Finished 30 steps at 30 Hz. Final position: 4.07179
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999987
<< Finished 60 steps at 60 Hz. Final position: 0.998893
<< Finished 30 steps at 30 Hz. Final position: 0.99417
max 15 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.9813
<< Finished 100 steps at 100 Hz. Final position: 44.9197
<< Finished 60 steps at 60 Hz. Final position: 44.8079
<< Finished 30 steps at 30 Hz. Final position: 44.8892
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.9637
<< Finished 100 steps at 100 Hz. Final position: 29.8348
<< Finished 60 steps at 60 Hz. Final position: 29.6534
<< Finished 30 steps at 30 Hz. Final position: 29.5013
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.94549
<< Finished 100 steps at 100 Hz. Final position: 4.67464
<< Finished 60 steps at 60 Hz. Final position: 4.69588
<< Finished 30 steps at 30 Hz. Final position: 3.64771
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999988
<< Finished 60 steps at 60 Hz. Final position: 0.998703
<< Finished 30 steps at 30 Hz. Final position: 0.994792
max 10 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.9695
<< Finished 100 steps at 100 Hz. Final position: 44.882
<< Finished 60 steps at 60 Hz. Final position: 44.9373
<< Finished 30 steps at 30 Hz. Final position: 44.6227
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.935
<< Finished 100 steps at 100 Hz. Final position: 29.771
<< Finished 60 steps at 60 Hz. Final position: 29.7721
<< Finished 30 steps at 30 Hz. Final position: 29.4246
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.9052
<< Finished 100 steps at 100 Hz. Final position: 4.65617
<< Finished 60 steps at 60 Hz. Final position: 4.62355
<< Finished 30 steps at 30 Hz. Final position: 3.9646
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999989
<< Finished 60 steps at 60 Hz. Final position: 0.998956
<< Finished 30 steps at 30 Hz. Final position: 0.993704
max 5 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 44.9803
<< Finished 100 steps at 100 Hz. Final position: 44.9109
<< Finished 60 steps at 60 Hz. Final position: 44.903
<< Finished 30 steps at 30 Hz. Final position: 44.7792
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 29.9535
<< Finished 100 steps at 100 Hz. Final position: 29.8034
<< Finished 60 steps at 60 Hz. Final position: 29.5829
<< Finished 30 steps at 30 Hz. Final position: 29.6838
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 4.94099
<< Finished 100 steps at 100 Hz. Final position: 4.66523
<< Finished 60 steps at 60 Hz. Final position: 4.44343
<< Finished 30 steps at 30 Hz. Final position: 3.5473
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999988
<< Finished 60 steps at 60 Hz. Final position: 0.998958
<< Finished 30 steps at 30 Hz. Final position: 0.995482
max 3 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 45.0394
<< Finished 100 steps at 100 Hz. Final position: 44.9692
<< Finished 60 steps at 60 Hz. Final position: 44.847
<< Finished 30 steps at 30 Hz. Final position: 44.69
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 30.0643
<< Finished 100 steps at 100 Hz. Final position: 29.8278
<< Finished 60 steps at 60 Hz. Final position: 29.803
<< Finished 30 steps at 30 Hz. Final position: 29.5404
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 5.09172
<< Finished 100 steps at 100 Hz. Final position: 4.77863
<< Finished 60 steps at 60 Hz. Final position: 4.62727
<< Finished 30 steps at 30 Hz. Final position: 4.36807
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999987
<< Finished 60 steps at 60 Hz. Final position: 0.998888
<< Finished 30 steps at 30 Hz. Final position: 0.9952
max 2 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 45.093
<< Finished 100 steps at 100 Hz. Final position: 44.8818
<< Finished 60 steps at 60 Hz. Final position: 44.7908
<< Finished 30 steps at 30 Hz. Final position: 44.6122
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 30.2181
<< Finished 100 steps at 100 Hz. Final position: 29.8874
<< Finished 60 steps at 60 Hz. Final position: 29.7461
<< Finished 30 steps at 30 Hz. Final position: 29.326
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 5.27164
<< Finished 100 steps at 100 Hz. Final position: 4.5986
<< Finished 60 steps at 60 Hz. Final position: 4.50991
<< Finished 30 steps at 30 Hz. Final position: 4.06084
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 1
<< Finished 100 steps at 100 Hz. Final position: 0.999988
<< Finished 60 steps at 60 Hz. Final position: 0.998936
<< Finished 30 steps at 30 Hz. Final position: 0.993844
max 1 substeps wrote:
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 46.076
<< Finished 100 steps at 100 Hz. Final position: 45.4047
<< Finished 60 steps at 60 Hz. Final position: 45.3614
<< Finished 30 steps at 30 Hz. Final position: 45.1331
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 33.9136
<< Finished 100 steps at 100 Hz. Final position: 32.0674
<< Finished 60 steps at 60 Hz. Final position: 32.4089
<< Finished 30 steps at 30 Hz. Final position: 33.4197
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 14.5084
<< Finished 100 steps at 100 Hz. Final position: 9.30374
<< Finished 60 steps at 60 Hz. Final position: 11.221
<< Finished 30 steps at 30 Hz. Final position: 11.7972
(1.0 seconds elapsed)
<< Finished 300 steps at 300 Hz. Final position: 0.999509
<< Finished 100 steps at 100 Hz. Final position: 0.9975
<< Finished 60 steps at 60 Hz. Final position: 1.49259
<< Finished 30 steps at 30 Hz. Final position: 1.04568
max 0 substeps wrote:
(1.0 seconds elapsed)
<< Finished 493 steps at 300 Hz. Final position: -138199
<< Finished 187 steps at 100 Hz. Final position: -33714.1
<< Finished 116 steps at 60 Hz. Final position: -14794.6
<< Finished 60 steps at 30 Hz. Final position: -4528.75
(1.0 seconds elapsed)
<< Finished 431 steps at 300 Hz. Final position: -1.10227e+11
<< Finished 173 steps at 100 Hz. Final position: -2.15859e+10
<< Finished 112 steps at 60 Hz. Final position: -3.48767e+10
<< Finished 59 steps at 30 Hz. Final position: -6.02033e+09
(1.0 seconds elapsed)
<< Finished 362 steps at 300 Hz. Final position: -4.54513e+16
<< Finished 166 steps at 100 Hz. Final position: -1.23049e+16
<< Finished 107 steps at 60 Hz. Final position: -7.15754e+16
<< Finished 57 steps at 30 Hz. Final position: -7.48711e+15
(1.0 seconds elapsed)
<< Finished 331 steps at 300 Hz. Final position: -3.21032e+22
<< Finished 158 steps at 100 Hz. Final position: -2.85914e+22
<< Finished 103 steps at 60 Hz. Final position: -1.29481e+23
<< Finished 55 steps at 30 Hz. Final position: -5.61669e+21
Conclussions:
Obviously, bullet is inconsistent in its behaviour when maxSubsteps==0, no matter if you specify the substep timestep or not. IMHO this should be changed, since it is not intuitive. Passing maxSubsteps=0 should result in an exception being thrown, or something similar. Well, even better would be to simply return 0 as number of steps computed... but then the user has to check for this value (which he already should be doing anyway, except that in the helloworld demo this is
not done, which could clearly be one of the reasons why people can't achieve framerate independence if they base their code off the helloworld source.... haven't checked the rest of bullet demos, but i hope they don't repeat the same mistake!!)
We can see that the results differ depending on the maxSubsteps used.
In my tests, i've checked that using substepping, the number of steps per seconds almost always vary (sometimes 300, sometimes 299, sometimes 301, or 304, etc.). This should correct overtime, giving a correct average number of steps per second, and shows that the behaviour is very accurate, but not precise (see wikipedia on how these 2 terms differ xD). However, without substepping, the results are almost always 300 steps (as it should). This means that:
- Using both substepping and no-substepping gives perfect accuracy.
- Using substepping does not give perfect precission.
^----- all of this, i'm talking about simulated time vs. wall time. not about the accuracy/precission of the simulation itself.
Also, it must be noted that, in all cases, statemotions have been used. This means that, if the docs are correct, the interpolation could account for the differences between different maxSubsteps (with substepping enabled). Since i'm tired of testing, i won't try the same batch of tests without them. It's enough to know that, if using statemotions AND not using substepping you always get the same results (so no interpolation going on).
The rest of conclusions (why there are differences in the position of the body) are up to the reader, because i've had enough of these tests and can't think clearly enough to extract more conclussions out of the data anymore