Skip to content

Undocumented preconditions and units in the C headers #11

Description

@jcant0n

A collection of things a C caller cannot learn from the headers, gathered while writing the new test suites. Each one cost real time to discover, and each is one comment away from being free.

The caller must integrate gravity

CharacterVirtual_Update(dt, gravity, allocator) does not apply gravity to the character's velocity. Jolt's own header is explicit:

it's your own responsibility to apply gravity to the character velocity

@param inGravity ... only used when the character is standing on top of another object to apply downward force

A character with zero velocity does not move, whatever is passed for gravity. A test asserted otherwise, failed on all three platforms, and the wrapper was right. The documented pattern is read velocity, add gravity * dt, write it back, then Update.

This is the one most likely to cost somebody an afternoon: the symptom is a floating character with no error anywhere.

Preconditions that assert inside Jolt

call precondition
CharacterVirtual_SetInnerBodyShape requires a character created with an innerBodyShape
RagdollSettings_GetConstraintIndexForBodyIndex requires CalculateBodyIndexToConstraintIndex() first; CreateRagdoll does not call it
TrackedVehicleController_SetDriverInput / SetLeftRatio / SetRightRatio upstream asserts ratio != 0.0f, forwarded unguarded
WheeledVehicleControllerSettings_SetGearRatio zero-fills gaps, but the constructor asserts forward ratios > 0 and reverse < 0, so a sparse write asserts far from the cause
Body_GetWorldSpaceSurfaceNormal needs the empty SubShapeID sentinel, for which the C API exports no constant

Units and signs that the names do not suggest

  • Suspension MinLength is the fully raised pose and MaxLength the drooped one; natural length is max + preload.
  • A wheel's two friction curves use different X units: longitudinal is a dimensionless slip ratio in [0, 0.2], lateral a slip angle in degrees in [0, 20].
  • limitedSlipRatio must be > 1, with FLT_MAX meaning open.
  • CastCylinder_Create takes a convex radius fraction; CastSphere_Create takes a radius.
  • Every angle is radians.

Null fallbacks indistinguishable from real answers

  • CharacterVirtual_GetUp(NULL) returns (0,0,0) but Character_GetUp(NULL) returns (0,1,0).
  • GetGroundState(NULL) returns IN_AIR.
  • VehicleTransmissionSettings_GetMode(NULL) returns AUTO, which is 0.
  • Wheel_GetContactSubShapeID(NULL) returns 0, a valid sub-shape ID; the real empty sentinel is 0xFFFFFFFF.

Behaviours that look like bugs and are not

Recorded so nobody "fixes" them during a bump:

  • Ragdoll::GetPose is not the inverse of SetPose: it returns body 0's world position as the root offset and zeroes joint matrix 0's translation. Get then Set is a fixed point; Set then Get is not.
  • SkeletalAnimation::GetDuration() reads only animated joint 0's last keyframe. Other joints do not contribute, and Sample's looping wrap uses that value.
  • VehicleEngine::SetCurrentRPM clamps to [minRPM, maxRPM], so it is not plain assignment.
  • Wheel::GetContactPosition/Normal/Longitudinal/Lateral assert HasContact() upstream; the wrapper substitutes zeros.

Also

vehicle.cpp:196 reads sp.mFrequency unconditionally. Upstream keeps mFrequency and mStiffness in a union, so this is correct today — but 5.6.0 adds ESpringMode::MassNormalizedStiffnessAndDamping, and if that arrives with the union split the getter returns the wrong field for two of three modes and still compiles. test_vehicle_extra.c pins both ESpringMode and EMotorState as append-only, since both are converted with a bare cast.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions