follow, lookat, camera and path following done gulp! :)

beta.r3js.org
Theunis J. Botha 2016-12-08 19:43:16 +01:00
parent f774cad759
commit accc868f71
15 changed files with 1004 additions and 814 deletions

View File

@ -15,6 +15,7 @@
* @param maxY
* @param minZ
* @param maxZ
* @param quaternion GameLib.D3.Vector4
* @constructor
*/
GameLib.D3.API.Camera = function(
@ -32,7 +33,8 @@ GameLib.D3.API.Camera = function(
minY,
maxY,
minZ,
maxZ
maxZ,
quaternion
) {
if (GameLib.D3.Utils.UndefinedOrNull(id)) {
id = GameLib.D3.Utils.RandomId();
@ -60,7 +62,7 @@ GameLib.D3.API.Camera = function(
this.aspect = aspect;
if (GameLib.D3.Utils.UndefinedOrNull(near)) {
near = 0.1;
near = 0.001;
}
this.near = near;
@ -78,6 +80,11 @@ GameLib.D3.API.Camera = function(
}
this.position = position;
if (GameLib.D3.Utils.UndefinedOrNull(quaternion)) {
quaternion = new GameLib.D3.API.Vector4();
}
this.quaternion = quaternion;
if (GameLib.D3.Utils.UndefinedOrNull(lookAt)) {
lookAt = new GameLib.D3.API.Vector3(
0,

View File

@ -33,4 +33,114 @@ GameLib.D3.API.Matrix4 = function ApiMatrix4(
row3 = new GameLib.D3.API.Vector4(0, 0, 0, 1);
}
this.rows[3] = row3;
};
};
GameLib.D3.API.Matrix4.prototype.rotationMatrixX = function (radians) {
this.identity();
this.rows[1] = new GameLib.D3.API.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0);
this.rows[2] = new GameLib.D3.API.Vector4(0, Math.sin(radians), Math.cos(radians), 0);
return this;
};
GameLib.D3.API.Matrix4.prototype.rotationMatrixY = function (radians) {
this.identity();
this.rows[0] = new GameLib.D3.API.Vector4(
Math.cos(radians),
0,
Math.sin(radians),
0
);
this.rows[2] = new GameLib.D3.API.Vector4(
-1 * Math.sin(radians),
0,
Math.cos(radians),
0
);
return this;
};
GameLib.D3.API.Matrix4.prototype.rotationMatrixZ = function (radians) {
this.identity();
this.rows[0] = new GameLib.D3.API.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0);
this.rows[1] = new GameLib.D3.API.Vector4(Math.sin(radians), Math.cos(radians), 0, 0);
return this;
};
GameLib.D3.API.Matrix4.prototype.rotateX = function (radians, point) {
this.identity();
this.rotationMatrixX(radians);
return this.multiply(point);
};
GameLib.D3.API.Matrix4.prototype.rotateY = function (radians, point) {
this.identity();
this.rotationMatrixY(radians);
return this.multiply(point);
};
GameLib.D3.API.Matrix4.prototype.rotateZ = function (radians, point) {
this.identity();
this.rotationMatrixZ(radians);
return this.multiply(point);
};
GameLib.D3.API.Matrix4.prototype.multiply = function (mvp) {
if (mvp instanceof GameLib.D3.API.Vector4) {
return new GameLib.D3.API.Vector4(
this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w,
this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w,
this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w,
this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w
);
} else if (mvp instanceof GameLib.D3.API.Vector3) {
return new GameLib.D3.API.Vector3(
this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z,
this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z,
this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z
);
}
};
GameLib.D3.API.Matrix4.prototype.identity = function () {
this.rows = [
new GameLib.D3.API.Vector4(1, 0, 0, 0),
new GameLib.D3.API.Vector4(0, 1, 0, 0),
new GameLib.D3.API.Vector4(0, 0, 1, 0),
new GameLib.D3.API.Vector4(0, 0, 0, 1)
];
};
GameLib.D3.API.Matrix4.prototype.lookAt = function (position, target, up) {
var pv = new GameLib.D3.API.Vector3(position.x, position.y, position.z);
var z = pv.subtract(target).normalize();
if (z.squared() === 0) {
z.z = 1;
}
var x = up.cross(z).normalize();
if (x.squared() === 0) {
z.x += 0.0001;
x = up.cross(z).normalize();
}
var y = z.cross(x);
this.rows[0].x = x.x;
this.rows[0].y = x.y;
this.rows[0].z = x.z;
this.rows[1].x = y.x;
this.rows[1].y = y.y;
this.rows[1].z = y.z;
this.rows[2].x = z.x;
this.rows[2].y = z.y;
this.rows[2].z = z.z;
return this;
};

View File

@ -15,4 +15,236 @@ GameLib.D3.API.Vector3 = function ApiVector3(x, y, z) {
}
this.z = z;
};
GameLib.D3.API.Vector3.prototype.negate = function() {
this.x = -this.x;
this.y = -this.y;
this.z = -this.z;
return this;
};
GameLib.D3.API.Vector3.prototype.subtract = function (v) {
return new GameLib.D3.API.Vector3(
this.x - v.x,
this.y - v.y,
this.z - v.z
);
};
GameLib.D3.API.Vector3.prototype.sub = function (v) {
return new GameLib.D3.API.Vector3(
this.x - v.x,
this.y - v.y,
this.z - v.z
);
};
GameLib.D3.API.Vector3.prototype.cross = function (v) {
return new GameLib.D3.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.D3.API.Vector3.clockwise = function (u, v, w, viewPoint) {
var normal = GameLib.D3.API.Vector3.normal(u, v, w);
var uv = u.copy();
var winding = normal.dot(uv.subtract(viewPoint));
return (winding > 0);
};
GameLib.D3.API.Vector3.normal = function (u, v, w) {
var vv = v.copy();
var wv = w.copy();
return vv.subtract(u).cross(wv.subtract(u));
};
GameLib.D3.API.Vector3.prototype.lookAt = function (at, up) {
var lookAtMatrix = GameLib.D3.API.Matrix4.lookAt(this, at, up);
return this.multiply(lookAtMatrix);
};
GameLib.D3.API.Vector3.prototype.translate = function (v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
};
GameLib.D3.API.Vector3.prototype.add = function (v) {
return new GameLib.D3.API.Vector3(
this.x + v.x,
this.y + v.y,
this.z + v.z
);
};
GameLib.D3.API.Vector3.prototype.squared = function () {
return this.x * this.x + this.y * this.y + this.z * this.z;
};
GameLib.D3.API.Vector3.prototype.copy = function () {
return new GameLib.D3.API.Vector3(
this.x,
this.y,
this.z
);
};
GameLib.D3.API.Vector3.prototype.set = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
GameLib.D3.API.Vector3.prototype.lerp = function ( v, alpha ) {
return new GameLib.D3.API.Vector3(
this.x + ( v.x - this.x ) * alpha,
this.y + ( v.y - this.y ) * alpha,
this.z + ( v.z - this.z ) * alpha
);
};
GameLib.D3.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.D3.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;
}
};
GameLib.D3.API.Vector3.prototype.multiply = function (s) {
var x, y, z;
if (s instanceof GameLib.D3.API.Vector3) {
return new GameLib.D3.API.Vector3(
this.x * s.x,
this.y * s.y,
this.z * s.z
)
} else if (s instanceof GameLib.D3.API.Matrix4) {
x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z + s.rows[0].w;
y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z + s.rows[1].w;
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.API.Vector3(
x,
y,
z
);
} else if (s instanceof GameLib.D3.API.Matrix3) {
x = s.rows[0].x * this.x + s.rows[0].y * this.y + s.rows[0].z * this.z;
y = s.rows[1].x * this.x + s.rows[1].y * this.y + s.rows[1].z * this.z;
z = s.rows[2].x * this.x + s.rows[2].y * this.y + s.rows[2].z * this.z;
return new GameLib.D3.API.Vector3(
x,
y,
z
);
} else if(!isNaN(parseFloat(s)) && isFinite(s)) {
return new GameLib.D3.API.Vector3(
this.x * s,
this.y * s,
this.z * s
);
} else {
console.log("functionality not implemented - please do this");
throw new Error("not implemented");
}
};
GameLib.D3.API.Vector3.prototype.dot = function (v) {
return (this.x * v.x) + (this.y * v.y) + (this.z * v.z);
};
GameLib.D3.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.D3.API.Vector3(
this.x * invLength,
this.y * invLength,
this.z * invLength
);
};
GameLib.D3.API.Vector3.prototype.clone = function () {
return new GameLib.D3.API.Vector3(
this.x,
this.y,
this.z
);
};
GameLib.D3.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;
};
GameLib.D3.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.D3.API.Vector3.prototype.length = function() {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
};
GameLib.D3.API.Vector3.prototype.reflect = function(normal) {
return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) );
};
GameLib.D3.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 ) );
};

