r3-legacy/src/game-lib-api-vector3.js

268 lines
6.4 KiB
JavaScript

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.FromObject = function (objectVector) {
return new GameLib.API.Vector3(
objectVector.x,
objectVector.y,
objectVector.z
)
};