Skip to content

Commit

Permalink
refactor writter
Browse files Browse the repository at this point in the history
  • Loading branch information
qmuntal committed Oct 13, 2020
1 parent 3823b59 commit 6b9d993
Show file tree
Hide file tree
Showing 17 changed files with 378 additions and 550 deletions.
16 changes: 8 additions & 8 deletions README.md
Expand Up @@ -94,11 +94,11 @@ import (
)

func main() {
m := modeler.NewModeler()
positionAccessor := m.AddPosition(0, [][3]float32{{43, 43, 0}, {83, 43, 0}, {63, 63, 40}, {43, 83, 0}, {83, 83, 0}})
indicesAccessor := m.AddIndices(0, []uint8{0, 1, 2, 3, 1, 0, 0, 2, 3, 1, 4, 2, 4, 3, 2, 4, 1, 3})
colorIndices := m.AddColor(0, [][3]uint8{{50, 155, 255}, {0, 100, 200}, {255, 155, 50}, {155, 155, 155}, {25, 25, 25}})
m.Document.Meshes = []*gltf.Mesh{{
doc := gltf.NewDocument()
positionAccessor := modeler.WritePosition(doc, [][3]float32{{43, 43, 0}, {83, 43, 0}, {63, 63, 40}, {43, 83, 0}, {83, 83, 0}})
indicesAccessor := modeler.WriteIndices(doc, []uint8{0, 1, 2, 3, 1, 0, 0, 2, 3, 1, 4, 2, 4, 3, 2, 4, 1, 3})
colorIndices := modeler.WriteColor(doc, [][3]uint8{{50, 155, 255}, {0, 100, 200}, {255, 155, 50}, {155, 155, 155}, {25, 25, 25}})
doc.Meshes = []*gltf.Mesh{{
Name: "Pyramid",
Primitives: []*gltf.Primitive{{
Indices: gltf.Index(indicesAccessor),
Expand All @@ -108,9 +108,9 @@ func main() {
},
}},
}}
m.Nodes = []*gltf.Node{{Name: "Root", Mesh: gltf.Index(0)}}
m.Scenes[0].Nodes = append(m.Scenes[0].Nodes, 0)
if err := gltf.SaveBinary(m.Document, "./example.glb"); err != nil {
doc.Nodes = []*gltf.Node{{Name: "Root", Mesh: gltf.Index(0)}}
doc.Scenes[0].Nodes = append(doc.Scenes[0].Nodes, 0)
if err := gltf.SaveBinary(doc, "./example.glb"); err != nil {
panic(err)
}
}
Expand Down
8 changes: 4 additions & 4 deletions binary/bench_test.go
Expand Up @@ -9,7 +9,7 @@ import (
)

func BenchmarkNative(b *testing.B) {
s := 1000
var s uint32 = 1000
bs := make([]byte, s*SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3))
data := make([][3]float32, s)
b.ResetTimer()
Expand All @@ -21,17 +21,17 @@ func BenchmarkNative(b *testing.B) {
}

func BenchmarkWrite(b *testing.B) {
s := 1000
var s uint32 = 1000
bs := make([]byte, s*SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3))
data := make([][3]float32, s)
b.ResetTimer()
for n := 0; n < b.N; n++ {
Write(bs, data)
Write(bs, 0, data)
}
}

func BenchmarkWrite_builtint(b *testing.B) {
s := 1000
var s uint32 = 1000
bs := bytes.NewBuffer(make([]byte, s*SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3)))
data := make([][3]float32, s)
b.ResetTimer()
Expand Down
4 changes: 2 additions & 2 deletions binary/binary.go
Expand Up @@ -45,8 +45,8 @@ var Short shortComponent
// Ushort is the usnigned short implementation of Component.
var Ushort ushortComponent

// UInt is the unsigned int implementation of Component.
var UInt uintComponent
// Uint is the unsigned int implementation of Component.
var Uint uintComponent

// Float is the float implementation of Component.
var Float floatComponent
Expand Down
51 changes: 28 additions & 23 deletions binary/encode.go
Expand Up @@ -9,18 +9,18 @@ import (
"github.com/qmuntal/gltf"
)

// Read reads structured binary data from r into data.
// Read reads structured binary data from b into data.
// Data should be a slice of glTF predefined fixed-size types,
// else it fallbacks to `encoding/binary.Read`.
//
// If data length is greater than the length of b, Read returns io.ErrShortBuffer.
func Read(b []byte, data interface{}) error {
c, t, n := Type(data)
if n <= 0 {
if n == 0 {
return binary.Read(bytes.NewReader(b), binary.LittleEndian, data)
}
e := SizeOfElement(c, t)
if len(b) < n*e {
e := int(SizeOfElement(c, t))
if len(b) < int(n)*e {
return io.ErrShortBuffer
}
switch data := data.(type) {
Expand Down Expand Up @@ -184,46 +184,51 @@ func Read(b []byte, data interface{}) error {
}
case []uint32:
for i := range data {
data[i] = UInt.Scalar(b[e*i:])
data[i] = Uint.Scalar(b[e*i:])
}
case [][2]uint32:
for i := range data {
data[i] = UInt.Vec2(b[e*i:])
data[i] = Uint.Vec2(b[e*i:])
}
case [][3]uint32:
for i := range data {
data[i] = UInt.Vec3(b[e*i:])
data[i] = Uint.Vec3(b[e*i:])
}
case [][4]uint32:
for i := range data {
data[i] = UInt.Vec4(b[e*i:])
data[i] = Uint.Vec4(b[e*i:])
}
case [][2][2]uint32:
for i := range data {
data[i] = UInt.Mat2(b[e*i:])
data[i] = Uint.Mat2(b[e*i:])
}
case [][3][3]uint32:
for i := range data {
data[i] = UInt.Mat3(b[e*i:])
data[i] = Uint.Mat3(b[e*i:])
}
case [][4][4]uint32:
for i := range data {
data[i] = UInt.Mat4(b[e*i:])
data[i] = Uint.Mat4(b[e*i:])
}
}
return nil
}

// Write writes the binary representation of data into b.
// If stride is diferent than zero data will be interleaved.
//
// Data must be a slice of glTF predefined fixed-size types,
// else it fallbacks to `encoding/binary.Write`.
func Write(b []byte, data interface{}) error {
func Write(b []byte, stride uint32, data interface{}) error {
c, t, n := Type(data)
if n <= 0 {
if n == 0 {
return binary.Write(bytes.NewBuffer(b), binary.LittleEndian, data)
}
e := SizeOfElement(c, t)
if len(b) < e*n {
e := int(stride)
if stride == 0 {
e = int(SizeOfElement(c, t))
}
if len(b) < e*int(n) {
return io.ErrShortBuffer
}
switch data := data.(type) {
Expand All @@ -245,7 +250,7 @@ func Write(b []byte, data interface{}) error {
}
case []int8:
for i, x := range data {
b[i] = byte(x)
b[e*i] = byte(x)
}
case [][2]int8:
for i := range data {
Expand Down Expand Up @@ -383,31 +388,31 @@ func Write(b []byte, data interface{}) error {
}
case []uint32:
for i := range data {
UInt.PutScalar(b[e*i:], data[i])
Uint.PutScalar(b[e*i:], data[i])
}
case [][2]uint32:
for i := range data {
UInt.PutVec2(b[e*i:], data[i])
Uint.PutVec2(b[e*i:], data[i])
}
case [][3]uint32:
for i := range data {
UInt.PutVec3(b[e*i:], data[i])
Uint.PutVec3(b[e*i:], data[i])
}
case [][4]uint32:
for i := range data {
UInt.PutVec4(b[e*i:], data[i])
Uint.PutVec4(b[e*i:], data[i])
}
case [][2][2]uint32:
for i := range data {
UInt.PutMat2(b[e*i:], data[i])
Uint.PutMat2(b[e*i:], data[i])
}
case [][3][3]uint32:
for i := range data {
UInt.PutMat3(b[e*i:], data[i])
Uint.PutMat3(b[e*i:], data[i])
}
case [][4][4]uint32:
for i := range data {
UInt.PutMat4(b[e*i:], data[i])
Uint.PutMat4(b[e*i:], data[i])
}
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion binary/encode_test.go
Expand Up @@ -305,7 +305,7 @@ func TestWrite(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b := make([]byte, tt.args.n)
if err := Write(b, tt.args.data); (err != nil) != tt.wantErr {
if err := Write(b, 0, tt.args.data); (err != nil) != tt.wantErr {
t.Errorf("Write() error = %v, wantErr %v", err, tt.wantErr)
}
if !tt.wantErr && !reflect.DeepEqual(b, tt.want) {
Expand Down
11 changes: 6 additions & 5 deletions binary/example_test.go
Expand Up @@ -2,6 +2,7 @@ package binary_test

import (
"fmt"

"github.com/qmuntal/gltf"
"github.com/qmuntal/gltf/binary"
)
Expand All @@ -12,13 +13,13 @@ func ExampleWrite() {
vertices := [][3]float32{{43, 43, 0}, {83, 43, 0}, {63, 63, 40}, {43, 83, 0}, {83, 83, 0}}

// Allocate buffer
sizeIndices := len(indices) * binary.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
sizeVertices := len(vertices) * binary.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3)
sizeIndices := uint32(len(indices)) * binary.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
sizeVertices := uint32(len(vertices)) * binary.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3)
b := make([]byte, sizeIndices+sizeVertices)

// Write
binary.Write(b, indices)
binary.Write(b[sizeIndices:], vertices)
binary.Write(b, 0, indices)
binary.Write(b[sizeIndices:], 0, vertices)

fmt.Print(b)
// Output:
Expand All @@ -32,7 +33,7 @@ func ExampleRead() {

// Define buffer
b := []byte{0, 1, 2, 3, 1, 0, 0, 2, 3, 1, 4, 2, 4, 3, 2, 4, 1, 3, 0, 0, 44, 66, 0, 0, 44, 66, 0, 0, 0, 0, 0, 0, 166, 66, 0, 0, 44, 66, 0, 0, 0, 0, 0, 0, 124, 66, 0, 0, 124, 66, 0, 0, 32, 66, 0, 0, 44, 66, 0, 0, 166, 66, 0, 0, 0, 0, 0, 0, 166, 66, 0, 0, 166, 66, 0, 0, 0, 0}
sizeIndices := len(indices) * binary.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
sizeIndices := uint32(len(indices)) * binary.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)

// Write
binary.Read(b, indices)
Expand Down
37 changes: 6 additions & 31 deletions binary/size.go
Expand Up @@ -7,36 +7,11 @@ import (
"github.com/qmuntal/gltf"
)

// SizeOf returns the size, in bytes, of a component type.
func SizeOf(c gltf.ComponentType) int {
return map[gltf.ComponentType]int{
gltf.ComponentByte: 1,
gltf.ComponentUbyte: 1,
gltf.ComponentShort: 2,
gltf.ComponentUshort: 2,
gltf.ComponentUint: 4,
gltf.ComponentFloat: 4,
}[c]
}

// ComponentsOf returns the number of components of an accessor type.
func ComponentsOf(t gltf.AccessorType) int {
return map[gltf.AccessorType]int{
gltf.AccessorScalar: 1,
gltf.AccessorVec2: 2,
gltf.AccessorVec3: 3,
gltf.AccessorVec4: 4,
gltf.AccessorMat2: 4,
gltf.AccessorMat3: 9,
gltf.AccessorMat4: 16,
}[t]
}

// SizeOfElement returns the size, in bytes, of an element.
// The element size may not be (component size) * (number of components),
// as some of the elements are tightly packed in order to ensure
// that they are aligned to 4-byte boundaries.
func SizeOfElement(c gltf.ComponentType, t gltf.AccessorType) int {
func SizeOfElement(c gltf.ComponentType, t gltf.AccessorType) uint32 {
// special cases
switch {
case (t == gltf.AccessorVec3 || t == gltf.AccessorVec2) && (c == gltf.ComponentByte || c == gltf.ComponentUbyte):
Expand All @@ -50,17 +25,17 @@ func SizeOfElement(c gltf.ComponentType, t gltf.AccessorType) int {
case t == gltf.AccessorMat3 && (c == gltf.ComponentShort || c == gltf.ComponentUshort):
return 24
}
return SizeOf(c) * ComponentsOf(t)
return c.ByteSize() * t.Components()
}

// Type returns the associated glTF type data.
// If data is an slice, it also returns the length of the slice.
// If data does not have an associated glTF type, length will be -1.
func Type(data interface{}) (c gltf.ComponentType, t gltf.AccessorType, length int) {
// If data does not have an associated glTF type length will be 0.
func Type(data interface{}) (c gltf.ComponentType, t gltf.AccessorType, length uint32) {
v := reflect.ValueOf(data)
switch v.Kind() {
case reflect.Slice:
length = v.Len()
length = uint32(v.Len())
}
switch data.(type) {
case []int8, int8:
Expand Down Expand Up @@ -148,7 +123,7 @@ func Type(data interface{}) (c gltf.ComponentType, t gltf.AccessorType, length i
case [][4][4]float32, [4][4]float32:
c, t = gltf.ComponentFloat, gltf.AccessorMat4
default:
length = -1
length = 0
}
return
}
28 changes: 14 additions & 14 deletions binary/unsafe.go
Expand Up @@ -135,64 +135,64 @@ func (shortComponent) PutMat4(b []byte, v [4][4]int16) {
}

func (floatComponent) Scalar(b []byte) float32 {
v := UInt.Scalar(b)
v := Uint.Scalar(b)
return *(*float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutScalar(b []byte, v float32) {
UInt.PutScalar(b, *(*uint32)(unsafe.Pointer(&v)))
Uint.PutScalar(b, *(*uint32)(unsafe.Pointer(&v)))
}

func (floatComponent) Vec2(b []byte) [2]float32 {
v := UInt.Vec2(b)
v := Uint.Vec2(b)
return *(*[2]float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutVec2(b []byte, v [2]float32) {
UInt.PutVec2(b, *(*[2]uint32)(unsafe.Pointer(&v)))
Uint.PutVec2(b, *(*[2]uint32)(unsafe.Pointer(&v)))
}

func (floatComponent) Vec3(b []byte) [3]float32 {
v := UInt.Vec3(b)
v := Uint.Vec3(b)
return *(*[3]float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutVec3(b []byte, v [3]float32) {
UInt.PutVec3(b, *(*[3]uint32)(unsafe.Pointer(&v)))
Uint.PutVec3(b, *(*[3]uint32)(unsafe.Pointer(&v)))
}

func (floatComponent) Vec4(b []byte) [4]float32 {
v := UInt.Vec4(b)
v := Uint.Vec4(b)
return *(*[4]float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutVec4(b []byte, v [4]float32) {
UInt.PutVec4(b, *(*[4]uint32)(unsafe.Pointer(&v)))
Uint.PutVec4(b, *(*[4]uint32)(unsafe.Pointer(&v)))
}

func (floatComponent) Mat2(b []byte) [2][2]float32 {
v := UInt.Mat2(b)
v := Uint.Mat2(b)
return *(*[2][2]float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutMat2(b []byte, v [2][2]float32) {
UInt.PutMat2(b, *(*[2][2]uint32)(unsafe.Pointer(&v)))
Uint.PutMat2(b, *(*[2][2]uint32)(unsafe.Pointer(&v)))
}

func (floatComponent) Mat3(b []byte) [3][3]float32 {
v := UInt.Mat3(b)
v := Uint.Mat3(b)
return *(*[3][3]float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutMat3(b []byte, v [3][3]float32) {
UInt.PutMat3(b, *(*[3][3]uint32)(unsafe.Pointer(&v)))
Uint.PutMat3(b, *(*[3][3]uint32)(unsafe.Pointer(&v)))
}

func (floatComponent) Mat4(b []byte) [4][4]float32 {
v := UInt.Mat4(b)
v := Uint.Mat4(b)
return *(*[4][4]float32)(unsafe.Pointer(&v))
}

func (floatComponent) PutMat4(b []byte, v [4][4]float32) {
UInt.PutMat4(b, *(*[4][4]uint32)(unsafe.Pointer(&v)))
Uint.PutMat4(b, *(*[4][4]uint32)(unsafe.Pointer(&v)))
}

0 comments on commit 6b9d993

Please sign in to comment.