Skip to content

Take the wheel physics off the PhysObj interface where the entity can answer - #336

Open
Sycatle wants to merge 1 commit into
StyledStrike:mainfrom
Sycatle:perf/wheel-physics-entity-transforms
Open

Take the wheel physics off the PhysObj interface where the entity can answer#336
Sycatle wants to merge 1 commit into
StyledStrike:mainfrom
Sycatle:perf/wheel-physics-entity-transforms

Conversation

@Sycatle

@Sycatle Sycatle commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Addresses the measurements in #335, where a PhysObj access is shown to cost 90-175 us against 0.2 us for the entity-side call, and DoPhysics performs four of them per wheel per substep.

Three of the four are replaced. The fourth is deliberately left alone.

The substitutions

Each was measured on a live vehicle at arbitrary angles rather than derived from the docs:

replaced by deviation
phys:LocalToWorld( v ) ent:LocalToWorld( v ) 0.00098
phys:WorldToLocal( p ) ent:WorldToLocal( p ) 0.00098
phys:GetVelocityAtPoint( p ) velocity + angVel x ( p - masscentre ) 0.00016

There is no mass-centre offset to apply to the first two: the physics object local frame coincides with the entity one. That was my working assumption going in and it was wrong — applying it introduced 12 units of error everywhere.

The velocity form needs the angular velocity and the world mass centre. Both are derived once per substep in PhysicsSimulate, which already holds the physics object, and read by all four wheels. That trades sixteen accesses per vehicle per substep for one.

What is not replaced, and why

CalculateForceOffset stays. It returns an impulse — the torque divided by the inertia tensor including its coupling — not a plain cross product. Measured per-component ratios of 44.8 / 30.0 / 26.5 do not follow the inertia 1882 / 1702 / 301, so it is not a component-wise division and I could not reproduce it reliably.

It is also the call that applies force to the wheels. Reconstructing it slightly wrong would change how vehicles handle with nothing visibly broken, which is not a risk worth the last quarter of the gain.

Result

Eight vehicles, 413 frames each, same map and same player before and after, with every other local change identical in both arms:

before after
PhysObj calls 164.6 /frame 80.0 /frame
time in them 18.44 ms/frame 7.95 ms/frame
CServerGameDLL::GameFrame 26.01 ms/frame 13.88 ms/frame

I am deliberately not quoting a fleet-wide tick rate: the figure I have for that also includes a separate change slowing Think for parked vehicles, and attributing it here would overstate this patch.

Evidence that handling is unchanged

Trajectories were recorded tick by tick over a fixed 13-second input programme, three runs before and three after. The before/after deviation stays inside the same envelope as two runs of identical code — at worst 0.20 units of position over 430 ticks, with final positions agreeing to three decimals.

Bit-identical reproduction does not exist here, so "within the noise of the unmodified build" is the criterion, with the noise measured rather than assumed. It has also been driven in game.

Known issues

The change was developed and measured in a fork of this addon; what is proposed here is a clean port of it, differing only in identifier names and comments. The measurements above come from that fork, not from this branch.

… answer

Three of the four PhysObj calls in DoPhysics now go through their entity-side
equivalent. Each substitution was measured on a live vehicle at arbitrary angles
rather than derived, and the angular velocity and world mass centre are hoisted
into PhysicsSimulate so the four wheels share one lookup instead of taking four
each.

CalculateForceOffset is left alone: it returns an impulse, so the torque through
the inertia tensor including its coupling, and it is the call that applies force
to the wheels.

On eight vehicles, GameFrame drops from 26.01 to 13.88 ms per frame.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants