diff --git a/models/skelanim-empty.usda b/models/skelanim-empty.usda new file mode 100644 index 00000000..eba41c38 --- /dev/null +++ b/models/skelanim-empty.usda @@ -0,0 +1,25 @@ +#usda 1.0 +( + defaultPrim = "Root" + upAxis = "Z" +) + +def Xform "Root" +{ + def Skeleton "Skel" + { + uniform token[] joints = ["joint0"] + uniform matrix4d[] bindTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + ] + uniform matrix4d[] restTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + ] + + def SkelAnimation "EmptyAnim" + { + uniform token[] joints = ["joint0"] + # No animation data - edge case test + } + } +} diff --git a/models/skelanim-mixed.usda b/models/skelanim-mixed.usda new file mode 100644 index 00000000..5749f930 --- /dev/null +++ b/models/skelanim-mixed.usda @@ -0,0 +1,45 @@ +#usda 1.0 +( + defaultPrim = "Root" + upAxis = "Z" +) + +def Xform "Root" +{ + def Skeleton "Skel" + { + uniform token[] joints = ["root", "root/spine", "root/leftArm", "root/rightArm"] + uniform matrix4d[] bindTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-0.5, 1.5, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0.5, 1.5, 0, 1) ) + ] + uniform matrix4d[] restTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-0.5, 1.5, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0.5, 1.5, 0, 1) ) + ] + + def SkelAnimation "MixedAnim" + { + uniform token[] joints = ["root", "root/spine", "root/leftArm", "root/rightArm"] + + # Static translations (bind pose) + float3[] translations = [(0, 0, 0), (0, 1, 0), (-0.5, 1.5, 0), (0.5, 1.5, 0)] + + # Time-sampled rotations (animated) + quatf[] rotations.timeSamples = { + 0: [(1, 0, 0, 0), (1, 0, 0, 0), (1, 0, 0, 0), (1, 0, 0, 0)], + 0.5: [(0.9962, 0, 0.0872, 0), (1, 0, 0, 0), (0.9659, 0, 0, 0.2588), (0.9659, 0, 0, -0.2588)], + 1: [(0.9848, 0, 0.1736, 0), (1, 0, 0, 0), (0.8660, 0, 0, 0.5), (0.8660, 0, 0, -0.5)], + 1.5: [(0.9962, 0, 0.0872, 0), (1, 0, 0, 0), (0.9659, 0, 0, 0.2588), (0.9659, 0, 0, -0.2588)], + 2: [(1, 0, 0, 0), (1, 0, 0, 0), (1, 0, 0, 0), (1, 0, 0, 0)] + } + + # Static scales (uniform) + half3[] scales = [(1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1)] + } + } +} diff --git a/models/skelanim-rotation-only.usda b/models/skelanim-rotation-only.usda new file mode 100644 index 00000000..7fd42dd9 --- /dev/null +++ b/models/skelanim-rotation-only.usda @@ -0,0 +1,35 @@ +#usda 1.0 +( + defaultPrim = "Root" + upAxis = "Z" +) + +def Xform "Root" +{ + def Skeleton "Skel" + { + uniform token[] joints = ["joint0", "joint0/joint1"] + uniform matrix4d[] bindTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ) + ] + uniform matrix4d[] restTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ) + ] + + def SkelAnimation "RotationOnlyAnim" + { + uniform token[] joints = ["joint0", "joint0/joint1"] + + # Only rotations are animated, no translations or scales + quatf[] rotations.timeSamples = { + 0: [(1, 0, 0, 0), (1, 0, 0, 0)], + 0.5: [(0.9239, 0, 0.3827, 0), (0.9659, 0.2588, 0, 0)], + 1: [(0.7071, 0, 0.7071, 0), (0.8660, 0.5, 0, 0)], + 1.5: [(0.9239, 0, 0.3827, 0), (0.9659, 0.2588, 0, 0)], + 2: [(1, 0, 0, 0), (1, 0, 0, 0)] + } + } + } +} diff --git a/models/skelanim-single-joint.usda b/models/skelanim-single-joint.usda new file mode 100644 index 00000000..f1c3a509 --- /dev/null +++ b/models/skelanim-single-joint.usda @@ -0,0 +1,37 @@ +#usda 1.0 +( + defaultPrim = "Root" + upAxis = "Y" +) + +def Xform "Root" +{ + def Skeleton "Skel" + { + uniform token[] joints = ["bone"] + uniform matrix4d[] bindTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + ] + uniform matrix4d[] restTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + ] + + def SkelAnimation "SingleJointAnim" + { + uniform token[] joints = ["bone"] + + # Single joint with time-sampled rotation + float3[] translations = [(0, 0, 0)] + + quatf[] rotations.timeSamples = { + 0: [(1, 0, 0, 0)], + 0.25: [(0.9239, 0, 0.3827, 0)], + 0.5: [(0.7071, 0, 0.7071, 0)], + 0.75: [(0.9239, 0, 0.3827, 0)], + 1: [(1, 0, 0, 0)] + } + + half3[] scales = [(1, 1, 1)] + } + } +} diff --git a/models/skelanim-static.usda b/models/skelanim-static.usda new file mode 100644 index 00000000..809113c3 --- /dev/null +++ b/models/skelanim-static.usda @@ -0,0 +1,33 @@ +#usda 1.0 +( + defaultPrim = "Root" + upAxis = "Z" +) + +def Xform "Root" +{ + def Skeleton "Skel" + { + uniform token[] joints = ["joint0", "joint0/joint1", "joint0/joint1/joint2"] + uniform matrix4d[] bindTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ) + ] + uniform matrix4d[] restTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) ) + ] + + def SkelAnimation "StaticAnim" + { + uniform token[] joints = ["joint0", "joint0/joint1", "joint0/joint1/joint2"] + + # All static (non-time-sampled) values + float3[] translations = [(0.5, 0, 0), (0, 1.5, 0), (0, 0.75, 0)] + quatf[] rotations = [(1, 0, 0, 0), (0.7071, 0, 0.7071, 0), (0.9239, 0.3827, 0, 0)] + half3[] scales = [(1, 1, 1), (1.2, 1.2, 1.2), (0.8, 0.8, 0.8)] + } + } +} diff --git a/models/skelanim-timesampled.usda b/models/skelanim-timesampled.usda new file mode 100644 index 00000000..0a1afd0b --- /dev/null +++ b/models/skelanim-timesampled.usda @@ -0,0 +1,53 @@ +#usda 1.0 +( + defaultPrim = "Root" + upAxis = "Z" +) + +def Xform "Root" +{ + def Skeleton "Skel" + { + uniform token[] joints = ["joint0", "joint0/joint1"] + uniform matrix4d[] bindTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2, 0, 1) ) + ] + uniform matrix4d[] restTransforms = [ + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ), + ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2, 0, 1) ) + ] + + def SkelAnimation "Anim" + { + uniform token[] joints = ["joint0", "joint0/joint1"] + + # Time-sampled translations + float3[] translations.timeSamples = { + 0: [(0, 0, 0), (0, 2, 0)], + 1: [(1, 0, 0), (0, 2.5, 0)], + 2: [(2, 0, 0), (0, 3, 0)], + 3: [(1, 0, 0), (0, 2.5, 0)], + 4: [(0, 0, 0), (0, 2, 0)] + } + + # Time-sampled rotations + quatf[] rotations.timeSamples = { + 0: [(1, 0, 0, 0), (1, 0, 0, 0)], + 1: [(0.9239, 0, 0.3827, 0), (0.9659, 0.2588, 0, 0)], + 2: [(0.7071, 0, 0.7071, 0), (0.8660, 0.5, 0, 0)], + 3: [(0.9239, 0, 0.3827, 0), (0.9659, 0.2588, 0, 0)], + 4: [(1, 0, 0, 0), (1, 0, 0, 0)] + } + + # Time-sampled scales + half3[] scales.timeSamples = { + 0: [(1, 1, 1), (1, 1, 1)], + 1: [(1.2, 1, 1), (1, 1.1, 1)], + 2: [(1.5, 1, 1), (1, 1.2, 1)], + 3: [(1.2, 1, 1), (1, 1.1, 1)], + 4: [(1, 1, 1), (1, 1, 1)] + } + } + } +} diff --git a/models/synthetic-skin-16influences.usda b/models/synthetic-skin-16influences.usda new file mode 100644 index 00000000..e681e1c8 --- /dev/null +++ b/models/synthetic-skin-16influences.usda @@ -0,0 +1,114 @@ +#usda 1.0 +( + defaultPrim = "root" + upAxis = "Z" + metersPerUnit = 1 +) + +def SkelRoot "root" +{ + def Skeleton "Skeleton" + { + uniform token[] joints = [ + "Root", "Root/joint1", "Root/joint2", "Root/joint3", "Root/joint4", "Root/joint5", "Root/joint6", "Root/joint7", + "Root/joint8", "Root/joint9", "Root/joint10", "Root/joint11", "Root/joint12", "Root/joint13", "Root/joint14", "Root/joint15" + ] + uniform matrix4d[] bindTransforms = [ + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.5, 0, 1)) + ] + uniform matrix4d[] restTransforms = [ + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.5, 0, 1)) + ] + } + + def Mesh "Mesh" ( + prepend apiSchemas = ["SkelBindingAPI"] + ) + { + uniform bool doubleSided = 0 + int[] faceVertexCounts = [3, 3, 3, 3, 3, 3] + int[] faceVertexIndices = [0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 1] + rel skel:skeleton = + + point3f[] points = [ + (0, 0, 0), + (1, 0, 0), + (1, 1, 0), + (0, 1, 0), + (-1, 1, 0), + (-1, 0, 0), + (-1, -1, 0) + ] + + int[] primvars:skel:jointIndices = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ] ( + elementSize = 16 + interpolation = "vertex" + ) + + float[] primvars:skel:jointWeights = [ + 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, + 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, + 0.25, 0.20, 0.15, 0.10, 0.08, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01, 0.005, 0.003, 0.002, 0.001, 0.001, + 0.20, 0.18, 0.16, 0.14, 0.10, 0.08, 0.06, 0.04, 0.02, 0.01, 0.005, 0.003, 0.002, 0.001, 0.001, 0.001, + 0.01, 0.02, 0.04, 0.06, 0.08, 0.12, 0.16, 0.20, 0.16, 0.08, 0.04, 0.02, 0.005, 0.003, 0.001, 0.001, + 0.001, 0.002, 0.003, 0.005, 0.01, 0.02, 0.04, 0.06, 0.08, 0.12, 0.16, 0.20, 0.14, 0.10, 0.05, 0.02, + 0.001, 0.001, 0.002, 0.003, 0.005, 0.01, 0.02, 0.03, 0.04, 0.05, 0.08, 0.10, 0.15, 0.20, 0.18, 0.15, + 0.40, 0.25, 0.15, 0.10, 0.05, 0.03, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + ] ( + elementSize = 16 + interpolation = "vertex" + ) + + matrix4d primvars:skel:geomBindTransform = ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) + + normal3f[] normals = [ + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1) + ] ( + interpolation = "vertex" + ) + } +} diff --git a/models/synthetic-skin-32influences.usda b/models/synthetic-skin-32influences.usda new file mode 100644 index 00000000..3a3e48d9 --- /dev/null +++ b/models/synthetic-skin-32influences.usda @@ -0,0 +1,151 @@ +#usda 1.0 +( + defaultPrim = "root" + upAxis = "Z" + metersPerUnit = 1 +) + +def SkelRoot "root" +{ + def Skeleton "Skeleton" + { + uniform token[] joints = [ + "Root", "Root/joint1", "Root/joint2", "Root/joint3", "Root/joint4", "Root/joint5", "Root/joint6", "Root/joint7", + "Root/joint8", "Root/joint9", "Root/joint10", "Root/joint11", "Root/joint12", "Root/joint13", "Root/joint14", "Root/joint15", + "Root/joint16", "Root/joint17", "Root/joint18", "Root/joint19", "Root/joint20", "Root/joint21", "Root/joint22", "Root/joint23", + "Root/joint24", "Root/joint25", "Root/joint26", "Root/joint27", "Root/joint28", "Root/joint29", "Root/joint30", "Root/joint31" + ] + uniform matrix4d[] bindTransforms = [ + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.75, 0, 1)) + ] + uniform matrix4d[] restTransforms = [ + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 4.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 5.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 6.75, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.00, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.25, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.50, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 7.75, 0, 1)) + ] + } + + def Mesh "Mesh" ( + prepend apiSchemas = ["SkelBindingAPI"] + ) + { + uniform bool doubleSided = 0 + int[] faceVertexCounts = [4, 4] + int[] faceVertexIndices = [0, 1, 2, 3, 0, 3, 4, 5] + rel skel:skeleton = + + point3f[] points = [ + (0, 0, 0), + (2, 0, 0), + (2, 2, 0), + (0, 2, 0), + (-2, 2, 0), + (-2, 0, 0) + ] + + int[] primvars:skel:jointIndices = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + ] ( + elementSize = 32 + interpolation = "vertex" + ) + + float[] primvars:skel:jointWeights = [ + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, + 0.15, 0.12, 0.10, 0.08, 0.07, 0.06, 0.05, 0.045, 0.04, 0.035, 0.03, 0.025, 0.02, 0.018, 0.016, 0.014, + 0.012, 0.010, 0.009, 0.008, 0.007, 0.006, 0.005, 0.004, 0.003, 0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.002, 0.003, 0.005, 0.008, 0.012, 0.018, 0.025, 0.035, 0.045, 0.055, 0.065, 0.075, 0.080, 0.085, 0.088, + 0.085, 0.080, 0.070, 0.055, 0.040, 0.028, 0.018, 0.012, 0.008, 0.005, 0.003, 0.002, 0.001, 0.001, 0.001, 0.001, + 0.10, 0.08, 0.06, 0.04, 0.02, 0.01, 0.005, 0.003, 0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.002, 0.003, + 0.005, 0.01, 0.02, 0.04, 0.06, 0.08, 0.10, 0.08, 0.06, 0.04, 0.02, 0.01, 0.005, 0.003, 0.002, 0.001, + 0.001, 0.001, 0.001, 0.002, 0.002, 0.003, 0.004, 0.005, 0.006, 0.008, 0.010, 0.012, 0.015, 0.018, 0.022, 0.026, + 0.030, 0.035, 0.040, 0.045, 0.050, 0.055, 0.060, 0.070, 0.080, 0.090, 0.095, 0.090, 0.070, 0.050, 0.030, 0.020, + 0.30, 0.25, 0.20, 0.12, 0.08, 0.03, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + ] ( + elementSize = 32 + interpolation = "vertex" + ) + + matrix4d primvars:skel:geomBindTransform = ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) + + normal3f[] normals = [ + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1) + ] ( + interpolation = "vertex" + ) + } +} diff --git a/models/synthetic-skin-8influences.usda b/models/synthetic-skin-8influences.usda new file mode 100644 index 00000000..8c99b70b --- /dev/null +++ b/models/synthetic-skin-8influences.usda @@ -0,0 +1,86 @@ +#usda 1.0 +( + defaultPrim = "root" + upAxis = "Z" + metersPerUnit = 1 +) + +def SkelRoot "root" +{ + def Skeleton "Skeleton" + { + uniform token[] joints = ["Root", "Root/joint1", "Root/joint2", "Root/joint3", "Root/joint4", "Root/joint5", "Root/joint6", "Root/joint7"] + uniform matrix4d[] bindTransforms = [ + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.5, 0, 1)) + ] + uniform matrix4d[] restTransforms = [ + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2.5, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.0, 0, 1)), + ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3.5, 0, 1)) + ] + } + + def Mesh "Mesh" ( + prepend apiSchemas = ["SkelBindingAPI"] + ) + { + uniform bool doubleSided = 0 + int[] faceVertexCounts = [3, 3, 3, 3] + int[] faceVertexIndices = [0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1] + rel skel:skeleton = + + point3f[] points = [ + (0, 0, 0), + (1, 0, 0), + (1, 1, 0), + (0, 1, 0), + (-1, 0, 0) + ] + + int[] primvars:skel:jointIndices = [ + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7 + ] ( + elementSize = 8 + interpolation = "vertex" + ) + + float[] primvars:skel:jointWeights = [ + 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, + 0.30, 0.25, 0.20, 0.15, 0.05, 0.03, 0.01, 0.01, + 0.05, 0.10, 0.20, 0.30, 0.20, 0.10, 0.04, 0.01, + 0.01, 0.01, 0.03, 0.05, 0.15, 0.20, 0.25, 0.30, + 0.40, 0.30, 0.15, 0.10, 0.05, 0.0, 0.0, 0.0 + ] ( + elementSize = 8 + interpolation = "vertex" + ) + + matrix4d primvars:skel:geomBindTransform = ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) + + normal3f[] normals = [ + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1), + (0, 0, 1) + ] ( + interpolation = "vertex" + ) + } +} diff --git a/web/js/test-16influences.js b/web/js/test-16influences.js new file mode 100644 index 00000000..0161d048 --- /dev/null +++ b/web/js/test-16influences.js @@ -0,0 +1,64 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; +import fs from 'node:fs'; + +async function main() { + const loader = new TinyUSDZLoader(); + await loader.init(); + + const filePath = '../../models/synthetic-skin-16influences.usda'; + + try { + const data = fs.readFileSync(filePath); + + console.log(`Loading ${filePath} (${data.length} bytes)`); + + // Enable bone reduction in loader + loader.setEnableBoneReduction(true); + loader.setTargetBoneCount(4); + + // Load USD with bone reduction config + await new Promise((resolve, reject) => { + loader.parse( + data, + 'synthetic-skin-16influences.usda', + (usd) => { + console.log('\n=== USD loaded successfully ==='); + + // Get mesh info + const renderScene = usd.getRenderScene(); + console.log('\nScene has', renderScene.meshes.length, 'meshes'); + resolve(usd); + }, + (error) => { + console.error('Failed to load USD:', error); + reject(error); + }, + { + maxMemoryLimitMB: 2048 + } + ); + }).then((usd) => { + const renderScene = usd.getRenderScene(); + const meshes = renderScene.meshes; + console.log('\nMeshes found:', meshes.length); + + for (const mesh of meshes) { + console.log('\nMesh path:', mesh.abs_path); + if (mesh.joint_and_weights) { + console.log(' Joint and weights elementSize:', mesh.joint_and_weights.elementSize); + console.log(' Weights per vertex:', mesh.joint_and_weights.elementSize); + console.log(' Total joint indices:', mesh.joint_and_weights.jointIndices?.length); + console.log(' Total joint weights:', mesh.joint_and_weights.jointWeights?.length); + + const numVertices = mesh.joint_and_weights.jointIndices.length / mesh.joint_and_weights.elementSize; + console.log(' Number of vertices:', numVertices); + } + } + }); + + } catch (error) { + console.error('Error:', error); + } +} + +main(); \ No newline at end of file diff --git a/web/js/test-all-bone-reduction.js b/web/js/test-all-bone-reduction.js new file mode 100644 index 00000000..3db373b8 --- /dev/null +++ b/web/js/test-all-bone-reduction.js @@ -0,0 +1,96 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; +import fs from 'node:fs'; + +async function testFile(filePath, expectedElementSize) { + const loader = new TinyUSDZLoader(); + await loader.init(); + + try { + const data = fs.readFileSync(filePath); + + console.log(`\n=== Testing ${filePath} ===`); + console.log(`File size: ${data.length} bytes`); + console.log(`Expected elementSize: ${expectedElementSize}`); + + // Enable bone reduction in loader + loader.setEnableBoneReduction(true); + loader.setTargetBoneCount(4); + + // Load USD with bone reduction config + await new Promise((resolve, reject) => { + loader.parse( + data, + filePath.split('/').pop(), + (usd) => { + console.log('✓ USD loaded successfully'); + + // Get render scene + const ok = usd.toRenderScene(); + if (!ok) { + console.error('✗ Failed to convert to render scene'); + reject(new Error('Failed to convert to render scene')); + return; + } + + // Get the render scene data + const renderSceneJSON = usd.getRenderSceneAsJSON(); + const renderScene = JSON.parse(renderSceneJSON); + + console.log(`✓ Converted to render scene with ${renderScene.meshes.length} meshes`); + + for (const mesh of renderScene.meshes) { + if (mesh.joint_and_weights) { + const elementSize = mesh.joint_and_weights.elementSize; + console.log(` Mesh: ${mesh.abs_path}`); + console.log(` Original elementSize: ${expectedElementSize}`); + console.log(` After reduction: ${elementSize}`); + + if (elementSize === 4) { + console.log(` ✓ Bone reduction successful: ${expectedElementSize} → ${elementSize}`); + } else if (elementSize === expectedElementSize && expectedElementSize <= 4) { + console.log(` ✓ No reduction needed (already ≤ 4)`); + } else { + console.log(` ✗ Bone reduction failed: expected 4, got ${elementSize}`); + } + + const numIndices = mesh.joint_and_weights.jointIndices?.length || 0; + const numWeights = mesh.joint_and_weights.jointWeights?.length || 0; + const numVertices = numIndices / elementSize; + console.log(` Vertices: ${numVertices}`); + console.log(` Total indices: ${numIndices}`); + console.log(` Total weights: ${numWeights}`); + } + } + + resolve(); + }, + (error) => { + console.error('✗ Failed to load USD:', error); + reject(error); + }, + { + maxMemoryLimitMB: 2048 + } + ); + }); + + } catch (error) { + console.error('✗ Error:', error); + } +} + +async function main() { + const testFiles = [ + { path: '../../models/synthetic-skin-8influences.usda', elementSize: 8 }, + { path: '../../models/synthetic-skin-16influences.usda', elementSize: 16 }, + { path: '../../models/synthetic-skin-32influences.usda', elementSize: 32 } + ]; + + for (const test of testFiles) { + await testFile(test.path, test.elementSize); + } + + console.log('\n=== All tests completed ==='); +} + +main(); \ No newline at end of file diff --git a/web/js/test-anim-debug.js b/web/js/test-anim-debug.js new file mode 100644 index 00000000..94c911da --- /dev/null +++ b/web/js/test-anim-debug.js @@ -0,0 +1,44 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; + +async function main() { + const loader = new TinyUSDZLoader(); + await loader.init({ useMemory64: false }); + + const usd = await new Promise((resolve, reject) => { + loader.load('../../models/skintest-blender.usda', resolve, null, reject); + }); + + console.log('\n=== Animation Debug Info ==='); + const numAnims = usd.numAnimations(); + console.log(`Total animations: ${numAnims}`); + + for (let i = 0; i < numAnims; i++) { + const animInfo = usd.getAnimationInfo(i); + console.log(`\nAnimation ${i}:`); + console.log(' animInfo:', JSON.stringify(animInfo, null, 2)); + + const anim = usd.getAnimation(i); + console.log(' anim.channels:', anim.channels ? anim.channels.length : 0); + console.log(' anim.samplers:', anim.samplers ? anim.samplers.length : 0); + + if (anim.channels && anim.channels.length > 0) { + console.log('\n First few channels:'); + for (let j = 0; j < Math.min(3, anim.channels.length); j++) { + console.log(` Channel ${j}:`, JSON.stringify(anim.channels[j], null, 2)); + } + } + + if (anim.samplers && anim.samplers.length > 0) { + console.log('\n First sampler:'); + const sampler = anim.samplers[0]; + console.log(` times.length: ${sampler.times ? sampler.times.length : 0}`); + console.log(` values.length: ${sampler.values ? sampler.values.length : 0}`); + if (sampler.times && sampler.times.length > 0) { + console.log(` First time: ${sampler.times[0]}`); + console.log(` First values: [${sampler.values.slice(0, 3).join(', ')}]`); + } + } + } +} + +main().catch(console.error); diff --git a/web/js/test-boundaries.js b/web/js/test-boundaries.js new file mode 100644 index 00000000..c304de3e --- /dev/null +++ b/web/js/test-boundaries.js @@ -0,0 +1,21 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; +import fs from 'node:fs'; + +async function test(file, expected) { + const loader = new TinyUSDZLoader(); + await loader.init(); + const data = fs.readFileSync(file); + return new Promise((resolve) => { + loader.parse(data, file, + () => resolve('SUCCESS'), + () => resolve('FAIL') + ); + }); +} + +(async () => { + console.log('Testing boundary values (should succeed):', + await test('../../models/test-digit-boundaries.usda')); + console.log('Testing over-boundary values (should fail):', + await test('../../models/test-digit-over-boundaries.usda')); +})(); \ No newline at end of file diff --git a/web/js/test-digit-limits.js b/web/js/test-digit-limits.js new file mode 100644 index 00000000..bfc28eac --- /dev/null +++ b/web/js/test-digit-limits.js @@ -0,0 +1,58 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; +import fs from 'node:fs'; + +async function testFile(filePath, shouldFail = false) { + const loader = new TinyUSDZLoader(); + await loader.init(); + + try { + const data = fs.readFileSync(filePath); + + console.log(`\nTesting ${filePath} (${data.length} bytes)`); + console.log(`Expected to ${shouldFail ? 'FAIL' : 'SUCCEED'}`); + + // Load USD + await new Promise((resolve, reject) => { + loader.parse( + data, + filePath.split('/').pop(), + (usd) => { + if (shouldFail) { + console.log('✗ Unexpected: File loaded successfully (should have failed)'); + } else { + console.log('✓ File loaded successfully'); + } + resolve(); + }, + (error) => { + if (shouldFail) { + console.log('✓ Expected failure:', error.message || error); + } else { + console.error('✗ Unexpected failure:', error); + } + resolve(); // Don't reject so we can continue testing + } + ); + }); + + } catch (error) { + console.error('✗ Test error:', error); + } +} + +async function main() { + console.log('=== Testing Digit Length Guards ==='); + + // Test normal file with valid numbers + await testFile('../../models/test-large-numbers.usda', false); + + // Test file with excessive digits (should fail) + await testFile('../../models/test-excessive-digits.usda', true); + + // Test files with bone reduction (should still work) + await testFile('../../models/synthetic-skin-16influences.usda', false); + + console.log('\n=== All tests completed ==='); +} + +main(); \ No newline at end of file diff --git a/web/js/test-malicious.js b/web/js/test-malicious.js new file mode 100644 index 00000000..53362f09 --- /dev/null +++ b/web/js/test-malicious.js @@ -0,0 +1,10 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; +import fs from 'node:fs'; + +const loader = new TinyUSDZLoader(); +await loader.init(); +const data = fs.readFileSync('../../models/test-malicious-digits.usda'); +loader.parse(data, 'test', + () => console.log('UNEXPECTED: Malicious file loaded'), + (e) => console.log('GOOD: Malicious file rejected') +); \ No newline at end of file diff --git a/web/js/test-number-parsing.js b/web/js/test-number-parsing.js new file mode 100644 index 00000000..c0aa1ac2 --- /dev/null +++ b/web/js/test-number-parsing.js @@ -0,0 +1,37 @@ +import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js'; +import fs from 'node:fs'; + +async function main() { + const loader = new TinyUSDZLoader(); + await loader.init(); + + const filePath = '../../models/test-large-numbers.usda'; + + try { + const data = fs.readFileSync(filePath); + + console.log(`Loading ${filePath} (${data.length} bytes)`); + + // Load USD + await new Promise((resolve, reject) => { + loader.parse( + data, + 'test-large-numbers.usda', + (usd) => { + console.log('✓ USD loaded successfully'); + console.log('✓ Large number parsing test passed'); + resolve(); + }, + (error) => { + console.error('✗ Failed to load USD:', error); + reject(error); + } + ); + }); + + } catch (error) { + console.error('✗ Error:', error); + } +} + +main(); \ No newline at end of file