Skip to content

Commit

Permalink
Merge pull request #92 from qmuntal/invmatrix
Browse files Browse the repository at this point in the history
Implement inverse bind matrices reader and writer
  • Loading branch information
qmuntal authored Oct 17, 2024
2 parents 19bcd97 + 6347d9a commit aed1fc5
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
21 changes: 21 additions & 0 deletions modeler/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,27 @@ func ReadColor64(doc *gltf.Document, acr *gltf.Accessor, buffer [][4]uint16) ([]
return buffer, nil
}

// ReadInverseBindMatrices returns the data referenced by acr.
//
// See ReadAccessor for more info.
func ReadInverseBindMatrices(doc *gltf.Document, acr *gltf.Accessor, buffer [][4][4]float32) ([][4][4]float32, error) {
if acr.ComponentType != gltf.ComponentFloat {
return nil, errComponentType(acr.ComponentType)
}
if acr.Type != gltf.AccessorMat4 {
return nil, errAccessorType(acr.Type)
}
bufPtr := bufPool.Get().(*[]byte)
defer bufPool.Put(bufPtr)
data, err := ReadAccessor(doc, acr, *bufPtr)
if err != nil {
return nil, err
}
buffer = makeBufferOf(acr.Count, buffer)
copy(buffer, data.([][4][4]float32))
return buffer, nil
}

func errAccessorType(tp gltf.AccessorType) error {
return fmt.Errorf("gltf: accessor type %v not allowed", tp)
}
Expand Down
50 changes: 50 additions & 0 deletions modeler/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -694,3 +694,53 @@ func TestReadColor64(t *testing.T) {
})
}
}

func TestReadInverseBindMatrices(t *testing.T) {
type args struct {
data []byte
acr *gltf.Accessor
buffer [][4][4]float32
}
tests := []struct {
name string
args args
want [][4][4]float32
wantErr bool
}{
{"base", args{[]byte{
0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, &gltf.Accessor{BufferView: gltf.Index(0), Count: 1, Type: gltf.AccessorMat4, ComponentType: gltf.ComponentFloat}, nil},
[][4][4]float32{{{1, 2, 3, 4}}}, false,
},
{"incorrect-type", args{[]byte{}, &gltf.Accessor{
BufferView: gltf.Index(0), Type: gltf.AccessorMat2, ComponentType: gltf.ComponentFloat,
}, nil}, nil, true},
{"incorrect-componenttype", args{[]byte{}, &gltf.Accessor{
BufferView: gltf.Index(0), Type: gltf.AccessorMat4, ComponentType: gltf.ComponentByte,
}, nil}, nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
doc := &gltf.Document{
BufferViews: []*gltf.BufferView{
{Buffer: 0, ByteLength: len(tt.args.data)},
},
Buffers: []*gltf.Buffer{
{Data: tt.args.data, ByteLength: len(tt.args.data)},
},
}
got, err := modeler.ReadInverseBindMatrices(doc, tt.args.acr, tt.args.buffer)
if (err != nil) != tt.wantErr {
t.Errorf("ReadInverseBindMatrices() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ReadInverseBindMatrices() = %v, want %v", got, tt.want)
}
})
}

}
7 changes: 7 additions & 0 deletions modeler/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ func WriteJoints(doc *gltf.Document, data any) int {
return WriteAccessor(doc, gltf.TargetArrayBuffer, data)
}

// WriteInverseBindMatrices adds a new inverse bind matrices accessor to doc
// and fills the last buffer with data.
// If success it returns the index of the new accessor.
func WriteInverseBindMatrices(doc *gltf.Document, data [][4][4]float32) int {
return WriteAccessor(doc, gltf.TargetArrayBuffer, data)
}

func checkJoints(data any) error {
switch data.(type) {
case [][4]uint8, [][4]uint16:
Expand Down
43 changes: 43 additions & 0 deletions modeler/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,49 @@ func TestWriteImage(t *testing.T) {
}
}

func TestWriteInverseBindMatrices(t *testing.T) {
tests := []struct {
name string
m *gltf.Document
args [][4][4]float32
want int
wantDoc *gltf.Document
}{
{"base", &gltf.Document{
Accessors: []*gltf.Accessor{{}},
}, [][4][4]float32{{{1, 2, 3, 4}}}, 1, &gltf.Document{
Accessors: []*gltf.Accessor{
{},
{BufferView: gltf.Index(0), Count: 1, Type: gltf.AccessorMat4, ComponentType: gltf.ComponentFloat},
},
BufferViews: []*gltf.BufferView{
{ByteLength: 64, Target: gltf.TargetArrayBuffer},
},
Buffers: []*gltf.Buffer{
{ByteLength: 64, Data: []byte{
0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}},
},
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := modeler.WriteInverseBindMatrices(tt.m, tt.args)
if tt.want != got {
t.Errorf("WriteInverseBindMatrices() = %v, want %v", got, tt.want)
return
}
if diff := deep.Equal(tt.m, tt.wantDoc); diff != nil {
t.Errorf("WriteInverseBindMatrices() = %v", diff)
return
}
})
}
}

type errReader struct{}

func (r *errReader) Read(p []byte) (int, error) {
Expand Down

0 comments on commit aed1fc5

Please sign in to comment.