1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! World-coordinate helpers for Source 2's split position storage.
//!
//! Networked entities in Source 2 do not transmit a full world position
//! every tick. Each position is split across two networked fields:
//!
//! - an integer **cell index** (`m_cellX`, `m_cellY`, `m_cellZ`) identifying
//! which fixed-size cell of the world the entity is currently in, and
//! - a quantized **offset** (`m_vecOrigin.m_vecX`, etc.) describing where
//! inside that cell the entity sits, bounded to `[0, CELL_SIZE)`.
//!
//! The true world position (in Hammer units, the same coordinate space used
//! by Valve's level editor and `.vmap` data) is reconstructed via
//! [`cell_to_world`]. Reading the offset alone gives a sawtooth signal that
//! resets every time the entity crosses a cell boundary, not a usable
//! coordinate. See [`Entity::world_position`](crate::Entity::world_position)
//! for the typical entity-side combine.
/// Number of bits used by Source 2 to address a position within a cell.
///
/// The on-the-wire offset is quantized into a `2^CELL_BITS` window, so cells
/// are `CELL_SIZE` Hammer units wide on each axis.
pub const CELL_BITS: u32 = 9;
/// Edge length of a single cell in Hammer units (`2^CELL_BITS`).
pub const CELL_SIZE: f32 = as f32;
/// Half the addressable world extent in Hammer units.
///
/// Source 2's cell grid is centred on the world origin, so cell 0 starts at
/// `-WORLD_HALF` and cell indices run upward from there. This constant is the
/// shift applied in [`cell_to_world`] to translate cell-relative addresses
/// back to centred world coordinates.
pub const WORLD_HALF: f32 = 16384.0;
/// Combine a cell index and an in-cell offset into a world coordinate.
///
/// Applies the standard Source 2 transform `cell * CELL_SIZE - WORLD_HALF +
/// offset` along a single axis. Operate on each axis independently to
/// recover a full `[x, y, z]` world position; see
/// [`Entity::world_position`](crate::Entity::world_position) for the typical
/// entity-side combine that does this for all three axes at once.