Recursive AI

Pose cache (version 1)

All onescope docs

A pose cache holds the positions and orientations of a fixed set of things over consecutive steps, with no simulation behind them: a reference engine's pose dump, a baked clip. The shell opens one as a ghost source (see fields-links-ghosts.md). The reader is OneScope.Sdk.PoseCache; a module or a tool can write one with PoseCache.Create and Write.

All integers and floats are little endian. Frame k is the world at step start step + k.

magic            4 bytes   "OSPC"
version          u16       1
flags            u16       0 (any other value is an error)
dimensions       u8        2 or 3
reserved         u8 + u16  zero (any other value is an error, so a parsed cache always writes back to the same bytes)
entity count     u32       1 to 65 536
frame count      u32       1 to 4 194 304
start step       i64       0 or more
metres per unit  f64       0 (a unit with no physical size) or a positive finite number
text x 6         u16 length (at most 1024) + UTF-8 bytes, in this order:
                 unit name, module id, library version, scene, replay, label
entities         entity count x:
                   u64 id          not 0, unique
                   u8 shape        0 point, 1 sphere, 2 box, 3 capsule
                   3 bytes         zero
                   f32 x 3         size: sphere radius in x; box half extents; capsule radius in x and half length in y (axis is local Y); finite
                   u16 + bytes     name (at most 1024 bytes of UTF-8)
poses            frame count x entity count x 7 x f32: position x y z, rotation x y z w

The poses are the rest of the file: its length must equal frame count x entity count x 28 exactly, so a count cannot claim more than the file holds. A NaN position x means the entity is absent in that frame (the rotation is then ignored); every other value must be finite. A zero rotation reads as the identity.

The origin fields (module id, library version, scene, replay) are free text, each possibly empty. When replay is a plain file name (no directory part), the shell looks for it next to the cache and offers to open it with the named module; any other value offers nothing, so a cache can never point the shell at another folder.

Limits: the file is at most 256 MiB. Every length is checked against the bytes that remain before anything is allocated, sizes are computed with checked arithmetic, and every error is a ScopeFormatException that names the input, what was expected and the offset. Reading the bytes and writing them again gives the same bytes.