1 /* 2 Copyright (c) 2009 Seneca College 3 Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/) 4 */ 5 6 /** 7 @class c3dl.Actor is a base class for 3D objects. 8 */ 9 c3dl.Actor = function() 10 { 11 // Raw Position Values 12 this.left = c3dl.makeVector(1.0, 0.0, 0.0); // Left vector 13 this.up = c3dl.makeVector(0.0, 1.0, 0.0); // Up Vector 14 this.dir = c3dl.makeVector(0.0, 0.0, 1.0); // Forward Vector 15 this.pos = c3dl.makeVector(0.0, 0.0, 0.0); // Position 16 this.scaleVec = c3dl.makeVector(1.0, 1.0, 1.0); // Scale 17 18 // Delta Values for Animations 19 this.linVel = c3dl.makeVector(0.0, 0.0, 0.0); // Animation of positions 20 this.angVel = c3dl.makeVector(0.0, 0.0, 0.0); // Animations of rotation around (side Vector, up Vector, dir Vector) 21 22 this.name = "unnamed"; 23 } 24 25 // ------------------------------------------------------- 26 27 // Getters 28 29 /** 30 Get the position of the Actor relative to the world origin. 31 32 @returns {Array} The position of the Actor. 33 */ 34 c3dl.Actor.prototype.getPosition = function() 35 { 36 return c3dl.makeVector(this.pos[0], this.pos[1], this.pos[2]); 37 } 38 39 /** 40 The the Up Vector of the actor. 41 42 @returns {Array} The up Vector of the actor. 43 */ 44 c3dl.Actor.prototype.getUp = function() 45 { 46 return c3dl.makeVector(this.up[0], this.up[1], this.up[2]); 47 } 48 49 /** 50 Get the direction of the actor, where the actor is 51 'pointing' or looking'. 52 53 @returns {Array} The direction of the actor. 54 */ 55 c3dl.Actor.prototype.getDirection = function() 56 { 57 return c3dl.makeVector(this.dir[0], this.dir[1], this.dir[2]); 58 } 59 60 /** 61 Get the left Vector of the actor. 62 63 @returns {Array} The left Vector of the actor. 64 */ 65 c3dl.Actor.prototype.getLeft = function() 66 { 67 return c3dl.makeVector(this.left[0], this.left[1], this.left[2]); 68 } 69 70 /** 71 Get the linear velocity of the Actor. 72 73 @returns {Array} The linear velocity of the Actor. 74 */ 75 c3dl.Actor.prototype.getLinearVel = function() 76 { 77 return c3dl.makeVector(this.linVel[0], this.linVel[1], this.linVel[2]); 78 } 79 80 /** 81 Get the angular velocity of the Actor. 82 83 @returns {Array} The angular velocity of the Actor. 84 */ 85 c3dl.Actor.prototype.getAngularVel = function() 86 { 87 return c3dl.makeVector(this.angVel[0], this.angVel[1], this.angVel[2]); 88 } 89 90 /** 91 Get the scale factor of the Actor. It has a default value 92 of (1,1,1) when created. 93 94 @returns {Array} The scale amount of the Actor. 95 */ 96 c3dl.Actor.prototype.getScale = function() 97 { 98 return c3dl.makeVector(this.scaleVec[0], this.scaleVec[1], this.scaleVec[2]); 99 } 100 101 /** 102 Get the transformation of this node. Keep in mind that 103 if this node is 'animated', the matrix will be changing with 104 each update(). In that case, the matrix this function returns 105 will the the state the matrix is in at the time the function is called. 106 107 @return {Array} 108 */ 109 c3dl.Actor.prototype.getTransform = function() 110 { 111 var mat = c3dl.makePoseMatrix(this.left, this.up, this.dir, this.pos); 112 113 var smat = c3dl.makeMatrix(); 114 c3dl.setMatrix(smat, this.scaleVec[0], 0, 0, 0, 115 0, this.scaleVec[1], 0, 0, 116 0, 0, this.scaleVec[2], 0, 117 0, 0, 0, 1 ); 118 119 mat = c3dl.multiplyMatrixByMatrix(mat, smat); 120 121 return mat; 122 } 123 124 /** 125 Get the name of this actor. 126 127 @returns {String} actor's name 128 */ 129 c3dl.Actor.prototype.getName = function() 130 { 131 return this.name; 132 } 133 134 // Setters 135 136 /** 137 Set the transformation of this actor. 138 139 @param {Array} mat 140 */ 141 c3dl.Actor.prototype.setTransform = function(mat) 142 { 143 this.left = c3dl.makeVector(mat[0], mat[1], mat[2]); 144 this.up = c3dl.makeVector(mat[4], mat[5], mat[6]); 145 this.dir = c3dl.makeVector(mat[8], mat[9], mat[10]); 146 this.pos = c3dl.makeVector(mat[12], mat[13], mat[14]); 147 } 148 149 /** 150 */ 151 c3dl.Actor.prototype.resetTransform = function() 152 { 153 this.angVel = c3dl.makeVector(0.0, 0.0, 0.0); 154 this.linVel = c3dl.makeVector(0.0, 0.0, 0.0); 155 156 this.left = c3dl.makeVector(1.0, 0.0, 0.0); 157 this.up = c3dl.makeVector(0.0, 1.0, 0.0); 158 this.dir = c3dl.makeVector(0.0, 0.0, 1.0); 159 this.pos = c3dl.makeVector(0.0, 0.0, 0.0); 160 } 161 162 163 164 /** 165 Scale the Actor relative to its current scaling value. 166 Attempts to scale the x, y or z values of the Actor less 167 than or equal to zero will be ignored. 168 169 @param {Array} scaleVec The amount to scale the Actor. 170 */ 171 c3dl.Actor.prototype.scale = function(scaleVec) 172 { 173 if ( c3dl.isValidVector(scaleVec)) 174 { 175 // none of the values should be less than or equal to zero 176 if( scaleVec[0] > 0.0 && scaleVec[1] > 0.0 && scaleVec[2] > 0.0) 177 { 178 this.scaleVec = [ this.scaleVec[0] * scaleVec[0], 179 this.scaleVec[1] * scaleVec[1], 180 this.scaleVec[2] * scaleVec[2]]; 181 } 182 } 183 else 184 { 185 c3dl.debug.logWarning('Actor::scale() called with a parameter that\'s not a vector'); 186 } 187 } 188 189 /** 190 Set the new location of the Actor. 191 192 @param {Array} vecPos A vector containing the new location for the actor. 193 */ 194 c3dl.Actor.prototype.setPosition = function( vecPos ) 195 { 196 if (c3dl.isValidVector(vecPos)) 197 { 198 this.pos = vecPos; 199 } 200 else 201 { 202 c3dl.debug.logWarning("Actor::setPosition() called with a parameter that's not a vector"); 203 } 204 } 205 206 /** 207 Move the object relative to where it is currently, not relative 208 to the origin. 209 210 @param {Array} translation A vector which represents 211 how far away to move the actor from its current location. 212 */ 213 c3dl.Actor.prototype.translate = function( translation ) 214 { 215 this.pos = c3dl.addVectors(this.pos, translation); 216 } 217 218 219 /** 220 Set the point in space where the Actor will look at (No Animation). 221 222 @param {Array} newVec 223 */ 224 c3dl.Actor.prototype.setForward = function(newVec) 225 { 226 if (c3dl.isValidVector(newVec)) 227 { 228 // Figure out the direction of the point we are looking at 229 this.dir = this.pos; 230 c3dl.subtractVectors(this.dir,newVec, this.dir); 231 c3dl.normalizeVector(this.dir); 232 233 // Adjust the Up and Left vectors accordingly 234 c3dl.vectorCrossProduct(this.up, this.dir, this.left); 235 c3dl.normalizeVector(this.left); 236 c3dl.vectorCrossProduct(this.dir, this.up, this.up); 237 c3dl.normalizeVector(this.up); 238 } 239 else 240 { 241 c3dl.debug.logWarning('Actor::setForward() called with a parameter that\'s not a vector'); 242 } 243 } 244 245 /** 246 Set the orientation of Up (No Animation) 247 248 @param {Array} newVec 249 */ 250 c3dl.Actor.prototype.setUpVector = function(newVec) 251 { 252 if (c3dl.isValidVector(newVec)) 253 { 254 this.up = newVec; 255 } 256 else 257 { 258 c3dl.debug.logWarning('Actor::setUpVector() called with a parameter that\'s not a vector'); 259 } 260 } 261 262 /** 263 Set a new Linear Velocity that will be added to the Position on every update 264 265 @param {Array} newVec 266 */ 267 c3dl.Actor.prototype.setLinearVel = function(newVec) 268 { 269 if (c3dl.isValidVector(newVec)) 270 { 271 this.linVel = newVec; 272 } 273 else 274 { 275 c3dl.debug.logWarning('Actor::setLinearVel() called with a parameter that\'s not a vector'); 276 } 277 } 278 279 /** 280 Set a new Angular Veclocity that will be added to the rotation on 281 every update. 282 283 @param {Array} newVec 284 */ 285 c3dl.Actor.prototype.setAngularVel = function(newVec) 286 { 287 if (c3dl.isValidVector(newVec)) 288 { 289 this.angVel = newVec; 290 } 291 else 292 { 293 c3dl.debug.logWarning("Actor's setAngularVel() called with a parameter that's not a vector"); 294 } 295 } 296 297 /** 298 Set the name of this actor. 299 300 @param {String} name The new name of for this actor. 301 */ 302 c3dl.Actor.prototype.setName = function(name) 303 { 304 this.name = name; 305 } 306 307 // ------------------------------------------------------- 308 309 /** 310 Rotate Actor on an axis which is centered on the position of 311 the Actor. 312 313 @param {Array} axisVec 314 @param {float} angle in radians. 315 */ 316 c3dl.Actor.prototype.rotateOnAxis = function(axisVec, angle) 317 { 318 var rotateOnAxisQuat = c3dl.makeQuat(0, 0, 0, 0); 319 var rotateOnAxisMat = c3dl.makeZeroMatrix(); 320 321 if ( !c3dl.isValidVector(axisVec) ) 322 { 323 c3dl.debug.logWarning('Actor::rotateOnAxis() called with the first parameter not a vector'); 324 return; 325 } 326 if (isNaN(angle)) 327 { 328 c3dl.debug.logWarning('Actor::rotateOnAxis() called with the second parameter not a number'); 329 return; 330 } 331 if( angle == 0) 332 { 333 return; 334 } 335 336 // Create a proper Quaternion based on location and angle 337 c3dl.axisAngleToQuat(axisVec, angle, rotateOnAxisQuat); 338 339 // Create a rotation Matrix out of this quaternion 340 rotateOnAxisMat = c3dl.quatToMatrix(rotateOnAxisQuat); 341 342 // Apply changes to the remaining vectors 343 // 344 c3dl.multiplyMatrixByVector(rotateOnAxisMat, this.dir, this.dir); 345 c3dl.normalizeVector(this.dir); 346 347 c3dl.multiplyMatrixByVector(rotateOnAxisMat, this.left, this.left); 348 c3dl.normalizeVector(this.left); 349 350 c3dl.multiplyMatrixByVector(rotateOnAxisMat, this.up, this.up); 351 c3dl.normalizeVector(this.up); 352 } 353 354 /** 355 Rotate around the Up Vector by a hard amount (No Animation) 356 357 @param {float} angle in radians. 358 */ 359 c3dl.Actor.prototype.yaw = function(angle) 360 { 361 if(angle != 0) 362 { 363 this.rotateOnAxis(this.up, angle); 364 } 365 } 366 367 /** 368 Rotate around the Dir Vector by a hard amount (No Animation) 369 370 @param {float} angle in radians. 371 */ 372 c3dl.Actor.prototype.roll = function(angle) 373 { 374 if(angle != 0) 375 { 376 this.rotateOnAxis(this.dir, angle); 377 } 378 } 379 380 /** 381 Rotate around the Side Vector by a hard amount (No Animation) 382 383 @param {float} angle in radians. 384 */ 385 c3dl.Actor.prototype.pitch = function(angle) 386 { 387 if(angle != 0 ) 388 { 389 this.rotateOnAxis(this.left, angle); 390 } 391 } 392 393 /** 394 @private 395 396 Called automatically. Update animations, etc. 397 398 @param {float} timeStep 399 */ 400 c3dl.Actor.prototype.update = function(timeStep) 401 { 402 // if update took longer than 1/2 a second, it was 403 // probably the GC, so don't apply angular velocities 404 // since that will change the directions. 405 if(timeStep < 500) 406 { 407 // Add a velocity to the position 408 var velVec = this.linVel; 409 c3dl.multiplyVector(velVec, timeStep); 410 c3dl.addVectors(this.pos, velVec, this.pos); 411 412 // Apply some rotations to the orientation from the angular velocity 413 this.pitch(this.angVel[0] * timeStep); 414 this.yaw(this.angVel[1] * timeStep); 415 this.roll(this.angVel[2] * timeStep); 416 } 417 } 418 419 /** 420 @private 421 */ 422 c3dl.Actor.prototype.getCopy = function() 423 { 424 var actor = new c3dl.Actor(); 425 actor.clone(this); 426 return actor; 427 } 428 429 430 /** 431 */ 432 c3dl.Actor.getObjectType = function() 433 { 434 return c3dl.COLLADA; 435 } 436 437 /** 438 @private 439 */ 440 c3dl.Actor.prototype.clone = function(other) 441 { 442 this.left = c3dl.copyVector(other.left); 443 this.up = c3dl.copyVector(other.up); 444 this.dir = c3dl.copyVector(other.dir); 445 this.pos = c3dl.copyVector(other.pos); 446 this.scaleVec = c3dl.copyVector(other.scaleVec); 447 this.linVel = c3dl.copyVector(other.linVel); 448 this.angVel = c3dl.copyVector(other.angVel); 449 this.name = other.name; 450 } 451