GameLib.API.Vector3 = function (x, y, z) { if (GameLib.Utils.UndefinedOrNull(x)) { x = 0; } this.x = x; if (GameLib.Utils.UndefinedOrNull(y)) { y = 0; } this.y = y; if (GameLib.Utils.UndefinedOrNull(z)) { z = 0; } this.z = z; }; GameLib.API.Vector3.prototype.negate = function() { this.x = -this.x; this.y = -this.y; this.z = -this.z; return this; }; GameLib.API.Vector3.prototype.subtract = function (v) { return new GameLib.API.Vector3( this.x - v.x, this.y - v.y, this.z - v.z ); }; GameLib.API.Vector3.prototype.sub = function (v) { return new GameLib.API.Vector3( this.x - v.x, this.y - v.y, this.z - v.z ); }; GameLib.API.Vector3.prototype.cross = function (v) { return new GameLib.API.Vector3( this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x ); }; GameLib.API.Vector3.clockwise = function (u, v, w, viewPoint) { var normal = GameLib.API.Vector3.normal(u, v, w); var uv = u.copy(); var winding = normal.dot(uv.subtract(viewPoint)); return (winding > 0); }; GameLib.API.Vector3.normal = function (u, v, w) { var vv = v.copy(); var wv = w.copy(); return vv.subtract(u).cross(wv.subtract(u)); }; GameLib.API.Vector3.prototype.lookAt = function (at, up) { var lookAtMatrix = GameLib.API.Matrix4.lookAt(this, at, up); return this.multiply(lookAtMatrix); }; GameLib.API.Vector3.prototype.translate = function (v) { this.x += v.x; this.y += v.y; this.z += v.z; return this; }; GameLib.API.Vector3.prototype.add = function (v) { this.x += v.x; this.y += v.y; this.z += v.z; return this; }; GameLib.API.Vector3.prototype.squared = function () { return this.x * this.x + this.y * this.y + this.z * this.z; }; GameLib.API.Vector3.prototype.copy = function () { return new GameLib.API.Vector3( this.x, this.y, this.z ); }; GameLib.API.Vector3.prototype.set = function (x, y, z) { this.x = x; this.y = y; this.z = z; }; GameLib.API.Vector3.prototype.lerp = function ( v, alpha ) { return new GameLib.API.Vector3( this.x + ( v.x - this.x ) * alpha, this.y + ( v.y - this.y ) * alpha, this.z + ( v.z - this.z ) * alpha ); }; GameLib.API.Vector3.prototype.distanceTo = function(v) { var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; return Math.sqrt(dx * dx + dy * dy + dz * dz); }; /** * @return {number} */ GameLib.API.Vector3.AngleDirection = function(forward, directionToCheck, up) { var perp = forward.cross(directionToCheck); var dir = perp.dot(up); if (dir > 0.0) { return 1.0; } else if (dir < 0.0) { return -1.0; } else { return 0.0; } }; /** * Multiplies this vector with a scalar, vector or matrix. If you want a copy, copy() it first * @param object {Number | GameLib.API.Vector3 | GameLib.API.Vector4 | GameLib.API.Matrix3 | GameLib.API.Matrix4} * @param cross boolean true if you want the cross product, otherwise returns the scalar (dot or inner) product * @returns {GameLib.API.Vector3 | Number} */ GameLib.API.Vector3.prototype.multiply = function (object, cross) { var x, y, z; var a = object; var b = this; if (GameLib.Utils.UndefinedOrNull(cross)) { cross = false; } if (typeof object == 'number') { if (cross) { this.x *= object; this.y *= object; this.z *= object; return this; } else { return ((this.x * object) + (this.y * object) + (this.z * object)); } } if (object instanceof GameLib.API.Vector3) { if (cross) { x = (a.y * b.z) - (a.z * b.y); y = (a.z * b.x) - (a.x * b.z); z = (a.x * b.y) - (a.y * b.x); this.x = x; this.y = y; this.z = z; return this; } else { return ((this.x * object.x) + (this.y * object.y) + (this.z * object.z)); } } else { console.log("functionality not implemented - please do this"); throw new Error("not implemented"); } }; GameLib.API.Vector3.prototype.dot = function (v) { return (this.x * v.x) + (this.y * v.y) + (this.z * v.z); }; GameLib.API.Vector3.prototype.normalize = function () { var EPSILON = 0.000001; var v2 = this.squared(); if (v2 < EPSILON) { return this; //do nothing for zero vector } var invLength = 1.0 / Math.sqrt(v2); return new GameLib.API.Vector3( this.x * invLength, this.y * invLength, this.z * invLength ); }; GameLib.API.Vector3.prototype.clone = function () { return new GameLib.API.Vector3( this.x, this.y, this.z ); }; GameLib.API.Vector3.prototype.applyQuaternion = function(q) { var x = this.x, y = this.y, z = this.z; var qx = q.x, qy = q.y, qz = q.z, qw = q.w; // calculate quat * vector var ix = qw * x + qy * z - qz * y; var iy = qw * y + qz * x - qx * z; var iz = qw * z + qx * y - qy * x; var iw = - qx * x - qy * y - qz * z; // calculate result * inverse quat this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; return this; }; GameLib.API.Vector3.prototype.clamp = function(min, max) { this.x = Math.max( min.x, Math.min( max.x, this.x ) ); this.y = Math.max( min.y, Math.min( max.y, this.y ) ); this.z = Math.max( min.z, Math.min( max.z, this.z ) ); return this; }; GameLib.API.Vector3.prototype.length = function() { return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); }; GameLib.API.Vector3.prototype.reflect = function(normal) { return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) ); }; GameLib.API.Vector3.prototype.angleTo = function (v) { var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); return Math.acos( exports.Math.clamp( theta, - 1, 1 ) ); }; /** * Returns an API vector from an Object vector * @param objectVector * @constructor */ GameLib.API.Vector3.FromObjectVector = function (objectVector) { return new GameLib.API.Vector3( objectVector.x, objectVector.y, objectVector.z ) };