View File

@ -0,0 +1,97 @@
GameLib.D3.API.Vector4 = function ApiVector4(x, y, z, w) {
if (GameLib.D3.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.D3.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
if (GameLib.D3.Utils.UndefinedOrNull(z)) {
z = 0;
}
this.z = z;
if (GameLib.D3.Utils.UndefinedOrNull(w)) {
w = 1;
}
this.w = w;
};
GameLib.D3.API.Vector4.prototype.translate = function (v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
};
GameLib.D3.API.Vector4.prototype.copy = function () {
return new GameLib.D3.API.Vector4(
this.x,
this.y,
this.z,
this.w
);
};
/**
* Note, this normalize function leaves 'w' component untouched
*/
GameLib.D3.API.Vector4.prototype.normalize = function () {
var EPSILON = 0.000001;
var v2 = this.x * this.x + this.y * this.y + this.z * this.z;
if (v2 < EPSILON) {
return this; //do nothing for zero vector
}
var invLength = 1 / Math.sqrt(v2);
this.x *= invLength;
this.y *= invLength;
this.z *= invLength;
};
GameLib.D3.API.Vector4.prototype.multiply = function (s) {
if (s instanceof GameLib.D3.API.Vector3) {
this.x *= s.x;
this.y *= s.y;
this.z *= s.z;
} else if (s instanceof GameLib.D3.API.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 * this.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 * this.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 * this.w;
var w = s.rows[3].x * this.x + s.rows[3].y * this.y + s.rows[3].z * this.z + s.rows[3].w * this.w;
this.x = x;
this.y = y;
this.z = z;
this.w = w;
} else {
console.log("functionality not implemented - please do this");
throw new Error("not implemented");
}
};
GameLib.D3.API.Vector4.prototype.subtract = function (v) {
if (v instanceof GameLib.D3.API.Vector3) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
}
if (v instanceof GameLib.D3.API.Vector4) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
this.w -= v.w;
}
return this;
};

View File

