scene.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. "strings"
  8. "github.com/g3n/engine/core"
  9. "github.com/g3n/engine/gls"
  10. "github.com/g3n/engine/graphic"
  11. "github.com/g3n/engine/material"
  12. "github.com/g3n/engine/math32"
  13. )
  14. // NewScene returns a new collada empty scene
  15. func (d *Decoder) NewScene() (core.INode, error) {
  16. sc := d.dom.Scene
  17. if sc == nil {
  18. return nil, fmt.Errorf("No Scene element found")
  19. }
  20. ivs := sc.InstanceVisualScene
  21. if ivs == nil {
  22. return nil, fmt.Errorf("No InstanceVisualScene element found")
  23. }
  24. vs := findVisualScene(&d.dom, ivs.Url)
  25. if vs == nil {
  26. return nil, fmt.Errorf("VisualScene id:%s not found", ivs.Url)
  27. }
  28. // Creates parent scene
  29. scene := core.NewNode()
  30. // Rotate scene if necessary
  31. if d.dom.Asset.UpAxis == "Z_UP" {
  32. scene.SetRotationX(-math32.Pi / 2)
  33. }
  34. // Creates each node and adds it to the scene
  35. for _, n := range vs.Node {
  36. node, err := d.newNode(n)
  37. if err != nil {
  38. return nil, err
  39. }
  40. scene.Add(node)
  41. }
  42. return scene, nil
  43. }
  44. func (d *Decoder) newNode(cnode *Node) (core.INode, error) {
  45. var node core.INode
  46. switch nt := cnode.Instance.(type) {
  47. // Empty Node
  48. case nil:
  49. node = core.NewNode()
  50. // Geometry
  51. case *InstanceGeometry:
  52. // Get geometry instance
  53. geomi, gtype, err := d.GetGeometry(nt.Url)
  54. if err != nil {
  55. return nil, err
  56. }
  57. switch gtype {
  58. case gls.TRIANGLES:
  59. mesh := graphic.NewMesh(geomi, nil)
  60. geom := geomi.GetGeometry()
  61. // Associates the material in <bind_material> with the geometry group material
  62. for _, im := range nt.BindMaterial.TechniqueCommon.InstanceMaterial {
  63. matid := strings.TrimPrefix(im.Target, "#")
  64. for i := 0; i < geom.GroupCount(); i++ {
  65. group := geom.GroupAt(i)
  66. if group.Matid == matid {
  67. mat, err := d.GetMaterial(im.Target)
  68. if err != nil {
  69. return nil, err
  70. }
  71. mesh.AddGroupMaterial(mat, i)
  72. break
  73. }
  74. }
  75. }
  76. node = mesh
  77. case gls.POINTS:
  78. mat := material.NewPoint(&math32.Color{})
  79. mat.SetSize(30)
  80. node = graphic.NewPoints(geomi, mat)
  81. case gls.LINES:
  82. mat := material.NewBasic()
  83. node = graphic.NewLines(geomi, mat)
  84. case gls.LINE_STRIP:
  85. mat := material.NewBasic()
  86. node = graphic.NewLineStrip(geomi, mat)
  87. default:
  88. return nil, fmt.Errorf("primitive not supported")
  89. }
  90. default:
  91. return nil, fmt.Errorf("instance geometry type:%T not supported", nt)
  92. }
  93. n := node.GetNode()
  94. n.SetLoaderID(cnode.Id)
  95. // Apply transformation elements to the node
  96. for _, tei := range cnode.TransformationElements {
  97. switch te := tei.(type) {
  98. case *Matrix:
  99. // Get math32.Matrix from the matrix data and
  100. // transpose to a column matrix
  101. var m math32.Matrix4
  102. m.FromArray(te.Data[:], 0)
  103. m.Transpose()
  104. // Decompose the transformation matrix
  105. var position math32.Vector3
  106. var quaternion math32.Quaternion
  107. var scale math32.Vector3
  108. m.Decompose(&position, &quaternion, &scale)
  109. // Sets the node position, quaternion and scale
  110. n.SetPositionVec(&position)
  111. n.SetQuaternionQuat(&quaternion)
  112. n.SetScaleVec(&scale)
  113. case *Rotate:
  114. // Check angle of rotation
  115. if te.Data[3] == 0 {
  116. continue
  117. }
  118. var q math32.Quaternion
  119. axis := math32.Vector3{te.Data[0], te.Data[1], te.Data[2]}
  120. q.SetFromAxisAngle(&axis, math32.DegToRad(te.Data[3]))
  121. n.SetQuaternionQuat(&q)
  122. case *Scale:
  123. n.SetScale(te.Data[0], te.Data[1], te.Data[2])
  124. case *Translate:
  125. n.SetPosition(te.Data[0], te.Data[1], te.Data[2])
  126. default:
  127. return nil, fmt.Errorf("transformation element not supported")
  128. }
  129. }
  130. // Creates children nodes
  131. for _, child := range cnode.Node {
  132. c, err := d.newNode(child)
  133. if err != nil {
  134. return nil, err
  135. }
  136. n.Add(c)
  137. }
  138. return node, nil
  139. }
  140. func findVisualScene(dom *Collada, uri string) *VisualScene {
  141. id := strings.TrimPrefix(uri, "#")
  142. for _, vs := range dom.LibraryVisualScenes.VisualScene {
  143. if vs.Id == id {
  144. return vs
  145. }
  146. }
  147. return nil
  148. }