geometry.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  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. vboPositions := gls.NewVBO()
  260. vboPositions.AddAttrib("VertexPosition", 3).SetBuffer(positions)
  261. geom.AddVBO(vboPositions)
  262. // Creates VBO with vertex normals
  263. if normals.Size() > 0 {
  264. vboNormals := gls.NewVBO()
  265. vboNormals.AddAttrib("VertexNormal", 3).SetBuffer(normals)
  266. geom.AddVBO(vboNormals)
  267. }
  268. // Creates VBO with uv coordinates
  269. if uvs.Size() > 0 {
  270. vboUvs := gls.NewVBO()
  271. vboUvs.AddAttrib("VertexTexcoord", 2).SetBuffer(uvs)
  272. geom.AddVBO(vboUvs)
  273. }
  274. // Sets the geometry indices buffer
  275. geom.SetIndices(indices)
  276. // Add material groups to the geometry
  277. geom.AddGroupList(geomGroups)
  278. return geom, gls.TRIANGLES, nil
  279. }
  280. func newMeshTriangles(m *Mesh, tr *Triangles) (*geometry.Geometry, uint32, error) {
  281. return nil, 0, fmt.Errorf("not implemented yet")
  282. }
  283. func newMeshLines(m *Mesh, ln *Lines) (*geometry.Geometry, uint32, error) {
  284. if ln.Input == nil || len(ln.Input) == 0 {
  285. return nil, 0, fmt.Errorf("No inputs in lines")
  286. }
  287. // Get vertices positions
  288. if len(m.Vertices.Input) != 1 {
  289. return nil, 0, fmt.Errorf("Mesh.Vertices.Input length not supported")
  290. }
  291. vinp := m.Vertices.Input[0]
  292. if vinp.Semantic != "POSITION" {
  293. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Semantic:%s not supported", vinp.Semantic)
  294. }
  295. // Get vertices input source
  296. inps := getMeshSource(m, vinp.Source)
  297. if inps == nil {
  298. return nil, 0, fmt.Errorf("Source:%s not found", vinp.Source)
  299. }
  300. // Get vertices input float array
  301. // Ignore Accessor (??)
  302. posArray, ok := inps.ArrayElement.(*FloatArray)
  303. if !ok {
  304. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Source not FloatArray")
  305. }
  306. // Get VERTEX input
  307. inpVertex := getInputSemantic(ln.Input, "VERTEX")
  308. if inpVertex == nil {
  309. return nil, 0, fmt.Errorf("VERTEX input not found")
  310. }
  311. // Creates buffers
  312. positions := math32.NewArrayF32(0, 0)
  313. indices := math32.NewArrayU32(0, 0)
  314. mVindex := make(map[[3]float32]uint32)
  315. inputCount := len(ln.Input)
  316. var index uint32
  317. for i := 0; i < len(ln.P); i += inputCount {
  318. // Vertex position
  319. var vx [3]float32
  320. // Get position index from P
  321. posIndex := ln.P[i+inpVertex.Offset] * 3
  322. // Get position vector and appends to its buffer
  323. vx[0] = posArray.Data[posIndex]
  324. vx[1] = posArray.Data[posIndex+1]
  325. vx[2] = posArray.Data[posIndex+2]
  326. // If this vertex and its attributes has already been appended,
  327. // reuse it, adding its index to the index buffer
  328. // to reuse its index
  329. idx, ok := mVindex[vx]
  330. if ok {
  331. indices.Append(idx)
  332. continue
  333. }
  334. // Appends new vertex position and attributes to its buffers
  335. positions.Append(vx[0], vx[1], vx[2])
  336. indices.Append(index)
  337. // Save the index to this vertex position and attributes for
  338. // future reuse
  339. //mVindex[vx] = index
  340. index++
  341. }
  342. // Creates geometry
  343. geom := geometry.NewGeometry()
  344. // Creates VBO with vertex positions
  345. vboPositions := gls.NewVBO()
  346. vboPositions.AddAttrib("VertexPosition", 3).SetBuffer(positions)
  347. geom.AddVBO(vboPositions)
  348. // Sets the geometry indices buffer
  349. geom.SetIndices(indices)
  350. return geom, gls.LINES, nil
  351. }
  352. func newMeshLineStrips(m *Mesh, ls *LineStrips) (*geometry.Geometry, uint32, error) {
  353. return nil, 0, fmt.Errorf("not implemented yet")
  354. }
  355. func newMeshTrifans(m *Mesh, ls *Trifans) (*geometry.Geometry, uint32, error) {
  356. return nil, 0, fmt.Errorf("not implemented yet")
  357. }
  358. func newMeshTristrips(m *Mesh, ls *Tristrips) (*geometry.Geometry, uint32, error) {
  359. return nil, 0, fmt.Errorf("not implemented yet")
  360. }
  361. // Creates and returns pointer to a new geometry for POINTS
  362. func newMeshPoints(m *Mesh) (*geometry.Geometry, uint32, error) {
  363. // Get vertices positions
  364. if len(m.Vertices.Input) != 1 {
  365. return nil, 0, fmt.Errorf("Mesh.Vertices.Input length not supported")
  366. }
  367. vinp := m.Vertices.Input[0]
  368. if vinp.Semantic != "POSITION" {
  369. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Semantic:%s not supported", vinp.Semantic)
  370. }
  371. // Get vertices input source
  372. inps := getMeshSource(m, vinp.Source)
  373. if inps == nil {
  374. return nil, 0, fmt.Errorf("Source:%s not found", vinp.Source)
  375. }
  376. // Get vertices input float array
  377. // Ignore Accessor (??)
  378. posArray, ok := inps.ArrayElement.(*FloatArray)
  379. if !ok {
  380. return nil, 0, fmt.Errorf("Mesh.Vertices.Input.Source not FloatArray")
  381. }
  382. // Creates buffer and copy data
  383. positions := math32.NewArrayF32(posArray.Count, posArray.Count)
  384. //positions.CopyFrom(posArray.Data)
  385. copy(positions, posArray.Data)
  386. // Creates geometry and add VBO with vertex positions
  387. geom := geometry.NewGeometry()
  388. geom.AddVBO(gls.NewVBO().AddAttrib("VertexPosition", 3).SetBuffer(positions))
  389. return geom, gls.POINTS, nil
  390. }
  391. func getMeshSource(m *Mesh, uri string) *Source {
  392. id := strings.TrimPrefix(uri, "#")
  393. for _, s := range m.Source {
  394. if s.Id == id {
  395. return s
  396. }
  397. }
  398. return nil
  399. }
  400. func getInputSemantic(inps []InputShared, semantic string) *InputShared {
  401. for i := 0; i < len(inps); i++ {
  402. if inps[i].Semantic == semantic {
  403. return &inps[i]
  404. }
  405. }
  406. return nil
  407. }