loader.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gltf
  5. import (
  6. "bytes"
  7. "encoding/base64"
  8. "encoding/binary"
  9. "encoding/json"
  10. "fmt"
  11. "image"
  12. "image/draw"
  13. "io"
  14. "io/ioutil"
  15. "os"
  16. "path/filepath"
  17. "strings"
  18. "unsafe"
  19. "github.com/g3n/engine/camera"
  20. "github.com/g3n/engine/core"
  21. "github.com/g3n/engine/geometry"
  22. "github.com/g3n/engine/gls"
  23. "github.com/g3n/engine/graphic"
  24. "github.com/g3n/engine/material"
  25. "github.com/g3n/engine/math32"
  26. "github.com/g3n/engine/texture"
  27. )
  28. // ParseJSON parses the glTF data from the specified JSON file
  29. // and returns a pointer to the parsed structure.
  30. func ParseJSON(filename string) (*GLTF, error) {
  31. // Open file
  32. f, err := os.Open(filename)
  33. if err != nil {
  34. return nil, err
  35. }
  36. // Extract path from file
  37. path := filepath.Dir(filename)
  38. defer f.Close()
  39. return ParseJSONReader(f, path)
  40. }
  41. // ParseJSONReader parses the glTF JSON data from the specified reader
  42. // and returns a pointer to the parsed structure
  43. func ParseJSONReader(r io.Reader, path string) (*GLTF, error) {
  44. g := new(GLTF)
  45. g.path = path
  46. dec := json.NewDecoder(r)
  47. err := dec.Decode(g)
  48. if err != nil {
  49. return nil, err
  50. }
  51. return g, nil
  52. }
  53. // ParseBin parses the glTF data from the specified binary file
  54. // and returns a pointer to the parsed structure.
  55. func ParseBin(filename string) (*GLTF, error) {
  56. // Open file
  57. f, err := os.Open(filename)
  58. if err != nil {
  59. return nil, err
  60. }
  61. // Extract path from file
  62. path := filepath.Dir(filename)
  63. defer f.Close()
  64. return ParseBinReader(f, path)
  65. }
  66. // ParseBinReader parses the glTF data from the specified binary reader
  67. // and returns a pointer to the parsed structure
  68. func ParseBinReader(r io.Reader, path string) (*GLTF, error) {
  69. // Reads header
  70. var header GLBHeader
  71. err := binary.Read(r, binary.LittleEndian, &header)
  72. if err != nil {
  73. return nil, err
  74. }
  75. // Checks magic and version
  76. if header.Magic != GLBMagic {
  77. return nil, fmt.Errorf("Invalid GLB Magic field")
  78. }
  79. if header.Version < 2 {
  80. return nil, fmt.Errorf("GLB version:%v not supported", header.Version)
  81. }
  82. // Read first chunk (JSON)
  83. buf, err := readChunk(r, GLBJson)
  84. if err != nil {
  85. return nil, err
  86. }
  87. // Parse JSON into gltf object
  88. bb := bytes.NewBuffer(buf)
  89. gltf, err := ParseJSONReader(bb, path)
  90. if err != nil {
  91. return nil, err
  92. }
  93. // Check for and read second chunk (binary, optional)
  94. data, err := readChunk(r, GLBBin)
  95. if err != nil {
  96. return nil, err
  97. }
  98. gltf.data = data
  99. return gltf, nil
  100. }
  101. // readChunk reads a GLB chunk with the specified type and returns the data in a byte array.
  102. func readChunk(r io.Reader, chunkType uint32) ([]byte, error) {
  103. // Read chunk header
  104. var chunk GLBChunk
  105. err := binary.Read(r, binary.LittleEndian, &chunk)
  106. if err != nil {
  107. if err == io.EOF {
  108. return nil, nil
  109. }
  110. return nil, err
  111. }
  112. // Check chunk type
  113. if chunk.Type != chunkType {
  114. return nil, fmt.Errorf("expected GLB chunk type [%v] but obtained chunk type [%v]", chunkType, chunk.Type)
  115. }
  116. // Read chunk data
  117. data := make([]byte, chunk.Length)
  118. err = binary.Read(r, binary.LittleEndian, &data)
  119. if err != nil {
  120. return nil, err
  121. }
  122. return data, nil
  123. }
  124. // NewScene creates a parent Node which contains all nodes contained by
  125. // the specified scene index from the GLTF Scenes array
  126. func (g *GLTF) NewScene(si int) (core.INode, error) {
  127. // Check if provided scene index is valid
  128. if si < 0 || si >= len(g.Scenes) {
  129. return nil, fmt.Errorf("invalid scene index")
  130. }
  131. s := g.Scenes[si]
  132. scene := core.NewNode()
  133. scene.SetName(s.Name)
  134. for i := 0; i < len(s.Nodes); i++ {
  135. child, err := g.NewNode(i)
  136. if err != nil {
  137. return nil, err
  138. }
  139. scene.Add(child)
  140. }
  141. return scene, nil
  142. }
  143. // NewNode creates and returns a new Node described by the specified index
  144. // in the decoded GLTF Nodes array.
  145. func (g *GLTF) NewNode(i int) (core.INode, error) {
  146. var in core.INode
  147. var err error
  148. node := g.Nodes[i]
  149. // Check if the node is a Mesh (triangles, lines, etc...)
  150. if node.Mesh != nil {
  151. in, err = g.loadMesh(*node.Mesh)
  152. if err != nil {
  153. return nil, err
  154. }
  155. // Check if the node is Camera
  156. } else if node.Camera != nil {
  157. in, err = g.loadCamera(*node.Camera)
  158. if err != nil {
  159. return nil, err
  160. }
  161. // Other cases, return empty node
  162. } else {
  163. in = core.NewNode()
  164. }
  165. // Get *core.Node from core.INode
  166. n := in.GetNode()
  167. n.SetName(node.Name)
  168. // If defined, set node local transformation matrix
  169. if node.Matrix != nil {
  170. n.SetMatrix((*math32.Matrix4)(node.Matrix))
  171. // Otherwise, check rotation, scale and translation fields
  172. } else {
  173. // Rotation quaternion
  174. if node.Rotation != nil {
  175. log.Error("Rotation:%v", node.Translation)
  176. n.SetQuaternion(node.Rotation[0], node.Rotation[1], node.Rotation[2], node.Rotation[3])
  177. }
  178. // Scale
  179. if node.Scale != nil {
  180. log.Error("Scale:%v", node.Translation)
  181. n.SetScale(node.Scale[0], node.Scale[1], node.Scale[2])
  182. }
  183. // Translation
  184. if node.Translation != nil {
  185. log.Error("Translation:%v", node.Translation)
  186. n.SetPosition(node.Translation[0], node.Translation[1], node.Translation[2])
  187. }
  188. }
  189. // Recursively load node children and add them to the parent
  190. for _, ci := range node.Children {
  191. child, err := g.NewNode(ci)
  192. if err != nil {
  193. return nil, err
  194. }
  195. n.Add(child)
  196. }
  197. return in, nil
  198. }
  199. // loadCamera creates and returns a Camera Node
  200. // from the specified GLTF.Cameras index
  201. func (g *GLTF) loadCamera(ci int) (core.INode, error) {
  202. camDesc := g.Cameras[ci]
  203. if camDesc.Type == "perspective" {
  204. desc := camDesc.Perspective
  205. fov := 360 * (desc.Yfov) / 2 * math32.Pi
  206. aspect := float32(2) // TODO how to get the current aspect ratio of the viewport from here ?
  207. if desc.AspectRatio != nil {
  208. aspect = *desc.AspectRatio
  209. }
  210. far := float32(2E6)
  211. if desc.Zfar != nil {
  212. far = *desc.Zfar
  213. }
  214. cam := camera.NewPerspective(fov, aspect, desc.Znear, far)
  215. return cam, nil
  216. }
  217. if camDesc.Type == "orthographic" {
  218. desc := camDesc.Orthographic
  219. cam := camera.NewOrthographic(desc.Xmag/-2, desc.Xmag/2, desc.Ymag/2, desc.Ymag/-2, desc.Znear, desc.Zfar)
  220. return cam, nil
  221. }
  222. return nil, fmt.Errorf("unsupported camera type: %s", camDesc.Type)
  223. }
  224. // loadMesh creates and returns a Graphic Node (graphic.Mesh, graphic.Lines, graphic.Points, etc)
  225. // from the specified GLTF Mesh index
  226. func (g *GLTF) loadMesh(mi int) (core.INode, error) {
  227. var err error
  228. m := g.Meshes[mi]
  229. // Create container node
  230. meshNode := core.NewNode()
  231. for i := 0; i < len(m.Primitives); i++ {
  232. // Get primitive information
  233. p := m.Primitives[i]
  234. // Indexed Geometry
  235. indices := math32.NewArrayU32(0, 0)
  236. if p.Indices != nil {
  237. pidx, err := g.loadIndices(*p.Indices)
  238. if err != nil {
  239. return nil, err
  240. }
  241. indices = append(indices, pidx...)
  242. } else {
  243. // Non-indexed primitive
  244. // indices array stay empty
  245. }
  246. // Load primitive material
  247. var grMat material.IMaterial
  248. if p.Material != nil {
  249. grMat, err = g.loadMaterial(*p.Material)
  250. if err != nil {
  251. return nil, err
  252. }
  253. } else {
  254. grMat = g.newDefaultMaterial()
  255. }
  256. // Create geometry
  257. geom := geometry.NewGeometry()
  258. // Load primitive attributes
  259. for name, aci := range p.Attributes {
  260. // TODO
  261. //interleaved := g.isInterleaved(aci)
  262. //if interleaved {
  263. // buf, err := g.loadBufferView(*g.Accessors[aci].BufferView)
  264. // if err != nil {
  265. // return nil, err
  266. // }
  267. //}
  268. if name == "POSITION" {
  269. ppos, err := g.loadVec3(aci)
  270. if err != nil {
  271. return nil, err
  272. }
  273. vbo := gls.NewVBO()
  274. vbo.AddAttrib("VertexPosition", 3)
  275. vbo.SetBuffer(ppos)
  276. geom.AddVBO(vbo)
  277. continue
  278. }
  279. if name == "NORMAL" {
  280. pnorms, err := g.loadVec3(aci)
  281. if err != nil {
  282. return nil, err
  283. }
  284. vbo := gls.NewVBO()
  285. vbo.AddAttrib("VertexNormal", 3)
  286. vbo.SetBuffer(pnorms)
  287. geom.AddVBO(vbo)
  288. continue
  289. }
  290. if name == "TEXCOORD_0" {
  291. puvs, err := g.loadVec2(aci)
  292. if err != nil {
  293. return nil, err
  294. }
  295. vbo := gls.NewVBO()
  296. vbo.AddAttrib("VertexTexcoord", 2)
  297. vbo.SetBuffer(puvs)
  298. geom.AddVBO(vbo)
  299. continue
  300. }
  301. }
  302. // Creates Geometry and add attribute VBO
  303. if len(indices) > 0 {
  304. geom.SetIndices(indices)
  305. }
  306. //log.Error("positions:%v", positions)
  307. //log.Error("indices..:%v", indices)
  308. //log.Error("normals..:%v", normals)
  309. //log.Error("uvs0.....:%v", uvs0)
  310. //log.Error("VBUF size in number of floats:%v", len(vbuf))
  311. // Default mode is 4 (TRIANGLES)
  312. mode := TRIANGLES
  313. if p.Mode != nil {
  314. mode = *p.Mode
  315. }
  316. // Create Mesh
  317. if mode == TRIANGLES {
  318. primitiveMesh := graphic.NewMesh(geom, nil)
  319. primitiveMesh.AddMaterial(grMat, 0, 0)
  320. meshNode.Add(primitiveMesh)
  321. }
  322. // Create Lines
  323. if mode == LINES {
  324. primitiveMesh := graphic.NewLines(geom, grMat)
  325. meshNode.Add(primitiveMesh)
  326. }
  327. // Create LineStrip
  328. if mode == LINE_STRIP {
  329. primitiveMesh := graphic.NewLineStrip(geom, grMat)
  330. meshNode.Add(primitiveMesh)
  331. }
  332. // Create Points
  333. if mode == POINTS {
  334. primitiveMesh := graphic.NewPoints(geom, grMat)
  335. meshNode.Add(primitiveMesh)
  336. }
  337. // TODO error when primitive is unsupported
  338. // fmt.Errorf("Unsupported primitive:%v", mode)
  339. }
  340. return meshNode, nil
  341. }
  342. func (g *GLTF) newDefaultMaterial() material.IMaterial {
  343. return material.NewStandard(&math32.Color{0.5, 0.5, 0.5})
  344. }
  345. // loadMaterials loads the material specified by the material index
  346. func (g *GLTF) loadMaterial(mi int) (material.IMaterial, error) {
  347. mat := g.Materials[mi]
  348. // Checks for material extensions
  349. if mat.Extensions != nil {
  350. for ext, v := range mat.Extensions {
  351. if ext == "KHR_materials_common" {
  352. return g.loadMaterialCommon(v)
  353. } else {
  354. return nil, fmt.Errorf("Unsupported extension:%s", ext)
  355. }
  356. }
  357. return nil, fmt.Errorf("Empty material extensions")
  358. // Material should be PBR
  359. } else {
  360. return g.loadMaterialPBR(&mat)
  361. }
  362. }
  363. // loadTextureInfo loads the texture specified by the TextureInfo pointer
  364. func (g *GLTF) loadTextureInfo(ti *TextureInfo) (*texture.Texture2D, error) {
  365. return g.loadTexture(ti.Index)
  366. }
  367. // loadTexture loads the texture specified by its index
  368. func (g *GLTF) loadTexture(texi int) (*texture.Texture2D, error) {
  369. // loads texture image
  370. texDesc := g.Textures[texi]
  371. img, err := g.loadImage(texDesc.Source)
  372. if err != nil {
  373. return nil, err
  374. }
  375. tex := texture.NewTexture2DFromRGBA(img)
  376. // Get sampler and apply texture parameters
  377. samp := g.Samplers[texDesc.Sampler]
  378. // Magnification filter
  379. magFilter := gls.NEAREST
  380. if samp.MagFilter != nil {
  381. magFilter = *samp.MagFilter
  382. }
  383. tex.SetMagFilter(uint32(magFilter))
  384. // Minification filter
  385. minFilter := gls.NEAREST
  386. if samp.MinFilter != nil {
  387. minFilter = *samp.MinFilter
  388. }
  389. tex.SetMinFilter(uint32(minFilter))
  390. // S coordinate wrapping mode
  391. wrapS := gls.REPEAT
  392. if samp.WrapS != nil {
  393. wrapS = *samp.WrapS
  394. }
  395. tex.SetWrapS(uint32(wrapS))
  396. // T coordinate wrapping mode
  397. wrapT := gls.REPEAT
  398. if samp.WrapT != nil {
  399. wrapT = *samp.WrapT
  400. }
  401. tex.SetWrapT(uint32(wrapT))
  402. return tex, nil
  403. }
  404. // loadImage loads the image specified by the index of GLTF.Images
  405. // Image can be loaded from binary chunk file or data URI or external file.
  406. func (g *GLTF) loadImage(ii int) (*image.RGBA, error) {
  407. log.Error("loadImage:%v", ii)
  408. imgDesc := g.Images[ii]
  409. var data []byte
  410. var err error
  411. // If Uri is empty, load image from GLB binary chunk
  412. if imgDesc.Uri == "" {
  413. bvi := imgDesc.BufferView
  414. if bvi == nil {
  415. return nil, fmt.Errorf("Image has empty URI and no BufferView")
  416. }
  417. bv := g.BufferViews[*bvi]
  418. offset := 0
  419. if bv.ByteOffset != nil {
  420. offset = *bv.ByteOffset
  421. }
  422. data = g.data[offset : offset+bv.ByteLength]
  423. // Checks if image URI is data URL
  424. } else if isDataURL(imgDesc.Uri) {
  425. data, err = loadDataURL(imgDesc.Uri)
  426. if err != nil {
  427. return nil, err
  428. }
  429. // Load image data from file
  430. } else {
  431. fpath := filepath.Join(g.path, imgDesc.Uri)
  432. f, err := os.Open(fpath)
  433. if err != nil {
  434. return nil, err
  435. }
  436. defer f.Close()
  437. data, err = ioutil.ReadAll(f)
  438. if err != nil {
  439. return nil, err
  440. }
  441. }
  442. // Decodes image data
  443. bb := bytes.NewBuffer(data)
  444. img, _, err := image.Decode(bb)
  445. if err != nil {
  446. return nil, err
  447. }
  448. // Converts image to RGBA format
  449. rgba := image.NewRGBA(img.Bounds())
  450. if rgba.Stride != rgba.Rect.Size().X*4 {
  451. return nil, fmt.Errorf("unsupported stride")
  452. }
  453. draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)
  454. return rgba, nil
  455. }
  456. // loadVec3 load array of float32 values from the specified accessor index.
  457. // The acesssor must have type of VEC3 and component type of FLOAT
  458. func (g *GLTF) loadVec3(ai int) (math32.ArrayF32, error) {
  459. // Get Accessor for the specified index
  460. ac := g.Accessors[ai]
  461. if ac.BufferView == nil {
  462. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  463. }
  464. // Checks acessor ComponentType
  465. if ac.ComponentType != FLOAT {
  466. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  467. }
  468. // Checks acessor Type
  469. if ac.Type != VEC3 {
  470. return nil, fmt.Errorf("Accessor.ComponentType != VEC3 NOT SUPPORTED")
  471. }
  472. // Loads data from associated BufferView
  473. data, err := g.loadBufferView(*ac.BufferView)
  474. if err != nil {
  475. return nil, err
  476. }
  477. // Accessor offset into BufferView
  478. offset := 0
  479. if ac.ByteOffset != nil {
  480. offset = *ac.ByteOffset
  481. }
  482. data = data[offset:]
  483. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*3]
  484. return math32.ArrayF32(arr), nil
  485. }
  486. // loadVec2 load array of Vector2 from the specified accessor index
  487. func (g *GLTF) loadVec2(ai int) (math32.ArrayF32, error) {
  488. // Get Accessor for the specified index
  489. ac := g.Accessors[ai]
  490. if ac.BufferView == nil {
  491. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  492. }
  493. // Checks acessor ComponentType
  494. if ac.ComponentType != FLOAT {
  495. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  496. }
  497. // Checks acessor Type
  498. if ac.Type != VEC2 {
  499. return nil, fmt.Errorf("Accessor.ComponentType != VEC2 NOT SUPPORTED")
  500. }
  501. // Loads data from associated BufferView
  502. data, err := g.loadBufferView(*ac.BufferView)
  503. if err != nil {
  504. return nil, err
  505. }
  506. // Accessor offset into BufferView
  507. offset := 0
  508. if ac.ByteOffset != nil {
  509. offset = *ac.ByteOffset
  510. }
  511. data = data[offset:]
  512. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*2]
  513. return math32.ArrayF32(arr), nil
  514. }
  515. // loadIndices load the indices array specified by the Accessor index.
  516. func (g *GLTF) loadIndices(ai int) (math32.ArrayU32, error) {
  517. // Get Accessor for the specified index
  518. ac := g.Accessors[ai]
  519. if ac.BufferView == nil {
  520. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED YET")
  521. }
  522. // Loads indices data from associated BufferView
  523. data, err := g.loadBufferView(*ac.BufferView)
  524. if err != nil {
  525. return nil, err
  526. }
  527. // Accessor offset into BufferView
  528. offset := 0
  529. if ac.ByteOffset != nil {
  530. offset = *ac.ByteOffset
  531. }
  532. data = data[offset:]
  533. // If index component is UNSIGNED_INT nothing to do
  534. if ac.ComponentType == UNSIGNED_INT {
  535. arr := (*[1 << 30]uint32)(unsafe.Pointer(&data[0]))[:ac.Count]
  536. return math32.ArrayU32(arr), nil
  537. }
  538. // Converts UNSIGNED_SHORT indices to UNSIGNED_INT
  539. if ac.ComponentType == UNSIGNED_SHORT {
  540. indices := math32.NewArrayU32(ac.Count, ac.Count)
  541. for i := 0; i < ac.Count; i++ {
  542. indices[i] = uint32(data[i*2]) + uint32(data[i*2+1])*256
  543. }
  544. return indices, nil
  545. }
  546. // Converts UNSIGNED_BYTE indices to UNSIGNED_INT
  547. if ac.ComponentType == UNSIGNED_BYTE {
  548. indices := math32.NewArrayU32(ac.Count, ac.Count)
  549. for i := 0; i < ac.Count; i++ {
  550. indices[i] = uint32(data[i])
  551. }
  552. return indices, nil
  553. }
  554. return nil, fmt.Errorf("Unsupported Accessor ComponentType:%v", ac.ComponentType)
  555. }
  556. // isInterleaves checks if the BufferView used by the specified Accessor index is
  557. // interleaved or not
  558. func (g *GLTF) isInterleaved(aci int) bool {
  559. // Get the Accessor's BufferView
  560. accessor := g.Accessors[aci]
  561. if accessor.BufferView == nil {
  562. return false
  563. }
  564. bv := g.BufferViews[*accessor.BufferView]
  565. // Calculates the size in bytes of a complete attribute
  566. itemSize := TypeSizes[accessor.Type]
  567. itemBytes := int(gls.FloatSize) * itemSize
  568. // If the BufferView stride is equal to the item size, the buffer is not interleaved
  569. if bv.ByteStride == nil {
  570. return false
  571. }
  572. if *bv.ByteStride == itemBytes {
  573. return false
  574. }
  575. return true
  576. }
  577. // loadBufferView loads and returns a byte slice with data from the specified
  578. // BufferView index
  579. func (g *GLTF) loadBufferView(bvi int) ([]byte, error) {
  580. bv := g.BufferViews[bvi]
  581. buf, err := g.loadBuffer(bv.Buffer)
  582. if err != nil {
  583. return nil, err
  584. }
  585. offset := 0
  586. if bv.ByteOffset != nil {
  587. offset = *bv.ByteOffset
  588. }
  589. return buf[offset : offset+bv.ByteLength], nil
  590. }
  591. // loadBuffer loads and returns the data from the specified GLTF Buffer index
  592. func (g *GLTF) loadBuffer(bi int) ([]byte, error) {
  593. buf := &g.Buffers[bi]
  594. // If Buffer URI uses the chunk data field
  595. if buf.Uri == "" {
  596. return g.data, nil
  597. }
  598. // If buffer already loaded:
  599. log.Error("loadBuffer cache:%v", len(buf.data))
  600. if len(buf.data) > 0 {
  601. return buf.data, nil
  602. }
  603. // Checks if buffer URI is a data URI
  604. var data []byte
  605. var err error
  606. if isDataURL(buf.Uri) {
  607. data, err = loadDataURL(buf.Uri)
  608. if err != nil {
  609. return nil, err
  610. }
  611. // Loads external buffer file
  612. } else {
  613. log.Error("loadBuffer: loading file")
  614. // Try to load buffer from file
  615. fpath := filepath.Join(g.path, buf.Uri)
  616. f, err := os.Open(fpath)
  617. if err != nil {
  618. return nil, err
  619. }
  620. defer f.Close()
  621. data, err = ioutil.ReadAll(f)
  622. if err != nil {
  623. return nil, err
  624. }
  625. }
  626. // Checks data length
  627. if len(data) != buf.ByteLength {
  628. return nil, fmt.Errorf("Buffer:%d read data length:%d expected:%d", bi, len(data), buf.ByteLength)
  629. }
  630. // Cache buffer data
  631. buf.data = data
  632. log.Error("cache data:%v", len(buf.data))
  633. return data, nil
  634. }
  635. // dataURL describes a decoded data url string
  636. type dataURL struct {
  637. MediaType string
  638. Encoding string
  639. Data string
  640. }
  641. const (
  642. dataURLprefix = "data:"
  643. mimeBIN = "application/octet-stream"
  644. mimePNG = "image/png"
  645. mimeJPEG = "image/jpeg"
  646. )
  647. var validMediaTypes = []string{mimeBIN, mimePNG, mimeJPEG}
  648. // isDataURL checks if the specified string has the prefix of data URL
  649. func isDataURL(url string) bool {
  650. if strings.HasPrefix(url, dataURLprefix) {
  651. return true
  652. }
  653. return false
  654. }
  655. // loadDataURL decodes the specified data URI string (base64)
  656. func loadDataURL(url string) ([]byte, error) {
  657. var du dataURL
  658. err := parseDataURL(url, &du)
  659. if err != nil {
  660. return nil, err
  661. }
  662. // Checks for valid media type
  663. found := false
  664. for i := 0; i < len(validMediaTypes); i++ {
  665. if validMediaTypes[i] == du.MediaType {
  666. found = true
  667. break
  668. }
  669. }
  670. if !found {
  671. return nil, fmt.Errorf("Data URI media type:%s not supported", du.MediaType)
  672. }
  673. // Checks encoding
  674. if du.Encoding != "base64" {
  675. return nil, fmt.Errorf("Data URI encoding:%s not supported", du.Encoding)
  676. }
  677. // Decodes data from BASE64
  678. data, err := base64.StdEncoding.DecodeString(du.Data)
  679. if err != nil {
  680. return nil, err
  681. }
  682. return data, nil
  683. }
  684. // parseDataURL tries to parse the specified string as a data URL with the format:
  685. // data:[<mediatype>][;base64],<data>
  686. // and if successfull returns true and updates the specified pointer with the parsed fields.
  687. func parseDataURL(url string, du *dataURL) error {
  688. // Checks prefix
  689. if !isDataURL(url) {
  690. return fmt.Errorf("Specified string is not a data URL")
  691. }
  692. // Separates header from data
  693. body := url[len(dataURLprefix):]
  694. parts := strings.Split(body, ",")
  695. if len(parts) != 2 {
  696. return fmt.Errorf("Data URI contains more than one ','")
  697. }
  698. du.Data = parts[1]
  699. // Separates media type from optional encoding
  700. res := strings.Split(parts[0], ";")
  701. du.MediaType = res[0]
  702. if len(res) < 2 {
  703. return nil
  704. }
  705. if len(res) >= 2 {
  706. du.Encoding = res[1]
  707. }
  708. return nil
  709. }