310 lines
7.5 KiB
JavaScript
310 lines
7.5 KiB
JavaScript
|
/**
|
||
|
* Runtime vector3 for updating instance objects
|
||
|
* @param graphics GameLib.D3.Graphics
|
||
|
* @param parentObject GameLib.D3.*
|
||
|
* @param vector3 GameLib.D3.API.Vector3
|
||
|
* @param grain Number
|
||
|
* @constructor
|
||
|
*/
|
||
|
GameLib.D3.Vector3 = function RuntimeVector3(graphics, parentObject, vector3, grain) {
|
||
|
|
||
|
for (var property in vector3) {
|
||
|
if (vector3.hasOwnProperty(property)) {
|
||
|
this[property] = vector3[property];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GameLib.D3.Utils.Extend(GameLib.D3.Vector3, GameLib.D3.API.Vector3);
|
||
|
|
||
|
this.graphics = graphics;
|
||
|
|
||
|
this.graphics.isNotThreeThrow();
|
||
|
|
||
|
this.parentObject = parentObject;
|
||
|
|
||
|
if (GameLib.D3.Utils.UndefinedOrNull(grain)) {
|
||
|
grain = 0.001;
|
||
|
}
|
||
|
this.grain = grain;
|
||
|
|
||
|
this.instance = this.createInstance();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Creates an instance vector3
|
||
|
* @param update
|
||
|
* @returns {*}
|
||
|
*/
|
||
|
GameLib.D3.Vector3.prototype.createInstance = function(update) {
|
||
|
|
||
|
var instance = null;
|
||
|
|
||
|
if (update) {
|
||
|
instance = this.instance;
|
||
|
instance.x = this.x;
|
||
|
instance.y = this.y;
|
||
|
instance.z = this.z;
|
||
|
} else {
|
||
|
instance = new this.graphics.instance.Vector3(this.x, this.y, this.z);
|
||
|
}
|
||
|
|
||
|
return instance;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Updates the instance vector, calls updateInstance on the parent object
|
||
|
*/
|
||
|
GameLib.D3.Vector3.prototype.updateInstance = function() {
|
||
|
|
||
|
this.createInstance(true);
|
||
|
|
||
|
if (this.parentObject.updateInstance) {
|
||
|
this.parentObject.updateInstance();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Converts runtime vector to API Vector
|
||
|
* @returns {GameLib.D3.API.Vector3}
|
||
|
*/
|
||
|
GameLib.D3.Vector3.prototype.toApiVector = function() {
|
||
|
return new GameLib.D3.API.Vector3(
|
||
|
this.x,
|
||
|
this.y,
|
||
|
this.z
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.subtract = function (v) {
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x - v.x,
|
||
|
this.y - v.y,
|
||
|
this.z - v.z
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.sub = function (v) {
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x - v.x,
|
||
|
this.y - v.y,
|
||
|
this.z - v.z
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.cross = function (v) {
|
||
|
return new GameLib.D3.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.D3.Vector3.clockwise = function (u, v, w, viewPoint) {
|
||
|
var normal = GameLib.D3.Vector3.normal(u, v, w);
|
||
|
var uv = u.copy();
|
||
|
var winding = normal.dot(uv.subtract(viewPoint));
|
||
|
return (winding > 0);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.normal = function (u, v, w) {
|
||
|
var vv = v.copy();
|
||
|
var wv = w.copy();
|
||
|
return vv.subtract(u).cross(wv.subtract(u));
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.lookAt = function (at, up) {
|
||
|
var lookAtMatrix = GameLib.D3.Matrix4.lookAt(this, at, up);
|
||
|
return this.multiply(lookAtMatrix);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.translate = function (v) {
|
||
|
this.x += v.x;
|
||
|
this.y += v.y;
|
||
|
this.z += v.z;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.add = function (v) {
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x + v.x,
|
||
|
this.y + v.y,
|
||
|
this.z + v.z
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.squared = function () {
|
||
|
return this.x * this.x + this.y * this.y + this.z * this.z;
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.copy = function () {
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x,
|
||
|
this.y,
|
||
|
this.z
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.set = function (x, y, z) {
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.z = z;
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.lerp = function ( v, alpha ) {
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x + ( v.x - this.x ) * alpha,
|
||
|
this.y + ( v.y - this.y ) * alpha,
|
||
|
this.z + ( v.z - this.z ) * alpha
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.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.D3.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;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.multiply = function (s) {
|
||
|
if (s instanceof GameLib.D3.Vector3) {
|
||
|
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x * s.x,
|
||
|
this.y * s.y,
|
||
|
this.z * s.z
|
||
|
)
|
||
|
|
||
|
} else if (s instanceof GameLib.D3.Matrix4) {
|
||
|
|
||
|
var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w;
|
||
|
var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w;
|
||
|
var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z + s.rows[2].w;
|
||
|
|
||
|
return new GameLib.D3.Vector3(
|
||
|
x,
|
||
|
y,
|
||
|
z
|
||
|
);
|
||
|
|
||
|
} else if (s instanceof GameLib.D3.Matrix3) {
|
||
|
|
||
|
var x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z;
|
||
|
var y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z;
|
||
|
var z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z;
|
||
|
|
||
|
return new GameLib.D3.Vector3(
|
||
|
x,
|
||
|
y,
|
||
|
z
|
||
|
);
|
||
|
|
||
|
} else if(!isNaN(parseFloat(s)) && isFinite(s)) {
|
||
|
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x * s,
|
||
|
this.y * s,
|
||
|
this.z * s
|
||
|
);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
console.log("functionality not implemented - please do this");
|
||
|
throw new Error("not implemented");
|
||
|
return this;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.dot = function (v) {
|
||
|
return (this.x * v.x) + (this.y * v.y) + (this.z * v.z);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.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.D3.Vector3(
|
||
|
this.x * invLength,
|
||
|
this.y * invLength,
|
||
|
this.z * invLength
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.clone = function () {
|
||
|
return new GameLib.D3.Vector3(
|
||
|
this.x,
|
||
|
this.y,
|
||
|
this.z
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.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
|
||
|
|
||
|
return new GameLib.D3.Vector3(
|
||
|
ix * qw + iw * - qx + iy * - qz - iz * - qy,
|
||
|
iy * qw + iw * - qy + iz * - qx - ix * - qz,
|
||
|
iz * qw + iw * - qz + ix * - qy - iy * - qx
|
||
|
);
|
||
|
};
|
||
|
|
||
|
GameLib.D3.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.D3.Vector3.prototype.negate = function() {
|
||
|
this.x = -this.x;
|
||
|
this.y = -this.y;
|
||
|
this.z = -this.z;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.length = function() {
|
||
|
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
|
||
|
};
|
||
|
|
||
|
GameLib.D3.Vector3.prototype.reflect = function(normal) {
|
||
|
return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) );
|
||
|
};
|
||
|
|
||
|
GameLib.D3.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 ) );
|
||
|
};
|