# Support Matrix: draco-core vs C++ Draco
How `draco-core` maps onto upstream C++ Draco. `draco-core` is the raw `.drc`
**bitstream** layer only; file and scene formats live one level up in `draco-io`
(OBJ / PLY / FBX) and `draco-gltf` (full glTF / GLB scenes). The C++ reference is
the local checkout at `D:\Projects\Draco\src`.
## Status labels
| yes | Implemented. |
| explicit | Supported, but only by manual selection — never auto-chosen. |
| — | Supported, but not a default choice for new streams (only on explicit request). |
## Crate boundary
Which crate owns each area — so nothing reads as a gap when it is simply handled
at a different level of abstraction.
| `.drc` point-cloud / triangle-mesh / keyframe bitstream | yes | `draco-core` |
| `.drc` geometry & attribute metadata | yes | `draco-core` |
| glTF / GLB scenes + `KHR_draco_mesh_compression` | yes | `draco-gltf` (geometry via `draco-core`, document-preserving compress via `draco-io`) |
| glTF materials / textures / nodes / animations / skins / lights / extensions | yes (transcoder) | `draco-gltf` — preserved across a Draco round-trip; skinned geometry *is* compressed (`JOINTS_n`/`WEIGHTS_n`) |
| glTF `EXT_structural_metadata` / `EXT_mesh_features` | yes (glTF path) | `draco-gltf` — carried through as an opaque extension; semantic interpretation is future scene-layer work |
| OBJ / PLY / FBX | yes | `draco-io` |
## Raw geometry bitstreams
All decode and encode in `draco-core`.
| Point cloud, sequential | yes | yes | Core parity path. |
| Point cloud, KD-tree | yes | yes | Core parity path. |
| Triangle mesh, sequential | yes | yes | Core parity path. |
| Triangle mesh, EdgeBreaker standard | yes | yes | Main compressed mesh path. |
| Triangle mesh, EdgeBreaker valence | yes | yes | Behind `edgebreaker_valence_*`; decode covers every version, encode writes current streams by default and round-trips 1.2→current with `legacy_bitstream_encode`. |
| Triangle mesh, EdgeBreaker predictive (type `1`) | yes (≤ `0.9.1`) | decode yes, encode explicit | Legacy connectivity; behind the legacy features. See [Legacy & compatibility](#legacy--compatibility). |
## Attribute encoders & semantics
All four sequential attribute encoders decode and encode in `draco-core`:
`GENERIC`, `INTEGER`, `QUANTIZATION`, `NORMALS` (octahedral transform).
Semantics `POSITION`, `NORMAL`, `TEX_COORD`, `COLOR`, `GENERIC` are all
supported. Draco attributes are typed point attributes plus a semantic tag;
format-specific meaning (glTF accessors, FBX layers) belongs above `draco-core`.
## Prediction schemes
| `PREDICTION_NONE` | -2 | yes | yes | — |
| `PREDICTION_DIFFERENCE` | 0 | yes | yes | yes |
| `MESH_PREDICTION_PARALLELOGRAM` | 1 | yes | yes | yes |
| `MESH_PREDICTION_MULTI_PARALLELOGRAM` | 2 | decode only* | decode yes, encode explicit | — |
| `MESH_PREDICTION_TEX_COORDS_DEPRECATED` | 3 | decode only* | decode yes, encode explicit | — |
| `MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM` | 4 | yes | yes | yes |
| `MESH_PREDICTION_TEX_COORDS_PORTABLE` | 5 | yes | yes | yes |
| `MESH_PREDICTION_GEOMETRIC_NORMAL` | 6 | yes | yes | yes |
\* The public C++ encoder rejects ids 2 and 3; they remain real C++ *decoders*.
`draco-core` keeps their encode behind `legacy_bitstream_encode` + manual
selection, never auto-chosen.
## Prediction transforms
| Default / delta, `PREDICTION_TRANSFORM_WRAP` | yes | yes | Simple prediction paths. |
| `NORMAL_OCTAHEDRON` (id 2) | encode ≤ `0.9.1` | decode yes, encode explicit | Legacy normal transform; see [Legacy & compatibility](#legacy--compatibility). |
| `NORMAL_OCTAHEDRON_CANONICALIZED` (id 3) | yes (since `0.10.0`) | yes | Modern normal transform. |
## Entropy & bit coding
All decode and encode in `draco-core`: rANS bit coding, rANS symbol coding,
tagged symbols, raw symbols, direct bit coding, folded bit32 coding.
## Metadata
C++ Draco stores metadata entries as untyped byte blobs, with typed (`int32`,
`double`, array, string) APIs layered over the same bytes. `draco-core` follows
the same model and round-trips it through encode/decode.
| Geometry-level entries | yes | On `PointCloud`; `Mesh` inherits via its base. |
| Attribute metadata (by unique id) | yes | Keyed by Draco unique id, not vector index. |
| Lookup by string entry | yes | Mirrors C++ `GetAttributeMetadataByStringEntry`. |
| Nested sub-metadata | yes | C++-matching nesting limit. |
| Binary + typed (`int32`/`double`/array/string) values | yes | Raw bytes are the base API; typed helpers mirror C++ byte layout (explicit little-endian). |
| Encode/decode round-trip | yes | When bitstream header flags are available. |
Empty values are rejected, matching C++ Draco's metadata decoder.
## Keyframe animation
> Likely legacy. C++ Draco's `KeyframeAnimation` (2017, ~Draco `1.3.4`) is used
> nowhere in Draco's own pipeline — no CLI, no glTF/USD I/O, no JS binding, only
> its own unit tests. glTF does not use it either (it compresses only geometry).
> Treat the Rust port as bitstream-parity completeness, not a recommended path.
`draco-core` ports the container, encoder, and decoder as a thin typed wrapper
over the sequential point-cloud path (`KeyframeAnimation`,
`KeyframeAnimationEncoder`, `KeyframeAnimationDecoder`): timestamp track
(unique id `0`), multiple tracks, and quantized data all work. It adds no
dependencies and could be dropped without affecting any other path. This is
unrelated to glTF node animation, which `draco-gltf` preserves at the scene
level (see [Crate boundary](#crate-boundary)).
## Legacy & compatibility
`draco-core` matches observable C++ behavior for existing streams, including
awkward but compatibility-sensitive details. Every bitstream version from
`0.9.1` to current decodes, and every traversal (standard / predictive /
valence) round-trips behind the legacy features.
- **Feature flags.** Legacy decode lives behind `legacy_bitstream_decode`;
legacy encode lives behind `legacy_bitstream_encode`; valence lives behind
`edgebreaker_valence_*`.
- **EdgeBreaker predictive (type `1`).** C++ emitted it in `0.9.1` and replaced
it with valence (type `2`) in `0.10.0`; `1.0.0`+ never emit it. `draco-core`
decodes it, and encodes it only via the `force_predictive_traversal` option —
never auto-selected.
- **Normal octahedron (id 2).** C++ used it through `0.9.1`, then switched to the
canonicalized transform (id 3) in `0.10.0`. `draco-core` decodes id 2 and, for
pre-2.0 streams, also uses the historical `0.9.1` octahedron-to-vector float
conversion so byte output matches the old decoder exactly.
- **Pre-2.2 layout.** The pre-2.2 valence and constrained-multi-parallelogram
layouts decode with the default compatibility feature and encode with
`legacy_bitstream_encode`. They differ from
current streams in: a separate main traversal symbol stream, raw-bit (not
rANS) start faces, a split-count/mode prefix, hole events after topology
splits, a 2-bit split-edge selector, fixed-u32 counts before bitstream 2.0,
and an always-present header flags field.
- **Portable texcoord prediction** preserves the C++ cast/wrapping order around
unsigned intermediate arithmetic.