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 @class c3dl.Collada represents the model data from a collada file. To 8 load a collada file into a scene, the file must first be called 9 with c3dl.addModel('plane.dae'). This makes sure the file 10 is parsed before it is used. In the main function, you can create 11 instances of the collada file: 12 <br /> 13 <br /> 14 var collada = new c3dl.Collada();<br /> 15 collada.init('plane.dae');<br /> 16 17 @augments c3dl.Primitive 18 */ 19 c3dl.Collada = c3dl.inherit(c3dl.Primitive, function() 20 { 21 c3dl._superc(this); 22 23 this.path = null; 24 this.sceneGraph = null; 25 }); 26 27 28 /** 29 Get the path of collada file loaded. This is set when init() 30 is called. 31 32 @returns {String} 33 */ 34 c3dl.Collada.prototype.getPath = function() 35 { 36 if( this.isReady()) 37 { 38 return this.path; 39 } 40 } 41 42 /** 43 Get the angular velocity of the scenegraph's root node. 44 45 @returns 46 */ 47 c3dl.Collada.prototype.getAngularVel = function() 48 { 49 if( this.isReady()) 50 { 51 return this.sceneGraph.getAngularVel(); 52 } 53 } 54 55 /** 56 Get the linear velocity of the scenegraph's root node. 57 58 @returns 59 */ 60 c3dl.Collada.prototype.getLinearVel = function() 61 { 62 if( this.isReady()) 63 { 64 return this.sceneGraph.getLinearVel(); 65 } 66 } 67 68 /** 69 Get the position of the scene graph's root. 70 71 @returns {Array} 72 */ 73 c3dl.Collada.prototype.getPosition = function() 74 { 75 if( this.isReady()) 76 { 77 return this.sceneGraph.getPosition(); 78 } 79 } 80 81 /** 82 Set the angular velocity of the scenegraph's root node. 83 84 @param {Array} vec 85 */ 86 c3dl.Collada.prototype.setAngularVel = function(vec) 87 { 88 if( this.isReady()) 89 { 90 this.sceneGraph.setAngularVel(vec); 91 } 92 } 93 94 /** 95 Get the up vector of the scenegraph's root node. 96 97 @return {Array} 98 */ 99 c3dl.Collada.prototype.getUp = function() 100 { 101 if( this.isReady()) 102 { 103 return this.sceneGraph.getUp(); 104 } 105 } 106 107 /** 108 Get the left vector of the scenegraph's root node. 109 110 @return {Array} 111 */ 112 c3dl.Collada.prototype.getLeft = function() 113 { 114 if( this.isReady()) 115 { 116 return this.sceneGraph.getLeft(); 117 } 118 } 119 120 /** 121 Get the direction vector of the scenegraph's root node. 122 123 @returns {Array} 124 */ 125 c3dl.Collada.prototype.getDirection = function() 126 { 127 if( this.isReady()) 128 { 129 return this.sceneGraph.getDirection(); 130 } 131 } 132 133 /** 134 Can this object be picked when the user clicks on it? In some scripts using 135 the library, it may not make sense for wall, for example to be picked. If the 136 object cannot be picked, it will not tested against the ray which is generated 137 then the user clicks the canvas, thus increasing performance. 138 139 @returns {bool} true if the object can be picked, false otherwise. 140 */ 141 c3dl.Collada.prototype.getPickable = function() 142 { 143 if( this.isReady()) 144 { 145 return this.sceneGraph.getPickable(); 146 } 147 } 148 149 /** 150 Set whether this object should be included in picking tests. By omitting 151 objects which should not be interacted with, it can increase performance. 152 153 @param {bool} isPickable true if the object should be included in pikcing tests, 154 false otherwise. 155 */ 156 c3dl.Collada.prototype.setPickable = function(isPickable) 157 { 158 if( this.isReady()) 159 { 160 this.sceneGraph.setPickable(isPickable); 161 } 162 } 163 164 /** 165 Set the linear velocity of the scenegraph's root node. 166 167 @param {Array} vec 168 */ 169 c3dl.Collada.prototype.setLinearVel = function(vec) 170 { 171 if( this.isReady()) 172 { 173 this.sceneGraph.setLinearVel(vec); 174 } 175 } 176 177 /** 178 This should be called after the collada object is created. It will be 179 assigned a structural copy of the collada object which exists in the 180 ColladaManager. This object will then be able to update the 181 transformations without changing the object in the manager class. The 182 nodes are copied, however the arrays of vertices, normals, etc are not. 183 References exsist within this object which will point to the vertex arrays 184 in the manager object. 185 186 @param {string} daepath path of the collada file. 187 */ 188 c3dl.Collada.prototype.init = function(daePath) 189 { 190 this.path = daePath; 191 192 // if the file is already in the manager, just get a copy of it now, 193 // otherwise put it in queue. 194 195 // Before the scene begins, the user must first specify all the collada files 196 // they will use during the lifetime of the scene. When the scene begins, all 197 // the files they specified will be created and initialized. Either it will 198 // be the first time (they won't exist in the manager) or they want a new 199 // object, in which case a copy must be created. 200 if(c3dl.ColladaManager.isFileLoaded(this.path)) 201 { 202 this.sceneGraph = c3dl.ColladaManager.getSceneGraphCopy(this.path); 203 } 204 else 205 { 206 // this will be called if the scene is being initialized and we are 207 // placing collada objects in the manager. 208 c3dl.ColladaQueue.pushBack(this); 209 } 210 } 211 212 /** 213 @private 214 215 Called automatically 216 217 Update animations for linear velocity and angular velocity. 218 219 @param {float} timeStep 220 */ 221 c3dl.Collada.prototype.update = function(timeStep) 222 { 223 // keep checking to see if the file is done being loaded. 224 if(this.isReady()) 225 { 226 this.sceneGraph.update(timeStep); 227 } 228 else 229 { 230 c3dl.debug.logError('You must call addModel("' + this.path + '"); before canvasMain.'); 231 232 if(c3dl.ColladaManager.isFileLoaded(this.path)) 233 { 234 // get a copy of the scenegraph so we can modify it. 235 this.sceneGraph = c3dl.ColladaManager.getSceneGraphCopy(this.path); 236 } 237 } 238 } 239 240 /** 241 @private 242 */ 243 c3dl.Collada.prototype.setSceneGraph = function(sg) 244 { 245 this.sceneGraph = sg; 246 } 247 248 249 /** 250 @private 251 252 Called automatically 253 254 Render the collada object. 255 256 @param {context} glCanvas3D 257 @param {Scene} scene 258 */ 259 c3dl.Collada.prototype.render = function(glCanvas3D, scene) 260 { 261 if(this.sceneGraph && this.isVisible()) 262 { 263 // tell the root to render. The render() calls 264 // will propogate down the graph. 265 this.sceneGraph.render(glCanvas3D, scene); 266 } 267 } 268 269 /** 270 Scale the the scenegraph's root node. 271 272 @param {Array} scaleVec 273 */ 274 c3dl.Collada.prototype.scale = function(scaleVec) 275 { 276 if( this.isReady()) 277 { 278 this.sceneGraph.scale(scaleVec); 279 } 280 } 281 282 /** 283 Translate the entire Collada object. This will tell the root of the 284 Collada scenegraph to translate by 'trans'. 285 286 @param {Array} trans 287 */ 288 c3dl.Collada.prototype.translate = function(trans) 289 { 290 if( this.isReady()) 291 { 292 this.sceneGraph.translate(trans); 293 } 294 } 295 296 /** 297 Place the object to a new location relative to the world origin. 298 299 @param {Array} pos 300 */ 301 c3dl.Collada.prototype.setPosition = function(pos) 302 { 303 if( this.isReady()) 304 { 305 this.sceneGraph.setPosition(pos); 306 } 307 } 308 309 /** 310 Get the scenegraph of the Collada object. 311 312 @returns {c3dl.SceneNode} Root node of the Collada model's scenegraph. 313 */ 314 c3dl.Collada.prototype.getSceneGraph = function() 315 { 316 return this.sceneGraph; 317 } 318 319 /** 320 Set the texture of all the geometry sections (primitive collation elements 321 or primitiveSets) to this texture. 322 323 @param {string} texturePath Path of the texture. 324 */ 325 c3dl.Collada.prototype.setTexture = function(texturePath) 326 { 327 if(this.isReady()) 328 { 329 this.sceneGraph.setTexture(texturePath); 330 } 331 } 332 333 /** 334 Sets the material of all the geometry sections (primitive collation elements 335 or primitiveSets) to this material. Thus, the entire Collada object will be 336 rendered using this material. 337 338 @param {c3dl.Material} material 339 */ 340 c3dl.Collada.prototype.setMaterial = function(material) 341 { 342 if( this.isReady()) 343 { 344 this.sceneGraph.setMaterial(material); 345 } 346 } 347 348 /** 349 Set the way this Collada object should be rendered. The 350 Effect will be set to all the nodes within the Collada's 351 scenegraph. This should only be called once the scene has 352 been initialized since on initialization, the built-in 353 effects such as c3dl.effects.GOOCH, c3dl.effects.CARTOON, etc. 354 are created. 355 356 @param {c3dl.Effect} effect 357 */ 358 c3dl.Collada.prototype.setEffect = function(effect) 359 { 360 // add type checking? 361 this.sceneGraph.setEffect(effect); 362 } 363 364 /** 365 Rotate around the up vector by a hard amount. 366 367 @param {float} angle in radians. 368 */ 369 c3dl.Collada.prototype.yaw = function(angle) 370 { 371 if(this.isReady()) 372 { 373 this.sceneGraph.yaw(angle); 374 } 375 } 376 377 /** 378 Rotate around the side vector by a hard amount. 379 380 @param {float} angle in radians. 381 */ 382 c3dl.Collada.prototype.pitch = function(angle) 383 { 384 if( this.isReady()) 385 { 386 this.sceneGraph.pitch(angle); 387 } 388 } 389 390 /** 391 @private 392 */ 393 c3dl.Collada.prototype.isReady = function() 394 { 395 return this.sceneGraph != null ? true: false; 396 } 397 398 /** 399 Rotate around the direction vector by a hard amount. 400 401 @param {float} angle in radians. 402 */ 403 c3dl.Collada.prototype.roll = function(angle) 404 { 405 if(this.isReady()) 406 { 407 this.sceneGraph.roll(angle); 408 } 409 } 410 411 /** 412 @private 413 */ 414 c3dl.Collada.prototype.getCopy = function() 415 { 416 var collada = new Collada(); 417 collada.clone(this); 418 return collada; 419 } 420 421 /** 422 @private 423 */ 424 c3dl.Collada.prototype.clone = function(other) 425 { 426 c3dl._super(this, arguments, "clone"); 427 428 this.path = other.path; 429 this.sceneGraph = other.sceneGraph.getCopy(); 430 } 431 432 /** 433 @private 434 Does the given ray intersect with this object? This function will 435 test the ray against all the geometry nodes in the scenegraph and 436 return true as soon as it finds an intersection. 437 438 @param {Array} rayOrigin The ray's origin in view space. 439 @param {Array} rayDir The ray's direction in view space. 440 441 @returns {bool} true if the ray intersects with one of the geometry nodes 442 in the scenegraph. 443 */ 444 c3dl.Collada.prototype.rayIntersectsEnclosures = function(rayOrigin, rayDir) 445 { 446 // Use the matrix stack, but clear it out first 447 c3dl.pushMatrix(); 448 c3dl.loadIdentity(); 449 450 var result = this.sceneGraph.rayIntersectsEnclosures(rayOrigin, rayDir); 451 452 // restore the stack to its previous state. 453 c3dl.popMatrix(); 454 return result; 455 } 456 457 c3dl.Collada.prototype.getObjectType = function() 458 { 459 return c3dl.COLLADA; 460 } 461 462 /** 463 @private 464 Does the given ray intersect with any of the triangles in this object? 465 466 @param {Array} rayOrigin ray's origin in world space. 467 @param {Array} rayDir A normalized direction vector. 468 469 @returns {bool} true if the ray intersects with any triangle in the object. 470 */ 471 c3dl.Collada.prototype.rayIntersectsTriangles = function(rayOrigin, rayDir) 472 { 473 // Use the matrix stack, but clear it out first 474 c3dl.pushMatrix(); 475 c3dl.loadIdentity(); 476 477 var result = this.sceneGraph.rayIntersectsTriangles(rayOrigin, rayDir); 478 479 // restore the stack to its previous state. 480 c3dl.popMatrix(); 481 return result; 482 } 483