@ -0,0 +1,224 @@
GameLib.D3.API.Vector4.Points = function () {
this.vectors = [];
};
GameLib.D3.API.Vector4.Points.prototype.add = function (vector) {
if (vector instanceof GameLib.D3.API.Vector3) {
vector = new GameLib.D3.API.Vector4(
vector.x,
vector.y,
vector.z,
1
)
}
if (!vector instanceof GameLib.D3.API.Vector4) {
console.warn("Vector needs to be of type Vector4");
throw new Error("Vector needs to be of type Vector4");
}
this.vectors.push(vector);
return this;
};
GameLib.D3.API.Vector4.Points.prototype.copy = function () {
var vectors = [];
for (var i = 0; i < this.vectors.length; i++) {
vectors.push(this.vectors[i].copy());
}
return vectors;
};
GameLib.D3.API.Vector4.Points.prototype.maximizeXDistance = function (grain) {
// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
var multiplier = 0;
var rotationMatrixY = new GameLib.D3.API.Matrix4().rotationMatrixY(grain);
var totalRadians = 0;
var backupVectors = this.copy();
var maxXDistance = 0;
for (var i = 0; i < Math.PI * 2; i += grain) {
multiplier++;
for (var j = 0; j < this.vectors.length; j++) {
this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]);
}
var distances = this.distances();
if (distances.x > maxXDistance) {
maxXDistance = distances.x;
totalRadians = multiplier * grain;
}
}
this.vectors = backupVectors;
// console.log("distance: " + maxXDistance + " radians : " + totalRadians);
var maxRotationMatrix = new GameLib.D3.API.Matrix4().rotationMatrixY(totalRadians);
for (var k = 0; k < this.vectors.length; k++) {
this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
}
// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
};
GameLib.D3.API.Vector4.Points.prototype.maximizeYDistance = function (grain) {
// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
var multiplier = 0;
var rotationMatrixX = new GameLib.D3.API.Matrix4().rotationMatrixX(grain);
var totalRadians = 0;
var backupVectors = this.copy();
var maxYDistance = 0;
for (var i = 0; i < Math.PI * 2; i += grain) {
multiplier++;
for (var j = 0; j < this.vectors.length; j++) {
this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]);
}
var distances = this.distances();
if (distances.y > maxYDistance) {
maxYDistance = distances.y;
totalRadians = multiplier * grain;
}
}
this.vectors = backupVectors;
// console.log("distance: " + maxYDistance + " radians : " + totalRadians);
var maxRotationMatrix = new GameLib.D3.API.Matrix4().rotationMatrixX(totalRadians);
for (var k = 0; k < this.vectors.length; k++) {
this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
}
// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
};
GameLib.D3.API.Vector4.Points.prototype.lookAt = function (at, up) {
var polyCenter = this.average();
console.log("poly center : " + JSON.stringify(polyCenter));
var lookAtMatrix = new GameLib.D3.API.Matrix4().lookAt(polyCenter, at, up);
lookAtMatrix.rows[0] = new GameLib.D3.API.Vector4(1, 0, 0, 0);
lookAtMatrix.rows[1] = new GameLib.D3.API.Vector4(0, 0, 1, 0);
lookAtMatrix.rows[2] = new GameLib.D3.API.Vector4(0, 1, 0, 0);
console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2));
for (var i = 0; i < this.vectors.length; i++) {
console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i]));
this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]);
console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i]));
}
};
GameLib.D3.API.Vector4.Points.prototype.distances = function () {
var minX = this.vectors[0].x;
var minY = this.vectors[0].y;
var minZ = this.vectors[0].z;
var maxX = this.vectors[0].x;
var maxY = this.vectors[0].y;
var maxZ = this.vectors[0].z;
for (var i = 0; i < this.vectors.length; i++) {
if (this.vectors[i].x < minX) {
minX = this.vectors[i].x;
}
if (this.vectors[i].y < minY) {
minY = this.vectors[i].y;
}
if (this.vectors[i].z < minZ) {
minZ = this.vectors[i].z;
}
if (this.vectors[i].x > maxX) {
maxX = this.vectors[i].x;
}
if (this.vectors[i].y > maxY) {
maxY = this.vectors[i].y;
}
if (this.vectors[i].z > maxZ) {
maxZ = this.vectors[i].z;
}
}
return new GameLib.D3.API.Vector3(
Math.abs(maxX - minX),
Math.abs(maxY - minY),
Math.abs(maxY - minZ)
)
};
GameLib.D3.API.Vector4.Points.prototype.average = function () {
var averageX = 0;
var averageY = 0;
var averageZ = 0;
for (var i = 0; i < this.vectors.length; i++) {
averageX += this.vectors[i].x;
averageY += this.vectors[i].y;
averageZ += this.vectors[i].z;
}
return new GameLib.D3.API.Vector3(
averageX / this.vectors.length,
averageY / this.vectors.length,
averageZ / this.vectors.length
);
};
GameLib.D3.API.Vector4.Points.prototype.negate = function () {
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].x *= -1;
this.vectors[i].y *= -1;
this.vectors[i].z *= -1;
}
return this;
};
GameLib.D3.API.Vector4.Points.prototype.toOrigin = function () {
var distanceFromOrigin = this.average().negate();
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].translate(distanceFromOrigin);
}
};

View File

