r3-legacy/src/game-lib-vector-4.js

324 lines
7.8 KiB
JavaScript

GameLib.D3.Vector4 = function(x, y, z, w) {
this.x = 0;
this.y = 0;
this.z = 0;
this.w = 0;
if (x) {
this.x = x;
}
if (y) {
this.y = y;
}
if (z) {
this.z = z;
}
if (w) {
this.w = w;
}
};
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 () {
// 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.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.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.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.Vector3(
averageX / this.vectors.length,
averageY / this.vectors.length,
averageZ / this.vectors.length
);
};
GameLib.D3.Vector4.Points.prototype.negative = 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().negative();
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].translate(distanceFromOrigin);
}
};