PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Rendering/SceneGraph/SceneGraphNode.cs

#
C# | 821 lines | 517 code | 68 blank | 236 comment | 21 complexity | 17b7892abd3061a6f055953ce7175358 MD5 | raw file
Possible License(s): Apache-2.0
  1. #region License
  2. /* Copyright : Santtu Syrjälä
  3. * License : New BSD
  4. *
  5. * SceneGraphNode for Delta Engine
  6. *
  7. * General purpose scene graph for 2D and 3D that is compatible with Delta Engines vertex constructs, cameras and rendering pipeline.
  8. *
  9. * If You find a bug, find a way to make it work faster or other additions to make it more useful please share them! You can find me in Delta Engine forums. You will get Your name
  10. * in here if YOU WISH.
  11. *
  12. * Addition : I don't wa...(of course I want) NEED money for this thing. I though would like You to include me in the credits portion of Your application if You like/use
  13. * this. It is NOT REQUIRED, though it would serve as a little thanks that would warm this programmer's heart.
  14. *
  15. * Changes :
  16. * 10.09.2011 : Release of the preview 0.1.0.0
  17. */
  18. #endregion
  19. using System;
  20. using System.Collections.Generic;
  21. using Delta.Utilities.Datatypes;
  22. namespace Delta.Rendering.SceneGraph
  23. {
  24. /// <summary>
  25. /// Represents Node that can be part of global Scene hierarchy.
  26. /// Note that every SceneNode can have more than one children.
  27. /// </summary>
  28. public class SceneGraphNode
  29. {
  30. #region Constants
  31. /// <summary>
  32. /// Sync object to be locked during RenderAll
  33. /// </summary>
  34. private static readonly object lockObject = new object();
  35. #endregion
  36. #region RenderOrder (Public)
  37. /// <summary>
  38. /// This property sets the child node render order. If ChildrenFirst then
  39. /// child nodes are processed first and then the current node, ChildrenLast
  40. /// is the opposite.
  41. /// </summary>
  42. public ChildrenRenderOrder RenderOrder
  43. {
  44. get;
  45. set;
  46. }
  47. #endregion
  48. #region Parent (Public)
  49. /// <summary>
  50. /// Gets the parent of this node.
  51. /// </summary>
  52. public SceneGraphNode Parent
  53. {
  54. get;
  55. private set;
  56. }
  57. #endregion
  58. #region Root (Public)
  59. /// <summary>
  60. /// Property to get the root node.
  61. /// </summary>
  62. public SceneGraphNode Root
  63. {
  64. get;
  65. private set;
  66. }
  67. #endregion
  68. #region Depth (Public)
  69. /// <summary>
  70. /// Gets the depth of the tree beginning from this node.
  71. /// </summary>
  72. public int Depth
  73. {
  74. get;
  75. private set;
  76. }
  77. #endregion
  78. #region ChildrenCount (Public)
  79. /// <summary>
  80. /// Gets the children count.
  81. /// </summary>
  82. public int ChildrenCount
  83. {
  84. get
  85. {
  86. return children.Count;
  87. }
  88. }
  89. #endregion
  90. #region Children (Public)
  91. /// <summary>
  92. /// Gets enumerator of all children of this node.
  93. /// </summary>
  94. public IEnumerable<SceneGraphNode> Children
  95. {
  96. get
  97. {
  98. return children;
  99. }
  100. }
  101. #endregion
  102. #region LocalPosition (Public)
  103. /// <summary>
  104. /// Gets or Sets the local position.
  105. /// Use method <see cref="GetLocalPosition"/> for performance.
  106. /// </summary>
  107. public Vector LocalPosition
  108. {
  109. get
  110. {
  111. return localPosition;
  112. }
  113. set
  114. {
  115. SetLocalPosition(ref value);
  116. }
  117. }
  118. #endregion
  119. #region LocalRotation (Public)
  120. /// <summary>
  121. /// Property to get the local rotation.
  122. /// Use method <see cref="GetLocalRotation"/> for performance.
  123. /// </summary>
  124. public Vector LocalRotation
  125. {
  126. get
  127. {
  128. UpdateTransformation();
  129. return localRotation;
  130. }
  131. set
  132. {
  133. SetLocalRotation(ref value);
  134. }
  135. }
  136. #endregion
  137. #region LocalScale (Public)
  138. /// <summary>
  139. /// Get or Sets the local scale.
  140. /// Use method <see cref="GetLocalScale"/> for performance.
  141. /// </summary>
  142. public Vector LocalScale
  143. {
  144. get
  145. {
  146. return localScale;
  147. }
  148. set
  149. {
  150. SetLocalScale(ref value);
  151. }
  152. }
  153. #endregion
  154. #region WorldPosition (Public)
  155. /// <summary>
  156. /// Gets the world position.
  157. /// Use method <see cref="GetWorldPosition"/> for performance.
  158. /// </summary>
  159. public Vector WorldPosition
  160. {
  161. get
  162. {
  163. Vector toReturn = Vector.Zero;
  164. GetWorldPosition(ref toReturn);
  165. return toReturn;
  166. }
  167. }
  168. #endregion
  169. #region WorldRotation (Public)
  170. /// <summary>
  171. /// Property to get the world rotation.
  172. /// Use method <see cref="GetWorldRotation"/> for performance.
  173. /// </summary>
  174. public Vector WorldRotation
  175. {
  176. get
  177. {
  178. Vector toReturn = Vector.Zero;
  179. GetWorldRotation(ref toReturn);
  180. return toReturn;
  181. }
  182. }
  183. #endregion
  184. #region WorldScale (Public)
  185. /// <summary>
  186. /// Gets the world scale.
  187. /// Use method <see cref="GetWorldScale"/> for performance.
  188. /// </summary>
  189. public Vector WorldScale
  190. {
  191. get
  192. {
  193. Vector toReturn = Vector.Zero;
  194. GetWorldScale(ref toReturn);
  195. return toReturn;
  196. }
  197. }
  198. #endregion
  199. #region LocalTransformation (Public)
  200. /// <summary>
  201. /// Local transformation matrix, copy value type.
  202. /// Use method <see cref="GetLocalTransformation"/> for performance.
  203. /// </summary>
  204. public Matrix LocalTransformation
  205. {
  206. get
  207. {
  208. UpdateTransformation();
  209. return localTransformation;
  210. }
  211. }
  212. #endregion
  213. #region WorldTransformation (Public)
  214. /// <summary>
  215. /// World transformation matrix, copy value type.
  216. /// Use method <see cref="GetWorldTransformation"/> for performance.
  217. /// </summary>
  218. public Matrix WorldTransformation
  219. {
  220. get
  221. {
  222. UpdateTransformation();
  223. return worldTransformation;
  224. }
  225. }
  226. #endregion
  227. #region Protected
  228. #region worldTransformation (Protected)
  229. /// <summary>
  230. /// Matrix combined with Parent local transformation.
  231. /// </summary>
  232. protected Matrix worldTransformation;
  233. #endregion
  234. #region Recalculate (Protected)
  235. /// <summary>
  236. /// If recalculate is true, UpdateTransformation recalculates world matrix.
  237. /// </summary>
  238. protected bool Recalculate
  239. {
  240. get
  241. {
  242. return recalculate;
  243. }
  244. private set
  245. {
  246. recalculate = value;
  247. foreach (SceneGraphNode node in children)
  248. {
  249. node.Recalculate = true;
  250. }
  251. }
  252. }
  253. #endregion
  254. #endregion
  255. #region Private
  256. #region localPosition (Private)
  257. /// <summary>
  258. /// Local position of this node.
  259. /// </summary>
  260. private Vector localPosition;
  261. #endregion
  262. #region localRotation (Private)
  263. /// <summary>
  264. /// Local rotation of this node.
  265. /// </summary>
  266. private Vector localRotation;
  267. #endregion
  268. #region localScale (Private)
  269. /// <summary>
  270. /// Local scale of this node.
  271. /// </summary>
  272. private Vector localScale;
  273. #endregion
  274. #region localTransformation (Private)
  275. /// <summary>
  276. /// Local transformation of this node.
  277. /// </summary>
  278. private Matrix localTransformation;
  279. #endregion
  280. #region recalculate (Private)
  281. /// <summary>
  282. /// Value that indicates whether to calculate the full transformation.
  283. /// </summary>
  284. private bool recalculate;
  285. #endregion
  286. #region children (Private)
  287. /// <summary>
  288. /// List containing all children of this node.
  289. /// </summary>
  290. private readonly List<SceneGraphNode> children = new List<SceneGraphNode>();
  291. #endregion
  292. #endregion
  293. #region Constructors
  294. /// <summary>
  295. /// Creates a new instance of <see cref="SceneGraphNode"/>
  296. /// </summary>
  297. public SceneGraphNode()
  298. {
  299. ResetLocal();
  300. Root = this;
  301. RenderOrder = ChildrenRenderOrder.ChildrenFirst;
  302. }
  303. #endregion
  304. #region ResetLocal (Public)
  305. /// <summary>
  306. /// Resets the node to original values.
  307. /// </summary>
  308. public void ResetLocal()
  309. {
  310. localPosition = Vector.Zero;
  311. localRotation = Vector.Zero;
  312. localScale = Vector.One;
  313. Recalculate = true;
  314. }
  315. #endregion
  316. #region Add (Public)
  317. /// <summary>
  318. /// Add a new node to the end of the child node list.
  319. /// </summary>
  320. /// <param name="toAdd">Node to add.</param>
  321. public void Add(SceneGraphNode toAdd)
  322. {
  323. // Check if node was already added.
  324. if (children.Contains(toAdd))
  325. {
  326. return;
  327. }
  328. children.Add(toAdd);
  329. toAdd.Root = Root;
  330. toAdd.Parent = this;
  331. toAdd.Recalculate = true;
  332. CheckDepth(toAdd);
  333. }
  334. /// <summary>
  335. /// Adds an enumerable list of SceneGraphNode to this node.
  336. /// </summary>
  337. /// <param name="toAdd">Nodes to add.</param>
  338. public void Add(IEnumerable<SceneGraphNode> toAdd)
  339. {
  340. foreach (SceneGraphNode iterNode in toAdd)
  341. {
  342. Add(iterNode);
  343. }
  344. }
  345. #endregion
  346. #region Insert (Public)
  347. /// <summary>
  348. /// Inserts node at specific position.
  349. /// </summary>
  350. /// <param name="index">Index where to insert.</param>
  351. /// <param name="toAdd">Node to add.</param>
  352. public void Insert(int index, SceneGraphNode toAdd)
  353. {
  354. children.Insert(index, toAdd);
  355. toAdd.Parent = this;
  356. toAdd.Root = Root;
  357. toAdd.Recalculate = true;
  358. CheckDepth(toAdd);
  359. }
  360. /// <summary>
  361. /// Inserts enumerable list of nodes at specific location.
  362. /// </summary>
  363. /// <param name="index">Index where to insert.</param>
  364. /// <param name="toAdd">Nodes to add.</param>
  365. public void Insert(int index, IEnumerable<SceneGraphNode> toAdd)
  366. {
  367. children.InsertRange(index, toAdd);
  368. foreach (SceneGraphNode node in toAdd)
  369. {
  370. node.Parent = this;
  371. node.Root = Root;
  372. node.Recalculate = true;
  373. CheckDepth(node);
  374. }
  375. }
  376. #endregion
  377. #region Remove (Public)
  378. /// <summary>
  379. /// Removes child node.
  380. /// </summary>
  381. /// <param name="toRemove">Node to remove.</param>
  382. /// <returns>True if remove succeeded.</returns>
  383. public bool Remove(SceneGraphNode toRemove)
  384. {
  385. // Check if children exists.
  386. if (children.Contains(toRemove) == false)
  387. {
  388. return false;
  389. }
  390. bool toReturn = children.Remove(toRemove);
  391. if (toReturn)
  392. {
  393. toRemove.Root = null;
  394. toRemove.Parent = null;
  395. toRemove.CheckDepth(null);
  396. }
  397. CheckDepth(null);
  398. return toReturn;
  399. }
  400. #endregion
  401. #region RemoveAt (Public)
  402. /// <summary>
  403. /// Removes child node at index.
  404. /// </summary>
  405. /// <param name="index">Index where to remove.</param>
  406. public void RemoveAt(int index)
  407. {
  408. if (index > children.Count - 1)
  409. {
  410. throw new ArgumentOutOfRangeException("index");
  411. }
  412. SceneGraphNode toRemove = children[index];
  413. toRemove.Root = null;
  414. children.RemoveAt(index);
  415. toRemove.Parent = null;
  416. toRemove.CheckDepth(null);
  417. CheckDepth(null);
  418. }
  419. #endregion
  420. #region RemoveFromParent (Public)
  421. /// <summary>
  422. /// Removes this node from parent.
  423. /// </summary>
  424. public void RemoveFromParent()
  425. {
  426. if (Parent != null)
  427. {
  428. Parent.Remove(this);
  429. }
  430. }
  431. #endregion
  432. #region Clear (Public)
  433. /// <summary>
  434. /// Removes all child nodes.
  435. /// </summary>
  436. public void Clear()
  437. {
  438. children.Clear();
  439. CheckDepth(null);
  440. }
  441. #endregion
  442. #region GetLocalPosition (Public)
  443. /// <summary>
  444. /// Method to get the local position.
  445. /// </summary>
  446. /// <param name="whereToSet">Where to store the position.</param>
  447. public void GetLocalPosition(ref Vector whereToSet)
  448. {
  449. UpdateTransformation();
  450. whereToSet = localPosition;
  451. }
  452. #endregion
  453. #region SetLocalPosition (Public)
  454. /// <summary>
  455. /// Set the local position.
  456. /// </summary>
  457. /// <param name="toSet">What to set.</param>
  458. public virtual void SetLocalPosition(ref Vector toSet)
  459. {
  460. localPosition = toSet;
  461. Recalculate = true;
  462. }
  463. /// <summary>
  464. /// Set local position.
  465. /// </summary>
  466. /// <param name="x">X coordinate.</param>
  467. /// <param name="y">Y coordinate.</param>
  468. /// <param name="z">Z coordinate.</param>
  469. public virtual void SetLocalPosition(float x, float y, float z)
  470. {
  471. localPosition.X = x;
  472. localPosition.Y = y;
  473. localPosition.Z = z;
  474. Recalculate = true;
  475. }
  476. #endregion
  477. #region OffsetLocalPosition (Public)
  478. /// <summary>
  479. /// Offset the local position with given value.
  480. /// </summary>
  481. /// <param name="toSet">What to offset.</param>
  482. /// <param name="toOffset">Offset</param>
  483. public virtual void OffsetLocalPosition(ref Vector toOffset)
  484. {
  485. localPosition.X += toOffset.X;
  486. localPosition.Y += toOffset.Y;
  487. localPosition.Z += toOffset.Z;
  488. Recalculate = true;
  489. }
  490. /// <summary>
  491. /// Method to offset local position.
  492. /// </summary>
  493. /// <param name="x">X coordinate.</param>
  494. /// <param name="y">Y coordinate.</param>
  495. /// <param name="z">Z coordinate.</param>
  496. public virtual void OffsetLocalPosition(float x, float y, float z)
  497. {
  498. localPosition.X += x;
  499. localPosition.Y += y;
  500. localPosition.Z += z;
  501. Recalculate = true;
  502. }
  503. #endregion
  504. #region GetLocalRotation (Public)
  505. /// <summary>
  506. /// Method to get the local rotation.
  507. /// </summary>
  508. /// <param name="whereToSet">Where to store the rotation.</param>
  509. public void GetLocalRotation(ref Vector whereToSet)
  510. {
  511. UpdateTransformation();
  512. whereToSet = localRotation;
  513. }
  514. #endregion
  515. #region SetLocalRotation (Public)
  516. /// <summary>
  517. /// Method to set the local rotation.
  518. /// </summary>
  519. /// <param name="toSet">What to set.</param>
  520. public virtual void SetLocalRotation(ref Vector toSet)
  521. {
  522. localRotation = toSet;
  523. Recalculate = true;
  524. }
  525. /// <summary>
  526. /// Method to set local rotation.
  527. /// </summary>
  528. /// <param name="x">X coordinate.</param>
  529. /// <param name="y">Y coordinate.</param>
  530. /// <param name="z">Z coordinate.</param>
  531. public virtual void SetLocalRotation(float x, float y, float z)
  532. {
  533. localRotation.X = x;
  534. localRotation.Y = y;
  535. localRotation.Z = z;
  536. Recalculate = true;
  537. }
  538. #endregion
  539. #region GetLocalScale (Public)
  540. /// <summary>
  541. /// Method to get the local scale.
  542. /// </summary>
  543. /// <param name="whereToSet">Where to store the scale.</param>
  544. public void GetLocalScale(ref Vector whereToSet)
  545. {
  546. UpdateTransformation();
  547. whereToSet = localScale;
  548. }
  549. #endregion
  550. #region SetLocalScale (Public)
  551. /// <summary>
  552. /// Method for setting the local scale.
  553. /// </summary>
  554. /// <param name="toSet">What to set.</param>
  555. public virtual void SetLocalScale(ref Vector toSet)
  556. {
  557. localScale = toSet;
  558. Recalculate = true;
  559. }
  560. /// <summary>
  561. /// Method for setting local scale.
  562. /// </summary>
  563. /// <param name="x">X coordinate.</param>
  564. /// <param name="y">Y coordinate.</param>
  565. /// <param name="z">Z coordinate.</param>
  566. public virtual void SetLocalScale(float x, float y, float z)
  567. {
  568. localScale.X = x;
  569. localScale.Y = y;
  570. localScale.Z = z;
  571. Recalculate = true;
  572. }
  573. #endregion
  574. #region GetLocalTransformation (Public)
  575. /// <summary>
  576. /// Method to get the local transformation matrix.
  577. /// </summary>
  578. /// <param name="whereToGet">Where the local matrix is stored.</param>
  579. public void GetLocalTransformation(ref Matrix whereToGet)
  580. {
  581. UpdateTransformation();
  582. whereToGet = localTransformation;
  583. }
  584. #endregion
  585. #region GetWorldTransformation (Public)
  586. /// <summary>
  587. /// Method to get the world transformation matrix.
  588. /// </summary>
  589. /// <param name="whereToGet">Where the world matrix is stored.</param>
  590. public void GetWorldTransformation(ref Matrix whereToGet)
  591. {
  592. UpdateTransformation();
  593. whereToGet = worldTransformation;
  594. }
  595. #endregion
  596. #region GetWorldPosition (Public)
  597. /// <summary>
  598. /// Method to get the world position of the node.
  599. /// </summary>
  600. /// <param name="whereToSet">Where to store the position.</param>
  601. public void GetWorldPosition(ref Vector whereToSet)
  602. {
  603. UpdateTransformation();
  604. whereToSet = worldTransformation.Translation;
  605. }
  606. #endregion
  607. #region GetWorldRotation (Public)
  608. /// <summary>
  609. /// Method to getting the world rotation.
  610. /// </summary>
  611. /// <param name="whereToSet">Where to store the rotation.</param>
  612. public void GetWorldRotation(ref Vector whereToSet)
  613. {
  614. UpdateTransformation();
  615. // There could be easier way to do this...
  616. SceneGraphNode current = this;
  617. whereToSet.X = 0;
  618. whereToSet.Y = 0;
  619. whereToSet.Z = 0;
  620. while (current != null)
  621. {
  622. Vector.Add(ref whereToSet, ref current.localRotation, out whereToSet);
  623. current = current.Parent;
  624. }
  625. whereToSet.X = whereToSet.X % 360.0f;
  626. whereToSet.Y = whereToSet.Y % 360.0f;
  627. whereToSet.Z = whereToSet.Z % 360.0f;
  628. }
  629. #endregion
  630. #region GetWorldScale (Public)
  631. /// <summary>
  632. ///Get the world scale.
  633. /// </summary>
  634. /// <param name="whereToSet">Where to store the scale.</param>
  635. public void GetWorldScale(ref Vector whereToSet)
  636. {
  637. UpdateTransformation();
  638. whereToSet = worldTransformation.Scaling;
  639. }
  640. #endregion
  641. #region Render (Public)
  642. /// <summary>
  643. /// Render method to be called when this node is to be rendered.
  644. /// Override if you need to render this node.
  645. /// </summary>
  646. public virtual void Render()
  647. {
  648. }
  649. #endregion
  650. #region RenderAll (Public)
  651. /// <summary>
  652. /// Renders all child nodes and this node.
  653. /// </summary>
  654. public void RenderAll()
  655. {
  656. lock (lockObject)
  657. {
  658. UpdateTransformation();
  659. int i;
  660. switch (RenderOrder)
  661. {
  662. case ChildrenRenderOrder.ChildrenFirst:
  663. for (i = 0; i < children.Count; i++)
  664. {
  665. children[i].RenderAll();
  666. }
  667. // Render this node for last.
  668. Render();
  669. break;
  670. default:
  671. // Render this node for first.
  672. Render();
  673. for (i = 0; i < children.Count; i++)
  674. {
  675. children[i].RenderAll();
  676. }
  677. break;
  678. }
  679. }
  680. }
  681. #endregion
  682. #region Methods (Private)
  683. #region UpdateTransformation
  684. /// <summary>
  685. /// Updates local and world transformation if needed, so if Recalculate is
  686. /// true then it is recalculated.
  687. /// </summary>
  688. /// <returns>
  689. /// True if the matrices were recalculated.
  690. /// </returns>
  691. protected virtual bool UpdateTransformation()
  692. {
  693. bool toReturn = false;
  694. lock (this)
  695. {
  696. if (Recalculate)
  697. {
  698. // Order is: Scale - Rotation - Translation
  699. toReturn = true;
  700. localTransformation = Matrix.CreateScale(localScale);
  701. Matrix tempMatrix = Matrix.CreateRotationZYX(localRotation.X,
  702. localRotation.Y, localRotation.Z);
  703. Matrix.Multiply(ref localTransformation, ref tempMatrix,
  704. ref localTransformation);
  705. tempMatrix = Matrix.CreateTranslation(localPosition);
  706. Matrix.Multiply(ref localTransformation, ref tempMatrix,
  707. ref localTransformation);
  708. // Combine with parent, if any.
  709. if (Parent != null)
  710. {
  711. Parent.UpdateTransformation();
  712. Matrix.Multiply(ref localTransformation,
  713. ref Parent.worldTransformation, ref worldTransformation);
  714. }
  715. else
  716. {
  717. worldTransformation = localTransformation;
  718. }
  719. Recalculate = false;
  720. }
  721. }
  722. return toReturn;
  723. }
  724. #endregion
  725. #region CheckDepth
  726. /// <summary>
  727. /// Checks the node depth.
  728. /// </summary>
  729. /// <param name="toCheck">Graph node to check.</param>
  730. private void CheckDepth(SceneGraphNode toCheck)
  731. {
  732. int oldDepth = Depth;
  733. if (toCheck == null)
  734. {
  735. Depth = 0;
  736. foreach (SceneGraphNode node in children)
  737. {
  738. Depth = Math.Max(1 + node.Depth, Depth);
  739. }
  740. }
  741. else
  742. {
  743. Depth = Math.Max(1 + toCheck.Depth, Depth);
  744. }
  745. if (oldDepth != Depth && Parent != null)
  746. {
  747. Parent.CheckDepth(null);
  748. }
  749. }
  750. #endregion
  751. #endregion
  752. }
  753. }