Investigate entity position/rotation offsets #16

Closed
opened 2026-03-17 00:56:13 +00:00 by kit · 1 comment
Owner

Some entities appear slightly offset from their correct position or improperly rotated in the web client. We need to audit the full transform pipeline to find where the discrepancy comes from.

Possible causes

Server side

  • We read position from ICollideable::GetCollisionOrigin() — this may differ from the render origin for some entity types
  • Some entities have a render offset separate from collision origin (e.g., GetAbsOrigin() vs GetCollisionOrigin())
  • Angles: GetCollisionAngles() may not match the visual angles for all entity types

Client side — coordinate conversion

  • Source uses (X forward, Y left, Z up) — we convert to Three.js with (-Y, Z, -X)
  • Euler angle conversion: Source uses (pitch, yaw, roll) with specific axis conventions — our sourceAnglesToThreeQuat() may have edge cases
  • Euler order 'YXZ' and sign flips (-pitch, -yaw, +roll) need verification against Source's actual convention

Model-level offsets

  • Some MDL models define a root bone offset or origin adjustment
  • Attachment points and hitbox origins can differ from the model origin
  • Brush models (*N) use the brush's origin which may not be at (0,0,0) in model space

How to debug

  • Compare specific entity positions in the GMod console (Entity:GetPos(), Entity:GetAngles()) with what the web client receives
  • Check a few entity types: prop_physics, prop_dynamic, func_door, player
  • Look for consistent offset patterns (always off by N units, always rotated 90 degrees, etc.)

Relates to

  • #5 (asset rendering — model origin handling)
Some entities appear slightly offset from their correct position or improperly rotated in the web client. We need to audit the full transform pipeline to find where the discrepancy comes from. ## Possible causes ### Server side - We read position from `ICollideable::GetCollisionOrigin()` — this may differ from the render origin for some entity types - Some entities have a render offset separate from collision origin (e.g., `GetAbsOrigin()` vs `GetCollisionOrigin()`) - Angles: `GetCollisionAngles()` may not match the visual angles for all entity types ### Client side — coordinate conversion - Source uses (X forward, Y left, Z up) — we convert to Three.js with `(-Y, Z, -X)` - Euler angle conversion: Source uses (pitch, yaw, roll) with specific axis conventions — our `sourceAnglesToThreeQuat()` may have edge cases - Euler order `'YXZ'` and sign flips (`-pitch`, `-yaw`, `+roll`) need verification against Source's actual convention ### Model-level offsets - Some MDL models define a root bone offset or origin adjustment - Attachment points and hitbox origins can differ from the model origin - Brush models (`*N`) use the brush's origin which may not be at `(0,0,0)` in model space ## How to debug - Compare specific entity positions in the GMod console (`Entity:GetPos()`, `Entity:GetAngles()`) with what the web client receives - Check a few entity types: `prop_physics`, `prop_dynamic`, `func_door`, `player` - Look for consistent offset patterns (always off by N units, always rotated 90 degrees, etc.) ## Relates to - #5 (asset rendering — model origin handling)
Author
Owner

Related: #9 (animation system). Some position/rotation offsets may be caused by missing bone transforms or attachment point data. Worth re-evaluating after #9 is implemented to see which cases resolve and which are genuine transform bugs.

Related: #9 (animation system). Some position/rotation offsets may be caused by missing bone transforms or attachment point data. Worth re-evaluating after #9 is implemented to see which cases resolve and which are genuine transform bugs.
kit closed this issue 2026-03-17 10:59:58 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kit/gmod-web-stream#16
No description provided.