Skip to content

Commit

Permalink
feat: make configurable the number of physics calculus substeps
Browse files Browse the repository at this point in the history
  • Loading branch information
DaymareOn committed Apr 26, 2022
1 parent 6602530 commit 6476b1b
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 3 deletions.
10 changes: 10 additions & 0 deletions configs/configs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@
<groupIterations>16</groupIterations>
<groupEnableMLCP>false</groupEnableMLCP>
<erp>0.2</erp>
<!-- min-fps is the main frequency at which physics simulation will advance; in fact, it defines the main period of time at which the physics simulation will advance; (p=1/f).
min-fps should never be configured under 60, or the bullet physics engine will badly bug.
The higher it is, the better your physics simulation will be and the more costly for your CPU/GPU. 120 costs twice as much cpu as 60. -->
<min-fps>60</min-fps>
<!-- This setting allows you to choose between fps and physics simulation quality, at low fps.
maxSubSteps is the maximum number of physics calculus steps, each frame. Slowdowns are experienced when fps are below min-fps/maxSubSteps.
With the default value, slowdowns are experienced below 60/4 = 15 fps.
The higher it is, the more costly your physics simulation will be at low fps. 2 substeps cost twice as 1 substep.
When fps are above min-fps, one substep is enough; when fps are between min-fps/n and min-fps/(n+1), n+1 substeps are necessary.
The max value is 60, which allows for slowdowns below 5 fps when min-fps is at 300 (max value). -->
<maxSubSteps>4</maxSubSteps>
</solver>
</configs>
2 changes: 2 additions & 0 deletions hdtSMP64/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ namespace hdt
SkyrimPhysicsWorld::get()->min_fps = (btClamped(reader.readInt(), 1, 300));
SkyrimPhysicsWorld::get()->m_timeTick = 1.0f / SkyrimPhysicsWorld::get()->min_fps;
}
else if (reader.GetLocalName() == "maxSubSteps")
SkyrimPhysicsWorld::get()->m_maxSubSteps = btClamped(reader.readInt(), 1, 60);
else
{
_WARNING("Unknown config : %s", reader.GetLocalName());
Expand Down
5 changes: 2 additions & 3 deletions hdtSMP64/hdtSkyrimPhysicsWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,14 @@ namespace hdt
// This magic value directly impacts the number of computations and the time cost of the mod...
if (m_accumulatedInterval * 2.0f > tick)
{
// We limit the interval to 4 substeps.
// The interval is limited to a configurable number of substeps, by default 4.
// Additional substeps happens when there is a very sudden slowdown, or when fps is lower than min-fps,
// we have to compute for the passed time we haven't computed.
// n substeps means that when instant fps is n times lower than usual current fps, we stop computing.
// So, we guarantee no jitter for fps greater than min-fps / maxSubsteps.
// For example, if min-fps = 60 and maxSubsteps = 4, we guarantee no jitter for 15+ fps,
// at the cost of additional simulations.
const auto maxSubSteps = 4;
const auto remainingTimeStep = std::min(m_accumulatedInterval, tick * maxSubSteps);
const auto remainingTimeStep = std::min(m_accumulatedInterval, tick * m_maxSubSteps);

readTransform(remainingTimeStep);
updateActiveState();
Expand Down
1 change: 1 addition & 0 deletions hdtSMP64/hdtSkyrimPhysicsWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace hdt
int min_fps = 60;
int m_percentageOfFrameTime = 300; // percentage of time per frame doing hdt. Profiler shows 30% is reasonable. Out of 1000.
float m_timeTick = 1 / 60.f;
int m_maxSubSteps = 4;
bool m_clampRotations = true;
bool m_unclampedResets = true;
float m_unclampedResetAngle = 120.0f;
Expand Down

0 comments on commit 6476b1b

Please sign in to comment.