scene.go 3.9 KB

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