The XPD reader successfully handles two different spline data layouts based on primSize:
Files: box.xpd Use case: Complete grooming/hair data with detailed guide and styling information
Data Layout (51 floats):
- primitiveId (1)
- surfaceUV (2)
- CVs positions (15 = 5 CVs × 3)
- guideId (1)
- guideWeight (1)
- guideType (1)
- guideDirection (3)
- guidePrimRef (1)
- guideUV (2)
- surfaceNormal (3)
- cvParameters (15 = 5 CVs × 3)
- widthScale (4)
- additionalAttributes (2)
Total: 51 floats
Files: sample.xpd, spline_1_taper_1.xpd Use case: Simple spline data without detailed styling
Data Layout (25 floats):
- primitiveId (1)
- surfaceUV (2)
- CVs positions (15 = 5 CVs × 3)
- guideId (1)
- guideWeight (1)
- guideType (1)
- guideDirection (3)
- guidePrimRef (1)
Total: 25 floats
- primSize: 51
- numFaces: 6
- Total primitives: 144 (24+25+25+25+24+21)
- Parser status: ✅ All fields parsed correctly
- Output: box.json (351KB)
- primSize: 25
- numFaces: 444 (sparse, ~100 primitives total)
- Total primitives: ~100 (scattered across faces)
- Parser status: ✅ Correctly handles smaller format
- Output: samples/sample.json
- primSize: 25
- numFaces: 13
- Total primitives: 1 (on face 12)
- Parser status: ✅ Correctly handles smaller format
- Output: samples/spline_1_taper_1.json
The parser uses conditional logic to handle different data sizes:
// Parse guide data based on XGen spline format
if (remaining >= 7) {
// Parse guide id, weight, type, direction, primRef
...
}
// Only parse additional fields if they exist
if (remaining >= 9) {
// Parse guide UV
...
}
if (idx + 2 < offset + floats_per_prim) {
// Parse surface normal
...
}
// etc.This means the parser gracefully handles:
- Full format (51 floats): Parses all available fields
- Basic format (25 floats): Stops after guide data, doesn't try to read non-existent fields
- Future formats: Will work with any primSize as long as the basic fields are present
All formats share these core fields:
primitiveId: Unique spline IDsurfaceUV: [u, v] attachment point on surface
cvs: Array of 5 control vertices with positions [x, y, z]
guideId: Which guide curve this followsguideWeight: Influence (typically 0.1 = 10%)guideType: Type of guide (0 = standard)guideDirection: Tangent vector at attachmentguidePrimRef: Guide primitive reference index
guideUV: UV coordinates on guide surfacesurfaceNormal: Normal vector at attachment pointcvParameters: Per-CV parametric data (t-values 0.0-1.0)widthScale: Width/taper control (base, tip, params)additionalAttributes: Extra styling data
✅ Parser is robust and handles all tested formats correctly
The conditional parsing logic ensures compatibility with:
- Different primSize values (25, 51, potentially others)
- Different primVersion values (all tested files use version 3)
- Sparse data (many faces with 0 primitives)
- Various mesh topologies (6 faces to 444 faces)