geometry.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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 collada
  5. import (
  6. "fmt"
  7. "github.com/g3n/engine/geometry"
  8. "github.com/g3n/engine/gls"
  9. "github.com/g3n/engine/math32"
  10. "reflect"
  11. "strings"
  12. )
  13. // GetGeometry returns a pointer to an instance of the geometry
  14. // with the specified id in the Collada document, its primitive type
  15. // and an error. If no previous instance of the geometry was found
  16. // the geometry is created
  17. func (d *Decoder) GetGeometry(id string) (geometry.IGeometry, uint32, error) {
  18. // If geometry already created, returns it
  19. ginst, ok := d.geometries[id]
  20. if ok {
  21. return ginst.geom, ginst.ptype, nil
  22. }
  23. // Creates geometry and saves it associated with its id
  24. geom, ptype, err := d.NewGeometry(id)
  25. if err != nil {
  26. return nil, 0, err
  27. }
  28. d.geometries[id] = geomInstance{geom, ptype}
  29. return geom, ptype, nil
  30. }
  31. // NewGeometry creates and returns a pointer to a new instance of the geometry
  32. // with the specified id in the Collada document, its primitive type and and error.
  33. func (d *Decoder) NewGeometry(id string) (geometry.IGeometry, uint32, error) {
  34. id = strings.TrimPrefix(id, "#")
  35. // Look for geometry with specified id in the dom
  36. var geo *Geometry
  37. for _, g := range d.dom.LibraryGeometries.Geometry {
  38. if g.Id == id {
  39. geo = g
  40. break
  41. }
  42. }
  43. if geo == nil {
  44. return nil, 0, fmt.Errorf("Geometry:%s not found", id)
  45. }
  46. // Geometry type
  47. switch gt := geo.GeometricElement.(type) {
  48. // Collada mesh category includes points, lines, linestrips, triangles,
  49. // triangle fans, triangle strips and polygons.
  50. case *Mesh:
  51. return newMesh(gt)
  52. // B-Spline
  53. // Bezier
  54. // NURBS
  55. // Patch
  56. default:
  57. return nil, 0, fmt.Errorf("GeometryElement:%T not supported", gt)
  58. }
  59. }
  60. func newMesh(m *Mesh) (*geometry.Geometry, uint32, error) {
  61. // If no primitive elements present, it is a mesh of points
  62. if len(m.PrimitiveElements) == 0 {
  63. return newMeshPoints(m)
  64. }
  65. // All the primitive elements must be of the same type
  66. var etype reflect.Type
  67. for i := 0; i < len(m.PrimitiveElements); i++ {
  68. el := m.PrimitiveElements[i]
  69. if i == 0 {
  70. etype = reflect.TypeOf(el)
  71. } else {
  72. if reflect.TypeOf(el) != etype {
  73. return nil, 0, fmt.Errorf("primitive elements of different types")
  74. }
  75. }
  76. }
  77. pei := m.PrimitiveElements[0]
  78. switch pet := pei.(type) {
  79. case *Polylist:
  80. return newMeshPolylist(m, m.PrimitiveElements)
  81. case *Triangles:
  82. return newMeshTriangles(m, pet)
  83. case *Lines:
  84. return newMeshLines(m, pet)
  85. case *LineStrips:
  86. return newMeshLineStrips(m, pet)
  87. case *Trifans:
  88. return newMeshTrifans(m, pet)
  89. case *Tristrips:
  90. return newMeshTristrips(m, pet)
  91. default:
  92. return nil, 0, fmt.Errorf("PrimitiveElement:%T not supported", pet)
  93. }
  94. }
  95. // Creates a geometry from a polylist
  96. // Only triangles are supported
  97. func newMeshPolylist(m *Mesh, pels []interface{}) (*geometry.Geometry, uint32, error) {
  98. // Get vertices positions
  99. if len(m.Vertices.Input) != 1 {
  100. return nil, 0, fmt.Errorf("Mesh.Vertices.Input length not supported")
  101. }
  102. vinp := m.Vertices.Input[0]
  103. if vinp.Semantic != "POSITION" {
  104. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Semantic:%s not supported", vinp.Semantic)
  105. }
  106. // Get vertices input source
  107. inps := getMeshSource(m, vinp.Source)
  108. if inps == nil {
  109. return nil, 0, fmt.Errorf("Source:%s not found", vinp.Source)
  110. }
  111. // Get vertices input float array
  112. // Ignore Accessor (??)
  113. posArray, ok := inps.ArrayElement.(*FloatArray)
  114. if !ok {
  115. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Source not FloatArray")
  116. }
  117. // Creates buffers
  118. positions := math32.NewArrayF32(0, 0)
  119. normals := math32.NewArrayF32(0, 0)
  120. uvs := math32.NewArrayF32(0, 0)
  121. indices := math32.NewArrayU32(0, 0)
  122. // Creates vertices attributes map for reusing indices
  123. mVindex := make(map[[8]float32]uint32)
  124. var index uint32
  125. geomGroups := make([]geometry.Group, 0)
  126. groupMatindex := 0
  127. // For each Polylist
  128. for _, pel := range pels {
  129. // Checks if element is Polylist
  130. pl, ok := pel.(*Polylist)
  131. if !ok {
  132. return nil, 0, fmt.Errorf("Element is not a Polylist")
  133. }
  134. // If Polylist has not inputs, ignore
  135. if pl.Input == nil || len(pl.Input) == 0 {
  136. continue
  137. }
  138. // Checks if all Vcount elements are triangles
  139. for _, v := range pl.Vcount {
  140. if v != 3 {
  141. return nil, 0, fmt.Errorf("Only triangles are supported in Polylist")
  142. }
  143. }
  144. // Get VERTEX input
  145. inpVertex := getInputSemantic(pl.Input, "VERTEX")
  146. if inpVertex == nil {
  147. return nil, 0, fmt.Errorf("VERTEX input not found")
  148. }
  149. // Get optional NORMAL input
  150. inpNormal := getInputSemantic(pl.Input, "NORMAL")
  151. var normArray *FloatArray
  152. if inpNormal != nil {
  153. // Get normals source
  154. source := getMeshSource(m, inpNormal.Source)
  155. if source == nil {
  156. return nil, 0, fmt.Errorf("NORMAL source:%s not found", inpNormal.Source)
  157. }
  158. // Get normals source float array
  159. normArray, ok = source.ArrayElement.(*FloatArray)
  160. if !ok {
  161. return nil, 0, fmt.Errorf("NORMAL source:%s not float array", inpNormal.Source)
  162. }
  163. }
  164. // Get optional TEXCOORD input
  165. inpTexcoord := getInputSemantic(pl.Input, "TEXCOORD")
  166. var texArray *FloatArray
  167. if inpTexcoord != nil {
  168. // Get texture coordinates source
  169. source := getMeshSource(m, inpTexcoord.Source)
  170. if source == nil {
  171. return nil, 0, fmt.Errorf("TEXCOORD source:%s not found", inpTexcoord.Source)
  172. }
  173. // Get texture coordinates source float array
  174. texArray, ok = source.ArrayElement.(*FloatArray)
  175. if !ok {
  176. return nil, 0, fmt.Errorf("TEXCOORD source:%s not float array", inpTexcoord.Source)
  177. }
  178. }
  179. // Initialize geometry group
  180. groupStart := indices.Size()
  181. // For each primitive index
  182. inputCount := len(pl.Input)
  183. for i := 0; i < len(pl.P); i += inputCount {
  184. // Vertex attributes: position(3) + normal(3) + uv(2)
  185. var vx [8]float32
  186. // Vertex position
  187. posIndex := pl.P[i+inpVertex.Offset] * 3
  188. // Get position vector and appends to its buffer
  189. vx[0] = posArray.Data[posIndex]
  190. vx[1] = posArray.Data[posIndex+1]
  191. vx[2] = posArray.Data[posIndex+2]
  192. // Optional vertex normal
  193. if inpNormal != nil {
  194. // Get normal index from P
  195. normIndex := pl.P[i+inpNormal.Offset] * 3
  196. // Get normal vector and appends to its buffer
  197. vx[3] = normArray.Data[normIndex]
  198. vx[4] = normArray.Data[normIndex+1]
  199. vx[5] = normArray.Data[normIndex+2]
  200. }
  201. // Optional vertex texture coordinate
  202. if inpTexcoord != nil {
  203. // Get normal index from P
  204. texIndex := pl.P[i+inpTexcoord.Offset] * 2
  205. // Get normal vector and appends to its buffer
  206. vx[6] = texArray.Data[texIndex]
  207. vx[7] = texArray.Data[texIndex+1]
  208. }
  209. // If this vertex and its attributes has already been appended,
  210. // reuse it, adding its index to the index buffer
  211. // to reuse its index
  212. idx, ok := mVindex[vx]
  213. if ok {
  214. indices.Append(idx)
  215. continue
  216. }
  217. // Appends new vertex position and attributes to its buffers
  218. positions.Append(vx[0], vx[1], vx[2])
  219. if inpNormal != nil {
  220. normals.Append(vx[3], vx[4], vx[5])
  221. }
  222. if inpTexcoord != nil {
  223. uvs.Append(vx[6], vx[7])
  224. }
  225. indices.Append(index)
  226. // Save the index to this vertex position and attributes for
  227. // future reuse
  228. mVindex[vx] = index
  229. index++
  230. }
  231. // Adds this geometry group to the list
  232. geomGroups = append(geomGroups, geometry.Group{
  233. Start: groupStart,
  234. Count: indices.Size() - groupStart,
  235. Matindex: groupMatindex,
  236. Matid: pl.Material,
  237. })
  238. groupMatindex++
  239. }
  240. // Debug dump
  241. //for i := 0; i < positions.Size()/3; i++ {
  242. // vidx := i*3
  243. // msg := fmt.Sprintf("i:%2d position:%v %v %v",
  244. // i, positions.Get(vidx), positions.Get(vidx+1), positions.Get(vidx+2))
  245. // if normals.Size() > 0 {
  246. // msg += fmt.Sprintf("\tnormal:%v %v %v",
  247. // normals.Get(vidx), normals.Get(vidx+1), normals.Get(vidx+2))
  248. // }
  249. // if uvs.Size() > 0 {
  250. // msg += fmt.Sprintf("\tuv:%v %v", uvs.Get(i*2), uvs.Get(i*2+1))
  251. // }
  252. // log.Debug("%s", msg)
  253. //}
  254. //log.Debug("indices(%d):%v", indices.Size(), indices)
  255. //log.Debug("groups:%v", geomGroups)
  256. // Creates geometry
  257. geom := geometry.NewGeometry()
  258. // Creates VBO with vertex positions
  259. geom.AddVBO(gls.NewVBO(positions).AddAttrib(gls.VertexPosition, 3))
  260. // Creates VBO with vertex normals
  261. if normals.Size() > 0 {
  262. geom.AddVBO(gls.NewVBO(normals).AddAttrib(gls.VertexNormal, 3))
  263. }
  264. // Creates VBO with uv coordinates
  265. if uvs.Size() > 0 {
  266. geom.AddVBO(gls.NewVBO(uvs).AddAttrib(gls.VertexTexcoord, 2))
  267. }
  268. // Sets the geometry indices buffer
  269. geom.SetIndices(indices)
  270. // Add material groups to the geometry
  271. geom.AddGroupList(geomGroups)
  272. return geom, gls.TRIANGLES, nil
  273. }
  274. func newMeshTriangles(m *Mesh, tr *Triangles) (*geometry.Geometry, uint32, error) {
  275. return nil, 0, fmt.Errorf("not implemented yet")
  276. }
  277. func newMeshLines(m *Mesh, ln *Lines) (*geometry.Geometry, uint32, error) {
  278. if ln.Input == nil || len(ln.Input) == 0 {
  279. return nil, 0, fmt.Errorf("No inputs in lines")
  280. }
  281. // Get vertices positions
  282. if len(m.Vertices.Input) != 1 {
  283. return nil, 0, fmt.Errorf("Mesh.Vertices.Input length not supported")
  284. }
  285. vinp := m.Vertices.Input[0]
  286. if vinp.Semantic != "POSITION" {
  287. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Semantic:%s not supported", vinp.Semantic)
  288. }
  289. // Get vertices input source
  290. inps := getMeshSource(m, vinp.Source)
  291. if inps == nil {
  292. return nil, 0, fmt.Errorf("Source:%s not found", vinp.Source)
  293. }
  294. // Get vertices input float array
  295. // Ignore Accessor (??)
  296. posArray, ok := inps.ArrayElement.(*FloatArray)
  297. if !ok {
  298. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Source not FloatArray")
  299. }
  300. // Get VERTEX input
  301. inpVertex := getInputSemantic(ln.Input, "VERTEX")
  302. if inpVertex == nil {
  303. return nil, 0, fmt.Errorf("VERTEX input not found")
  304. }
  305. // Creates buffers
  306. positions := math32.NewArrayF32(0, 0)
  307. indices := math32.NewArrayU32(0, 0)
  308. mVindex := make(map[[3]float32]uint32)
  309. inputCount := len(ln.Input)
  310. var index uint32
  311. for i := 0; i < len(ln.P); i += inputCount {
  312. // Vertex position
  313. var vx [3]float32
  314. // Get position index from P
  315. posIndex := ln.P[i+inpVertex.Offset] * 3
  316. // Get position vector and appends to its buffer
  317. vx[0] = posArray.Data[posIndex]
  318. vx[1] = posArray.Data[posIndex+1]
  319. vx[2] = posArray.Data[posIndex+2]
  320. // If this vertex and its attributes has already been appended,
  321. // reuse it, adding its index to the index buffer
  322. // to reuse its index
  323. idx, ok := mVindex[vx]
  324. if ok {
  325. indices.Append(idx)
  326. continue
  327. }
  328. // Appends new vertex position and attributes to its buffers
  329. positions.Append(vx[0], vx[1], vx[2])
  330. indices.Append(index)
  331. // Save the index to this vertex position and attributes for
  332. // future reuse
  333. //mVindex[vx] = index
  334. index++
  335. }
  336. // Creates geometry
  337. geom := geometry.NewGeometry()
  338. // Creates VBO with vertex positions
  339. geom.AddVBO(gls.NewVBO(positions).AddAttrib(gls.VertexPosition, 3))
  340. // Sets the geometry indices buffer
  341. geom.SetIndices(indices)
  342. return geom, gls.LINES, nil
  343. }
  344. func newMeshLineStrips(m *Mesh, ls *LineStrips) (*geometry.Geometry, uint32, error) {
  345. return nil, 0, fmt.Errorf("not implemented yet")
  346. }
  347. func newMeshTrifans(m *Mesh, ls *Trifans) (*geometry.Geometry, uint32, error) {
  348. return nil, 0, fmt.Errorf("not implemented yet")
  349. }
  350. func newMeshTristrips(m *Mesh, ls *Tristrips) (*geometry.Geometry, uint32, error) {
  351. return nil, 0, fmt.Errorf("not implemented yet")
  352. }
  353. // Creates and returns pointer to a new geometry for POINTS
  354. func newMeshPoints(m *Mesh) (*geometry.Geometry, uint32, error) {
  355. // Get vertices positions
  356. if len(m.Vertices.Input) != 1 {
  357. return nil, 0, fmt.Errorf("Mesh.Vertices.Input length not supported")
  358. }
  359. vinp := m.Vertices.Input[0]
  360. if vinp.Semantic != "POSITION" {
  361. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Semantic:%s not supported", vinp.Semantic)
  362. }
  363. // Get vertices input source
  364. inps := getMeshSource(m, vinp.Source)
  365. if inps == nil {
  366. return nil, 0, fmt.Errorf("Source:%s not found", vinp.Source)
  367. }
  368. // Get vertices input float array
  369. // Ignore Accessor (??)
  370. posArray, ok := inps.ArrayElement.(*FloatArray)
  371. if !ok {
  372. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Source not FloatArray")
  373. }
  374. // Creates buffer and copy data
  375. positions := math32.NewArrayF32(posArray.Count, posArray.Count)
  376. //positions.CopyFrom(posArray.Data)
  377. copy(positions, posArray.Data)
  378. // Creates geometry and add VBO with vertex positions
  379. geom := geometry.NewGeometry()
  380. geom.AddVBO(gls.NewVBO(positions).AddAttrib(gls.VertexPosition, 3))
  381. return geom, gls.POINTS, nil
  382. }
  383. func getMeshSource(m *Mesh, uri string) *Source {
  384. id := strings.TrimPrefix(uri, "#")
  385. for _, s := range m.Source {
  386. if s.Id == id {
  387. return s
  388. }
  389. }
  390. return nil
  391. }
  392. func getInputSemantic(inps []InputShared, semantic string) *InputShared {
  393. for i := 0; i < len(inps); i++ {
  394. if inps[i].Semantic == semantic {
  395. return &inps[i]
  396. }
  397. }
  398. return nil
  399. }