{"id":13413185,"url":"https://github.com/qmuntal/gltf","last_synced_at":"2025-05-16T03:05:23.800Z","repository":{"id":41055499,"uuid":"165896210","full_name":"qmuntal/gltf","owner":"qmuntal","description":"Go library for encoding glTF 2.0 files","archived":false,"fork":false,"pushed_at":"2024-11-12T10:36:41.000Z","size":4717,"stargazers_count":256,"open_issues_count":3,"forks_count":32,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-19T04:33:29.230Z","etag":null,"topics":["3d","gltf","go","golang","webgl"],"latest_commit_sha":null,"homepage":"https://www.khronos.org/gltf/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qmuntal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"qmuntal"}},"created_at":"2019-01-15T17:43:54.000Z","updated_at":"2025-04-16T12:41:59.000Z","dependencies_parsed_at":"2024-06-18T13:45:09.893Z","dependency_job_id":"b5d131f6-1e64-4120-86ef-4067e3da28d1","html_url":"https://github.com/qmuntal/gltf","commit_stats":null,"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qmuntal%2Fgltf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qmuntal%2Fgltf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qmuntal%2Fgltf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qmuntal%2Fgltf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qmuntal","download_url":"https://codeload.github.com/qmuntal/gltf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254459088,"owners_count":22074605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","gltf","go","golang","webgl"],"created_at":"2024-07-30T20:01:34.660Z","updated_at":"2025-05-16T03:05:18.790Z","avatar_url":"https://github.com/qmuntal.png","language":"Go","funding_links":["https://github.com/sponsors/qmuntal"],"categories":["Relational Databases","Images","Go","3D / Math","Images 图像处理","图片"],"sub_categories":["Search and Analytic Databases","Advanced Console UIs","SQL 查询语句构建库","检索及分析资料库"],"readme":"# gltf [![PkgGoDev](https://pkg.go.dev/badge/github.com/qmuntal/gltf)](https://pkg.go.dev/github.com/qmuntal/gltf) [![Test](https://github.com/qmuntal/gltf/actions/workflows/test.yml/badge.svg)](https://github.com/qmuntal/gltf/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/qmuntal/gltf/badge.svg?branch=master)](https://coveralls.io/github/qmuntal/gltf?branch=master) [![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go)\n\n\u003cdiv align=\"center\"\u003e\n    \u003cp\u003eA Go module for efficient and robust serialization/deserialization of glTF 2.0, a royalty-free specification for the efficient transmission and loading of 3D scenes and models by applications, also known as \"the JPEG of 3D\".\u003c/p\u003e\n    \u003cp align=\"center\"\u003e\n        \u003ca href=\"#star-main-features\"\u003eMain Features\u003c/a\u003e ❘\n        \u003ca href=\"#scroll-getting-started\"\u003eGetting Started\u003c/a\u003e ❘\n        \u003ca href=\"#raising_hand-contributing\"\u003eContributing\u003c/a\u003e ❘\n        \u003ca href=\"#about-the-project\"\u003eAbout The Project\u003c/a\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg width=\"640\" src=\"./assets/gopher_high.png\" alt=\"Gopher glTF\"\u003e\u003c/p\u003e\n\n## :star: Main Features\n\n- [gltf.Document](https://pkg.go.dev/github.com/qmuntal/gltf#Document): Idiomatic glTF data model\n- [gltf.Open](https://pkg.go.dev/github.com/qmuntal/gltf#Open) / [gltf.Save](https://pkg.go.dev/github.com/qmuntal/gltf#Save): `.glTF` and `.glb` [d]encoding support\n- [qmuntal/gltf/ext](https://pkg.go.dev/github.com/qmuntal/gltf/ext): Built-in extensability mechanism with principal extensions provided out of the box\n- [qmuntal/gltf/modeler](https://pkg.go.dev/github.com/qmuntal/gltf/modeler): Friendly package to read and write accessors and buffer views\n- [qmuntal/gltf/binary](https://pkg.go.dev/github.com/qmuntal/gltf/binary): Friendly and efficient package to read and write bytes from buffers\n\n## :scroll: Getting started\n\n### Data Model\n\n`qmuntal/gltf` implements the whole glTF 2.0 specification. The top level element is the [gltf.Document](https://pkg.go.dev/github.com/qmuntal/gltf#Document) and it contains all the information to hold a gltf document in memory:\n\n```go\n// This document does not produce any valid glTF, it is just an example.\ngltf.Document{\n  Accessors: []*gltf.Accessor{\n      {BufferView: gltf.Index(0), ComponentType: gltf.ComponentUshort, Type: gltf.AccessorScalar},\n  },\n  Asset: gltf.Asset{Version: \"2.0\", Generator: \"qmuntal/gltf\"},\n  BufferViews: []*gltf.BufferView{\n      {ByteLength: 72, ByteOffset: 0, Target: gltf.TargetElementArrayBuffer},\n  },\n  Buffers: []*gltf.Buffer{{ByteLength: 1033, URI: bufferData}},\n  Meshes: []*gltf.Mesh{{\n    Name: \"Cube\",\n  }},\n  Nodes: []*gltf.Node{{Name: \"Cube\", Mesh: gltf.Index(0)}},\n  Scene:    gltf.Index(0),\n  Scenes:   []*gltf.Scene{{Name: \"Root Scene\", Nodes: []int{0}}},\n}\n```\n\n### Optional parameters\n\nAll optional properties whose default value does not match with the golang type zero value are defines as pointers. Take the following guidelines into account when working with optional values:\n\n- It is safe to not define them when writing the glTF if the desired value is the default one.\n- It is safe to expect that the optional values are not nil when reading a glTF.\n- When assigning values to optional properties it may be helpful to use these utility functions:\n  - `gltf.Index(1)`\n  - `gltf.Float(0.5)`\n\n### Reading a document\n\nA [gltf.Document](https://pkg.go.dev/github.com/qmuntal/gltf#Document) can be decoded from any `io.Reader` by using [gltf.Decoder](https://pkg.go.dev/github.com/qmuntal/gltf#Decoder):\n\n```go\nresp, _ := http.Get(\"https://example.com/static/foo.gltf\")\nvar doc gltf.Document\ngltf.NewDecoder(resp.Body).Decode(\u0026doc)\nfmt.Print(doc.Asset)\n```\n\nWhen working with the file system it is more convenient to use [gltf.Open](https://pkg.go.dev/github.com/qmuntal/gltf#Open) as it automatically manages relative external buffers:\n\n```go\ndoc, _ := gltf.Open(\"./foo.gltf\")\nfmt.Print(doc.Asset)\n```\n\nIn both cases the decoder will automatically detect if the file is JSON/ASCII (gltf) or Binary (glb) based on its content.\n\n### Writing a document\n\nA [gltf.Document](https://pkg.go.dev/github.com/qmuntal/gltf#Document) can be encoded to any `io.Writer` by using [gltf.Encoder](https://pkg.go.dev/github.com/qmuntal/gltf#Encoder):\n\n```go\nvar buf bytes.Buffer\ngltf.NewEncoder(\u0026buf).Encode(\u0026doc)\nhttp.Post(\"http://example.com/upload\", \"model/gltf+binary\", \u0026buf)\n```\n\nBy default `gltf.NewEncoder` outputs a binary file, to generate a JSON/ASCII file set `AsBinary` to false:\n\n```go\nvar buf bytes.Buffer\nenc := gltf.NewEncoder(\u0026buf)\nenc.AsBinary = false\nenc.Encode(\u0026doc)\nhttp.Post(\"http://example.com/upload\", \"model/gltf+json\", \u0026buf)\n```\n\nWhen working with the file system it is more convenient to use [gltf.Save](https://pkg.go.dev/github.com/qmuntal/gltf#Save) and [gltf.SaveBinary](https://pkg.go.dev/github.com/qmuntal/gltf#SaveBinary) as it automatically manages relative external buffers:\n\n```go\ngltf.Save(\u0026doc, \"./foo.gltf\")\ngltf.SaveBinary(\u0026doc, \"./foo.glb\")\n```\n\n### Manipulating buffer views and accessors\n\nThe package [gltf/modeler](https://pkg.go.dev/github.com/qmuntal/gltf/modeler) defines a friendly API to read and write accessors and buffer views, abstracting away all the byte manipulation work and the idiosyncrasy of the glTF spec.\n\nThe following example creates a single colored triangle:\n\n![screenshot](./assets/color-triangle.png)\n\n```go\ndoc := gltf.NewDocument()\ndoc.Meshes = []*gltf.Mesh{{\n    Name: \"Pyramid\",\n    Primitives: []*gltf.Primitive{{\n        Indices: gltf.Index(modeler.WriteIndices(doc, []uint16{0, 1, 2})),\n        Attributes: gltf.PrimitiveAttributes{\n          gltf.POSITION: modeler.WritePosition(doc, [][3]float32{{0, 0, 0}, {0, 10, 0}, {0, 0, 10}}),\n          gltf.COLOR_0:  modeler.WriteColor(doc, [][3]uint8{{255, 0, 0}, {0, 255, 0}, {0, 0, 255}}),\n        },\n    }},\n}}\ndoc.Nodes = []*gltf.Node{{Name: \"Pyramid\", Mesh: gltf.Index(0)}}\ndoc.Scenes[0].Nodes = append(doc.Scenes[0].Nodes, 0)\ngltf.Save(doc, \"./test.gltf\")\n```\n\n### Data interleaving\n\nThe data of the attributes that are stored in a single bufferView may be stored as an Array-Of-Structures, which may produce a rendering perfomance boost in static attributes. `qmuntal/gltf/modeler` facilitates the creation of interleaved accessors and buffer views with the methods [WritePrimitiveAttributes](https://pkg.go.dev/github.com/qmuntal/gltf/modeler#WritePrimitiveAttributes), [WriteAccessorsInterleaved](https://pkg.go.dev/github.com/qmuntal/gltf/modeler#WriteAccessorsInterleaved), and [WriteBufferViewInterleaved](https://pkg.go.dev/github.com/qmuntal/gltf/modeler#WriteBufferViewInterleaved) being the first one the most recommended for creating mesh primitives:\n\n```go\ndoc := gltf.NewDocument()\nattrs, _ := modeler.WritePrimitiveAttributes(doc,\n    modeler.PrimitiveAttribute{Name: gltf.POSITION, Data: [][3]float32{{0, 0, 0}, {0, 10, 0}, {0, 0, 10}}},\n    modeler.PrimitiveAttribute{Name: gltf.COLOR_0, Data: [][3]uint8{{255, 0, 0}, {0, 255, 0}, {0, 0, 255}}},\n)\ndoc.Meshes = []*gltf.Mesh{{\n    Name: \"Pyramid\",\n    Primitives: []*gltf.Primitive{{\n        Indices: gltf.Index(modeler.WriteIndices(doc, []uint16{0, 1, 2})),\n        Attributes: attrs,\n    }},\n}}\ndoc.Nodes = []*gltf.Node{{Name: \"Pyramid\", Mesh: gltf.Index(0)}}\ndoc.Scenes[0].Nodes = append(doc.Scenes[0].Nodes, 0)\ngltf.Save(doc, \"./test.gltf\")\n```\n\n### Manipulating bytes\n\nThe package [gltf/binary](https://pkg.go.dev/github.com/qmuntal/gltf/binary) defines a friendly and efficient API to read and write bytes from buffers, abstracting away all the byte manipulation work. This package is very low level and normal users should use `gltf/modeler` instead as it provides another level of abstraction that understands how bytes are associated to other entities.\n\nThis package is very similary to the Go `binary` package, the main differences are that it is highly specialized in glTF data types and that it only have to deal with little endian encoding.\n\n### Dealing with extensions\n\n`qmuntal/gltf` is designed to support dynamic extensions. By default only the core specification is decoded and the data inside the extensions objects are stored as `json.RawMessage` so they can be decoded by the caller or automatically encoded when saving the document.\n\nSome of the official extensions are implemented under [ext](ext/).\n\nTo decode one of the supported extensions the only required action is to import the associated package, this way the extension will not be stored as `json.RawMessage` but as the type defined in the extension package:\n\n```go\nimport (\n  \"github.com/qmuntal/gltf\"\n  \"github.com/qmuntal/gltf/ext/lightspunctual\"\n)\n\nfunc main() {\n  doc, _ := gltf.Open(\"./foo.gltf\")\n    if v, ok := doc.Extensions[lightspunctual.ExtensionName]; ok {\n        for _, l := range v.(lightspunctual.Lights) {\n            fmt.Print(l.Type)\n        }\n    }\n}\n```\n\nIt is not necessary to call `gltf.RegisterExtension` for built-in extensions, as these auto-register themselves when the package is initialized.\n\n#### External extension\n\nThis list is the list of known extensions implemented in other modules:\n\n- [draco-go/gltf/draco](https://github.com/qmuntal/draco-go)\n\n#### Custom extensions\n\nTo implement a custom extension encoding, provide a `struct` that can be encoded as a JSON object as dictated by the spec.\n\nTo implement a custom extension decoding, call [gltf.RegisterExtension](https://pkg.go.dev/github.com/qmuntal/gltf#RegisterExtension) at least once before decoding, providing the identifier of the extension and a function that decodes the JSON bytes to the desired `struct`:\n\n```go\nconst ExtensionName = \"FAKE_Extension\"\n\ntype Foo struct {\n    BufferView int          `json:\"bufferView\"`\n    Attributes gltf.Attributes  `json:\"attributes\"`\n}\n\nfunc init() {\n    gltf.RegisterExtension(ExtensionName, Unmarshal)\n}\n\nfunc Unmarshal(data []byte) (any, error) {\n    foo := new(Foo)\n    err := json.Unmarshal(data, foo)\n    return foo, err\n}\n```\n\n## :raising_hand: Contributing\n\nPRs, issues, and feedback from ninja gophers are very welcomed.\n\n## About The Project\n\nThis library is a complete implementation of glTF 2.0, and its explicit aim is to provide a production-ready, idiomatic and curated API to perform any kind of glTF manipulation.\n\nIt is out of the scope to implement convertes to/from other file formats and to provide mechanisms to create and manipulate 3D geometry.\n\nThe current API is still not frozen and can suffer minor changes until it reached v1.0.\n\nPlease use the issue tracker or the if you'd like to report problems or discuss features.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqmuntal%2Fgltf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqmuntal%2Fgltf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqmuntal%2Fgltf/lists"}