To track primitives (such as triangles) through various operations, a tracking ID can be provided. Internally, each primitive has a 64 bit ID (with some upper bits reserved for flags). When enabled on a surface, all operations try to keep track of these IDs (even across variadic and iterated Booleans and multiple Operations). Resulting IDs can be obtained by using Operation::ExportToTrianglesF32WithID and Operation::ExportToIndexedTrianglesF32WithID instead of the versions without 'WithID'. When this contains primitives from untracked surfaces, then their IDs are binary all-one, i.e. uint64_t(-1).
The ID is structured as follows: [2bit flags][30bit surface ID][32bit primitive ID] represented as an uint64_t.
The flags are [1bit is-inverted][1bit is-subset]:
- if is-inverted is true, the winding order of the primitive changed. For triangles, this means (v0,v1,v2) is emitted as (v0,v2,v1), i.e. last two vertices are swapped.
- if is-subset is false, then the emitted primitive is input primitive either unchanged or order-swapped (if is-inverted is true).
- if is-subset is true, then the emitted primitive is a proper subset of the input, e.g. due to cutting up faces during Booleans.
The primitives of a surface are contiguously numbered by default with a customizable start index.
For example, given two surfaces A and B with 1000 and 2000 faces each, you could track them as: A->TrackID(0) B->TrackID(1) which would result in A's faces being (0,0..999) and B's faces being (1,0..1999).
But you could also track them as: A->TrackID(0, 0) B->TrackID(0, 1000) which would result in A's faces being (0,0..999) and B's faces being (0,1000..2999).
This gives plenty of flexibility on how to track input primitives. Should these options not suffice, SurfaceBuilder::TrackIDRaw and SurfaceBuilder::TrackPrimitiveIDs allow additional flexibility.
Signature
class SurfaceBuilder:
// Enables primitive tracking using a structured surface and primitive ID scheme
fun trackID(
surfaceID: uint32_t,
primitiveStartID: uint32_t = 0,
)