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 /** 9 @class c3dl.FreeCamera A camera which can be freely moved around in a scene. 10 @augments c3dl.Camera 11 */ 12 c3dl.FreeCamera = c3dl.inherit(c3dl.Camera, function() 13 { 14 c3dl._superc(this); 15 16 // Delta Values for Animations 17 this.linVel = [0.0, 0.0, 0.0]; // Animation of positions 18 this.angVel = [0.0, 0.0, 0.0]; // Animations of rotation around (side Vector, up Vector, dir Vector) 19 }); 20 21 /** 22 Get the camera's angular velocity 23 24 @return {Array} 25 */ 26 c3dl.FreeCamera.prototype.getAngularVel = function() 27 { 28 return [this.angVel[0], this.angVel[1], this.angVel[2]]; 29 } 30 31 32 /** 33 Get the camera's linear velocity 34 35 @returns {Array} 36 */ 37 c3dl.FreeCamera.prototype.getLinearVel = function() 38 { 39 return [this.linVel[0], this.linVel[1], this.linVel[2]]; 40 } 41 42 43 /** 44 Rotate around the Side Vector by a hard amount (No Animation). 45 46 @param {float} angle in radians. 47 */ 48 c3dl.FreeCamera.prototype.pitch = function(angle) 49 { 50 this.rotateOnAxis(this.left, angle); 51 } 52 53 54 /** 55 Rotate around the Dir Vector by a hard amount (No Animation). 56 57 @param {float} angle in radians. 58 */ 59 c3dl.FreeCamera.prototype.roll = function(angle) 60 { 61 this.rotateOnAxis(this.dir, angle); 62 } 63 64 65 /** 66 Rotate camera on an Axis which is centered on the position of the camera. 67 68 @param {Array} axisVec 69 @param {float} angle in radians. 70 */ 71 c3dl.FreeCamera.prototype.rotateOnAxis = function(axisVec, angle) 72 { 73 if ( !c3dl.isValidVector(axisVec) ) 74 { 75 c3dl.debug.logWarning('FreeCamera::rotateOnAxis() called with the first parameter not a vector'); 76 return; 77 } 78 if (isNaN(angle)) 79 { 80 c3dl.debug.logWarning('FreeCamera::rotateOnAxis() called with the second parameter not a number'); 81 return; 82 } 83 84 // Create a proper Quaternion based on location and angle 85 var quat = c3dl.axisAngleToQuat(axisVec, angle); 86 87 // Create a rotation Matrix out of this quaternion 88 var mat = c3dl.quatToMatrix(quat); 89 90 // Apply changes to the remaining vectors 91 c3dl.multiplyMatrixByVector(mat, this.dir, this.dir); 92 c3dl.normalizeVector(this.dir); 93 94 c3dl.multiplyMatrixByVector(mat, this.left, this.left); 95 c3dl.normalizeVector(this.left); 96 97 c3dl.multiplyMatrixByVector(mat, this.up, this.up); 98 c3dl.normalizeVector(this.up); 99 } 100 101 102 /** 103 Set a new Angular Veclocity that will be added to the rotation on 104 every update. 105 106 @param {Array} newVec 107 */ 108 c3dl.FreeCamera.prototype.setAngularVel = function(newVec) 109 { 110 if (c3dl.isValidVector(newVec)) 111 { 112 this.angVel = c3dl.makeVector(newVec[0], newVec[1], newVec[2]); 113 } 114 else 115 { 116 c3dl.debug.logWarning('FreeCamera::setAngularVel() called with a parameter that\'s not a vector'); 117 } 118 } 119 120 121 /** 122 Set a new linear velocity that will be added to the position 123 on every update. 124 125 @param {Array} newVec A vector which contains the direction 126 and speed of the camera. 127 */ 128 c3dl.FreeCamera.prototype.setLinearVel = function(newVec) 129 { 130 if (c3dl.isValidVector(newVec)) 131 { 132 this.linVel = c3dl.makeVector(newVec[0], newVec[1], newVec[2]); 133 } 134 else 135 { 136 c3dl.debug.logWarning('FreeCamera::setLinearVel() called with a parameter that\'s not a vector'); 137 } 138 } 139 140 141 /** 142 Set the point in space where the camera will look at 143 (No Animation). 144 145 @param {Array} newVec The new point the camera will 146 look at. 147 */ 148 c3dl.FreeCamera.prototype.setLookAtPoint = function(newVec) 149 { 150 if (c3dl.isValidVector(newVec)) 151 { 152 // if the position hasn't yet been changed and they want the 153 // camera to look at [0,0,0], that will create a problem. 154 if(c3dl.isVectorEqual(this.pos,[0,0,0]) && c3dl.isVectorEqual(newVec,[0,0,0])) 155 { 156 c3dl.debug.logWarning("Cannot lookAt [0,0,0] since camera is at [0,0,0]." + 157 " Move camera before calling setLookAt()"); 158 } 159 else 160 { 161 // Figure out the direction of the point we are looking at. 162 this.dir = c3dl.subtractVectors( newVec,this.pos); 163 c3dl.normalizeVector(this.dir); 164 165 // Adjust the Up and Left vectors accordingly 166 c3dl.vectorCrossProduct([0,1,0],this.dir, this.left); 167 c3dl.normalizeVector(this.left); 168 c3dl.vectorCrossProduct(this.dir, this.left, this.up); 169 c3dl.normalizeVector(this.up); 170 } 171 } 172 else 173 { 174 c3dl.debug.logWarning("FreeCamera::setLookAtPoint() called with a parameter that's not a vector"); 175 } 176 } 177 178 179 /** 180 Set the new location of the camera. 181 182 @param {Array} newVec An absolute value of where to 183 place the camera. 184 */ 185 c3dl.FreeCamera.prototype.setPosition = function(newVec) 186 { 187 if (c3dl.isValidVector(newVec)) 188 { 189 // Set the new Position of the eye 190 this.pos = newVec; 191 } 192 else 193 { 194 c3dl.debug.logWarning("FreeCamera::setPosition() called with a parameter that's not a vector"); 195 } 196 } 197 198 199 /** 200 Set the orientation of Up (No Animation). 201 202 @param {Array} newVec 203 */ 204 c3dl.FreeCamera.prototype.setUpVector = function(newVec) 205 { 206 if (c3dl.isValidVector(newVec)) 207 { 208 this.up = c3dl.makeVector(newVec[0], newVec[1], newVec[2]); 209 } 210 else 211 { 212 c3dl.debug.logWarning('FreeCamera::setUpVector() called with a parameter that\'s not a vector'); 213 } 214 } 215 216 217 /** 218 Get a string representation of this camera. 219 220 @param {null|String} delimiter A string which will separate values. Typically will be 221 "," , "\n" or "<br />". If none is specified, "," will be used. 222 223 @returns {String} a string representation of this camera. 224 */ 225 c3dl.FreeCamera.prototype.toString = function(delimiter) 226 { 227 // make sure user passed up a string if they actually decided 228 // to specify a delimiter. 229 if(!delimiter || typeof(delimiter) != "string") 230 { 231 delimiter = ","; 232 } 233 234 // get the c3dl.Camera's toString() 235 var cameraToStr = c3dl._super(this, arguments, "toString"); 236 237 var FreeCameraToStr = "c3dl.FreeCamera: " + delimiter + 238 "angular velocity = " + this.getAngularVel() + delimiter + 239 "linear velocity = " + this.getLinearVel() + delimiter; 240 241 return cameraToStr + FreeCameraToStr; 242 } 243 244 245 /** 246 @private 247 248 Called automatically. 249 250 Update Animation of the camera. 251 252 @param {float} timeStep 253 */ 254 c3dl.FreeCamera.prototype.update = function(timeStep) 255 { 256 // 257 if (c3dl.isVectorZero(this.linVel) && c3dl.isVectorZero(this.angVel)) 258 { 259 return false; 260 } 261 262 if (c3dl.vectorLengthSq(this.linVel) > 0.0) 263 { 264 // Add a velocity to the position 265 var velVec = c3dl.makeVector(this.linVel[0], this.linVel[1], this.linVel[2]); 266 c3dl.multiplyVector(velVec, timeStep, velVec); 267 268 c3dl.addVectors(this.pos, velVec, this.pos); 269 } 270 271 if (c3dl.vectorLengthSq(this.angVel) > 0.0) 272 { 273 // Apply some rotations to the orientation from the angular velocity 274 this.pitch(this.angVel[0] * timeStep); 275 this.yaw(this.angVel[1] * timeStep); 276 this.roll(this.angVel[2] * timeStep); 277 } 278 } 279 280 281 /** 282 Rotate around the Up Vector by a hard amount (No Animation). 283 284 @param {float} angle in radians. 285 */ 286 c3dl.FreeCamera.prototype.yaw = function(angle) 287 { 288 this.rotateOnAxis(this.up, angle); 289 } 290