Repository: qmuntal/gltf
Pull request #85 (2024-06-28 14:20:31)

Use int instead of uint32 for all non-wire data
This is a big breaking change, but it makes the API easier to use within the Go ecosystem.


Patch:
diff --git a/README.md b/README.md
index 1bd4e55..2827baa 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ gltf.Document{
   }},
   Nodes: []*gltf.Node{{Name: "Cube", Mesh: gltf.Index(0)}},
   Scene:    gltf.Index(0),
-  Scenes:   []*gltf.Scene{{Name: "Root Scene", Nodes: []uint32{0}}},
+  Scenes:   []*gltf.Scene{{Name: "Root Scene", Nodes: []int{0}}},
 }
 ```
 
@@ -198,7 +198,7 @@ To implement a custom extension decoding, call [gltf.RegisterExtension](https://
 const ExtensionName = "FAKE_Extension"
 
 type Foo struct {
-    BufferView uint32          `json:"bufferView"`
+    BufferView int          `json:"bufferView"`
     Attributes gltf.Attributes  `json:"attributes"`
 }
 
diff --git a/binary/encode.go b/binary/encode.go
index e9964c5..01a4226 100644
--- a/binary/encode.go
+++ b/binary/encode.go
@@ -14,7 +14,7 @@ import (
 //
 // Data should be a slice of glTF predefined fixed-size types.
 // If data length is greater than the length of b, Read returns io.ErrShortBuffer.
-func Read(b []byte, byteStride uint32, data any) error {
+func Read(b []byte, byteStride int, data any) error {
 	c, t, n := Type(data)
 	size := gltf.SizeOfElement(c, t)
 	if byteStride == 0 {
@@ -222,7 +222,7 @@ func Read(b []byte, byteStride uint32, data any) error {
 //
 // Data must be a slice of glTF predefined fixed-size types,
 // else it fallbacks to `encoding/binary.Write`.
-func Write(b []byte, stride uint32, data any) error {
+func Write(b []byte, stride int, data any) error {
 	c, t, n := Type(data)
 	if n == 0 {
 		return binary.Write(bytes.NewBuffer(b), binary.LittleEndian, data)
diff --git a/binary/slice.go b/binary/slice.go
index ee32462..5c0bcf1 100644
--- a/binary/slice.go
+++ b/binary/slice.go
@@ -11,7 +11,7 @@ import (
 // MakeSliceBuffer returns the slice type associated with c and t and with the given element count.
 // If the buffer is an slice which type matches with the expected by the acr then it will
 // be used as backing slice.
-func MakeSliceBuffer(c gltf.ComponentType, t gltf.AccessorType, count uint32, buffer any) any {
+func MakeSliceBuffer(c gltf.ComponentType, t gltf.AccessorType, count int, buffer any) any {
 	if buffer == nil {
 		return MakeSlice(c, t, count)
 	}
@@ -32,7 +32,7 @@ func MakeSliceBuffer(c gltf.ComponentType, t gltf.AccessorType, count uint32, bu
 // MakeSlice returns the slice type associated with c and t and with the given element count.
 // For example, if c is gltf.ComponentFloat and t is gltf.AccessorVec3
 // then MakeSlice(c, t, 5) is equivalent to make([][3]float32, 5).
-func MakeSlice(c gltf.ComponentType, t gltf.AccessorType, count uint32) any {
+func MakeSlice(c gltf.ComponentType, t gltf.AccessorType, count int) any {
 	var tp reflect.Type
 	switch c {
 	case gltf.ComponentUbyte:
@@ -63,17 +63,17 @@ func MakeSlice(c gltf.ComponentType, t gltf.AccessorType, count uint32) any {
 	case gltf.AccessorMat4:
 		tp = reflect.ArrayOf(4, reflect.ArrayOf(4, tp))
 	}
-	return reflect.MakeSlice(reflect.SliceOf(tp), int(count), int(count)).Interface()
+	return reflect.MakeSlice(reflect.SliceOf(tp), count, count).Interface()
 }
 
 // Type returns the associated glTF type data.
 // It panics if data is not an slice.
-func Type(data any) (c gltf.ComponentType, t gltf.AccessorType, count uint32) {
+func Type(data any) (c gltf.ComponentType, t gltf.AccessorType, count int) {
 	v := reflect.ValueOf(data)
 	if v.Kind() != reflect.Slice {
 		panic(fmt.Sprintf("gltf: binary.Type expecting a slice but got %s", v.Kind()))
 	}
-	count = uint32(v.Len())
+	count = v.Len()
 	switch data.(type) {
 	case []int8:
 		c, t = gltf.ComponentByte, gltf.AccessorScalar
diff --git a/const.go b/const.go
index 6f125fe..495daed 100644
--- a/const.go
+++ b/const.go
@@ -50,8 +50,8 @@ const (
 )
 
 // ByteSize returns the size of a component in bytes.
-func (c ComponentType) ByteSize() uint32 {
-	return map[ComponentType]uint32{
+func (c ComponentType) ByteSize() int {
+	return map[ComponentType]int{
 		ComponentByte:   1,
 		ComponentUbyte:  1,
 		ComponentShort:  2,
@@ -104,8 +104,8 @@ const (
 )
 
 // Components returns the number of components of an accessor type.
-func (a AccessorType) Components() uint32 {
-	return map[AccessorType]uint32{
+func (a AccessorType) Components() int {
+	return map[AccessorType]int{
 		AccessorScalar: 1,
 		AccessorVec2:   2,
 		AccessorVec3:   3,
@@ -161,7 +161,7 @@ const (
 )
 
 // PrimitiveAttributes is a map that each key corresponds to mesh attribute semantic and each value is the index of the accessor containing attribute's data.
-type PrimitiveAttributes = map[string]uint32
+type PrimitiveAttributes = map[string]int
 
 // PrimitiveMode defines the type of primitives to render. All valid values correspond to WebGL enums.
 type PrimitiveMode uint8
diff --git a/decoder.go b/decoder.go
index 9f166ad..8ca826c 100644
--- a/decoder.go
+++ b/decoder.go
@@ -176,7 +176,7 @@ func (d *Decoder) decodeBinaryBuffer(buffer *Buffer) error {
 	if err != nil {
 		return err
 	}
-	if header.Type != glbChunkBIN || header.Length < buffer.ByteLength {
+	if header.Type != glbChunkBIN || header.Length < uint32(buffer.ByteLength) {
 		return errors.New("gltf: Invalid GLB BIN header")
 	}
 	buffer.Data = make([]byte, buffer.ByteLength)
diff --git a/encode.go b/encode.go
index 9c189a2..48f2967 100644
--- a/encode.go
+++ b/encode.go
@@ -165,10 +165,10 @@ func (e *Encoder) encodeBinary(doc *Document) (bool, error) {
 	}
 
 	hasBinChunk := len(doc.Buffers) > 0 && doc.Buffers[0].URI == ""
-	var binPaddedLength uint32
+	var binPaddedLength int
 	if hasBinChunk {
 		binPaddedLength = ((doc.Buffers[0].ByteLength + 3) / 4) * 4
-		header.Length += uint32(8) + binPaddedLength
+		header.Length += uint32(8 + binPaddedLength)
 	}
 
 	err = binary.Write(e.w, binary.LittleEndian, &header)
@@ -184,7 +184,7 @@ func (e *Encoder) encodeBinary(doc *Document) (bool, error) {
 		for i := range binPadding {
 			binPadding[i] = 0
 		}
-		binHeader := chunkHeader{Length: binPaddedLength, Type: glbChunkBIN}
+		binHeader := chunkHeader{Length: uint32(binPaddedLength), Type: glbChunkBIN}
 		binary.Write(e.w, binary.LittleEndian, &binHeader)
 		e.w.Write(binBuffer.Data)
 		_, err = e.w.Write(binPadding)
diff --git a/ext/lightspuntual/lightspuntual.go b/ext/lightspuntual/lightspuntual.go
index 71e0c43..7a922f8 100644
--- a/ext/lightspuntual/lightspuntual.go
+++ b/ext/lightspuntual/lightspuntual.go
@@ -46,7 +46,7 @@ const (
 )
 
 // LightIndex is the id of the light referenced by this node.
-type LightIndex uint32
+type LightIndex int
 
 // Spot defines the spot cone.
 type Spot struct {
diff --git a/ext/texturetransform/transform.go b/ext/texturetransform/transform.go
index 089b069..9d4c496 100644
--- a/ext/texturetransform/transform.go
+++ b/ext/texturetransform/transform.go
@@ -35,7 +35,7 @@ type TextureTranform struct {
 	Offset   [2]float64 `json:"offset"`
 	Rotation float64    `json:"rotation,omitempty"`
 	Scale    [2]float64 `json:"scale"`
-	TexCoord *uint32    `json:"texCoord,omitempty"`
+	TexCoord *int       `json:"texCoord,omitempty"`
 }
 
 // ScaleOrDefault returns the node scale if it represents a valid scale factor, else return the default one.
diff --git a/gltf.go b/gltf.go
index edb1419..883cba1 100644
--- a/gltf.go
+++ b/gltf.go
@@ -7,8 +7,8 @@ import (
 	"sync"
 )
 
-// Index is an utility function that returns a pointer to a uint32.
-func Index(i uint32) *uint32 {
+// Index is an utility function that returns a pointer to a int.
+func Index(i int) *int {
 	return &i
 }
 
@@ -44,7 +44,7 @@ type Document struct {
 	Meshes             []*Mesh       `json:"meshes,omitempty" validate:"dive"`
 	Nodes              []*Node       `json:"nodes,omitempty" validate:"dive"`
 	Samplers           []*Sampler    `json:"samplers,omitempty" validate:"dive"`
-	Scene              *uint32       `json:"scene,omitempty"`
+	Scene              *int          `json:"scene,omitempty"`
 	Scenes             []*Scene      `json:"scenes,omitempty" validate:"dive"`
 	Skins              []*Skin       `json:"skins,omitempty" validate:"dive"`
 	Textures           []*Texture    `json:"textures,omitempty" validate:"dive"`
@@ -69,11 +69,11 @@ type Accessor struct {
 	Extensions    Extensions    `json:"extensions,omitempty"`
 	Extras        any           `json:"extras,omitempty"`
 	Name          string        `json:"name,omitempty"`
-	BufferView    *uint32       `json:"bufferView,omitempty"`
-	ByteOffset    uint32        `json:"byteOffset,omitempty"`
+	BufferView    *int          `json:"bufferView,omitempty"`
+	ByteOffset    int           `json:"byteOffset,omitempty"`
 	ComponentType ComponentType `json:"componentType" validate:"lte=5"`
 	Normalized    bool          `json:"normalized,omitempty"`      // Specifies whether integer data values should be normalized.
-	Count         uint32        `json:"count" validate:"required"` // The number of attributes referenced by this accessor.
+	Count         int           `json:"count" validate:"required"` // The number of attributes referenced by this accessor.
 	Type          AccessorType  `json:"type" validate:"lte=6"`
 	Max           []float64     `json:"max,omitempty" validate:"omitempty,lte=16"` // Maximum value of each component in this attribute.
 	Min           []float64     `json:"min,omitempty" validate:"omitempty,lte=16"` // Minimum value of each component in this attribute.
@@ -84,7 +84,7 @@ type Accessor struct {
 type Sparse struct {
 	Extensions Extensions    `json:"extensions,omitempty"`
 	Extras     any           `json:"extras,omitempty"`
-	Count      uint32        `json:"count" validate:"gte=1"` // Number of entries stored in the sparse array.
+	Count      int           `json:"count" validate:"gte=1"` // Number of entries stored in the sparse array.
 	Indices    SparseIndices `json:"indices"`                // Index array of size count that points to those accessor attributes that deviate from their initialization value.
 	Values     SparseValues  `json:"values"`                 // Array of size count times number of components, storing the displaced accessor attributes pointed by indices.
 }
@@ -93,16 +93,16 @@ type Sparse struct {
 type SparseValues struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
-	BufferView uint32     `json:"bufferView"`
-	ByteOffset uint32     `json:"byteOffset,omitempty"`
+	BufferView int        `json:"bufferView"`
+	ByteOffset int        `json:"byteOffset,omitempty"`
 }
 
 // SparseIndices defines the indices of those attributes that deviate from their initialization value.
 type SparseIndices struct {
 	Extensions    Extensions    `json:"extensions,omitempty"`
 	Extras        any           `json:"extras,omitempty"`
-	BufferView    uint32        `json:"bufferView"`
-	ByteOffset    uint32        `json:"byteOffset,omitempty"`
+	BufferView    int           `json:"bufferView"`
+	ByteOffset    int           `json:"byteOffset,omitempty"`
 	ComponentType ComponentType `json:"componentType" validate:"oneof=2 4 5"`
 }
 
@@ -114,7 +114,7 @@ type Buffer struct {
 	Extras     any        `json:"extras,omitempty"`
 	Name       string     `json:"name,omitempty"`
 	URI        string     `json:"uri,omitempty" validate:"omitempty"`
-	ByteLength uint32     `json:"byteLength" validate:"required"`
+	ByteLength int        `json:"byteLength" validate:"required"`
 	Data       []byte     `json:"-"`
 }
 
@@ -148,10 +148,10 @@ func (b *Buffer) marshalData() ([]byte, error) {
 type BufferView struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
-	Buffer     uint32     `json:"buffer"`
-	ByteOffset uint32     `json:"byteOffset,omitempty"`
-	ByteLength uint32     `json:"byteLength" validate:"required"`
-	ByteStride uint32     `json:"byteStride,omitempty" validate:"omitempty,gte=4,lte=252"`
+	Buffer     int        `json:"buffer"`
+	ByteOffset int        `json:"byteOffset,omitempty"`
+	ByteLength int        `json:"byteLength" validate:"required"`
+	ByteStride int        `json:"byteStride,omitempty" validate:"omitempty,gte=4,lte=252"`
 	Target     Target     `json:"target,omitempty" validate:"omitempty,oneof=34962 34963"`
 	Name       string     `json:"name,omitempty"`
 }
@@ -161,7 +161,7 @@ type Scene struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
 	Name       string     `json:"name,omitempty"`
-	Nodes      []uint32   `json:"nodes,omitempty" validate:"omitempty,unique"`
+	Nodes      []int      `json:"nodes,omitempty" validate:"omitempty,unique"`
 }
 
 // A Node in the node hierarchy.
@@ -170,11 +170,11 @@ type Node struct {
 	Extensions  Extensions  `json:"extensions,omitempty"`
 	Extras      any         `json:"extras,omitempty"`
 	Name        string      `json:"name,omitempty"`
-	Camera      *uint32     `json:"camera,omitempty"`
-	Children    []uint32    `json:"children,omitempty" validate:"omitempty,unique"`
-	Skin        *uint32     `json:"skin,omitempty"`
+	Camera      *int        `json:"camera,omitempty"`
+	Children    []int       `json:"children,omitempty" validate:"omitempty,unique"`
+	Skin        *int        `json:"skin,omitempty"`
 	Matrix      [16]float64 `json:"matrix"` // A 4x4 transformation matrix stored in column-major order.
-	Mesh        *uint32     `json:"mesh,omitempty"`
+	Mesh        *int        `json:"mesh,omitempty"`
 	Rotation    [4]float64  `json:"rotation" validate:"omitempty,dive,gte=-1,lte=1"` // The node's unit quaternion rotation in the order (x, y, z, w), where w is the scalar.
 	Scale       [3]float64  `json:"scale"`
 	Translation [3]float64  `json:"translation"`
@@ -215,9 +215,9 @@ type Skin struct {
 	Extensions          Extensions `json:"extensions,omitempty"`
 	Extras              any        `json:"extras,omitempty"`
 	Name                string     `json:"name,omitempty"`
-	InverseBindMatrices *uint32    `json:"inverseBindMatrices,omitempty"`      // The index of the accessor containing the floating-point 4x4 inverse-bind matrices.
-	Skeleton            *uint32    `json:"skeleton,omitempty"`                 // The index of the node used as a skeleton root. When undefined, joints transforms resolve to scene root.
-	Joints              []uint32   `json:"joints" validate:"omitempty,unique"` // Indices of skeleton nodes, used as joints in this skin.
+	InverseBindMatrices *int       `json:"inverseBindMatrices,omitempty"`      // The index of the accessor containing the floating-point 4x4 inverse-bind matrices.
+	Skeleton            *int       `json:"skeleton,omitempty"`                 // The index of the node used as a skeleton root. When undefined, joints transforms resolve to scene root.
+	Joints              []int      `json:"joints" validate:"omitempty,unique"` // Indices of skeleton nodes, used as joints in this skin.
 }
 
 // A Camera projection. A node can reference a camera to apply a transform to place the camera in the scene.
@@ -263,8 +263,8 @@ type Primitive struct {
 	Extensions Extensions            `json:"extensions,omitempty"`
 	Extras     any                   `json:"extras,omitempty"`
 	Attributes PrimitiveAttributes   `json:"attributes"`
-	Indices    *uint32               `json:"indices,omitempty"` // The index of the accessor that contains the indices.
-	Material   *uint32               `json:"material,omitempty"`
+	Indices    *int                  `json:"indices,omitempty"` // The index of the accessor that contains the indices.
+	Material   *int                  `json:"material,omitempty"`
 	Mode       PrimitiveMode         `json:"mode,omitempty" validate:"lte=6"`
 	Targets    []PrimitiveAttributes `json:"targets,omitempty" validate:"omitempty,dive,dive,keys,oneof=POSITION NORMAL TANGENT,endkeys"` // Only POSITION, NORMAL, and TANGENT supported.
 }
@@ -296,8 +296,8 @@ func (m *Material) AlphaCutoffOrDefault() float64 {
 type NormalTexture struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
-	Index      *uint32    `json:"index,omitempty"`
-	TexCoord   uint32     `json:"texCoord,omitempty"` // The index of texture's TEXCOORD attribute used for texture coordinate mapping.
+	Index      *int       `json:"index,omitempty"`
+	TexCoord   int        `json:"texCoord,omitempty"` // The index of texture's TEXCOORD attribute used for texture coordinate mapping.
 	Scale      *float64   `json:"scale,omitempty"`
 }
 
@@ -313,8 +313,8 @@ func (n *NormalTexture) ScaleOrDefault() float64 {
 type OcclusionTexture struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
-	Index      *uint32    `json:"index,omitempty"`
-	TexCoord   uint32     `json:"texCoord,omitempty"` // The index of texture's TEXCOORD attribute used for texture coordinate mapping.
+	Index      *int       `json:"index,omitempty"`
+	TexCoord   int        `json:"texCoord,omitempty"` // The index of texture's TEXCOORD attribute used for texture coordinate mapping.
 	Strength   *float64   `json:"strength,omitempty" validate:"omitempty,gte=0,lte=1"`
 }
 
@@ -365,8 +365,8 @@ func (p *PBRMetallicRoughness) BaseColorFactorOrDefault() [4]float64 {
 type TextureInfo struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
-	Index      uint32     `json:"index"`
-	TexCoord   uint32     `json:"texCoord,omitempty"` // The index of texture's TEXCOORD attribute used for texture coordinate mapping.
+	Index      int        `json:"index"`
+	TexCoord   int        `json:"texCoord,omitempty"` // The index of texture's TEXCOORD attribute used for texture coordinate mapping.
 }
 
 // A Texture and its sampler.
@@ -374,8 +374,8 @@ type Texture struct {
 	Extensions Extensions `json:"extensions,omitempty"`
 	Extras     any        `json:"extras,omitempty"`
 	Name       string     `json:"name,omitempty"`
-	Sampler    *uint32    `json:"sampler,omitempty"`
-	Source     *uint32    `json:"source,omitempty"`
+	Sampler    *int       `json:"sampler,omitempty"`
+	Source     *int       `json:"source,omitempty"`
 }
 
 // Sampler of a texture for filtering and wrapping modes.
@@ -397,7 +397,7 @@ type Image struct {
 	Name       string     `json:"name,omitempty"`
 	URI        string     `json:"uri,omitempty" validate:"omitempty"`
 	MimeType   string     `json:"mimeType,omitempty" validate:"omitempty,oneof=image/jpeg image/png"` // Manadatory if BufferView is defined.
-	BufferView *uint32    `json:"bufferView,omitempty"`                                               // Use this instead of the image's uri property.
+	BufferView *int       `json:"bufferView,omitempty"`                                               // Use this instead of the image's uri property.
 }
 
 // IsEmbeddedResource returns true if the buffer points to an embedded resource.
@@ -434,16 +434,16 @@ type Animation struct {
 type AnimationSampler struct {
 	Extensions    Extensions    `json:"extensions,omitempty"`
 	Extras        any           `json:"extras,omitempty"`
-	Input         uint32        `json:"input"` // The index of an accessor containing keyframe input values.
+	Input         int           `json:"input"` // The index of an accessor containing keyframe input values.
 	Interpolation Interpolation `json:"interpolation,omitempty" validate:"lte=2"`
-	Output        uint32        `json:"output"` // The index of an accessor containing keyframe output values.
+	Output        int           `json:"output"` // The index of an accessor containing keyframe output values.
 }
 
 // The AnimationChannel targets an animation's sampler at a node's property.
 type AnimationChannel struct {
 	Extensions Extensions             `json:"extensions,omitempty"`
 	Extras     any                    `json:"extras,omitempty"`
-	Sampler    uint32                 `json:"sampler"`
+	Sampler    int                    `json:"sampler"`
 	Target     AnimationChannelTarget `json:"target"`
 }
 
@@ -455,7 +455,7 @@ type AnimationChannel struct {
 type AnimationChannelTarget struct {
 	Extensions Extensions  `json:"extensions,omitempty"`
 	Extras     any         `json:"extras,omitempty"`
-	Node       *uint32     `json:"node,omitempty"`
+	Node       *int        `json:"node,omitempty"`
 	Path       TRSProperty `json:"path" validate:"lte=4"`
 }
 
@@ -489,7 +489,7 @@ func queryExtension(key string) (func([]byte) (any, error), bool) {
 // 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 ComponentType, t AccessorType) uint32 {
+func SizeOfElement(c ComponentType, t AccessorType) int {
 	// special cases
 	switch {
 	case (t == AccessorVec3 || t == AccessorVec2) && (c == ComponentByte || c == ComponentUbyte):
diff --git a/modeler/read.go b/modeler/read.go
index 344417c..be040c4 100644
--- a/modeler/read.go
+++ b/modeler/read.go
@@ -90,8 +90,8 @@ func ReadAccessor(doc *gltf.Document, acr *gltf.Accessor, buffer any) (any, erro
 	return buffer, nil
 }
 
-func readBufferView(doc *gltf.Document, bufferViewIndex uint32) ([]byte, error) {
-	if uint32(len(doc.BufferViews)) <= bufferViewIndex {
+func readBufferView(doc *gltf.Document, bufferViewIndex int) ([]byte, error) {
+	if len(doc.BufferViews) <= bufferViewIndex {
 		return nil, errors.New("gltf: bufferview index overflows")
 	}
 	return ReadBufferView(doc, doc.BufferViews[bufferViewIndex])
@@ -102,13 +102,13 @@ func readBufferView(doc *gltf.Document, bufferViewIndex uint32) ([]byte, error)
 // It is safe to use even with malformed documents.
 // If that happens it will return an error instead of panic.
 func ReadBufferView(doc *gltf.Document, bv *gltf.BufferView) ([]byte, error) {
-	if uint32(len(doc.Buffers)) <= bv.Buffer {
+	if len(doc.Buffers) <= bv.Buffer {
 		return nil, errors.New("gltf: buffer index overflows")
 	}
 	buf := doc.Buffers[bv.Buffer].Data
 
 	high := bv.ByteOffset + bv.ByteLength
-	if uint32(len(buf)) < high {
+	if len(buf) < high {
 		return nil, io.ErrShortBuffer
 	}
 	return buf[bv.ByteOffset:high], nil
@@ -132,8 +132,8 @@ func ReadIndices(doc *gltf.Document, acr *gltf.Accessor, buffer []uint32) ([]uin
 	if err != nil {
 		return nil, err
 	}
-	if uint32(len(buffer)) < acr.Count {
-		buffer = append(buffer, make([]uint32, acr.Count-uint32(len(buffer)))...)
+	if len(buffer) < acr.Count {
+		buffer = append(buffer, make([]uint32, acr.Count-len(buffer))...)
 	} else {
 		buffer = buffer[:acr.Count]
 	}
@@ -204,8 +204,8 @@ func ReadTextureCoord(doc *gltf.Document, acr *gltf.Accessor, buffer [][2]float3
 	if err != nil {
 		return nil, err
 	}
-	if uint32(len(buffer)) < acr.Count {
-		buffer = append(buffer, make([][2]float32, acr.Count-uint32(len(buffer)))...)
+	if len(buffer) < acr.Count {
+		buffer = append(buffer, make([][2]float32, acr.Count-len(buffer))...)
 	} else {
 		buffer = buffer[:acr.Count]
 	}
@@ -246,8 +246,8 @@ func ReadWeights(doc *gltf.Document, acr *gltf.Accessor, buffer [][4]float32) ([
 	if err != nil {
 		return nil, err
 	}
-	if uint32(len(buffer)) < acr.Count {
-		buffer = append(buffer, make([][4]float32, acr.Count-uint32(len(buffer)))...)
+	if len(buffer) < acr.Count {
+		buffer = append(buffer, make([][4]float32, acr.Count-len(buffer))...)
 	} else {
 		buffer = buffer[:acr.Count]
 	}
@@ -290,8 +290,8 @@ func ReadJoints(doc *gltf.Document, acr *gltf.Accessor, buffer [][4]uint16) ([][
 	if err != nil {
 		return nil, err
 	}
-	if uint32(len(buffer)) < acr.Count {
-		buffer = append(buffer, make([][4]uint16, acr.Count-uint32(len(buffer)))...)
+	if len(buffer) < acr.Count {
+		buffer = append(buffer, make([][4]uint16, acr.Count-len(buffer))...)
 	} else {
 		buffer = buffer[:acr.Count]
 	}
@@ -346,8 +346,8 @@ func ReadColor(doc *gltf.Document, acr *gltf.Accessor, buffer [][4]uint8) ([][4]
 	if err != nil {
 		return nil, err
 	}
-	if uint32(len(buffer)) < acr.Count {
-		buffer = append(buffer, make([][4]uint8, acr.Count-uint32(len(buffer)))...)
+	if len(buffer) < acr.Count {
+		buffer = append(buffer, make([][4]uint8, acr.Count-len(buffer))...)
 	} else {
 		buffer = buffer[:acr.Count]
 	}
@@ -405,8 +405,8 @@ func ReadColor64(doc *gltf.Document, acr *gltf.Accessor, buffer [][4]uint16) ([]
 	if err != nil {
 		return nil, err
 	}
-	if uint32(len(buffer)) < acr.Count {
-		buffer = append(buffer, make([][4]uint16, acr.Count-uint32(len(buffer)))...)
+	if len(buffer) < acr.Count {
+		buffer = append(buffer, make([][4]uint16, acr.Count-len(buffer))...)
 	} else {
 		buffer = buffer[:acr.Count]
 	}
diff --git a/modeler/write.go b/modeler/write.go
index 21b5928..9bb541e 100644
--- a/modeler/write.go
+++ b/modeler/write.go
@@ -18,7 +18,7 @@ import (
 // WriteIndices adds a new INDICES accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WriteIndices(doc *gltf.Document, data any) uint32 {
+func WriteIndices(doc *gltf.Document, data any) int {
 	switch data.(type) {
 	case []uint16, []uint32:
 	default:
@@ -30,21 +30,21 @@ func WriteIndices(doc *gltf.Document, data any) uint32 {
 // WriteNormal adds a new NORMAL accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WriteNormal(doc *gltf.Document, data [][3]float32) uint32 {
+func WriteNormal(doc *gltf.Document, data [][3]float32) int {
 	return WriteAccessor(doc, gltf.TargetArrayBuffer, data)
 }
 
 // WriteTangent adds a new TANGENT accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WriteTangent(doc *gltf.Document, data [][4]float32) uint32 {
+func WriteTangent(doc *gltf.Document, data [][4]float32) int {
 	return WriteAccessor(doc, gltf.TargetArrayBuffer, data)
 }
 
 // WriteTextureCoord adds a new TEXTURECOORD accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WriteTextureCoord(doc *gltf.Document, data any) uint32 {
+func WriteTextureCoord(doc *gltf.Document, data any) int {
 	normalized, err := checkTextureCoord(data)
 	if err != nil {
 		panic(err)
@@ -69,7 +69,7 @@ func checkTextureCoord(data any) (bool, error) {
 // WriteWeights adds a new WEIGHTS accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WriteWeights(doc *gltf.Document, data any) uint32 {
+func WriteWeights(doc *gltf.Document, data any) int {
 	normalized, err := checkWeights(data)
 	if err != nil {
 		panic(err)
@@ -94,7 +94,7 @@ func checkWeights(data any) (bool, error) {
 // WriteJoints adds a new JOINTS accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WriteJoints(doc *gltf.Document, data any) uint32 {
+func WriteJoints(doc *gltf.Document, data any) int {
 	err := checkJoints(data)
 	if err != nil {
 		panic(err)
@@ -114,7 +114,7 @@ func checkJoints(data any) error {
 // WritePosition adds a new POSITION accessor to doc
 // and fills the last buffer with data.
 // If success it returns the index of the new accessor.
-func WritePosition(doc *gltf.Document, data [][3]float32) uint32 {
+func WritePosition(doc *gltf.Document, data [][3]float32) int {
 	index := WriteAccessor(doc, gltf.TargetArrayBuffer, data)
 	min, max := minMaxFloat32(data)
 	doc.Accessors[index].Min = min[:]
@@ -137,7 +137,7 @@ func minMaxFloat32(data [][3]float32) ([3]float64, [3]float64) {
 // WriteColor adds a new COLOR accessor to doc
 // and fills the buffer with data.
 // If success it returns the index of the new accessor.
-func WriteColor(doc *gltf.Document, data any) uint32 {
+func WriteColor(doc *gltf.Document, data any) int {
 	normalized, err := checkColor(data)
 	if err != nil {
 		panic(err)
@@ -162,7 +162,7 @@ func checkColor(data any) (bool, error) {
 // WriteImage adds a new image to doc
 // and fills the buffer with the image data.
 // If success it returns the index of the new image.
-func WriteImage(doc *gltf.Document, name string, mimeType string, r io.Reader) (uint32, error) {
+func WriteImage(doc *gltf.Document, name string, mimeType string, r io.Reader) (int, error) {
 	var data []byte
 	switch r := r.(type) {
 	case *bytes.Buffer:
@@ -180,13 +180,13 @@ func WriteImage(doc *gltf.Document, name string, mimeType string, r io.Reader) (
 		MimeType:   mimeType,
 		BufferView: gltf.Index(index),
 	})
-	return uint32(len(doc.Images) - 1), nil
+	return len(doc.Images) - 1, nil
 }
 
 // WriteAccessor adds a new Accessor to doc
 // and fills the buffer with the data.
 // Returns the index of the new accessor.
-func WriteAccessor(doc *gltf.Document, target gltf.Target, data any) uint32 {
+func WriteAccessor(doc *gltf.Document, target gltf.Target, data any) int {
 	ensurePadding(doc)
 	index := WriteBufferView(doc, target, data)
 	c, a, l := binary.Type(data)
@@ -197,7 +197,7 @@ func WriteAccessor(doc *gltf.Document, target gltf.Target, data any) uint32 {
 		Type:          a,
 		Count:         l,
 	})
-	return uint32(len(doc.Accessors) - 1)
+	return len(doc.Accessors) - 1
 }
 
 // WriteAccessorsInterleaved adds as many accessors as
@@ -206,14 +206,14 @@ func WriteAccessor(doc *gltf.Document, target gltf.Target, data any) uint32 {
 // Returns an slice with the indices of the newly created accessors,
 // with the same order as data or an error if the data elements
 // don´t have all the same length.
-func WriteAccessorsInterleaved(doc *gltf.Document, data ...any) ([]uint32, error) {
+func WriteAccessorsInterleaved(doc *gltf.Document, data ...any) ([]int, error) {
 	ensurePadding(doc)
 	index, err := WriteBufferViewInterleaved(doc, data...)
 	if err != nil {
 		return nil, err
 	}
-	indices := make([]uint32, len(data))
-	var byteOffset uint32
+	indices := make([]int, len(data))
+	var byteOffset int
 	for i, d := range data {
 		c, t, l := binary.Type(d)
 		doc.Accessors = append(doc.Accessors, &gltf.Accessor{
@@ -224,7 +224,7 @@ func WriteAccessorsInterleaved(doc *gltf.Document, data ...any) ([]uint32, error
 			Count:         l,
 		})
 		byteOffset += gltf.SizeOfElement(c, t)
-		indices[i] = uint32(len(doc.Accessors) - 1)
+		indices[i] = len(doc.Accessors) - 1
 	}
 	return indices, nil
 }
@@ -295,20 +295,20 @@ func WritePrimitiveAttributes(doc *gltf.Document, attr ...PrimitiveAttribute) (g
 // If success it returns the index of the new buffer view.
 // Returns the index of the new buffer view or an error if the data elements
 // don´t have all the same length.
-func WriteBufferViewInterleaved(doc *gltf.Document, data ...any) (uint32, error) {
+func WriteBufferViewInterleaved(doc *gltf.Document, data ...any) (int, error) {
 	return writeBufferViews(doc, gltf.TargetArrayBuffer, data...)
 }
 
 // WriteBufferView adds a new BufferView to doc
 // and fills the buffer with the data.
 // Returns the index of the new buffer view.
-func WriteBufferView(doc *gltf.Document, target gltf.Target, data any) uint32 {
+func WriteBufferView(doc *gltf.Document, target gltf.Target, data any) int {
 	index, _ := writeBufferViews(doc, target, data)
 	return index
 }
 
-func writeBufferViews(doc *gltf.Document, target gltf.Target, data ...any) (uint32, error) {
-	var refLength, stride, size uint32
+func writeBufferViews(doc *gltf.Document, target gltf.Target, data ...any) (int, error) {
+	var refLength, stride, size int
 	for i, d := range data {
 		c, a, l := binary.Type(d)
 		if i == 0 {
@@ -325,7 +325,7 @@ func writeBufferViews(doc *gltf.Document, target gltf.Target, data ...any) (uint
 		}
 	}
 	buffer := lastBuffer(doc)
-	offset := uint32(len(buffer.Data))
+	offset := len(buffer.Data)
 	buffer.ByteLength += size
 	buffer.Data = append(buffer.Data, make([]byte, size)...)
 	dataOffset := offset
@@ -336,19 +336,19 @@ func writeBufferViews(doc *gltf.Document, target gltf.Target, data ...any) (uint
 		dataOffset += gltf.SizeOfElement(c, a)
 	}
 	bufferView := &gltf.BufferView{
-		Buffer:     uint32(len(doc.Buffers)) - 1,
+		Buffer:     len(doc.Buffers) - 1,
 		ByteLength: size,
 		ByteOffset: offset,
 		ByteStride: stride,
 		Target:     target,
 	}
 	doc.BufferViews = append(doc.BufferViews, bufferView)
-	return uint32(len(doc.BufferViews)) - 1, nil
+	return len(doc.BufferViews) - 1, nil
 }
 
 func ensurePadding(doc *gltf.Document) {
 	buffer := lastBuffer(doc)
-	padding := getPadding(uint32(len(buffer.Data)))
+	padding := getPadding(len(buffer.Data))
 	buffer.Data = append(buffer.Data, make([]byte, padding)...)
 	buffer.ByteLength += padding
 }
@@ -360,7 +360,7 @@ func lastBuffer(doc *gltf.Document) *gltf.Buffer {
 	return doc.Buffers[len(doc.Buffers)-1]
 }
 
-func getPadding(offset uint32) uint32 {
+func getPadding(offset int) int {
 	padAlign := offset % 4
 	if padAlign == 0 {
 		return 0


Test patch:
diff --git a/binary/bench_test.go b/binary/bench_test.go
index 3b6ee6a..78af388 100644
--- a/binary/bench_test.go
+++ b/binary/bench_test.go
@@ -9,7 +9,7 @@ import (
 )
 
 func BenchmarkNative(b *testing.B) {
-	var s uint32 = 1000
+	var s int = 1000
 	bs := make([]byte, s*gltf.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3))
 	data := make([][3]float32, s)
 	b.ResetTimer()
@@ -21,7 +21,7 @@ func BenchmarkNative(b *testing.B) {
 }
 
 func BenchmarkWrite(b *testing.B) {
-	var s uint32 = 1000
+	var s int = 1000
 	bs := make([]byte, s*gltf.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3))
 	data := make([][3]float32, s)
 	b.ResetTimer()
@@ -31,7 +31,7 @@ func BenchmarkWrite(b *testing.B) {
 }
 
 func BenchmarkWrite_builtint(b *testing.B) {
-	var s uint32 = 1000
+	var s int = 1000
 	bs := bytes.NewBuffer(make([]byte, s*gltf.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3)))
 	data := make([][3]float32, s)
 	b.ResetTimer()
diff --git a/binary/example_test.go b/binary/example_test.go
index 5a33924..80b31fc 100644
--- a/binary/example_test.go
+++ b/binary/example_test.go
@@ -13,8 +13,8 @@ func ExampleWrite() {
 	vertices := [][3]float32{{43, 43, 0}, {83, 43, 0}, {63, 63, 40}, {43, 83, 0}, {83, 83, 0}}
 
 	// Allocate buffer
-	sizeIndices := uint32(len(indices)) * gltf.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
-	sizeVertices := uint32(len(vertices)) * gltf.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3)
+	sizeIndices := len(indices) * gltf.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
+	sizeVertices := len(vertices) * gltf.SizeOfElement(gltf.ComponentFloat, gltf.AccessorVec3)
 	b := make([]byte, sizeIndices+sizeVertices)
 
 	// Write
@@ -33,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 := uint32(len(indices)) * gltf.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
+	sizeIndices := len(indices) * gltf.SizeOfElement(gltf.ComponentUbyte, gltf.AccessorScalar)
 
 	// Read
 	binary.Read(b, 0, indices)
diff --git a/binary/slice_test.go b/binary/slice_test.go
index aa5e036..05fec2a 100644
--- a/binary/slice_test.go
+++ b/binary/slice_test.go
@@ -11,7 +11,7 @@ func TestMakeSlice(t *testing.T) {
 	type args struct {
 		c     gltf.ComponentType
 		t     gltf.AccessorType
-		count uint32
+		count int
 	}
 	tests := []struct {
 		name string
@@ -81,7 +81,7 @@ func TestMakeSliceBuffer(t *testing.T) {
 	type args struct {
 		c      gltf.ComponentType
 		t      gltf.AccessorType
-		count  uint32
+		count  int
 		buffer any
 	}
 	tests := []struct {
diff --git a/decoder_test.go b/decoder_test.go
index dc35e9b..8309910 100644
--- a/decoder_test.go
+++ b/decoder_test.go
@@ -50,7 +50,7 @@ func TestOpen(t *testing.T) {
 			Nodes:     []*Node{{Mesh: Index(0), Name: "Cube", Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}}},
 			Samplers:  []*Sampler{{WrapS: WrapRepeat, WrapT: WrapRepeat}},
 			Scene:     Index(0),
-			Scenes:    []*Scene{{Nodes: []uint32{0}}},
+			Scenes:    []*Scene{{Nodes: []int{0}}},
 			Textures: []*Texture{
 				{Sampler: Index(0), Source: Index(0)}, {Sampler: Index(0), Source: Index(1)},
 			},
@@ -77,7 +77,7 @@ func TestOpen(t *testing.T) {
 				{Camera: Index(1), Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}, Translation: [3]float64{0.5, 0.5, 3.0}},
 			},
 			Scene:  nil,
-			Scenes: []*Scene{{Nodes: []uint32{0, 1, 2}}},
+			Scenes: []*Scene{{Nodes: []int{0, 1, 2}}},
 		}, false},
 		{args{"testdata/BoxVertexColors/glTF-Binary/BoxVertexColors.glb", ""}, &Document{
 			Accessors: []*Accessor{
@@ -99,14 +99,14 @@ func TestOpen(t *testing.T) {
 			Materials: []*Material{{Name: "Default", AlphaMode: AlphaOpaque, AlphaCutoff: Float(0.5), PBRMetallicRoughness: &PBRMetallicRoughness{BaseColorFactor: &[4]float64{0.8, 0.8, 0.8, 1}, MetallicFactor: Float(0.1), RoughnessFactor: Float(0.99)}}},
 			Meshes:    []*Mesh{{Name: "Cube", Primitives: []*Primitive{{Indices: Index(0), Material: Index(0), Mode: PrimitiveTriangles, Attributes: PrimitiveAttributes{POSITION: 1, COLOR_0: 3, NORMAL: 2, TEXCOORD_0: 4}}}}},
 			Nodes: []*Node{
-				{Name: "RootNode", Children: []uint32{1, 2, 3}, Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}},
+				{Name: "RootNode", Children: []int{1, 2, 3}, Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}},
 				{Name: "Mesh", Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}},
 				{Name: "Cube", Mesh: Index(0), Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}},
 				{Name: "Texture Group", Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}},
 			},
 			Samplers: []*Sampler{{WrapS: WrapRepeat, WrapT: WrapRepeat}},
 			Scene:    Index(0),
-			Scenes:   []*Scene{{Name: "Root Scene", Nodes: []uint32{0}}},
+			Scenes:   []*Scene{{Name: "Root Scene", Nodes: []int{0}}},
 		}, false},
 		{args{"testdata/Box With Spaces/glTF/Box With Spaces.gltf", ""}, &Document{
 			Accessors: []*Accessor{
@@ -135,7 +135,7 @@ func TestOpen(t *testing.T) {
 			Meshes:   []*Mesh{{Name: "Cube", Primitives: []*Primitive{{Indices: Index(3), Material: Index(0), Mode: PrimitiveTriangles, Attributes: PrimitiveAttributes{NORMAL: 1, POSITION: 0, TEXCOORD_0: 2}}}}},
 			Nodes:    []*Node{{Mesh: Index(0), Name: "Cube", Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}}},
 			Scene:    Index(0),
-			Scenes:   []*Scene{{Name: "Scene", Nodes: []uint32{0}}},
+			Scenes:   []*Scene{{Name: "Scene", Nodes: []int{0}}},
 			Textures: []*Texture{{Source: Index(0)}, {Source: Index(1)}, {Source: Index(2)}},
 		}, false},
 	}
diff --git a/encode_test.go b/encode_test.go
index e48ca4b..9efbc90 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -216,9 +216,9 @@ func TestEncoder_Encode(t *testing.T) {
 			}},
 		}}}, false},
 		{"withNodes", args{&Document{Nodes: []*Node{
-			{Extras: 8.0, Name: "n-1", Camera: Index(1), Children: []uint32{1, 2}, Skin: Index(3),
+			{Extras: 8.0, Name: "n-1", Camera: Index(1), Children: []int{1, 2}, Skin: Index(3),
 				Matrix: [16]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, Mesh: Index(15), Rotation: [4]float64{1.5, 1.3, 12, 0}, Scale: [3]float64{1, 3, 4}, Translation: [3]float64{0, 7.8, 9}, Weights: []float64{1, 3}},
-			{Extras: 8.0, Name: "n-2", Camera: Index(1), Children: []uint32{1, 2}, Skin: Index(3),
+			{Extras: 8.0, Name: "n-2", Camera: Index(1), Children: []int{1, 2}, Skin: Index(3),
 				Matrix: [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, Mesh: Index(15), Rotation: [4]float64{0, 0, 0, 1}, Scale: [3]float64{1, 1, 1}},
 		}}}, false},
 		{"withSampler", args{&Document{Samplers: []*Sampler{
@@ -227,12 +227,12 @@ func TestEncoder_Encode(t *testing.T) {
 		}}}, false},
 		{"withScene", args{&Document{Scene: Index(1)}}, false},
 		{"withScenes", args{&Document{Scenes: []*Scene{
-			{Extras: 8.0, Name: "s_1", Nodes: []uint32{1, 2}},
-			{Extras: 8.0, Name: "s_2", Nodes: []uint32{2, 3}},
+			{Extras: 8.0, Name: "s_1", Nodes: []int{1, 2}},
+			{Extras: 8.0, Name: "s_2", Nodes: []int{2, 3}},
 		}}}, false},
 		{"withSkins", args{&Document{Skins: []*Skin{
-			{Extras: 8.0, Name: "skin_1", InverseBindMatrices: Index(2), Skeleton: Index(4), Joints: []uint32{5, 6}},
-			{Extras: 8.0, Name: "skin_2", InverseBindMatrices: Index(3), Skeleton: Index(4), Joints: []uint32{7, 8}},
+			{Extras: 8.0, Name: "skin_1", InverseBindMatrices: Index(2), Skeleton: Index(4), Joints: []int{5, 6}},
+			{Extras: 8.0, Name: "skin_2", InverseBindMatrices: Index(3), Skeleton: Index(4), Joints: []int{7, 8}},
 		}}}, false},
 		{"withTextures", args{&Document{Textures: []*Texture{
 			{Extras: 8.0, Name: "t_1", Sampler: Index(2), Source: Index(3)},
diff --git a/example_test.go b/example_test.go
index 4999cd9..17ef25e 100644
--- a/example_test.go
+++ b/example_test.go
@@ -38,14 +38,14 @@ func ExampleSave() {
 		}},
 		Meshes: []*gltf.Mesh{{Name: "Cube", Primitives: []*gltf.Primitive{{Indices: gltf.Index(0), Material: gltf.Index(0), Mode: gltf.PrimitiveTriangles, Attributes: gltf.PrimitiveAttributes{gltf.POSITION: 1, gltf.COLOR_0: 3, gltf.NORMAL: 2, gltf.TEXCOORD_0: 4}}}}},
 		Nodes: []*gltf.Node{
-			{Name: "RootNode", Children: []uint32{1, 2, 3}},
+			{Name: "RootNode", Children: []int{1, 2, 3}},
 			{Name: "Mesh"},
 			{Name: "Cube", Mesh: gltf.Index(0)},
 			{Name: "Texture Group"},
 		},
 		Samplers: []*gltf.Sampler{{WrapS: gltf.WrapRepeat, WrapT: gltf.WrapRepeat}},
 		Scene:    gltf.Index(0),
-		Scenes:   []*gltf.Scene{{Name: "Root Scene", Nodes: []uint32{0}}},
+		Scenes:   []*gltf.Scene{{Name: "Root Scene", Nodes: []int{0}}},
 	}
 	if err := gltf.SaveBinary(doc, "./example.glb"); err != nil {
 		panic(err)
diff --git a/gltf_test.go b/gltf_test.go
index 030fa73..836db1d 100644
--- a/gltf_test.go
+++ b/gltf_test.go
@@ -303,7 +303,7 @@ func TestSizeOfElement(t *testing.T) {
 	tests := []struct {
 		name string
 		args args
-		want uint32
+		want int
 	}{
 		{"byte-vec2", args{ComponentByte, AccessorVec2}, 4},
 		{"ubyte-vec2", args{ComponentUbyte, AccessorVec2}, 4},
diff --git a/modeler/example_test.go b/modeler/example_test.go
index f50c198..a9c7253 100644
--- a/modeler/example_test.go
+++ b/modeler/example_test.go
@@ -50,7 +50,7 @@ func ExampleWriteImage() {
 		Name: "Texture",
 		PBRMetallicRoughness: &gltf.PBRMetallicRoughness{
 			BaseColorTexture: &gltf.TextureInfo{
-				Index: uint32(len(doc.Textures) - 1),
+				Index: len(doc.Textures) - 1,
 			},
 			MetallicFactor: gltf.Float(0),
 		},
@@ -64,7 +64,7 @@ func ExampleWriteImage() {
 					gltf.POSITION:   positionAccessor,
 					gltf.TEXCOORD_0: textureAccessor,
 				},
-				Material: gltf.Index(uint32(len(doc.Materials) - 1)),
+				Material: gltf.Index(len(doc.Materials) - 1),
 			},
 		},
 	}}
diff --git a/modeler/read_test.go b/modeler/read_test.go
index 3d50830..fc39554 100644
--- a/modeler/read_test.go
+++ b/modeler/read_test.go
@@ -17,10 +17,10 @@ func TestReadColor64_ReuseBuffer(t *testing.T) {
 	}
 	doc := &gltf.Document{
 		BufferViews: []*gltf.BufferView{
-			{Buffer: 0, ByteLength: uint32(len(data))},
+			{Buffer: 0, ByteLength: len(data)},
 		},
 		Buffers: []*gltf.Buffer{
-			{Data: data, ByteLength: uint32(len(data))},
+			{Data: data, ByteLength: len(data)},
 		},
 	}
 	var buf [][4]uint16
@@ -264,10 +264,10 @@ func TestReadIndices(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadIndices(doc, tt.args.acr, tt.args.buffer)
@@ -311,10 +311,10 @@ func TestReadNormal(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadNormal(doc, tt.args.acr, tt.args.buffer)
@@ -358,10 +358,10 @@ func TestReadTangent(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadTangent(doc, tt.args.acr, tt.args.buffer)
@@ -411,10 +411,10 @@ func TestReadTextureCoord(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadTextureCoord(doc, tt.args.acr, tt.args.buffer)
@@ -464,10 +464,10 @@ func TestReadWeights(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadWeights(doc, tt.args.acr, tt.args.buffer)
@@ -511,10 +511,10 @@ func TestReadJoints(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadJoints(doc, tt.args.acr, tt.args.buffer)
@@ -558,10 +558,10 @@ func TestReadPosition(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadPosition(doc, tt.args.acr, tt.args.buffer)
@@ -617,10 +617,10 @@ func TestReadColor(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadColor(doc, tt.args.acr, tt.args.buffer)
@@ -676,10 +676,10 @@ func TestReadColor64(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			doc := &gltf.Document{
 				BufferViews: []*gltf.BufferView{
-					{Buffer: 0, ByteLength: uint32(len(tt.args.data))},
+					{Buffer: 0, ByteLength: len(tt.args.data)},
 				},
 				Buffers: []*gltf.Buffer{
-					{Data: tt.args.data, ByteLength: uint32(len(tt.args.data))},
+					{Data: tt.args.data, ByteLength: len(tt.args.data)},
 				},
 			}
 			got, err := ReadColor64(doc, tt.args.acr, tt.args.buffer)
diff --git a/modeler/write_test.go b/modeler/write_test.go
index 527f71f..c7e9775 100644
--- a/modeler/write_test.go
+++ b/modeler/write_test.go
@@ -55,7 +55,7 @@ func TestWriteAttributesInterleaved(t *testing.T) {
 	if len(doc.Accessors) != 10 {
 		t.Errorf("TestWriteAttributesInterleaved() accessors size = %v, want 10", len(doc.Accessors))
 	}
-	want := map[string]uint32{
+	want := map[string]int{
 		gltf.POSITION:   0,
 		gltf.NORMAL:     1,
 		gltf.TANGENT:    2,
@@ -210,7 +210,7 @@ func TestWriteNormal(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"base", &gltf.Document{
@@ -252,7 +252,7 @@ func TestWriteTangent(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"base", &gltf.Document{
@@ -294,7 +294,7 @@ func TestWritePosition(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"base", &gltf.Document{
@@ -336,7 +336,7 @@ func TestWriteJoints(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"uint8", &gltf.Document{
@@ -393,7 +393,7 @@ func TestWriteWeights(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"uint8", &gltf.Document{
@@ -465,7 +465,7 @@ func TestWriteTextureCoord(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"uint8", &gltf.Document{
@@ -537,7 +537,7 @@ func TestWriteIndices(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"uint16", &gltf.Document{
@@ -594,7 +594,7 @@ func TestWriteColor(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 	}{
 		{"uint8", &gltf.Document{
@@ -667,7 +667,7 @@ func TestWriteImage(t *testing.T) {
 		name    string
 		m       *gltf.Document
 		args    args
-		want    uint32
+		want    int
 		wantDoc *gltf.Document
 		wantErr bool
 	}{