The attribute section holds the values at the vertices: positions, normals, colours, texture coordinates and any other data. Draco compresses each attribute in three steps: it quantises floating-point values to integers, predicts each value from values already decoded, and entropy-codes the small corrections. A decoder reverses them. Attributes are grouped into attribute decoders; with Edgebreaker, each decoder after the first has its own seams in the connectivity.
Attribute decoders
| Field | Type | Meaning |
|---|---|---|
num_attributes_decoders | UI8 | Number of attribute decoders |
| With Edgebreaker only, for each decoder: | ||
att_dec_data_id | UI8 | The decoder’s id (“attribute decoder ids” in the specification) |
att_dec_decoder_type | UI8 | 0 MESH_VERTEX_ATTRIBUTE, one value per vertex; 1 MESH_CORNER_ATTRIBUTE, values per corner, split at seams |
att_dec_traversal_method | UI8 | Order in which values are visited: 0 MESH_TRAVERSAL_DEPTH_FIRST, 1 MESH_TRAVERSAL_PREDICTION_DEGREE (vertices with more decoded neighbours first) |
| Then, for each decoder: | ||
att_dec_num_attributes | varUI32 | Number of attributes in this decoder |
| For each of its attributes: | ||
att_dec_att_type | UI8 | What the attribute is; see below |
att_dec_data_type | UI8 | The type of each component; see below |
att_dec_num_components | UI8 | Components per value, for example 3 for a position |
att_dec_normalized | UI8 | 1 when integer values stand for numbers from 0 to 1 (or −1 to 1) |
att_dec_unique_id | varUI32 | The attribute’s id, which metadata refers to |
| Then, for each of its attributes: | ||
seq_att_dec_decoder_type | UI8 | 0 generic, 1 integer, 2 quantisation, 3 normals; see below |
| Attribute type | Name | Data type | Name | |
|---|---|---|---|---|
| 0 | POSITION | 1 | DT_INT8 | |
| 1 | NORMAL | 2 | DT_UINT8 | |
| 2 | COLOR | 3 | DT_INT16 | |
| 3 | TEX_COORD | 4 | DT_UINT16 | |
| 4 | GENERIC | 5 | DT_INT32 | |
| 6 | DT_UINT32 | |||
| 7 | DT_INT64 | |||
| 8 | DT_UINT64 | |||
| 9 | DT_FLOAT32 | |||
| 10 | DT_FLOAT64 | |||
| 11 | DT_BOOL |
These two lists come from the Draco library’s source, since the specification names
the fields without listing their values. Data type 0 (DT_INVALID) is not a
legal value. Builds of the library with transcoder support add tangent, material,
joints and weights attribute types after GENERIC, which the source notes
would be a change to the bitstream.
Sequential decoder types
| Value | Name | Values stored as | Extra data at the end |
|---|---|---|---|
| 0 | SEQUENTIAL_ATTRIBUTE_ENCODER_GENERIC | The attribute’s own data type, unpredicted | None |
| 1 | SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER | Predicted integers | None |
| 2 | SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION | Floats quantised to integers, then predicted | Quantisation data |
| 3 | SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS | Unit normals as two octahedral coordinates, then predicted | Quantisation bits |
Attribute values
After the decoder headers, and after the decoder has worked out the order in which to visit the values from the connectivity, each decoder’s attributes follow in turn:
| Field | Type | Meaning |
|---|---|---|
seq_att_dec_prediction_scheme | I8 | The prediction scheme; see below |
| Unless the scheme is −2 (none): | ||
seq_att_dec_prediction_transform_type | I8 | How a prediction and a correction combine; see below |
seq_int_att_dec_compressed | UI8 | 1 when the corrections are entropy-coded |
| Corrections | Symbols | values × components symbols |
| Prediction data | See below | Data the scheme needs, if any |
| Transform data | See below | Data the transform needs |
Each symbol becomes a signed correction: an even symbol s is s ÷ 2, and an odd one is −(s − 1) ÷ 2 − 1. So 0, 1, 2, 3, 4 stand for 0, −1, 1, −2, 2. After all attributes come the quantisation data, attribute by attribute. The specification covers only predicted, entropy-coded values; attributes with no prediction or with uncompressed corrections are defined by the library’s source alone.
Prediction schemes
| Value | Name | Predicts each value from | Prediction data in the file |
|---|---|---|---|
| −2 | PREDICTION_NONE | Nothing | None |
| −1 | PREDICTION_UNDEFINED | Not a stored value | None |
| 0 | PREDICTION_DIFFERENCE | The previous value in decoding order (the first from 0) | None |
| 1 | MESH_PREDICTION_PARALLELOGRAM | A parallelogram completed from the opposite triangle: next + previous − opposite | None |
| 2 | MESH_PREDICTION_MULTI_PARALLELOGRAM | Several parallelograms averaged; in the library’s source, not in the specification | Not described |
| 3 | MESH_PREDICTION_TEX_COORDS_DEPRECATED | An older texture coordinate scheme; in the library’s source, not in the specification | Not described |
| 4 | MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM | Up to four parallelograms (kMaxNumParallelograms), leaving out those across crease edges | Crease flags |
| 5 | MESH_PREDICTION_TEX_COORDS_PORTABLE | The triangle’s positions and the texture coordinates already decoded, projecting the new point into texture space | Orientations |
| 6 | MESH_PREDICTION_GEOMETRIC_NORMAL | The normal computed from the surrounding triangles’ positions | Flip bits |
The mesh schemes need positions already decoded, so positions are in the first attribute decoder and the other attributes come after.
| Scheme | Prediction data |
|---|---|
| 4 | For each of the 4 parallelogram counts: constrained_multi_num_flags (varUI32); when above 0, a probability (UI8), a size (varUI32) and that many bytes of rABS data giving one crease bit per flag |
| 5 | tex_coords_num_orientations (UI32), then a probability (UI8), a size (varUI32) and rABS data: one bit per orientation, where 0 flips the previous orientation and 1 keeps it, starting from “true” |
| 6 | The transform data first, then a probability (UI8), a size (varUI32) and rABS data: one bit per value saying whether to flip the predicted normal |
Prediction transforms
| Value | Name | Data | Meaning |
|---|---|---|---|
| −1 | PREDICTION_TRANSFORM_NONE | None | Not a stored value |
| 0 | PREDICTION_TRANSFORM_DELTA | None | Value = prediction + correction; in the library’s source |
| 1 | PREDICTION_TRANSFORM_WRAP | min I32, max I32 | The prediction is clamped to min…max; value = clamped prediction + correction, wrapped back into min…max by adding or subtracting (max − min + 1) |
| 2 | PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON | Not described | Octahedral normal transform; in the library’s source |
| 3 | PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED | max_q_val I32, then an unused I32 | Corrections to octahedral normal coordinates, worked in a canonical quarter of the octahedron so that they stay small |
With transform 3, the symbols are taken as they are, without the signed conversion above.
Quantisation
For decoder type 2, after the values:
| Field | Type | Meaning |
|---|---|---|
quantized_data_min_values | Float × components | The smallest value of each component |
quantized_data_max_value_df | Float | The range: the largest difference from the minimum over all components |
quantized_data_quantization_bits | UI8 | Bits per quantised value |
A quantised integer q becomes
min[c] + q × range ÷ (2bits − 1), with the sign of
q kept. For decoder type 3 only the quantisation bits (UI8) are stored:
the two integer octahedral coordinates, each up to 2bits − 1, are turned
back into a unit vector.