node.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  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 core
  5. import (
  6. "github.com/g3n/engine/gls"
  7. "github.com/g3n/engine/math32"
  8. "strings"
  9. )
  10. // INode is the interface for all node types.
  11. type INode interface {
  12. IDispatcher
  13. GetNode() *Node
  14. UpdateMatrixWorld()
  15. Raycast(*Raycaster, *[]Intersect)
  16. Render(gs *gls.GLS)
  17. Dispose()
  18. }
  19. // Node represents an object in 3D space existing within a hierarchy.
  20. type Node struct {
  21. Dispatcher // Embedded event dispatcher
  22. parent INode // Parent node
  23. children []INode // Children nodes
  24. name string // Optional node name
  25. loaderID string // ID used by loader
  26. visible bool // Whether the node is visible
  27. matNeedsUpdate bool // Whether the the local matrix needs to be updated because position or scale has changed
  28. rotNeedsUpdate bool // Whether the euler rotation and local matrix need to be updated because the quaternion has changed
  29. userData interface{} // Generic user data
  30. // Spatial properties
  31. position math32.Vector3 // Node position in 3D space (relative to parent)
  32. scale math32.Vector3 // Node scale (relative to parent)
  33. direction math32.Vector3 // Initial direction (relative to parent)
  34. rotation math32.Vector3 // Node rotation specified in Euler angles (relative to parent)
  35. quaternion math32.Quaternion // Node rotation specified as a Quaternion (relative to parent)
  36. matrix math32.Matrix4 // Local transform matrix. Contains all position/rotation/scale information (relative to parent)
  37. matrixWorld math32.Matrix4 // World transform matrix. Contains all absolute position/rotation/scale information (i.e. relative to very top parent, generally the scene)
  38. }
  39. // NewNode returns a pointer to a new Node.
  40. func NewNode() *Node {
  41. n := new(Node)
  42. n.Init()
  43. return n
  44. }
  45. // Init initializes the node.
  46. // Normally called by other types which embed a Node.
  47. func (n *Node) Init() {
  48. n.Dispatcher.Initialize()
  49. n.children = make([]INode, 0)
  50. n.visible = true
  51. // Initialize spatial properties
  52. n.position.Set(0, 0, 0)
  53. n.scale.Set(1, 1, 1)
  54. n.direction.Set(0, 0, 1)
  55. n.rotation.Set(0, 0, 0)
  56. n.quaternion.Set(0, 0, 0, 1)
  57. n.matrix.Identity()
  58. n.matrixWorld.Identity()
  59. }
  60. // GetNode satisfies the INode interface
  61. // and returns a pointer to the embedded Node.
  62. func (n *Node) GetNode() *Node {
  63. return n
  64. }
  65. // Raycast satisfies the INode interface.
  66. func (n *Node) Raycast(rc *Raycaster, intersects *[]Intersect) {
  67. }
  68. // Render satisfies the INode interface.
  69. func (n *Node) Render(gs *gls.GLS) {
  70. }
  71. // Dispose satisfies the INode interface.
  72. func (n *Node) Dispose() {
  73. }
  74. // SetParent sets the parent.
  75. func (n *Node) SetParent(iparent INode) {
  76. n.parent = iparent
  77. }
  78. // Parent returns the parent.
  79. func (n *Node) Parent() INode {
  80. return n.parent
  81. }
  82. // SetName sets the (optional) name.
  83. // The name can be used for debugging or other purposes.
  84. func (n *Node) SetName(name string) {
  85. n.name = name
  86. }
  87. // Name returns the (optional) name.
  88. func (n *Node) Name() string {
  89. return n.name
  90. }
  91. // SetLoaderID is normally used by external loaders, such as Collada,
  92. // to assign an ID to the node with the ID value in the node description.
  93. // Can be used to find other loaded nodes.
  94. func (n *Node) SetLoaderID(id string) {
  95. n.loaderID = id
  96. }
  97. // LoaderID returns an optional ID set when this node was
  98. // created by an external loader such as Collada.
  99. func (n *Node) LoaderID() string {
  100. return n.loaderID
  101. }
  102. // SetVisible sets the visibility of the node.
  103. func (n *Node) SetVisible(state bool) {
  104. n.visible = state
  105. n.matNeedsUpdate = true
  106. }
  107. // Visible returns the visibility of the node.
  108. func (n *Node) Visible() bool {
  109. return n.visible
  110. }
  111. // SetChanged sets the matNeedsUpdate flag of the node.
  112. func (n *Node) SetChanged(changed bool) {
  113. n.matNeedsUpdate = changed
  114. }
  115. // Changed returns the matNeedsUpdate flag of the node.
  116. func (n *Node) Changed() bool {
  117. return n.matNeedsUpdate
  118. }
  119. // SetUserData sets the generic user data associated to the node.
  120. func (n *Node) SetUserData(data interface{}) {
  121. n.userData = data
  122. }
  123. // UserData returns the generic user data associated to the node.
  124. func (n *Node) UserData() interface{} {
  125. return n.userData
  126. }
  127. // FindPath finds a node with the specified path starting with this node and
  128. // searching in all its children recursively.
  129. // A path is the sequence of the names from the first node to the desired node
  130. // separated by the forward slash.
  131. func (n *Node) FindPath(path string) INode {
  132. // Internal recursive function to find node
  133. var finder func(inode INode, path string) INode
  134. finder = func(inode INode, path string) INode {
  135. // Get first component of the path
  136. parts := strings.Split(path, "/")
  137. if len(parts) == 0 {
  138. return nil
  139. }
  140. first := parts[0]
  141. // Checks current node
  142. node := inode.GetNode()
  143. if node.name != first {
  144. return nil
  145. }
  146. // If the path has finished this is the desired node
  147. rest := strings.Join(parts[1:], "/")
  148. if rest == "" {
  149. return inode
  150. }
  151. // Otherwise search in this node children
  152. for _, ichild := range node.children {
  153. found := finder(ichild, rest)
  154. if found != nil {
  155. return found
  156. }
  157. }
  158. return nil
  159. }
  160. return finder(n, path)
  161. }
  162. // FindLoaderID looks in the specified node and in all its children
  163. // for a node with the specified loaderID and if found returns it.
  164. // Returns nil if not found.
  165. func (n *Node) FindLoaderID(id string) INode {
  166. var finder func(parent INode, id string) INode
  167. finder = func(parent INode, id string) INode {
  168. pnode := parent.GetNode()
  169. if pnode.loaderID == id {
  170. return parent
  171. }
  172. for _, child := range pnode.children {
  173. found := finder(child, id)
  174. if found != nil {
  175. return found
  176. }
  177. }
  178. return nil
  179. }
  180. return finder(n, id)
  181. }
  182. // Children returns the list of children.
  183. func (n *Node) Children() []INode {
  184. return n.children
  185. }
  186. // Add adds the specified node to the list of children and sets its parent pointer.
  187. // If the specified node had a parent, the specified node is removed from the original parent's list of children.
  188. func (n *Node) Add(ichild INode) *Node {
  189. n.setParentOf(ichild)
  190. n.children = append(n.children, ichild)
  191. return n
  192. }
  193. // AddAt adds the specified node to the list of children at the specified index and sets its parent pointer.
  194. // If the specified node had a parent, the specified node is removed from the original parent's list of children.
  195. func (n *Node) AddAt(idx int, ichild INode) {
  196. // Validate position
  197. if idx < 0 || idx > len(n.children) {
  198. panic("Node.AddAt: invalid position")
  199. }
  200. n.setParentOf(ichild)
  201. // Insert child in the specified position
  202. n.children = append(n.children, nil)
  203. copy(n.children[idx+1:], n.children[idx:])
  204. n.children[idx] = ichild
  205. }
  206. // setParentOf is used by Add and AddAt.
  207. // It verifies that the node is not being added to itself and sets the parent pointer of the specified node.
  208. // If the specified node had a parent, the specified node is removed from the original parent's list of children.
  209. // It does not add the specified node to the list of children.
  210. func (n *Node) setParentOf(ichild INode) {
  211. child := ichild.GetNode()
  212. if n == child {
  213. panic("Node.{Add,AddAt}: object can't be added as a child of itself")
  214. }
  215. // If the specified node already has a parent,
  216. // remove it from the original parent's list of children
  217. if child.parent != nil {
  218. child.parent.GetNode().Remove(ichild)
  219. }
  220. child.parent = n
  221. }
  222. // ChildAt returns the child at the specified index.
  223. func (n *Node) ChildAt(idx int) INode {
  224. if idx < 0 || idx >= len(n.children) {
  225. return nil
  226. }
  227. return n.children[idx]
  228. }
  229. // ChildIndex returns the index of the specified child (-1 if not found).
  230. func (n *Node) ChildIndex(ichild INode) int {
  231. for idx := 0; idx < len(n.children); idx++ {
  232. if n.children[idx] == ichild {
  233. return idx
  234. }
  235. }
  236. return -1
  237. }
  238. // Remove removes the specified INode from the list of children.
  239. // Returns true if found or false otherwise.
  240. func (n *Node) Remove(ichild INode) bool {
  241. for pos, current := range n.children {
  242. if current == ichild {
  243. copy(n.children[pos:], n.children[pos+1:])
  244. n.children[len(n.children)-1] = nil
  245. n.children = n.children[:len(n.children)-1]
  246. ichild.GetNode().parent = nil
  247. return true
  248. }
  249. }
  250. return false
  251. }
  252. // RemoveAt removes the child at the specified index.
  253. func (n *Node) RemoveAt(idx int) INode {
  254. // Validate position
  255. if idx < 0 || idx >= len(n.children) {
  256. panic("Node.RemoveAt: invalid position")
  257. }
  258. child := n.children[idx]
  259. // Remove child from children list
  260. copy(n.children[idx:], n.children[idx+1:])
  261. n.children[len(n.children)-1] = nil
  262. n.children = n.children[:len(n.children)-1]
  263. return child
  264. }
  265. // RemoveAll removes all children.
  266. func (n *Node) RemoveAll(recurs bool) {
  267. for pos, ichild := range n.children {
  268. n.children[pos] = nil
  269. ichild.GetNode().parent = nil
  270. if recurs {
  271. ichild.GetNode().RemoveAll(recurs)
  272. }
  273. }
  274. n.children = n.children[0:0]
  275. }
  276. // DisposeChildren removes and disposes of all children.
  277. // If 'recurs' is true, call DisposeChildren on each child recursively.
  278. func (n *Node) DisposeChildren(recurs bool) {
  279. for pos, ichild := range n.children {
  280. n.children[pos] = nil
  281. ichild.GetNode().parent = nil
  282. if recurs {
  283. ichild.GetNode().DisposeChildren(true)
  284. }
  285. ichild.Dispose()
  286. }
  287. n.children = n.children[0:0]
  288. }
  289. // SetPosition sets the position.
  290. func (n *Node) SetPosition(x, y, z float32) {
  291. n.position.Set(x, y, z)
  292. n.matNeedsUpdate = true
  293. }
  294. // SetPositionVec sets the position based on the specified vector pointer.
  295. func (n *Node) SetPositionVec(vpos *math32.Vector3) {
  296. n.position = *vpos
  297. n.matNeedsUpdate = true
  298. }
  299. // SetPositionX sets the X coordinate of the position.
  300. func (n *Node) SetPositionX(x float32) {
  301. n.position.X = x
  302. n.matNeedsUpdate = true
  303. }
  304. // SetPositionY sets the Y coordinate of the position.
  305. func (n *Node) SetPositionY(y float32) {
  306. n.position.Y = y
  307. n.matNeedsUpdate = true
  308. }
  309. // SetPositionZ sets the Z coordinate of the position.
  310. func (n *Node) SetPositionZ(z float32) {
  311. n.position.Z = z
  312. n.matNeedsUpdate = true
  313. }
  314. // Position returns the position as a vector.
  315. func (n *Node) Position() math32.Vector3 {
  316. return n.position
  317. }
  318. // SetRotation sets the global rotation in Euler angles (radians).
  319. func (n *Node) SetRotation(x, y, z float32) {
  320. n.rotation.Set(x, y, z)
  321. n.quaternion.SetFromEuler(&n.rotation)
  322. n.matNeedsUpdate = true
  323. }
  324. // SetRotationVec sets the global rotation in Euler angles (radians) based on the specified vector pointer.
  325. func (n *Node) SetRotationVec(vrot *math32.Vector3) {
  326. n.rotation = *vrot
  327. n.quaternion.SetFromEuler(&n.rotation)
  328. n.matNeedsUpdate = true
  329. }
  330. // SetRotationQuat sets the global rotation based on the specified quaternion pointer.
  331. func (n *Node) SetRotationQuat(quat *math32.Quaternion) {
  332. n.quaternion = *quat
  333. n.rotNeedsUpdate = true
  334. }
  335. // SetRotationX sets the global X rotation to the specified angle in radians.
  336. func (n *Node) SetRotationX(x float32) {
  337. if n.rotNeedsUpdate {
  338. n.rotation.SetFromQuaternion(&n.quaternion)
  339. n.rotNeedsUpdate = false
  340. }
  341. n.rotation.X = x
  342. n.quaternion.SetFromEuler(&n.rotation)
  343. n.matNeedsUpdate = true
  344. }
  345. // SetRotationY sets the global Y rotation to the specified angle in radians.
  346. func (n *Node) SetRotationY(y float32) {
  347. if n.rotNeedsUpdate {
  348. n.rotation.SetFromQuaternion(&n.quaternion)
  349. n.rotNeedsUpdate = false
  350. }
  351. n.rotation.Y = y
  352. n.quaternion.SetFromEuler(&n.rotation)
  353. n.matNeedsUpdate = true
  354. }
  355. // SetRotationZ sets the global Z rotation to the specified angle in radians.
  356. func (n *Node) SetRotationZ(z float32) {
  357. if n.rotNeedsUpdate {
  358. n.rotation.SetFromQuaternion(&n.quaternion)
  359. n.rotNeedsUpdate = false
  360. }
  361. n.rotation.Z = z
  362. n.quaternion.SetFromEuler(&n.rotation)
  363. n.matNeedsUpdate = true
  364. }
  365. // Rotation returns the current global rotation in Euler angles (radians).
  366. func (n *Node) Rotation() math32.Vector3 {
  367. if n.rotNeedsUpdate {
  368. n.rotation.SetFromQuaternion(&n.quaternion)
  369. n.rotNeedsUpdate = false
  370. }
  371. return n.rotation
  372. }
  373. // RotateOnAxis rotates around the specified local axis the specified angle in radians.
  374. func (n *Node) RotateOnAxis(axis *math32.Vector3, angle float32) {
  375. var rotQuat math32.Quaternion
  376. rotQuat.SetFromAxisAngle(axis, angle)
  377. n.QuaternionMult(&rotQuat)
  378. }
  379. // RotateX rotates around the local X axis the specified angle in radians.
  380. func (n *Node) RotateX(x float32) {
  381. n.RotateOnAxis(&math32.Vector3{1,0,0}, x)
  382. }
  383. // RotateY rotates around the local Y axis the specified angle in radians.
  384. func (n *Node) RotateY(y float32) {
  385. n.RotateOnAxis(&math32.Vector3{0,1,0}, y)
  386. }
  387. // RotateZ rotates around the local Z axis the specified angle in radians.
  388. func (n *Node) RotateZ(z float32) {
  389. n.RotateOnAxis(&math32.Vector3{0,0,1}, z)
  390. }
  391. // SetQuaternion sets the quaternion based on the specified quaternion unit multiples.
  392. func (n *Node) SetQuaternion(x, y, z, w float32) {
  393. n.quaternion.Set(x, y, z, w)
  394. n.rotNeedsUpdate = true
  395. }
  396. // SetQuaternionVec sets the quaternion based on the specified quaternion unit multiples vector.
  397. func (n *Node) SetQuaternionVec(q *math32.Vector4) {
  398. n.quaternion.Set(q.X, q.Y, q.Z, q.W)
  399. n.rotNeedsUpdate = true
  400. }
  401. // SetQuaternionQuat sets the quaternion based on the specified quaternion pointer.
  402. func (n *Node) SetQuaternionQuat(q *math32.Quaternion) {
  403. n.quaternion = *q
  404. n.rotNeedsUpdate = true
  405. }
  406. // QuaternionMult multiplies the current quaternion by the specified quaternion.
  407. func (n *Node) QuaternionMult(q *math32.Quaternion) {
  408. n.quaternion.Multiply(q)
  409. n.rotNeedsUpdate = true
  410. }
  411. // Quaternion returns the current quaternion.
  412. func (n *Node) Quaternion() math32.Quaternion {
  413. return n.quaternion
  414. }
  415. // SetScale sets the scale.
  416. func (n *Node) SetScale(x, y, z float32) {
  417. n.scale.Set(x, y, z)
  418. n.matNeedsUpdate = true
  419. }
  420. // SetScaleVec sets the scale based on the specified vector pointer.
  421. func (n *Node) SetScaleVec(scale *math32.Vector3) {
  422. n.scale = *scale
  423. n.matNeedsUpdate = true
  424. }
  425. // SetScaleX sets the X scale.
  426. func (n *Node) SetScaleX(sx float32) {
  427. n.scale.X = sx
  428. n.matNeedsUpdate = true
  429. }
  430. // SetScaleY sets the Y scale.
  431. func (n *Node) SetScaleY(sy float32) {
  432. n.scale.Y = sy
  433. n.matNeedsUpdate = true
  434. }
  435. // SetScaleZ sets the Z scale.
  436. func (n *Node) SetScaleZ(sz float32) {
  437. n.scale.Z = sz
  438. n.matNeedsUpdate = true
  439. }
  440. // Scale returns the current scale.
  441. func (n *Node) Scale() math32.Vector3 {
  442. return n.scale
  443. }
  444. // SetDirection sets the direction.
  445. func (n *Node) SetDirection(x, y, z float32) {
  446. n.direction.Set(x, y, z)
  447. n.matNeedsUpdate = true
  448. }
  449. // SetDirectionVec sets the direction based on a vector pointer.
  450. func (n *Node) SetDirectionVec(vdir *math32.Vector3) {
  451. n.direction = *vdir
  452. n.matNeedsUpdate = true
  453. }
  454. // Direction returns the direction.
  455. func (n *Node) Direction() math32.Vector3 {
  456. return n.direction
  457. }
  458. // SetMatrix sets the local transformation matrix.
  459. func (n *Node) SetMatrix(m *math32.Matrix4) {
  460. n.matrix = *m
  461. n.matrix.Decompose(&n.position, &n.quaternion, &n.scale)
  462. }
  463. // Matrix returns a copy of the local transformation matrix.
  464. func (n *Node) Matrix() math32.Matrix4 {
  465. return n.matrix
  466. }
  467. // WorldPosition updates the world matrix and sets
  468. // the specified vector to the current world position of this node.
  469. func (n *Node) WorldPosition(result *math32.Vector3) {
  470. n.UpdateMatrixWorld()
  471. result.SetFromMatrixPosition(&n.matrixWorld)
  472. }
  473. // WorldQuaternion updates the world matrix and sets
  474. // the specified quaternion to the current world quaternion of this node.
  475. func (n *Node) WorldQuaternion(result *math32.Quaternion) {
  476. var position math32.Vector3
  477. var scale math32.Vector3
  478. n.UpdateMatrixWorld()
  479. n.matrixWorld.Decompose(&position, result, &scale)
  480. }
  481. // WorldRotation updates the world matrix and sets
  482. // the specified vector to the current world rotation of this node in Euler angles.
  483. func (n *Node) WorldRotation(result *math32.Vector3) {
  484. var quaternion math32.Quaternion
  485. n.WorldQuaternion(&quaternion)
  486. result.SetFromQuaternion(&quaternion)
  487. }
  488. // WorldScale updates the world matrix and sets
  489. // the specified vector to the current world scale of this node.
  490. func (n *Node) WorldScale(result *math32.Vector3) {
  491. var position math32.Vector3
  492. var quaternion math32.Quaternion
  493. n.UpdateMatrixWorld()
  494. n.matrixWorld.Decompose(&position, &quaternion, result)
  495. }
  496. // WorldDirection updates the world matrix and sets
  497. // the specified vector to the current world direction of this node.
  498. func (n *Node) WorldDirection(result *math32.Vector3) {
  499. var quaternion math32.Quaternion
  500. n.WorldQuaternion(&quaternion)
  501. *result = n.direction
  502. result.ApplyQuaternion(&quaternion)
  503. }
  504. // MatrixWorld returns a copy of the matrix world of this node.
  505. func (n *Node) MatrixWorld() math32.Matrix4 {
  506. return n.matrixWorld
  507. }
  508. // UpdateMatrix updates (if necessary) the local transform matrix
  509. // of this node based on its position, quaternion, and scale.
  510. func (n *Node) UpdateMatrix() bool {
  511. if !n.matNeedsUpdate && !n.rotNeedsUpdate {
  512. return false
  513. }
  514. n.matrix.Compose(&n.position, &n.quaternion, &n.scale)
  515. n.matNeedsUpdate = false
  516. return true
  517. }
  518. // UpdateMatrixWorld updates this node world transform matrix and of all its children
  519. func (n *Node) UpdateMatrixWorld() {
  520. n.UpdateMatrix()
  521. if n.parent == nil {
  522. n.matrixWorld = n.matrix
  523. } else {
  524. parent := n.parent.GetNode()
  525. n.matrixWorld.MultiplyMatrices(&parent.matrixWorld, &n.matrix)
  526. }
  527. // Update this Node children matrices
  528. for _, ichild := range n.children {
  529. ichild.UpdateMatrixWorld()
  530. }
  531. }