geometry.go 13 KB

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