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