loader.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  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. log.Error("loadTexture:%+v", ti)
  383. // loads texture image
  384. texDesc := g.Textures[ti.Index]
  385. img, err := g.loadImage(texDesc.Source)
  386. if err != nil {
  387. return nil, err
  388. }
  389. tex := texture.NewTexture2DFromRGBA(img)
  390. // Get sampler and apply texture parameters
  391. samp := g.Samplers[texDesc.Sampler]
  392. // Magnification filter
  393. magFilter := gls.NEAREST
  394. if samp.MagFilter != nil {
  395. magFilter = *samp.MagFilter
  396. }
  397. tex.SetMagFilter(uint32(magFilter))
  398. // Minification filter
  399. minFilter := gls.NEAREST
  400. if samp.MinFilter != nil {
  401. minFilter = *samp.MinFilter
  402. }
  403. tex.SetMinFilter(uint32(minFilter))
  404. // S coordinate wrapping mode
  405. wrapS := gls.REPEAT
  406. if samp.WrapS != nil {
  407. wrapS = *samp.WrapS
  408. }
  409. tex.SetWrapS(uint32(wrapS))
  410. // T coordinate wrapping mode
  411. wrapT := gls.REPEAT
  412. if samp.WrapT != nil {
  413. wrapT = *samp.WrapT
  414. }
  415. tex.SetWrapT(uint32(wrapT))
  416. return tex, nil
  417. }
  418. // loadImage loads the image specified by the index of GLTF.Images
  419. // Image can be loaded from binary chunk file or data URI or external file.
  420. func (g *GLTF) loadImage(ii int) (*image.RGBA, error) {
  421. log.Error("loadImage:%v", ii)
  422. imgDesc := g.Images[ii]
  423. var data []byte
  424. var err error
  425. // If Uri is empty, load image from GLB binary chunk
  426. if imgDesc.Uri == "" {
  427. bvi := imgDesc.BufferView
  428. if bvi == nil {
  429. return nil, fmt.Errorf("Image has empty URI and no BufferView")
  430. }
  431. bv := g.BufferViews[*bvi]
  432. offset := 0
  433. if bv.ByteOffset != nil {
  434. offset = *bv.ByteOffset
  435. }
  436. data = g.data[offset : offset+bv.ByteLength]
  437. // Checks if image URI is data URL
  438. } else if isDataURL(imgDesc.Uri) {
  439. data, err = loadDataURL(imgDesc.Uri)
  440. if err != nil {
  441. return nil, err
  442. }
  443. // Load image data from file
  444. } else {
  445. fpath := filepath.Join(g.path, imgDesc.Uri)
  446. f, err := os.Open(fpath)
  447. if err != nil {
  448. return nil, err
  449. }
  450. defer f.Close()
  451. data, err = ioutil.ReadAll(f)
  452. if err != nil {
  453. return nil, err
  454. }
  455. }
  456. // Decodes image data
  457. bb := bytes.NewBuffer(data)
  458. img, _, err := image.Decode(bb)
  459. if err != nil {
  460. return nil, err
  461. }
  462. // Converts image to RGBA format
  463. rgba := image.NewRGBA(img.Bounds())
  464. if rgba.Stride != rgba.Rect.Size().X*4 {
  465. return nil, fmt.Errorf("unsupported stride")
  466. }
  467. draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)
  468. return rgba, nil
  469. }
  470. // loadVec3 load array of float32 values from the specified accessor index.
  471. // The acesssor must have type of VEC3 and component type of FLOAT
  472. func (g *GLTF) loadVec3(ai int) (math32.ArrayF32, error) {
  473. // Get Accessor for the specified index
  474. ac := g.Accessors[ai]
  475. if ac.BufferView == nil {
  476. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  477. }
  478. // Checks acessor ComponentType
  479. if ac.ComponentType != FLOAT {
  480. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  481. }
  482. // Checks acessor Type
  483. if ac.Type != VEC3 {
  484. return nil, fmt.Errorf("Accessor.ComponentType != VEC3 NOT SUPPORTED")
  485. }
  486. // Loads data from associated BufferView
  487. data, err := g.loadBufferView(*ac.BufferView)
  488. if err != nil {
  489. return nil, err
  490. }
  491. // Accessor offset into BufferView
  492. offset := 0
  493. if ac.ByteOffset != nil {
  494. offset = *ac.ByteOffset
  495. }
  496. data = data[offset:]
  497. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*3]
  498. return math32.ArrayF32(arr), nil
  499. }
  500. // loadVec2 load array of Vector2 from the specified accessor index
  501. func (g *GLTF) loadVec2(ai int) (math32.ArrayF32, error) {
  502. // Get Accessor for the specified index
  503. ac := g.Accessors[ai]
  504. if ac.BufferView == nil {
  505. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED")
  506. }
  507. // Checks acessor ComponentType
  508. if ac.ComponentType != FLOAT {
  509. return nil, fmt.Errorf("Accessor.ComponentType != FLOAT NOT SUPPORTED")
  510. }
  511. // Checks acessor Type
  512. if ac.Type != VEC2 {
  513. return nil, fmt.Errorf("Accessor.ComponentType != VEC2 NOT SUPPORTED")
  514. }
  515. // Loads data from associated BufferView
  516. data, err := g.loadBufferView(*ac.BufferView)
  517. if err != nil {
  518. return nil, err
  519. }
  520. // Accessor offset into BufferView
  521. offset := 0
  522. if ac.ByteOffset != nil {
  523. offset = *ac.ByteOffset
  524. }
  525. data = data[offset:]
  526. arr := (*[1 << 30]float32)(unsafe.Pointer(&data[0]))[:ac.Count*2]
  527. return math32.ArrayF32(arr), nil
  528. }
  529. // loadIndices load the indices array specified by the Accessor index.
  530. func (g *GLTF) loadIndices(ai int) (math32.ArrayU32, error) {
  531. // Get Accessor for the specified index
  532. ac := g.Accessors[ai]
  533. if ac.BufferView == nil {
  534. return nil, fmt.Errorf("Accessor.BufferView == nil NOT SUPPORTED YET")
  535. }
  536. // Loads indices data from associated BufferView
  537. data, err := g.loadBufferView(*ac.BufferView)
  538. if err != nil {
  539. return nil, err
  540. }
  541. // Accessor offset into BufferView
  542. offset := 0
  543. if ac.ByteOffset != nil {
  544. offset = *ac.ByteOffset
  545. }
  546. data = data[offset:]
  547. // If index component is UNSIGNED_INT nothing to do
  548. if ac.ComponentType == UNSIGNED_INT {
  549. arr := (*[1 << 30]uint32)(unsafe.Pointer(&data[0]))[:ac.Count]
  550. return math32.ArrayU32(arr), nil
  551. }
  552. // Converts UNSIGNED_SHORT indices to UNSIGNED_INT
  553. if ac.ComponentType == UNSIGNED_SHORT {
  554. indices := math32.NewArrayU32(ac.Count, ac.Count)
  555. for i := 0; i < ac.Count; i++ {
  556. indices[i] = uint32(data[i*2]) + uint32(data[i*2+1])*256
  557. }
  558. return indices, nil
  559. }
  560. // Converts UNSIGNED_BYTE indices to UNSIGNED_INT
  561. if ac.ComponentType == UNSIGNED_BYTE {
  562. indices := math32.NewArrayU32(ac.Count, ac.Count)
  563. for i := 0; i < ac.Count; i++ {
  564. indices[i] = uint32(data[i*4]) + uint32(data[i*4+1])*256 +
  565. uint32(data[i*4+2])*256*256 + uint32(data[i*4+3])*256*256*256
  566. }
  567. return indices, nil
  568. }
  569. return nil, fmt.Errorf("Unsupported Accessor ComponentType:%v", ac.ComponentType)
  570. }
  571. // isInterleaves checks if the BufferView used by the specified Accessor index is
  572. // interleaved or not
  573. func (g *GLTF) isInterleaved(aci int) bool {
  574. // Get the Accessor's BufferView
  575. accessor := g.Accessors[aci]
  576. if accessor.BufferView == nil {
  577. return false
  578. }
  579. bv := g.BufferViews[*accessor.BufferView]
  580. // Calculates the size in bytes of a complete attribute
  581. itemSize := TypeSizes[accessor.Type]
  582. itemBytes := int(gls.FloatSize) * itemSize
  583. // If the BufferView stride is equal to the item size, the buffer is not interleaved
  584. if bv.ByteStride == nil {
  585. return false
  586. }
  587. if *bv.ByteStride == itemBytes {
  588. return false
  589. }
  590. return true
  591. }
  592. // loadBufferView loads and returns a byte slice with data from the specified
  593. // BufferView index
  594. func (g *GLTF) loadBufferView(bvi int) ([]byte, error) {
  595. bv := g.BufferViews[bvi]
  596. buf, err := g.loadBuffer(bv.Buffer)
  597. if err != nil {
  598. return nil, err
  599. }
  600. offset := 0
  601. if bv.ByteOffset != nil {
  602. offset = *bv.ByteOffset
  603. }
  604. return buf[offset : offset+bv.ByteLength], nil
  605. }
  606. // loadBuffer loads and returns the data from the specified GLTF Buffer index
  607. func (g *GLTF) loadBuffer(bi int) ([]byte, error) {
  608. buf := &g.Buffers[bi]
  609. // If Buffer URI uses the chunk data field
  610. if buf.Uri == "" {
  611. return g.data, nil
  612. }
  613. // If buffer already loaded:
  614. log.Error("loadBuffer cache:%v", len(buf.data))
  615. if len(buf.data) > 0 {
  616. return buf.data, nil
  617. }
  618. // Checks if buffer URI is a data URI
  619. var data []byte
  620. var err error
  621. if isDataURL(buf.Uri) {
  622. data, err = loadDataURL(buf.Uri)
  623. if err != nil {
  624. return nil, err
  625. }
  626. // Loads external buffer file
  627. } else {
  628. log.Error("loadBuffer: loading file")
  629. // Try to load buffer from file
  630. fpath := filepath.Join(g.path, buf.Uri)
  631. f, err := os.Open(fpath)
  632. if err != nil {
  633. return nil, err
  634. }
  635. defer f.Close()
  636. data, err = ioutil.ReadAll(f)
  637. if err != nil {
  638. return nil, err
  639. }
  640. }
  641. // Checks data length
  642. if len(data) != buf.ByteLength {
  643. return nil, fmt.Errorf("Buffer:%d read data length:%d expected:%d", bi, len(data), buf.ByteLength)
  644. }
  645. // Cache buffer data
  646. buf.data = data
  647. log.Error("cache data:%v", len(buf.data))
  648. return data, nil
  649. }
  650. // dataURL describes a decoded data url string
  651. type dataURL struct {
  652. MediaType string
  653. Encoding string
  654. Data string
  655. }
  656. const (
  657. dataURLprefix = "data:"
  658. mimeBIN = "application/octet-stream"
  659. mimePNG = "image/png"
  660. mimeJPEG = "image/jpeg"
  661. )
  662. var validMediaTypes = []string{mimeBIN, mimePNG, mimeJPEG}
  663. // isDataURL checks if the specified string has the prefix of data URL
  664. func isDataURL(url string) bool {
  665. if strings.HasPrefix(url, dataURLprefix) {
  666. return true
  667. }
  668. return false
  669. }
  670. // loadDataURL decodes the specified data URI string (base64)
  671. func loadDataURL(url string) ([]byte, error) {
  672. var du dataURL
  673. err := parseDataURL(url, &du)
  674. if err != nil {
  675. return nil, err
  676. }
  677. // Checks for valid media type
  678. found := false
  679. for i := 0; i < len(validMediaTypes); i++ {
  680. if validMediaTypes[i] == du.MediaType {
  681. found = true
  682. break
  683. }
  684. }
  685. if !found {
  686. return nil, fmt.Errorf("Data URI media type:%s not supported", du.MediaType)
  687. }
  688. // Checks encoding
  689. if du.Encoding != "base64" {
  690. return nil, fmt.Errorf("Data URI encoding:%s not supported", du.Encoding)
  691. }
  692. // Decodes data from BASE64
  693. data, err := base64.StdEncoding.DecodeString(du.Data)
  694. if err != nil {
  695. return nil, err
  696. }
  697. return data, nil
  698. }
  699. // parseDataURL tries to parse the specified string as a data URL with the format:
  700. // data:[<mediatype>][;base64],<data>
  701. // and if successfull returns true and updates the specified pointer with the parsed fields.
  702. func parseDataURL(url string, du *dataURL) error {
  703. // Checks prefix
  704. if !isDataURL(url) {
  705. return fmt.Errorf("Specified string is not a data URL")
  706. }
  707. // Separates header from data
  708. body := url[len(dataURLprefix):]
  709. parts := strings.Split(body, ",")
  710. if len(parts) != 2 {
  711. return fmt.Errorf("Data URI contains more than one ','")
  712. }
  713. du.Data = parts[1]
  714. // Separates media type from optional encoding
  715. res := strings.Split(parts[0], ";")
  716. du.MediaType = res[0]
  717. if len(res) < 2 {
  718. return nil
  719. }
  720. if len(res) >= 2 {
  721. du.Encoding = res[1]
  722. }
  723. return nil
  724. }