/c3dl/scenegraph/scenenode.js

https://github.com/Callaghan/c3dl · JavaScript · 304 lines · 172 code · 29 blank · 103 comment · 33 complexity · 8d564bfe81c2b93fbc446c148f1e3c8e MD5 · raw file

  1. /*
  2. Copyright (c) 2008 Seneca College
  3. Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
  4. */
  5. /**
  6. @private
  7. @class c3dl.SceneNode
  8. */
  9. c3dl.SceneNode = c3dl.inherit(c3dl.Primitive, function () {
  10. c3dl._superc(this);
  11. // An array of c3dl.Actors
  12. this.children = [];
  13. this.parent =null;
  14. });
  15. /**
  16. @private
  17. Get a copy of this node and all its children.
  18. */
  19. c3dl.SceneNode.prototype.getCopy = function () {
  20. var sceneNode = new c3dl.SceneNode();
  21. sceneNode.clone(this);
  22. return sceneNode;
  23. }
  24. /**
  25. @private
  26. */
  27. c3dl.SceneNode.prototype.clone = function (other) {
  28. c3dl._super(this, arguments, "clone");
  29. // copy all the children
  30. for (var i = 0, len = other.children.length; i < len; i++) {
  31. this.addChild(other.children[i].getCopy());
  32. }
  33. }
  34. /**
  35. @private
  36. Add a child to this node
  37. @param child
  38. */
  39. c3dl.SceneNode.prototype.addChild = function (child) {
  40. this.children.push(child);
  41. child.parent = this;
  42. }
  43. /**
  44. @private
  45. private until function is tested.
  46. Ask every child node if they are named 'nodeName'.
  47. @param nodeName
  48. */
  49. c3dl.SceneNode.prototype.findNode = function (nodeName) {
  50. var child = null;
  51. // check first if this node is the one user is looking for.
  52. if (nodeName == this.name) {
  53. child = this;
  54. }
  55. // otherwise check the children
  56. else {
  57. for (var i = 0, len = this.children.length; i < len; i++) {
  58. //
  59. if (this.children[i] instanceof c3dl.SceneNode) {
  60. child = this.children[i].findNode(nodeName);
  61. // if we found something it wont be null, so we can
  62. // skip checking the other nodes
  63. if (child != null) {
  64. break;
  65. }
  66. }
  67. }
  68. }
  69. return child;
  70. }
  71. /**
  72. @private
  73. Called automatically.
  74. Update animations, etc.
  75. @param {float} timeStep
  76. */
  77. c3dl.SceneNode.prototype.update = function (timeStep, scaleVec) {
  78. c3dl._super(this, arguments, "update");
  79. c3dl.multiplyVectorByVector(scaleVec, this.scaleVec, scaleVec);
  80. c3dl.pushMatrix();
  81. c3dl.multMatrix(this.getTransform());
  82. c3dl.matrixMode(c3dl.PROJECTION);
  83. c3dl.pushMatrix();
  84. c3dl.multMatrix(this.getRotateMat());
  85. c3dl.matrixMode(c3dl.MODELVIEW);
  86. c3dl.multiplyVector(this.linVel, timeStep, c3dl.vec1);
  87. c3dl.addVectors(this.pos, c3dl.vec1, this.pos);
  88. for (var i = 0; i < this.children.length; i++) {
  89. this.children[i].update(timeStep, scaleVec);
  90. }
  91. // Apply some rotations to the orientation from the angular velocity
  92. this.pitch(this.angVel[0] * timeStep);
  93. this.yaw(this.angVel[1] * timeStep);
  94. this.roll(this.angVel[2] * timeStep);
  95. c3dl.popMatrix();
  96. c3dl.matrixMode(c3dl.PROJECTION);
  97. c3dl.popMatrix();
  98. c3dl.matrixMode(c3dl.MODELVIEW);
  99. }
  100. /**
  101. @private
  102. Called automatically.
  103. When scene nodes are rendered, they first push on their matrix
  104. onto the stack, and render their children. By doing this, all
  105. children will be rendered relative to their parent which is this node.
  106. */
  107. c3dl.SceneNode.prototype.render = function (glCanvas3D, scene) {
  108. c3dl.pushMatrix();
  109. c3dl.multMatrix(this.getTransform());
  110. for (var i = 0, len = this.children.length; i < len; i++) {
  111. this.children[i].render(glCanvas3D, scene);
  112. }
  113. c3dl.popMatrix();
  114. }
  115. c3dl.SceneNode.prototype.renderBoundingVolumes = function (scene) {
  116. for (var i = 0, len = this.children.length; i < len; i++) {
  117. this.children[i].renderBoundingVolumes(scene);
  118. }
  119. }
  120. /**
  121. @private
  122. Set the texture for all the geometry leaves in the scenegraph.
  123. This should be used when a model file has many meshes and each
  124. mesh uses the same texture file.
  125. @param {String} textureName
  126. */
  127. c3dl.SceneNode.prototype.setTexture = function (textureName) {
  128. for (var i = 0, len = this.children.length; i < len; i++) {
  129. this.children[i].setTexture(textureName);
  130. }
  131. }
  132. c3dl.SceneNode.prototype.updateTextureByName = function (oldTexturePath,newTexturePath)
  133. {
  134. for (var i = 0, len = this.children.length; i < len; i++)
  135. {
  136. this.children[i].updateTextureByName(oldTexturePath,newTexturePath);
  137. }
  138. }
  139. /**
  140. @private
  141. */
  142. c3dl.SceneNode.prototype.setMaterial = function (material) {
  143. for (var i = 0, len = this.children.length; i < len; i++) {
  144. this.children[i].setMaterial(material);
  145. }
  146. }
  147. /**
  148. */
  149. c3dl.SceneNode.prototype.setEffect = function (effect) {
  150. for (var i = 0, len = this.children.length; i < len; i++) {
  151. this.children[i].setEffect(effect);
  152. }
  153. }
  154. /**
  155. @private
  156. Called automatically
  157. Do any of the triangles in any of the geometry child nodes of this node intersect
  158. with the given ray?
  159. @param {Array} rayOrigin
  160. @param {Array} rayDir
  161. @returns {bool} true if any child geometry node has intersected the ray.
  162. */
  163. c3dl.SceneNode.prototype.rayIntersectsTriangles = function (rayOrigin, rayDir) {
  164. c3dl.pushMatrix();
  165. c3dl.multMatrix(this.getTransform());
  166. var passed = false;
  167. for (var i = 0, len = this.children.length; i < len; i++) {
  168. // found a node which passed, we don't have to test the rest of the nodes.
  169. if (this.children[i].rayIntersectsTriangles(rayOrigin, rayDir)) {
  170. passed = true;
  171. break;
  172. }
  173. }
  174. c3dl.popMatrix();
  175. return passed;
  176. }
  177. /**
  178. @private
  179. Called automatically.
  180. Do any of the geometry child nodes of this node intersect with the given ray?
  181. @param {Array} rayOrigin
  182. @param {Array} rayDir
  183. @returns {bool} true if any child geometry node has intersected the ray.
  184. */
  185. c3dl.SceneNode.prototype.rayIntersectsEnclosures = function (rayOrigin, rayDir) {
  186. var passed = false;
  187. // iterate over each child or stop until we find one which has passed the Bounding
  188. // sphere test.
  189. for (var i = 0, len = this.children.length; i < len; i++) {
  190. // found a node which passed, we don't have to test the rest of the nodes.
  191. if (this.children[i].rayIntersectsEnclosures(rayOrigin, rayDir)) {
  192. passed = true;
  193. break;
  194. }
  195. }
  196. return passed;
  197. }
  198. c3dl.SceneNode.prototype.getBoundingVolumes = function () {
  199. var boundingVolumes = [];
  200. for (var i = 0; i < this.children.length; i++) {
  201. if (this.children[i] instanceof c3dl.SceneNode) {
  202. boundingVolumes = boundingVolumes.concat(this.children[i].getBoundingVolumes());
  203. }
  204. else if (this.children[i] instanceof c3dl.Geometry) {
  205. for (var j = 0; j < this.children[i].getPrimitiveSets().length; j++) {
  206. if (this.children[i].getPrimitiveSets()[j].getBoundingVolume()) {
  207. boundingVolumes = boundingVolumes.concat(this.children[i].getPrimitiveSets()[j].getBoundingVolume());
  208. }
  209. }
  210. }
  211. }
  212. return boundingVolumes;
  213. }
  214. c3dl.SceneNode.prototype.getAllVerts = function (first) {
  215. var allverts = [];
  216. var numverts = 0;
  217. var temp2 = [],
  218. temp3 = [];
  219. c3dl.pushMatrix();
  220. if (!first)c3dl.multMatrix(this.getTransform());
  221. for (var i = 0; i < this.children.length; i++) {
  222. if (this.children[i] instanceof c3dl.SceneNode) {
  223. allverts = allverts.concat(this.children[i].getAllVerts());
  224. }
  225. else if (this.children[i] instanceof c3dl.Geometry) {
  226. for (var j = 0; j < this.children[i].getPrimitiveSets().length; j++) {
  227. if (this.children[i].getPrimitiveSets()[j].getBoundingVolume()) {
  228. var temp = this.children[i].getPrimitiveSets()[j].getBoundingVolume().getMaxMins();
  229. temp2 = c3dl.multiplyMatrixByVector(c3dl.peekMatrix(), [temp[0], temp[2], temp[4]]);
  230. temp3 = c3dl.multiplyMatrixByVector(c3dl.peekMatrix(), [temp[1], temp[3], temp[5]]);
  231. allverts.push(temp2[0]);
  232. allverts.push(temp2[1]);
  233. allverts.push(temp2[2]);
  234. allverts.push(temp3[0]);
  235. allverts.push(temp3[1]);
  236. allverts.push(temp3[2]);
  237. }
  238. }
  239. }
  240. }
  241. c3dl.popMatrix();
  242. return allverts;
  243. }
  244. c3dl.SceneNode.prototype.center = function (realposition) {
  245. var temp = new c3dl.SceneNode();
  246. for (var j = 0; j < this.children.length; j++) {
  247. temp.addChild(this.children[j]);
  248. }
  249. this.children = [];
  250. this.addChild(temp);
  251. temp.setTransform(c3dl.makePoseMatrix([1, 0, 0], [0, 1, 0], [0, 0, 1], [-realposition[0], -realposition[1], -realposition[2]]));
  252. }