@ -1,23 +0,0 @@
GameLib.D3.API.Vector4 = function ApiVector4(x, y, z, w) {
if (GameLib.D3.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.D3.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
if (GameLib.D3.Utils.UndefinedOrNull(z)) {
z = 0;
}
this.z = z;
if (GameLib.D3.Utils.UndefinedOrNull(w)) {
w = 1;
}
this.w = w;
};

View File

@ -24,6 +24,12 @@ GameLib.D3.Camera = function Camera(
this.position
);
this.quaternion = new GameLib.D3.Vector4(
graphics,
this,
this.quaternion
);
this.lookAt = new GameLib.D3.Vector3(
graphics,
this,
@ -88,9 +94,16 @@ GameLib.D3.Camera.prototype.createInstance = function(update) {
instance.far = this.far;
}
instance.position.copy(this.position.instance);
instance.position.x = this.position.x;
instance.position.y = this.position.y;
instance.position.z = this.position.z;
instance.lookAt(this.lookAt.instance);
instance.quaternion.x = this.quaternion.x;
instance.quaternion.y = this.quaternion.y;
instance.quaternion.z = this.quaternion.z;
instance.quaternion.w = this.quaternion.w;
// instance.lookAt(this.lookAt.instance);
instance.updateProjectionMatrix();

View File

@ -4,31 +4,36 @@
* @param id
* @param name String
* @param camera GameLib.D3.Camera
* @param parentEntity GameLib.D3.Entity
* @constructor
*/
GameLib.D3.ComponentCamera = function ComponentCamera(
id,
name,
camera
camera,
parentEntity
) {
this.id = id || GameLib.D3.Utils.RandomId();
if (GameLib.D3.Utils.UndefinedOrNull(id)) {
id = GameLib.D3.Utils.RandomId();
}
this.id = id;
if (typeof name == 'undefined') {
if (GameLib.D3.Utils.UndefinedOrNull(name)) {
name = this.constructor.name;
}
this.name = name;
this.parentEntity = null;
if (GameLib.D3.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
// Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object.
GameLib.D3.Utils.Extend(GameLib.D3.ComponentCamera, GameLib.D3.ComponentInterface);
if (typeof camera == 'undefined') {
if (GameLib.D3.Utils.UndefinedOrNull(camera)) {
camera = null;
}
this.camera = camera;
// Component fields
this.camera = camera.instance;
GameLib.D3.Utils.Extend(GameLib.D3.ComponentCamera, GameLib.D3.ComponentInterface);
};
///////////////////////// Methods to override //////////////////////////
@ -36,11 +41,25 @@ GameLib.D3.ComponentCamera.prototype.onLateUpdate = function(
deltaTime,
parentEntity
) {
this.camera.quaternion.copy(parentEntity.quaternion).normalize();
this.camera.position.copy(parentEntity.position);
parentEntity.quaternion.x = this.camera.quaternion.x;
parentEntity.quaternion.y = this.camera.quaternion.y;
parentEntity.quaternion.z = this.camera.quaternion.z;
parentEntity.quaternion.w = this.camera.quaternion.w;
if (this.camera) {
this.camera.quaternion.copy(this.parentEntity.quaternion);
this.camera.quaternion.normalize();
this.camera.position.copy(this.parentEntity.position);
this.camera.quaternion.updateInstance();
this.camera.position.updateInstance();
this.parentEntity.quaternion.x = this.camera.quaternion.x;
this.parentEntity.quaternion.y = this.camera.quaternion.y;
this.parentEntity.quaternion.z = this.camera.quaternion.z;
this.parentEntity.quaternion.w = this.camera.quaternion.w;
this.parentEntity.quaternion.updateInstance();
} else {
console.warn('no camera object');
}
};

View File

@ -2,31 +2,49 @@
*
* @param id
* @param name
* @param graphics GameLib.D3.Graphics
* @param targetEntity GameLib.D3.Entity
* @param targetOffset GameLib.D3.API.Vector3
* @param minDistance
* @param moveSpeed
* @param parentEntity
* @param target GameLib.D3.Vector3
* @param targetToParent GameLib.D3.Vector3
* @param rotatedTargetOffset GameLib.D3.Vector3
* @param rotated GameLib.D3.Vector4
* @constructor
*/
GameLib.D3.ComponentFollow = function ComponentFollow(
id,
name,
graphics,
targetEntity,
targetOffset,
minDistance,
moveSpeed
moveSpeed,
parentEntity,
target,
targetToParent,
rotatedTargetOffset,
rotated
) {
this.id = id || GameLib.D3.Utils.RandomId();
if (GameLib.D3.Utils.UndefinedOrNull(id)) {
id = GameLib.D3.Utils.RandomId();
}
this.id = id;
if (typeof name == 'undefined') {
if (GameLib.D3.Utils.UndefinedOrNull(name)) {
name = this.constructor.name;
}
this.name = name;
// Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object.
GameLib.D3.Utils.Extend(GameLib.D3.ComponentFollow, GameLib.D3.ComponentInterface);
this.graphics = graphics;
this.graphics.isNotThreeThrow();
this.parentEntity = null;
if (GameLib.D3.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.D3.Utils.UndefinedOrNull(targetEntity)) {
targetEntity = null;
@ -34,20 +52,62 @@ GameLib.D3.ComponentFollow = function ComponentFollow(
this.targetEntity = targetEntity;
if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) {
targetOffset = new GameLib.D3.API.Vector3(0, 0, 0);
targetOffset = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
}
this.targetOffset = targetOffset;
this.moveSpeed = moveSpeed || 12.5;
this.minDistance = minDistance || 0;
};
if (GameLib.D3.Utils.UndefinedOrNull(moveSpeed)) {
moveSpeed = 12.5;
}
this.moveSpeed = moveSpeed;
if(typeof THREE != "undefined") {
ComponentFollow_Target_Vec3 = new THREE.Vector3();
ComponentFollow_TargetToParent_Vec3 = new THREE.Vector3();
ComponentFollow_rotatedTargetOffset_Vec3 = new THREE.Vector3();
ComponentFollow_tempQuaternion = new THREE.Quaternion();
}
if (GameLib.D3.Utils.UndefinedOrNull(minDistance)) {
minDistance = 0;
}
this.minDistance = minDistance;
if (GameLib.D3.Utils.UndefinedOrNull(target)) {
target = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
}
this.target = target;
if (GameLib.D3.Utils.UndefinedOrNull(targetToParent)) {
targetToParent = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
}
this.targetToParent = targetToParent;
if (GameLib.D3.Utils.UndefinedOrNull(rotatedTargetOffset)) {
rotatedTargetOffset = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
}
this.rotatedTargetOffset = rotatedTargetOffset;
if (GameLib.D3.Utils.UndefinedOrNull(rotated)) {
rotated = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
}
this.rotated = rotated;
GameLib.D3.Utils.Extend(GameLib.D3.ComponentFollow, GameLib.D3.ComponentInterface);
};
///////////////////////// Methods to override //////////////////////////
GameLib.D3.ComponentFollow.prototype.onUpdate = function(
@ -55,54 +115,57 @@ GameLib.D3.ComponentFollow.prototype.onUpdate = function(
parentEntity
) {
if(this.targetEntity) {
if (this.targetEntity) {
ComponentFollow_tempQuaternion.set(
this.targetEntity.quaternion.x,
this.targetEntity.quaternion.y,
this.targetEntity.quaternion.z,
this.targetEntity.quaternion.w
);
this.rotated.x = this.targetEntity.quaternion.x;
this.rotated.y = this.targetEntity.quaternion.y;
this.rotated.z = this.targetEntity.quaternion.z;
this.rotated.w = this.targetEntity.quaternion.w;
ComponentFollow_rotatedTargetOffset_Vec3.set(
this.targetOffset.x,
this.targetOffset.y,
this.targetOffset.z
);
this.rotated.updateInstance();
ComponentFollow_rotatedTargetOffset_Vec3 =
ComponentFollow_rotatedTargetOffset_Vec3.applyQuaternion(
ComponentFollow_tempQuaternion
);
this.rotatedTargetOffset.x = this.targetOffset.x;
this.rotatedTargetOffset.y = this.targetOffset.y;
this.rotatedTargetOffset.z = this.targetOffset.z;
ComponentFollow_Target_Vec3.set(
this.targetEntity.position.x + ComponentFollow_rotatedTargetOffset_Vec3.x,
this.targetEntity.position.y + ComponentFollow_rotatedTargetOffset_Vec3.y,
this.targetEntity.position.z + ComponentFollow_rotatedTargetOffset_Vec3.z
);
this.rotatedTargetOffset.applyQuaternion(this.rotated);
ComponentFollow_TargetToParent_Vec3.set(
parentEntity.position.x - this.targetEntity.position.x,
parentEntity.position.y - this.targetEntity.position.y,
parentEntity.position.z - this.targetEntity.position.z
);
this.rotatedTargetOffset.updateInstance();
ComponentFollow_TargetToParent_Vec3.normalize();
this.target.x = this.targetEntity.position.x + this.rotatedTargetOffset.x;
this.target.y = this.targetEntity.position.y + this.rotatedTargetOffset.y;
this.target.z = this.targetEntity.position.z + this.rotatedTargetOffset.z;
ComponentFollow_TargetToParent_Vec3.set(
ComponentFollow_TargetToParent_Vec3.x * this.minDistance,
ComponentFollow_TargetToParent_Vec3.y * this.minDistance,
ComponentFollow_TargetToParent_Vec3.z * this.minDistance
);
this.target.updateInstance();
ComponentFollow_Target_Vec3.set(
ComponentFollow_Target_Vec3.x + ComponentFollow_TargetToParent_Vec3.x,
ComponentFollow_Target_Vec3.y + ComponentFollow_TargetToParent_Vec3.y,
ComponentFollow_Target_Vec3.z + ComponentFollow_TargetToParent_Vec3.z
);
this.targetToParent.x = this.parentEntity.position.x - this.targetEntity.position.x;
this.targetToParent.y = this.parentEntity.position.y - this.targetEntity.position.y;
this.targetToParent.z = this.parentEntity.position.z - this.targetEntity.position.z;
this.targetToParent.normalize();
this.targetToParent.x *= this.minDistance;
this.targetToParent.y *= this.minDistance;
this.targetToParent.z *= this.minDistance;
this.targetToParent.updateInstance();
this.target.x = this.target.x + this.targetToParent.x;
this.target.y = this.target.y + this.targetToParent.y;
this.target.z = this.target.z + this.targetToParent.z;
this.target.updateInstance();
var t = deltaTime * this.moveSpeed;
//t = t * t * t * (t * (6.0 * t - 15.0) + 10.0);
parentEntity.position = parentEntity.position.lerp(ComponentFollow_Target_Vec3, t);
var lerp = this.parentEntity.position.lerp(this.target, t);
this.parentEntity.position.x = lerp.x;
this.parentEntity.position.y = lerp.y;
this.parentEntity.position.z = lerp.z;
this.parentEntity.position.updateInstance();
}
};

View File

@ -1,116 +1,128 @@
/**
*
* Looks from parentEntity to targetEntity (default up is 0,1,0)
* @param id
* @param name
* @param targetEntity
* @param targetOffset
* @param graphics GameLib.D3.Graphics
* @param parentEntity GameLib.D3.Entity
* @param targetEntity GameLib.D3.Entity
* @param targetOffset GameLib.D3.Vector3
* @param rotationSpeed
* @param lookAtMatrix GameLib.D3.Matrix4
* @param up GameLib.D3.Vector3
* @constructor
*/
GameLib.D3.ComponentLookAt = function ComponentLookAt(
id,
name,
graphics,
parentEntity,
targetEntity,
targetOffset,
rotationSpeed
rotationSpeed,
lookAtMatrix,
up
) {
this.id = id || GameLib.D3.Utils.RandomId();
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.D3.Utils.UndefinedOrNull(id)) {
id = GameLib.D3.Utils.RandomId();
}
this.id = id;
if (typeof name == 'undefined') {
if (GameLib.D3.Utils.UndefinedOrNull(name)) {
name = this.constructor.name;
}
this.name = name;
this.parentEntity = null;
// Todo: this should be executed somewhere in game-lib-z, so that we don't execute it on every construction of an object.
GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface);
// todo: USE TARGET OFFSET.
if (GameLib.D3.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.D3.Utils.UndefinedOrNull(targetEntity)) {
targetEntity = null;
}
this.targetEntity = targetEntity;
if(GameLib.D3.Utils.UndefinedOrNull(targetOffset)) {
targetOffset = new GameLib.D3.API.Vector3(0, 0, 0);
targetOffset = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
}
this.targetOffset = targetOffset;
this.lastTargetQuaternion = new GameLib.D3.API.Vector4(0, 0, 0, 1);
this.rotationSpeed = rotationSpeed || 22.0;
};
if (GameLib.D3.Utils.UndefinedOrNull(rotationSpeed)) {
rotationSpeed = 22.0;
}
this.rotationSpeed = rotationSpeed;
if(typeof THREE != "undefined") {
ComponentLookAt_rotatedTargetOffset = new THREE.Vector3();
ComponentLookAt_currentPos = new THREE.Vector3();
ComponentLookAt_targetPos = new THREE.Vector3();
ComponentLookAt_upVector = new THREE.Vector3(0, 1, 0);
ComponentLookAt_targetQuaternion = new THREE.Quaternion(0, 0, 0, 1);
ComponentLookAt_tmpQuaternion = new THREE.Quaternion(0, 0, 0, 1);
ComponentLookAt_newRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1);
ComponentLookAt_lastRotationQuaternion = new THREE.Quaternion(0, 0, 0, 1);
ComponentLookAt_lookAtMatrix = new THREE.Matrix4();
}
if (GameLib.D3.Utils.UndefinedOrNull(lookAtMatrix)) {
lookAtMatrix = new GameLib.D3.Matrix4(
this.graphics,
this,
new GameLib.D3.API.Matrix4()
);
}
this.lookAtMatrix = lookAtMatrix;
if(GameLib.D3.Utils.UndefinedOrNull(up)) {
up = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 1, 0)
);
}
this.up = up;
this.targetPosition = new GameLib.D3.Vector3(
this.graphics,
this,
new GameLib.D3.API.Vector3(0, 0, 0)
);
this.currentRotation = new GameLib.D3.Vector4(
this.graphics,
this,
new GameLib.D3.API.Vector4()
);
GameLib.D3.Utils.Extend(GameLib.D3.ComponentLookAt, GameLib.D3.ComponentInterface);
};
///////////////////////// Methods to override //////////////////////////
GameLib.D3.ComponentLookAt.prototype.onUpdate = function(
deltaTime,
parentEntity
) {
if(this.targetEntity) {
var target = this.targetEntity.position;
if (this.targetEntity) {
ComponentLookAt_currentPos.set(
parentEntity.position.x,
parentEntity.position.y,
parentEntity.position.z
this.targetPosition.x = this.targetEntity.position.x + this.targetOffset.x;
this.targetPosition.y = this.targetEntity.position.y + this.targetOffset.y;
this.targetPosition.z = this.targetEntity.position.z + this.targetOffset.z;
this.targetPosition.updateInstance();
this.lookAtMatrix.lookAt(
this.parentEntity.position,
this.targetPosition,
this.up
);
ComponentLookAt_lastRotationQuaternion.set(
this.lastTargetQuaternion.x,
this.lastTargetQuaternion.y,
this.lastTargetQuaternion.z,
this.lastTargetQuaternion.w
);
ComponentLookAt_rotatedTargetOffset.set(
this.targetOffset.x,
this.targetOffset.y,
this.targetOffset.z
);
ComponentLookAt_targetQuaternion.set(
this.targetEntity.quaternion.x,
this.targetEntity.quaternion.y,
this.targetEntity.quaternion.z,
this.targetEntity.quaternion.w
);
ComponentLookAt_rotatedTargetOffset =
ComponentLookAt_rotatedTargetOffset.applyQuaternion(
ComponentLookAt_targetQuaternion
);
ComponentLookAt_targetPos.set(
target.x + ComponentLookAt_rotatedTargetOffset.x,
target.y + ComponentLookAt_rotatedTargetOffset.y,
target.z + ComponentLookAt_rotatedTargetOffset.z
);
ComponentLookAt_lookAtMatrix.lookAt(
ComponentLookAt_currentPos,
ComponentLookAt_targetPos,
ComponentLookAt_upVector
);
ComponentLookAt_tmpQuaternion.setFromRotationMatrix(ComponentLookAt_lookAtMatrix);
this.currentRotation.setFromRotationMatrix(this.lookAtMatrix);
var t = deltaTime * this.rotationSpeed;
t = t * t * t * (t * (6.0 * t - 15.0) + 10.0);
THREE.Quaternion.slerp(ComponentLookAt_lastRotationQuaternion, ComponentLookAt_tmpQuaternion, ComponentLookAt_newRotationQuaternion, t);
this.currentRotation.slerp(this.currentRotation, t);
this.parentEntity.quaternion.x = this.lastTargetQuaternion.x = ComponentLookAt_newRotationQuaternion.x;
this.parentEntity.quaternion.y = this.lastTargetQuaternion.y = ComponentLookAt_newRotationQuaternion.y;
this.parentEntity.quaternion.z = this.lastTargetQuaternion.z = ComponentLookAt_newRotationQuaternion.z;
this.parentEntity.quaternion.w = this.lastTargetQuaternion.w = ComponentLookAt_newRotationQuaternion.w;
this.parentEntity.quaternion.x = this.currentRotation.x;
this.parentEntity.quaternion.y = this.currentRotation.y;
this.parentEntity.quaternion.z = this.currentRotation.z;
this.parentEntity.quaternion.w = this.currentRotation.w;
this.parentEntity.quaternion.updateInstance();
}
};

View File

@ -271,6 +271,33 @@ GameLib.D3.Material.prototype.createInstance = function(update) {
fog: this.fog
});
} else if (this.materialType == GameLib.D3.Material.MATERIAL_TYPE_BASIC) {
instance = new THREE.MeshBasicMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
blending: this.blending,
blendSrc: this.blendSrc,
blendDst: this.blendDst,
blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
polygonOffset: this.polygonOffset,
polygonOffsetFactor: this.polygonOffsetFactor,
polygonOffsetUnits: this.polygonOffsetUnits,
alphaTest: this.alphaTest,
clippingPlanes: this.clippingPlanes,
clipShadows: this.clipShadows,
overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
vertexColors: GameLib.D3.Material.TYPE_NO_COLORS,
fog: this.fog
});
} else {
console.log("material type is not implemented yet: " + this.materialType + " - material indexes could be screwed up");
}

View File

@ -108,81 +108,6 @@ GameLib.D3.Matrix4.prototype.updateInstance = function() {
this.createInstance(true);
};
GameLib.D3.Matrix4.prototype.rotationMatrixX = function (radians) {
this.identity();
this.rows[1] = new GameLib.D3.API.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0);
this.rows[2] = new GameLib.D3.API.Vector4(0, Math.sin(radians), Math.cos(radians), 0);
return this;
};
GameLib.D3.Matrix4.prototype.rotationMatrixY = function (radians) {
this.identity();
this.rows[0] = new GameLib.D3.API.Vector4(
Math.cos(radians),
0,
Math.sin(radians),
0
);
this.rows[2] = new GameLib.D3.API.Vector4(
-1 * Math.sin(radians),
0,
Math.cos(radians),
0
);
return this;
};
GameLib.D3.Matrix4.prototype.rotationMatrixZ = function (radians) {
this.identity();
this.rows[0] = new GameLib.D3.API.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0);
this.rows[1] = new GameLib.D3.API.Vector4(Math.sin(radians), Math.cos(radians), 0, 0);
return this;
};
GameLib.D3.Matrix4.prototype.rotateX = function (radians, point) {
this.identity();
this.rotationMatrixX(radians);
return this.multiply(point);
};
GameLib.D3.Matrix4.prototype.rotateY = function (radians, point) {
this.identity();
this.rotationMatrixY(radians);
return this.multiply(point);
};
GameLib.D3.Matrix4.prototype.rotateZ = function (radians, point) {
this.identity();
this.rotationMatrixZ(radians);
return this.multiply(point);
};
GameLib.D3.Matrix4.prototype.multiply = function (mvp) {
if (mvp instanceof GameLib.D3.API.Vector4) {
return new GameLib.D3.API.Vector4(
this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w,
this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w,
this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w,
this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w
);
} else if (mvp instanceof GameLib.D3.API.Vector3) {
return new GameLib.D3.API.Vector3(
this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z,
this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z,
this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z
);
}
};
GameLib.D3.Matrix4.prototype.identity = function () {
this.rows = [
new GameLib.D3.API.Vector4(1, 0, 0, 0),
new GameLib.D3.API.Vector4(0, 1, 0, 0),
new GameLib.D3.API.Vector4(0, 0, 1, 0),
new GameLib.D3.API.Vector4(0, 0, 0, 1)
];
};
GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) {
this.instance.lookAt(position.instance, target.instance, up.instance);
@ -206,34 +131,5 @@ GameLib.D3.Matrix4.prototype.lookAt = function (position, target, up) {
this.rows[3].y = this.instance.elements[13];
this.rows[3].z = this.instance.elements[14];
this.rows[3].w = this.instance.elements[15];
// var pv = new GameLib.D3.API.Vector3(position.x, position.y, position.z);
//
// var z = pv.subtract(target).normalize();
//
// if (z.squared() === 0) {
// z.z = 1;
// }
//
// var x = up.cross(z).normalize();
//
// if (x.squared() === 0) {
// z.x += 0.0001;
// x = up.cross(z).normalize();
// }
//
// var y = z.cross(x);
//
// this.rows[0].x = x.x;
// this.rows[0].y = x.y;
// this.rows[0].z = x.z;
//
// this.rows[1].x = y.x;
// this.rows[1].y = y.y;
// this.rows[1].z = y.z;
//
// this.rows[2].x = z.x;
// this.rows[2].y = z.y;
// this.rows[2].z = z.z;
//
// return this;
};

View File

@ -23,24 +23,34 @@ GameLib.D3.Mesh = function Mesh(
this.position = new GameLib.D3.Vector3(
graphics,
this,
this.position
this.position,
0.001
);
this.scale = new GameLib.D3.Vector3(
graphics,
this,
this.scale
this.scale,
0.001
);
this.up = new GameLib.D3.Vector3(
graphics,
this,
this.up
this.up,
0.001
);
/**
* We don't do a Runtime rotation since it interferes with the quaternion update
*/
this.rotation = new GameLib.D3.Vector3(
graphics,
this,
this.rotation,
0.001
);
this.quaternion = new GameLib.D3.Vector4(
graphics,
@ -322,8 +332,20 @@ GameLib.D3.Mesh.prototype.createInstance = function(update) {
instance.up.z = this.up.z;
/**
* We don't do rotation - its dealt with by quaternion
* We don't do rotation for now - it should be dealt with by quaternion
*/
// instance.rotation.x = this.rotation.x;
// instance.rotation.y = this.rotation.y;
// instance.rotation.z = this.rotation.z;
//
// instance.quaternion.setFromEuler(
// new THREE.Euler(
// instance.rotation.x,
// instance.rotation.y,
// instance.rotation.z
// )
// );
//
instance.quaternion.x = this.quaternion.x;
instance.quaternion.y = this.quaternion.y;
instance.quaternion.z = this.quaternion.z;

View File

@ -73,238 +73,4 @@ GameLib.D3.Vector3.prototype.toApiVector = function() {
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 ) );
};

View File

@ -15,6 +15,8 @@ GameLib.D3.Vector4 = function RuntimeVector4(
for (var property in vector4) {
if (vector4.hasOwnProperty(property)) {
this[property] = vector4[property];
}
}
@ -82,43 +84,6 @@ GameLib.D3.Vector4.prototype.toApiVector = function() {
);
};
GameLib.D3.Vector4.prototype.translate = function (v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
};
GameLib.D3.Vector4.prototype.copy = function () {
return new GameLib.D3.Vector4(
this.x,
this.y,
this.z,
this.w
);
};
GameLib.D3.Vector4.prototype.multiply = function (s) {
if (s instanceof 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 * this.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 * this.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 * this.w;
var w = s.rows[3].x * this.x + s.rows[3].y * this.y + s.rows[3].z * this.z + s.rows[3].w * this.w;
this.x = x;
this.y = y;
this.z = z;
this.w = w;
} else {
console.log("functionality not implemented - please do this");
throw new Error("not implemented");
}
};
GameLib.D3.Vector4.prototype.normalize = function () {
this.updateInstance();
@ -129,270 +94,10 @@ GameLib.D3.Vector4.prototype.normalize = function () {
this.y = this.instance.y;
this.z = this.instance.z;
this.w = this.instance.w;
//
//
//
// // note - leave w untouched
// var EPSILON = 0.000001;
//
// var v2 = this.x * this.x + this.y * this.y + this.z * this.z;
//
// if (v2 < EPSILON) {
// return this; //do nothing for zero vector
// }
//
// var invLength = 1 / Math.sqrt(v2);
//
// this.x *= invLength;
// this.y *= invLength;
// this.z *= invLength;
return this;
};
GameLib.D3.Vector4.prototype.subtract = function (v) {
if (v instanceof GameLib.D3.API.Vector3) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
}
if (v instanceof GameLib.D3.Vector4) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
this.w -= v.w;
}
return this;
};
GameLib.D3.Vector4.Points = function () {
this.vectors = [];
};
GameLib.D3.Vector4.Points.prototype.add = function (vector) {
if (vector instanceof GameLib.D3.API.Vector3) {
vector = new GameLib.D3.Vector4(
vector.x,
vector.y,
vector.z,
1
)
}
if (!vector instanceof GameLib.D3.Vector4) {
console.warn("Vector needs to be of type Vector4");
throw new Error("Vector needs to be of type Vector4");
}
this.vectors.push(vector);
return this;
};
GameLib.D3.Vector4.Points.prototype.copy = function () {
var vectors = [];
for (var i = 0; i < this.vectors.length; i++) {
vectors.push(this.vectors[i].copy());
}
return vectors;
};
GameLib.D3.Vector4.Points.prototype.maximizeXDistance = function (grain) {
// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
var multiplier = 0;
var rotationMatrixY = new GameLib.D3.Matrix4().rotationMatrixY(grain);
var totalRadians = 0;
var backupVectors = this.copy();
var maxXDistance = 0;
for (var i = 0; i < Math.PI * 2; i += grain) {
multiplier++;
for (var j = 0; j < this.vectors.length; j++) {
this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]);
}
var distances = this.distances();
if (distances.x > maxXDistance) {
maxXDistance = distances.x;
totalRadians = multiplier * grain;
}
}
this.vectors = backupVectors;
// console.log("distance: " + maxXDistance + " radians : " + totalRadians);
var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixY(totalRadians);
for (var k = 0; k < this.vectors.length; k++) {
this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
}
// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
};
GameLib.D3.Vector4.Points.prototype.maximizeYDistance = function (grain) {
// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
var multiplier = 0;
var rotationMatrixX = new GameLib.D3.Matrix4().rotationMatrixX(grain);
var totalRadians = 0;
var backupVectors = this.copy();
var maxYDistance = 0;
for (var i = 0; i < Math.PI * 2; i += grain) {
multiplier++;
for (var j = 0; j < this.vectors.length; j++) {
this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]);
}
var distances = this.distances();
if (distances.y > maxYDistance) {
maxYDistance = distances.y;
totalRadians = multiplier * grain;
}
}
this.vectors = backupVectors;
// console.log("distance: " + maxYDistance + " radians : " + totalRadians);
var maxRotationMatrix = new GameLib.D3.Matrix4().rotationMatrixX(totalRadians);
for (var k = 0; k < this.vectors.length; k++) {
this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
}
// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
};
GameLib.D3.Vector4.Points.prototype.lookAt = function (at, up) {
var polyCenter = this.average();
console.log("poly center : " + JSON.stringify(polyCenter));
var lookAtMatrix = new GameLib.D3.Matrix4().lookAt(polyCenter, at, up);
lookAtMatrix.rows[0] = new GameLib.D3.Vector4(1, 0, 0, 0);
lookAtMatrix.rows[1] = new GameLib.D3.Vector4(0, 0, 1, 0);
lookAtMatrix.rows[2] = new GameLib.D3.Vector4(0, 1, 0, 0);
console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2));
for (var i = 0; i < this.vectors.length; i++) {
console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i]));
this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]);
console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i]));
}
};
GameLib.D3.Vector4.Points.prototype.distances = function () {
var minX = this.vectors[0].x;
var minY = this.vectors[0].y;
var minZ = this.vectors[0].z;
var maxX = this.vectors[0].x;
var maxY = this.vectors[0].y;
var maxZ = this.vectors[0].z;
for (var i = 0; i < this.vectors.length; i++) {
if (this.vectors[i].x < minX) {
minX = this.vectors[i].x;
}
if (this.vectors[i].y < minY) {
minY = this.vectors[i].y;
}
if (this.vectors[i].z < minZ) {
minZ = this.vectors[i].z;
}
if (this.vectors[i].x > maxX) {
maxX = this.vectors[i].x;
}
if (this.vectors[i].y > maxY) {
maxY = this.vectors[i].y;
}
if (this.vectors[i].z > maxZ) {
maxZ = this.vectors[i].z;
}
}
return new GameLib.D3.API.Vector3(
Math.abs(maxX - minX),
Math.abs(maxY - minY),
Math.abs(maxY - minZ)
)
};
GameLib.D3.Vector4.Points.prototype.average = function () {
var averageX = 0;
var averageY = 0;
var averageZ = 0;
for (var i = 0; i < this.vectors.length; i++) {
averageX += this.vectors[i].x;
averageY += this.vectors[i].y;
averageZ += this.vectors[i].z;
}
return new GameLib.D3.API.Vector3(
averageX / this.vectors.length,
averageY / this.vectors.length,
averageZ / this.vectors.length
);
};
GameLib.D3.Vector4.Points.prototype.negate = function () {
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].x *= -1;
this.vectors[i].y *= -1;
this.vectors[i].z *= -1;
}
return this;
};
GameLib.D3.Vector4.Points.prototype.toOrigin = function () {
var distanceFromOrigin = this.average().negate();
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].translate(distanceFromOrigin);
}
};
/**
*
* @param matrix4 GameLib.D3.Matrix4
@ -406,3 +111,23 @@ GameLib.D3.Vector4.prototype.setFromRotationMatrix = function(matrix4) {
this.z = this.instance.z;
this.w = this.instance.w;
};
/**
*
* @param vector4 GameLib.D3.Vector4
* @param t
* @returns {GameLib.D3.Vector4}
*/
GameLib.D3.Vector4.prototype.slerp = function (vector4, t) {
this.updateInstance();
this.instance.slerp(vector4.instance, t);
this.x = this.instance.x;
this.y = this.instance.y;
this.z = this.instance.z;
this.w = this.instance.w;
return this;
};