56 lines
1.7 KiB
Go
56 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestWriteSkeletonGLB(t *testing.T) {
|
|
for _, skeletonKey := range []string{"smplx22", "soma30", "g1skel34"} {
|
|
t.Run(skeletonKey, func(t *testing.T) {
|
|
skeleton := skeletonDefinitions[skeletonKey]
|
|
path := filepath.Join(t.TempDir(), "animation.glb")
|
|
roots := []float32{0, 0, 0, 1, 0, 0}
|
|
rotations := make([]float32, 2*len(skeleton.parents)*4)
|
|
for frame := 0; frame < 2; frame++ {
|
|
for joint := range skeleton.parents {
|
|
rotations[(frame*len(skeleton.parents)+joint)*4+3] = 1
|
|
}
|
|
}
|
|
if err := writeSkeletonGLB(path, roots, rotations, skeleton); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertSkeletonGLB(t, path, len(skeleton.parents))
|
|
})
|
|
}
|
|
}
|
|
|
|
func assertSkeletonGLB(t *testing.T, path string, expectedJoints int) {
|
|
t.Helper()
|
|
b, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(b) < 20 || binary.LittleEndian.Uint32(b) != 0x46546c67 || binary.LittleEndian.Uint32(b[4:]) != 2 || int(binary.LittleEndian.Uint32(b[8:])) != len(b) {
|
|
t.Fatalf("invalid GLB header")
|
|
}
|
|
jsonLength := int(binary.LittleEndian.Uint32(b[12:]))
|
|
if binary.LittleEndian.Uint32(b[16:]) != 0x4e4f534a || 20+jsonLength > len(b) {
|
|
t.Fatalf("invalid GLB JSON chunk")
|
|
}
|
|
var document struct {
|
|
Asset map[string]string `json:"asset"`
|
|
Nodes []json.RawMessage `json:"nodes"`
|
|
Animations []json.RawMessage `json:"animations"`
|
|
}
|
|
if err := json.Unmarshal(b[20:20+jsonLength], &document); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if document.Asset["version"] != "2.0" || len(document.Nodes) != expectedJoints || len(document.Animations) != 1 {
|
|
t.Fatalf("unexpected GLB document: %s", b[20:20+jsonLength])
|
|
}
|
|
}
|