loader.go 20 KB

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