loader.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  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. vbo := gls.NewVBO()
  236. // Array of primitive materials
  237. type matGroup struct {
  238. imat material.IMaterial
  239. start int
  240. count int
  241. }
  242. grMats := make([]matGroup, 0)
  243. // Process mesh primitives
  244. var mode int = -1
  245. var err error
  246. m := g.Meshes[mi]
  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.AddAttribEx("VertexPosition", 3, 0, uint32(len(vbuf)*int(gls.FloatSize)))
  296. vbuf = append(vbuf, ppos...)
  297. continue
  298. }
  299. if name == "NORMAL" {
  300. pnorms, err := g.loadVec3(aci)
  301. if err != nil {
  302. return nil, err
  303. }
  304. vbo.AddAttribEx("VertexNormal", 3, 0, uint32(len(vbuf)*int(gls.FloatSize)))
  305. vbuf = append(vbuf, pnorms...)
  306. continue
  307. }
  308. if name == "TEXCOORD_0" {
  309. puvs, err := g.loadVec2(aci)
  310. if err != nil {
  311. return nil, err
  312. }
  313. vbo.AddAttribEx("VertexTexcoord", 2, 0, uint32(len(vbuf)*int(gls.FloatSize)))
  314. vbuf = append(vbuf, puvs...)
  315. continue
  316. }
  317. }
  318. }
  319. // Creates Geometry and add attribute VBO
  320. geom := geometry.NewGeometry()
  321. if len(indices) > 0 {
  322. geom.SetIndices(indices)
  323. }
  324. if len(vbuf) > 0 {
  325. vbo.SetBuffer(vbuf)
  326. geom.AddVBO(vbo)
  327. }
  328. //log.Error("positions:%v", positions)
  329. //log.Error("indices..:%v", indices)
  330. //log.Error("normals..:%v", normals)
  331. //log.Error("uvs0.....:%v", uvs0)
  332. log.Error("VBUF size in number of floats:%v", len(vbuf))
  333. // Create Mesh
  334. if mode == TRIANGLES {
  335. node := graphic.NewMesh(geom, nil)
  336. for i := 0; i < len(grMats); i++ {
  337. grm := grMats[i]
  338. node.AddMaterial(grm.imat, grm.start, grm.count)
  339. }
  340. return node, nil
  341. }
  342. // Create Lines
  343. if mode == LINES {
  344. node := graphic.NewLines(geom, grMats[0].imat)
  345. return node, nil
  346. }
  347. // Create LineStrip
  348. if mode == LINE_STRIP {
  349. node := graphic.NewLineStrip(geom, grMats[0].imat)
  350. return node, nil
  351. }
  352. // Create Points
  353. if mode == POINTS {
  354. node := graphic.NewPoints(geom, grMats[0].imat)
  355. return node, nil
  356. }
  357. return nil, fmt.Errorf("Unsupported primitive:%v", mode)
  358. }
  359. func (g *GLTF) newDefaultMaterial() material.IMaterial {
  360. return material.NewStandard(&math32.Color{0.5, 0.5, 0.5})
  361. }
  362. // loadMaterials loads the material specified by the material index
  363. func (g *GLTF) loadMaterial(mi int) (material.IMaterial, error) {
  364. mat := g.Materials[mi]
  365. // Checks for material extensions
  366. if mat.Extensions != nil {
  367. for ext, v := range mat.Extensions {
  368. if ext == "KHR_materials_common" {
  369. return g.loadMaterialCommon(v)
  370. } else {
  371. return nil, fmt.Errorf("Unsupported extension:%s", ext)
  372. }
  373. }
  374. return nil, fmt.Errorf("Empty material extensions")
  375. // Material should be PBR
  376. } else {
  377. return g.loadMaterialPBR(&mat)
  378. }
  379. }
  380. // loadTextureInfo loads the texture specified by the TextureInfo pointer
  381. func (g *GLTF) loadTextureInfo(ti *TextureInfo) (*texture.Texture2D, error) {
  382. return g.loadTexture(ti.Index)
  383. }
  384. // loadTexture loads the texture specified by its index
  385. func (g *GLTF) loadTexture(texi int) (*texture.Texture2D, error) {
  386. // loads texture image
  387. texDesc := g.Textures[texi]
  388. img, err := g.loadImage(texDesc.Source)
  389. if err != nil {
  390. return nil, err
  391. }
  392. tex := texture.NewTexture2DFromRGBA(img)
  393. // Get sampler and apply texture parameters
  394. samp := g.Samplers[texDesc.Sampler]
  395. // Magnification filter
  396. magFilter := gls.NEAREST
  397. if samp.MagFilter != nil {
  398. magFilter = *samp.MagFilter
  399. }
  400. tex.SetMagFilter(uint32(magFilter))
  401. // Minification filter
  402. minFilter := gls.NEAREST
  403. if samp.MinFilter != nil {
  404. minFilter = *samp.MinFilter
  405. }
  406. tex.SetMinFilter(uint32(minFilter))
  407. // S coordinate wrapping mode
  408. wrapS := gls.REPEAT
  409. if samp.WrapS != nil {
  410. wrapS = *samp.WrapS
  411. }
  412. tex.SetWrapS(uint32(wrapS))
  413. // T coordinate wrapping mode
  414. wrapT := gls.REPEAT
  415. if samp.WrapT != nil {
  416. wrapT = *samp.WrapT
  417. }
  418. tex.SetWrapT(uint32(wrapT))
  419. return tex, nil
  420. }
  421. // loadImage loads the image specified by the index of GLTF.Images
  422. // Image can be loaded from binary chunk file or data URI or external file.
  423. func (g *GLTF) loadImage(ii int) (*image.RGBA, error) {
  424. log.Error("loadImage:%v", ii)
  425. imgDesc := g.Images[ii]
  426. var data []byte
  427. var err error
  428. // If Uri is empty, load image from GLB binary chunk
  429. if imgDesc.Uri == "" {
  430. bvi := imgDesc.BufferView
  431. if bvi == nil {
  432. return nil, fmt.Errorf("Image has empty URI and no BufferView")
  433. }
  434. bv := g.BufferViews[*bvi]
  435. offset := 0
  436. if bv.ByteOffset != nil {
  437. offset = *bv.ByteOffset
  438. }
  439. data = g.data[offset : offset+bv.ByteLength]
  440. // Checks if image URI is data URL
  441. } else if isDataURL(imgDesc.Uri) {
  442. data, err = loadDataURL(imgDesc.Uri)
  443. if err != nil {
  444. return nil, err
  445. }
  446. // Load image data from file
  447. } else {
  448. fpath := filepath.Join(g.path, imgDesc.Uri)
  449. f, err := os.Open(fpath)
  450. if err != nil {
  451. return nil, err
  452. }
  453. defer f.Close()
  454. data, err = ioutil.ReadAll(f)
  455. if err != nil {
  456. return nil, err
  457. }
  458. }
  459. // Decodes image data
  460. bb := bytes.NewBuffer(data)
  461. img, _, err := image.Decode(bb)
  462. if err != nil {
  463. return nil, err
  464. }
  465. // Converts image to RGBA format
  466. rgba := image.NewRGBA(img.Bounds())
  467. if rgba.Stride != rgba.Rect.Size().X*4 {
  468. return nil, fmt.Errorf("unsupported stride")
  469. }
  470. draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)
  471. return rgba, nil
  472. }
  473. // loadVec3 load array of float32 values from the specified accessor index.
  474. // The acesssor must have type of VEC3 and component type of FLOAT
  475. func (g *GLTF) loadVec3(ai int) (math32.ArrayF32, error) {
  476. // Get Accessor for the specified index
  477. ac := g.Accessors[ai]
  478. if ac.BufferView == nil {
  479. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  480. }
  481. // Checks acessor ComponentType
  482. if ac.ComponentType != FLOAT {
  483. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  484. }
  485. // Checks acessor Type
  486. if ac.Type != VEC3 {
  487. return nil, fmt.Errorf("Accessor.ComponentType != VEC3 NOT SUPPORTED")
  488. }
  489. // Loads data from associated BufferView
  490. data, err := g.loadBufferView(*ac.BufferView)
  491. if err != nil {
  492. return nil, err
  493. }
  494. // Accessor offset into BufferView
  495. offset := 0
  496. if ac.ByteOffset != nil {
  497. offset = *ac.ByteOffset
  498. }
  499. data = data[offset:]
  500. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*3]
  501. return math32.ArrayF32(arr), nil
  502. }
  503. // loadVec2 load array of Vector2 from the specified accessor index
  504. func (g *GLTF) loadVec2(ai int) (math32.ArrayF32, error) {
  505. // Get Accessor for the specified index
  506. ac := g.Accessors[ai]
  507. if ac.BufferView == nil {
  508. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  509. }
  510. // Checks acessor ComponentType
  511. if ac.ComponentType != FLOAT {
  512. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  513. }
  514. // Checks acessor Type
  515. if ac.Type != VEC2 {
  516. return nil, fmt.Errorf("Accessor.ComponentType != VEC2 NOT SUPPORTED")
  517. }
  518. // Loads data from associated BufferView
  519. data, err := g.loadBufferView(*ac.BufferView)
  520. if err != nil {
  521. return nil, err
  522. }
  523. // Accessor offset into BufferView
  524. offset := 0
  525. if ac.ByteOffset != nil {
  526. offset = *ac.ByteOffset
  527. }
  528. data = data[offset:]
  529. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*2]
  530. return math32.ArrayF32(arr), nil
  531. }
  532. // loadIndices load the indices array specified by the Accessor index.
  533. func (g *GLTF) loadIndices(ai int) (math32.ArrayU32, error) {
  534. // Get Accessor for the specified index
  535. ac := g.Accessors[ai]
  536. if ac.BufferView == nil {
  537. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED YET")
  538. }
  539. // Loads indices data from associated BufferView
  540. data, err := g.loadBufferView(*ac.BufferView)
  541. if err != nil {
  542. return nil, err
  543. }
  544. // Accessor offset into BufferView
  545. offset := 0
  546. if ac.ByteOffset != nil {
  547. offset = *ac.ByteOffset
  548. }
  549. data = data[offset:]
  550. // If index component is UNSIGNED_INT nothing to do
  551. if ac.ComponentType == UNSIGNED_INT {
  552. arr := (*[1 << 30]uint32)(unsafe.Pointer(&data[0]))[:ac.Count]
  553. return math32.ArrayU32(arr), nil
  554. }
  555. // Converts UNSIGNED_SHORT indices to UNSIGNED_INT
  556. if ac.ComponentType == UNSIGNED_SHORT {
  557. indices := math32.NewArrayU32(ac.Count, ac.Count)
  558. for i := 0; i < ac.Count; i++ {
  559. indices[i] = uint32(data[i*2]) + uint32(data[i*2+1])*256
  560. }
  561. return indices, nil
  562. }
  563. // Converts UNSIGNED_BYTE indices to UNSIGNED_INT
  564. if ac.ComponentType == UNSIGNED_BYTE {
  565. indices := math32.NewArrayU32(ac.Count, ac.Count)
  566. for i := 0; i < ac.Count; i++ {
  567. indices[i] = uint32(data[i])
  568. }
  569. return indices, nil
  570. }
  571. return nil, fmt.Errorf("Unsupported Accessor ComponentType:%v", ac.ComponentType)
  572. }
  573. // isInterleaves checks if the BufferView used by the specified Accessor index is
  574. // interleaved or not
  575. func (g *GLTF) isInterleaved(aci int) bool {
  576. // Get the Accessor's BufferView
  577. accessor := g.Accessors[aci]
  578. if accessor.BufferView == nil {
  579. return false
  580. }
  581. bv := g.BufferViews[*accessor.BufferView]
  582. // Calculates the size in bytes of a complete attribute
  583. itemSize := TypeSizes[accessor.Type]
  584. itemBytes := int(gls.FloatSize) * itemSize
  585. // If the BufferView stride is equal to the item size, the buffer is not interleaved
  586. if bv.ByteStride == nil {
  587. return false
  588. }
  589. if *bv.ByteStride == itemBytes {
  590. return false
  591. }
  592. return true
  593. }
  594. // loadBufferView loads and returns a byte slice with data from the specified
  595. // BufferView index
  596. func (g *GLTF) loadBufferView(bvi int) ([]byte, error) {
  597. bv := g.BufferViews[bvi]
  598. buf, err := g.loadBuffer(bv.Buffer)
  599. if err != nil {
  600. return nil, err
  601. }
  602. offset := 0
  603. if bv.ByteOffset != nil {
  604. offset = *bv.ByteOffset
  605. }
  606. return buf[offset : offset+bv.ByteLength], nil
  607. }
  608. // loadBuffer loads and returns the data from the specified GLTF Buffer index
  609. func (g *GLTF) loadBuffer(bi int) ([]byte, error) {
  610. buf := &g.Buffers[bi]
  611. // If Buffer URI uses the chunk data field
  612. if buf.Uri == "" {
  613. return g.data, nil
  614. }
  615. // If buffer already loaded:
  616. log.Error("loadBuffer cache:%v", len(buf.data))
  617. if len(buf.data) > 0 {
  618. return buf.data, nil
  619. }
  620. // Checks if buffer URI is a data URI
  621. var data []byte
  622. var err error
  623. if isDataURL(buf.Uri) {
  624. data, err = loadDataURL(buf.Uri)
  625. if err != nil {
  626. return nil, err
  627. }
  628. // Loads external buffer file
  629. } else {
  630. log.Error("loadBuffer: loading file")
  631. // Try to load buffer from file
  632. fpath := filepath.Join(g.path, buf.Uri)
  633. f, err := os.Open(fpath)
  634. if err != nil {
  635. return nil, err
  636. }
  637. defer f.Close()
  638. data, err = ioutil.ReadAll(f)
  639. if err != nil {
  640. return nil, err
  641. }
  642. }
  643. // Checks data length
  644. if len(data) != buf.ByteLength {
  645. return nil, fmt.Errorf("Buffer:%d read data length:%d expected:%d", bi, len(data), buf.ByteLength)
  646. }
  647. // Cache buffer data
  648. buf.data = data
  649. log.Error("cache data:%v", len(buf.data))
  650. return data, nil
  651. }
  652. // dataURL describes a decoded data url string
  653. type dataURL struct {
  654. MediaType string
  655. Encoding string
  656. Data string
  657. }
  658. const (
  659. dataURLprefix = "data:"
  660. mimeBIN = "application/octet-stream"
  661. mimePNG = "image/png"
  662. mimeJPEG = "image/jpeg"
  663. )
  664. var validMediaTypes = []string{mimeBIN, mimePNG, mimeJPEG}
  665. // isDataURL checks if the specified string has the prefix of data URL
  666. func isDataURL(url string) bool {
  667. if strings.HasPrefix(url, dataURLprefix) {
  668. return true
  669. }
  670. return false
  671. }
  672. // loadDataURL decodes the specified data URI string (base64)
  673. func loadDataURL(url string) ([]byte, error) {
  674. var du dataURL
  675. err := parseDataURL(url, &du)
  676. if err != nil {
  677. return nil, err
  678. }
  679. // Checks for valid media type
  680. found := false
  681. for i := 0; i < len(validMediaTypes); i++ {
  682. if validMediaTypes[i] == du.MediaType {
  683. found = true
  684. break
  685. }
  686. }
  687. if !found {
  688. return nil, fmt.Errorf("Data URI media type:%s not supported", du.MediaType)
  689. }
  690. // Checks encoding
  691. if du.Encoding != "base64" {
  692. return nil, fmt.Errorf("Data URI encoding:%s not supported", du.Encoding)
  693. }
  694. // Decodes data from BASE64
  695. data, err := base64.StdEncoding.DecodeString(du.Data)
  696. if err != nil {
  697. return nil, err
  698. }
  699. return data, nil
  700. }
  701. // parseDataURL tries to parse the specified string as a data URL with the format:
  702. // data:[<mediatype>][;base64],<data>
  703. // and if successfull returns true and updates the specified pointer with the parsed fields.
  704. func parseDataURL(url string, du *dataURL) error {
  705. // Checks prefix
  706. if !isDataURL(url) {
  707. return fmt.Errorf("Specified string is not a data URL")
  708. }
  709. // Separates header from data
  710. body := url[len(dataURLprefix):]
  711. parts := strings.Split(body, ",")
  712. if len(parts) != 2 {
  713. return fmt.Errorf("Data URI contains more than one ','")
  714. }
  715. du.Data = parts[1]
  716. // Separates media type from optional encoding
  717. res := strings.Split(parts[0], ";")
  718. du.MediaType = res[0]
  719. if len(res) < 2 {
  720. return nil
  721. }
  722. if len(res) >= 2 {
  723. du.Encoding = res[1]
  724. }
  725. return nil
  726. }