For the complete documentation index, see llms.txt. This page is also available as Markdown.

OSC message format

Use this reference when building your own receiving integration. For the network and first-message check, see OSC output in Stage 2.

The messages below describe the current sender implementation. If you maintain an integration for an older installation, inspect the received type tags, especially for the legacy skeleton layout.

Transport

  • OSC over UDP; set the receiver's port to the same value as Target port.

  • Message addresses are case-sensitive. Point-cloud addresses can be customized in an installation; /MOVIN/PointCloud is the default.

  • OSC numeric arguments are big-endian. Use an OSC decoder for string padding, addresses, and type tags instead of treating a datagram as plain text.

  • UDP packets can be lost, duplicated, or arrive out of order. Do not treat receipt of one packet as receipt of a complete frame.

Connection test

/movin/test has type tag ,i: one signed 32-bit integer. It is a test value, not a tracked-person count. The workspace sends it when Test connection is selected, including during preview.

Point cloud

Default address: /MOVIN/PointCloud.

Each message contains five integer arguments, followed by XYZ float triples:

seq, total_points, chunk_idx, num_chunks, chunk_n, x1, y1, z1, ...
Field
Meaning

seq

Frame sequence number; group chunks with the same sequence

total_points

Point count in the complete frame

chunk_idx

Zero-based index of this chunk

num_chunks

Number of chunks in the frame

chunk_n

Number of points in this chunk

XYZ triples

3 × chunk_n float32 arguments, in meters

The type tag is ,iiiii followed by 3 × chunk_n occurrences of f. For a one-point chunk, it is ,iiiiifff. This is a list of OSC arguments, not a blob.

To assemble a frame:

  1. Group packets by seq and validate that the frame counts agree.

  2. Store each chunk by chunk_idx; ignore duplicate copies of that chunk.

  3. Once indices 0 through num_chunks - 1 are present, concatenate their points in chunk order and check the count against total_points.

  4. Expire incomplete frames after a timeout appropriate to your application. Do not combine chunks from different frames. Reset stale state after reconnecting.

An empty selected cloud produces no point-cloud chunks. Use a receiver timeout to clear or mark stale content; do not display the last frame indefinitely.

Skeletons

One message is sent per bone. Root uses /VMC/Ext/Root/Pos; the remaining bones use /VMC/Ext/Bone/Pos. The current layout is:

  • actor and bone are strings. The default actor prefix is MOVIN, followed by a slot suffix, for example MOVIN_0. Group by actor as well as frame.

  • Actor names identify output slots, not a permanent identity across runs.

  • Positions are in meters; quaternion order is x, y, z, w.

  • Root and Hips use live positions; other bones carry rig offsets. Rotations are local to the skeleton hierarchy. Do not place every bone as an independent world-space point or assume the position fields are interchangeable.

  • frame_idx is an int32 frame index, not a timestamp in seconds. Standard VMC has no such field, so a generic VMC receiver may not accept these messages as is.

  • Handle missing actors with a timeout. OSC reception alone does not animate a character; map the bone names and transforms to your rig.

The current bone names are:

The hierarchy is Root → Hips → Spine → Chest → Neck → Head. Both shoulder chains attach to Chest; each continues through UpperArm → LowerArm → Hand. Both leg chains attach to Hips and continue through UpperLeg → LowerLeg → Foot → Toes.

Legacy skeleton layout

Older integrations may use ,sfffffffi: the same numeric fields but only the bone string, without actor. In that layout the bones now called Spine and Chest were named Chest and UpperChest. Detect the layout from the received type tags; do not feed a legacy message into the current parser.

Coordinate check in your application

The processing/display frame is Y-up. By default the sender flips X on output, and for skeleton rotations also flips quaternion Y and Z. Installations may configure that conversion differently; do not infer wire axes solely from the workspace screenshot or apply an extra mirror without checking.

Use one performer to check origin, scale, forward, and right in the receiving application. Then raise one arm to verify left/right bone mapping. Apply the conversion required by your engine once, consistently to points and skeletons.

If packets arrive but the content is wrong, first check chunk assembly, type tags, bone mapping, and coordinates before changing sensor calibration.

Last updated