Package github.com/matjam/bunyip/gltf
gltf
Package gltf loads glTF 2.0 models (.gltf with external or embedded buffers, and .glb) into plain Go slices: positions, normals, UVs, vertex colours, joints and weights, indices, materials with their textures and the KHR extensions the renderer supports (clearcoat, sheen, transmission, volume, IOR, emissive strength, texture transforms, specular, iridescence, anisotropy and converted specular-glossiness), decoded images, morph targets with their default weights, skins, animation clips (node transforms and morph weights) and the flattened node hierarchy with world matrices. Sparse accessors, which store only the elements a morph target moves, decode over the base data or over zeros when the accessor has no buffer view.
Load reads a file, Parse a byte slice; both return a Document. The package has no GPU dependency, so a tool or a server can read models too; gfx.LoadModel uploads a Document into meshes and materials, and phys can take a mesh's triangles as a static collider. Parse errors identify the invalid buffer, accessor, image, node or scene. Hierarchies are validated before resources are resolved: cycles, repeated children, multiple parents and invalid references are rejected. Scene roots must have no parent and be unique within each scene; the same root may be reused across scenes. Validation and flattening take linear work in the hierarchy size and support deep trees without a depth cutoff.
Index
- type AlphaMode
- type Animation
- type Channel
- type ChannelPath
- type Document
- type Instance
- type Material
- type Mesh
- type MorphTarget
- type Node
- type Primitive
- type Resolver
- type Skin
Types
type Animation source
type Animation struct {
Name string
Duration float32 // final channel key time in seconds
Channels []Channel
}
Animation is a named clip of node channels.
type Channel source
type Channel struct {
Node int
Path ChannelPath
Times []float32 // key times in seconds
Values []lin.Vec4 // xyz for translation and scale, xyzw for rotation; nil for weights
// Weights holds a PathWeights channel's keys: one weight per morph
// target for each time, in time order.
Weights []float32
Step bool // STEP interpolation; otherwise linear (cubic falls back to linear)
}
Channel is one animated node property with keyframes.
WeightCount source
func (c *Channel) WeightCount() int
WeightCount is the number of morph target weights per key of a PathWeights channel; zero for other paths.
type ChannelPath source
type ChannelPath uint8
ChannelPath says which node property a channel animates.
type Document source
type Document struct {
Meshes []Mesh
Materials []Material
Images []image.Image
Instances []Instance // every mesh placement in the default scene, flattened
Nodes []Node // the node hierarchy, for animation
Skins []Skin
Animations []Animation
}
Document is a decoded model.
Load source
func Load(path string) (*Document, error)
Load reads a .gltf or .glb file, resolving relative URIs next to it.
Load parses .gltf and .glb files without touching the GPU; gfx.LoadModel
uploads the result.
Example
package main
import (
"fmt"
"github.com/matjam/bunyip/gltf"
)
func main() {
doc, err := gltf.Load("robot.glb")
if err != nil {
return
}
fmt.Println(len(doc.Meshes), "meshes,", len(doc.Animations), "animation clips")
}
Parse source
func Parse(data []byte, resolve Resolver) (*Document, error)
Parse decodes .gltf JSON or a .glb container from memory. resolve may be nil when every buffer and image is embedded. Invalid buffer bounds and animation accessor shapes or key counts return an error. The hierarchy must be a forest with unique children and valid child, scene-root and default-scene indices. Malformed hierarchies return errors before resolving external resources.
Bounds source
func (d *Document) Bounds() (lo, hi lin.Vec3)
Bounds returns the axis-aligned box around every placed primitive.
IsDataImage source
func (d *Document) IsDataImage(i int) bool
IsDataImage reports whether any material uses image i as non-colour data, such as normals, metallic-roughness or extension factor maps. Pass a valid index into Images. An image reused for both colour and data is classified as data; separate images avoid that ambiguity.
type Instance source
type Instance struct {
Name string
Mesh int
Node int // node index, for animation
Skin int // -1 when not skinned
World lin.Mat4
}
Instance places a mesh in the world.
type Material source
type Material struct {
Name string
BaseColor [4]float32 // linear RGBA factor
Image int // albedo image index into Document.Images, or -1
Linear bool // sampler asks for linear filtering
Metallic float32 // factor; default 1
Roughness float32 // factor; default 1
MetalRoughImage int // G roughness, B metallic; -1 none
NormalImage int // -1 none
EmissiveImage int // -1 none
Emissive [3]float32
OcclusionImage int // R occlusion; -1 none
OcclusionStrength float32 // default 1
AlphaMode AlphaMode
AlphaCutoff float32 // for AlphaMask; default 0.5
DoubleSided bool
Unlit bool // KHR_materials_unlit: draw the base colour without lighting
OcclusionUV2 bool // the occlusion texture uses TEXCOORD_1
// UVOffset, UVRotation and UVScale are the base colour texture's
// KHR_texture_transform; Scale is 1,1 without one.
UVOffset [2]float32
UVRotation float32
UVScale [2]float32
Clearcoat float32 // KHR_materials_clearcoat factor
ClearcoatRoughness float32 // default 0
SheenColor [3]float32 // KHR_materials_sheen; zero for none
SheenRoughness float32
Transmission float32 // KHR_materials_transmission factor; zero for opaque
TransmissionImage int // R scales the factor; -1 none
IOR float32 // KHR_materials_ior; default 1.5
Thickness float32 // KHR_materials_volume thickness factor
ThicknessImage int // G scales the thickness, as glTF stores it; -1 none
AttenuationDistance float32 // zero for no absorption
AttenuationColor [3]float32 // default white
// Specular is KHR_materials_specular: SpecularFactor scales a
// dielectric's reflection (default 1) and SpecularColor tints it
// (default white). SpecularImage holds the strength in its alpha and
// SpecularColorImage the tint in its RGB; each is -1 when the file
// gives none.
SpecularFactor float32
SpecularColor [3]float32
SpecularImage int
SpecularColorImage int
// Iridescence is KHR_materials_iridescence, a thin film over the
// surface: IridescenceFactor is its strength (default 0),
// IridescenceIOR its index of refraction (default 1.3) and the film
// is between IridescenceThicknessMin and IridescenceThicknessMax
// nanometres thick (defaults 100 and 400). IridescenceImage scales
// the strength by its red channel and IridescenceThicknessImage
// places the thickness between the two by its green channel; each is
// -1 when the file gives none.
IridescenceFactor float32
IridescenceIOR float32
IridescenceThicknessMin float32
IridescenceThicknessMax float32
IridescenceImage int
IridescenceThicknessImage int
// Anisotropy is KHR_materials_anisotropy, a highlight stretched along
// the surface: AnisotropyStrength is how far (default 0) and
// AnisotropyRotation which way, in radians. AnisotropyImage holds a
// direction in red and green and a strength in blue, or -1.
AnisotropyStrength float32
AnisotropyRotation float32
AnisotropyImage int
// SpecGloss reports that the material came from
// KHR_materials_pbrSpecularGlossiness, which the loader converts to
// metallic-roughness: the factors above are the converted ones.
// SpecGlossImage is the extension's specular-glossiness image, whose
// alpha is the glossiness, or -1; the renderer turns it into a
// metallic-roughness map. Its RGB, the specular colour per texel, is
// not used, so a file whose specular colour varies across one
// material loads with the converted factors alone.
SpecGloss bool
SpecGlossImage int
// Glossiness is the extension's glossiness factor, which scales the
// image's alpha; 1 without the extension.
Glossiness float32
}
Material is a decoded metallic-roughness material. Defaults below are supplied by Parse for omitted file properties, not by the Go zero value. Image references index Document.Images; -1 means no image. A hand-built material must set unused image references to -1 explicitly.
type Mesh source
type Mesh struct {
Name string
Primitives []Primitive
// Weights are the default morph target weights, one per target; nil
// means every target at zero.
Weights []float32
// TargetNames names the morph targets when the file carries them in
// the mesh's extras; nil otherwise.
TargetNames []string
}
Mesh is one glTF mesh: a set of primitives drawn together.
TargetCount source
func (m *Mesh) TargetCount() int
TargetCount is the number of morph targets, from the first primitive.
type MorphTarget source
type MorphTarget struct {
Positions []lin.Vec3 // one per vertex
Normals []lin.Vec3 // nil when the target has none
}
MorphTarget is one blend shape of a primitive: offsets added to each vertex's position, and to its normal when the target has normals, scaled by the target's weight.
type Node source
type Node struct {
Name string
Parent int // -1 for a root
Children []int // indices into Document.Nodes
Translation lin.Vec3 // relative to Parent, in model units
Rotation lin.Quat // local rotation; Parse supplies identity when omitted
Scale lin.Vec3 // local scale; Parse supplies (1, 1, 1) when omitted
Mesh int // -1 none
Skin int // -1 none
// Weights are the node's own morph target weights, overriding the
// mesh's defaults; nil means the mesh's.
Weights []float32
}
Node is one node of the hierarchy with its rest-pose local transform.
type Primitive source
type Primitive struct {
Positions []lin.Vec3
Normals []lin.Vec3 // computed from the triangles when the file has none
UVs []lin.Vec2 // zero-filled when the file has none
Indices []uint32
Material int // index into Document.Materials, or -1
Joints [][4]uint8 // per vertex, when skinned
Weights [][4]float32
Colors []lin.Vec4 // COLOR_0, linear RGBA; nil when the file has none
UVs2 []lin.Vec2 // TEXCOORD_1; nil when the file has none
Targets []MorphTarget
}
Primitive is a triangle list with one material.
type Resolver source
type Resolver func(uri string) ([]byte, error)
Resolver fetches the bytes behind a relative URI in a .gltf file.
type Skin source
type Skin struct {
Name string
Joints []int // Document.Nodes indices, addressed by vertex joint indices
InverseBind []lin.Mat4 // inverse bind matrix for each entry in Joints
}
Skin binds joints (node indices) with their inverse bind matrices.
Source files
accessor.go doc.go example_test.go extensions_test.go fuzz_test.go gltf_test.go hierarchy.go hierarchy_validation_test.go images_test.go json.go load.go load_bench_test.go morph_test.go review_test.go sparse_test.go validation_regression_test.go