1 /** 2 * Copyright (C) 2009-2012 Klaus Reimer <k@ailis.de> 3 * See LICENSE.txt for licensing information 4 * 5 * @require threedee.js 6 */ 7 8 /** 9 * @constructor 10 * Constructs a new empty vector. 11 * 12 * @param {number=} x 13 * The X coordinate (Optional) 14 * @param {number=} y 15 * The Y coordinate (Optional) 16 * @param {number=} z 17 * The Z coordinate (Optional) 18 * 19 * @class 20 * A vector with three elements. 21 */ 22 threedee.Vector = function(x, y, z) 23 { 24 if (x) this.x = x; 25 if (y) this.y = y; 26 if (z) this.z = z; 27 threedee.Vector.counter++; 28 }; 29 30 /** 31 * Instance counter. 32 * @private 33 * @type {number} 34 */ 35 threedee.Vector.counter = 0; 36 37 /** 38 * The X coordinate. 39 * @type {number} 40 */ 41 threedee.Vector.prototype.x = 0; 42 43 /** 44 * The Y coordinate. 45 * @type {number} 46 */ 47 threedee.Vector.prototype.y = 0; 48 49 /** 50 * The Z coordinate. 51 * @type {number} 52 */ 53 threedee.Vector.prototype.z = 0; 54 55 /** 56 * Returns and resets the current instance counter. 57 * 58 * @return {number} 59 * The number of created instances since the last call 60 */ 61 threedee.Vector.count = function() 62 { 63 var value = threedee.Vector.counter; 64 threedee.Vector.counter = 0; 65 return value; 66 }; 67 68 /** 69 * Returns a copy of this vector. 70 * 71 * @param {?threedee.Vector=} v 72 * Optional target vector 73 * @return {!threedee.Vector} A copy of this vector (or the target vector) 74 */ 75 threedee.Vector.prototype.copy = function(v) 76 { 77 return (v ? v : new threedee.Vector()).set(this.x, this.y, this.z); 78 }; 79 80 /** 81 * Sets the vector coordinates. 82 * 83 * @param {number} x 84 * The X coordinate 85 * @param {number} y 86 * The Y coordinate 87 * @param {number} z 88 * The Z coordinate 89 * @return {!threedee.Vector} 90 * This vector 91 */ 92 threedee.Vector.prototype.set = function(x, y, z) 93 { 94 this.x = x; 95 this.y = y; 96 this.z = z; 97 return this; 98 }; 99 100 /** 101 * Adds the coordinates of the specified vector to this one. 102 * 103 * @param {!threedee.Vector} v 104 * The vector to add 105 * @return {!threedee.Vector} This vector 106 */ 107 threedee.Vector.prototype.add = function(v) 108 { 109 this.x += v.x; 110 this.y += v.y; 111 this.z += v.z; 112 return this; 113 }; 114 115 /** 116 * Subtracts the coordinates of the specified vector from this one. 117 * 118 * @param {!threedee.Vector} v 119 * The vector to subtract 120 * @return {!threedee.Vector} This vector 121 */ 122 threedee.Vector.prototype.sub = function(v) 123 { 124 this.x -= v.x; 125 this.y -= v.y; 126 this.z -= v.z; 127 return this; 128 }; 129 130 /** 131 * Scales the vector with the specified factors. 132 * 133 * @param {number} fx 134 * The X factor 135 * @param {number} fy 136 * The Y factor (Optional. Defaults to fx) 137 * @param {number} fz 138 * The Z factor (Optional. Defaults to fx) 139 * @return {!threedee.Vector} This vector 140 */ 141 threedee.Vector.prototype.scale = function(fx, fy, fz) 142 { 143 this.x *= fx; 144 this.y *= fy === undefined ? fx : fy; 145 this.z *= fy === undefined ? fx : fz; 146 return this; 147 }; 148 149 /** 150 * Creates and returns the dot product of this vector and the specified one. 151 * 152 * @param {!threedee.Vector} v 153 * The other vector 154 * @return {number} 155 * The dot product 156 */ 157 threedee.Vector.prototype.dot = function(v) 158 { 159 return this.x * v.x + this.y * v.y + this.z * v.z; 160 }; 161 162 /** 163 * Creates the cross product of this vector and the specified one and stores 164 * the result back into this vector. 165 * 166 * @param {!threedee.Vector} v 167 * The other vector 168 * @return {!threedee.Vector} This vector 169 */ 170 threedee.Vector.prototype.cross = function(v) 171 { 172 var x, y, z; 173 174 x = this.y * v.z - this.z * v.y; 175 y = this.z * v.x - this.x * v.z; 176 z = this.x * v.y - this.y * v.x; 177 this.x = x; 178 this.y = y; 179 this.z = z; 180 return this; 181 }; 182 183 /** 184 * Returns the length of the vector. 185 * 186 * @return {number} The vector length 187 */ 188 threedee.Vector.prototype.length = function() 189 { 190 return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); 191 }; 192 193 /** 194 * Converts this vector into a unit vector with length 1. 195 * 196 * @return {!threedee.Vector} This vector 197 */ 198 threedee.Vector.prototype.toUnit = function() 199 { 200 var len; 201 202 len = this.length(); 203 this.x /= len; 204 this.y /= len; 205 this.z /= len; 206 return this; 207 }; 208 209 /** 210 * Returns the angle between this vector and the specified one. 211 * 212 * @param {!threedee.Vector} v 213 * The other vector 214 * @return {number} 215 * The angle in clockwise RAD. 216 */ 217 threedee.Vector.prototype.getAngle = function(v) 218 { 219 return Math.acos(this.copy().toUnit().dot(v.toUnit())); 220 }; 221 222 /** 223 * Transforms this vector with the specified matrix. 224 * 225 * @param {!threedee.Matrix} m 226 * The matrix 227 * @return {!threedee.Vector} 228 * This vector 229 */ 230 threedee.Vector.prototype.transform = function(m) 231 { 232 return this.set( 233 m.m00 * this.x + m.m01 * this.y + m.m02 * this.z + m.m03, 234 m.m10 * this.x + m.m11 * this.y + m.m12 * this.z + m.m13, 235 m.m20 * this.x + m.m21 * this.y + m.m22 * this.z + m.m23); 236 }; 237 238 /** 239 * Converts the vector into a JSON object with keys 'x', 'y' and 'z'. 240 * 241 * @return {Object} 242 * The vector as a JSON object 243 */ 244 threedee.Vector.prototype.toJSON = function() 245 { 246 return { "x": this.x, "y": this.y, "z": this.z }; 247 }; 248 249 /** 250 * Creates a new vector instance with the data read from the 251 * specified JSON object (with keys 'x', 'y' and 'z'). Returns null if data 252 * was empty. 253 * 254 * @param {Object} data 255 * The vector as JSON object 256 * @return {threedee.Vector} The vector object or null if data was empty 257 */ 258 threedee.Vector.fromJSON = function(data) 259 { 260 if (!data) return null; 261 return new threedee.Vector(+data["x"], +data["y"], +data["z"]); 262 }; 263