/**
* jslint browser: true
*/
/**
* Creates new geometry with default values
* @class
* @constructor
*/
Ayce.Geometry = function () {
this.position = new Ayce.Vector3(0, 0, 0);
this.rotation = new Ayce.Quaternion();
this.scale = new Ayce.Vector3(1, 1, 1);
this.offset = new Ayce.Vector3(0, 0, 0);
};
Ayce.Geometry.prototype = {};
/**
* Creates box as new Ayce.Object3D
* @class
* @constructor
* @param {Number} a
* @param {Number} b
* @param {Number} c
*/
Ayce.Geometry.Box = function (a, b, c) {
Ayce.Geometry.call(this);
this.a = a || 0;
this.b = b || 0;
this.c = c || 0;
};
Ayce.Geometry.Box.prototype = new Ayce.Geometry();
/**
* Returns box geometry as Ayce.Object3D
* @param {Boolean} asWireframe
* @return {Ayce.Object3D} o3D
*/
Ayce.Geometry.Box.prototype.getO3D = function (asWireframe) {
var o3D = new Ayce.Object3D();
var o = this.offset;
var a = this.a;
var b = this.b;
var c = this.c;
o3D.vertices = [];
o3D.vertices.push(o.x + 0, o.y + 0, o.z + 0);
o3D.vertices.push(o.x + a, o.y + 0, o.z + 0);
o3D.vertices.push(o.x + 0, o.y + b, o.z + 0);
o3D.vertices.push(o.x + a, o.y + b, o.z + 0);
o3D.vertices.push(o.x + 0, o.y + 0, o.z + c);
o3D.vertices.push(o.x + a, o.y + 0, o.z + c);
o3D.vertices.push(o.x + 0, o.y + b, o.z + c);
o3D.vertices.push(o.x + a, o.y + b, o.z + c);
o3D.normals = [];
o3D.normals.push(-1, -1, -1);
o3D.normals.push( 1, -1, -1);
o3D.normals.push(-1, 1, -1);
o3D.normals.push( 1, 1, -1);
o3D.normals.push(-1, -1, 1);
o3D.normals.push( 1, -1, 1);
o3D.normals.push(-1, 1, 1);
o3D.normals.push( 1, 1, 1);
o3D.indices = [];
if (asWireframe) {
o3D.indices.push(0, 1);
o3D.indices.push(5, 1);
o3D.indices.push(4, 0);
o3D.indices.push(4, 5);
o3D.indices.push(2, 6);
o3D.indices.push(6, 7);
o3D.indices.push(7, 3);
o3D.indices.push(3, 2);
o3D.indices.push(0, 2);
o3D.indices.push(4, 6);
o3D.indices.push(5, 7);
o3D.indices.push(3, 1);
o3D.isWireframe = true;
} else {
//front
o3D.indices.push(2, 1, 0);
o3D.indices.push(2, 3, 1);
//back
o3D.indices.push(7, 4, 5);
o3D.indices.push(7, 6, 4);
//left
o3D.indices.push(6, 0, 4);
o3D.indices.push(6, 2, 0);
//right
o3D.indices.push(3, 5, 1);
o3D.indices.push(3, 7, 5);
//top
o3D.indices.push(0, 5, 4);
o3D.indices.push(0, 1, 5);
//bottom
o3D.indices.push(6, 3, 2);
o3D.indices.push(6, 7, 3);
}
o3D.position = this.position;
o3D.rotation = this.rotation;
o3D.scale = this.scale;
return o3D;
};
/**
* Returns true if specified point is within geometry
* @param {Ayce.Vector3} vector3
* @return b1
*/
Ayce.Geometry.Box.prototype.containsPoint = function (vector3) {
var scope = this;
var calcCorner = function (offset) {
var p = scope.position.copy().addVector3(offset).addVector3(scope.offset);
p.multiply(scope.scale.x, scope.scale.y, scope.scale.z);
p = scope.rotation.getRotatedPoint(p);
return p;
};
var pointPlane = function (s, a, b, p) {
a = a.copy().subtract(s.x, s.y, s.z);
b = b.copy().subtract(s.x, s.y, s.z);
var normal = a.copy().crossProduct(b).normalize();
var x = p.copy().subtract(s.x, s.y, s.z);
var cross = normal.dotProduct(x);
return cross;
};
var t1 = calcCorner(new Ayce.Vector3(0, 0, 0));
// var t2 = calcCorner(new Ayce.Vector3(this.a, 0, 0));
var t3 = calcCorner(new Ayce.Vector3(0, this.b, 0));
var t4 = calcCorner(new Ayce.Vector3(this.a, this.b, 0));
var b1 = calcCorner(new Ayce.Vector3(0, 0, this.c));
var b2 = calcCorner(new Ayce.Vector3(this.a, 0, this.c));
var b3 = calcCorner(new Ayce.Vector3(0, this.b, this.c));
var b4 = calcCorner(new Ayce.Vector3(this.a, this.b, this.c));
var top = pointPlane(b3, t3, b4, vector3);
var bottom = pointPlane(b1, b2, t1, vector3);
var left = pointPlane(b3, b1, t1, vector3);
var right = pointPlane(b4, t4, b2, vector3);
var front = pointPlane(b3, b4, b1, vector3);
var back = pointPlane(t3, t1, t4, vector3);
// console.log(top, bottom, left, right, front, back);
var b1 = (top > 0 && bottom > 0 && left > 0 && right > 0 && front > 0 && back > 0);
return b1;
};
/**
* Creates sphere geometry as Ayce.Object3D
* @class
* @constructor
* @param {Number} r
*/
Ayce.Geometry.Sphere = function (r) {
Ayce.Geometry.call(this);
this.r = r || 0;
};
Ayce.Geometry.Sphere.prototype = new Ayce.Geometry();
/**
* Returns sphere geometry as Ayce.Object3D
* @param {Boolean} asWireframe
* @param {Number} segments
* @param {Number} rings
* @return {Ayce.Object3D} o3D
*/
Ayce.Geometry.Sphere.prototype.getO3D = function (asWireframe, segments, rings) {
this.scale = null;
var longitudeBands = segments || 10;
var latitudeBands = rings || 10;
var radius = this.r;
var latNumber;
var longNumber;
var o = this.offset;
var o3D = new Ayce.Object3D();
o3D.vertices = [];
o3D.normals = [];
o3D.textureCoords = [];
for (latNumber = 0; latNumber <= latitudeBands; latNumber++) {
var theta = latNumber * Math.PI / latitudeBands;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
for (longNumber = 0; longNumber <= longitudeBands; longNumber++) {
var phi = longNumber * 2 * Math.PI / longitudeBands;
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
var x = cosPhi * sinTheta;
var y = cosTheta;
var z = sinPhi * sinTheta;
var u = 1 - (longNumber / longitudeBands);
var v = 1 - (latNumber / latitudeBands);
o3D.normals.push(x, y, z);
o3D.textureCoords.push(u, v);
o3D.vertices.push(radius * x + o.x, radius * y + o.y, radius * z + o.z);
}
}
if (asWireframe) {
o3D.isWireframe = true;
}
o3D.indices = [];
for (latNumber = 0; latNumber < latitudeBands; latNumber++) {
for (longNumber = 0; longNumber < longitudeBands; longNumber++) {
var first = (latNumber * (longitudeBands + 1)) + longNumber;
var second = first + longitudeBands + 1;
if (!asWireframe) {
o3D.indices.push(first + 1, second, first);
o3D.indices.push(first + 1, second + 1, second);
} else {
o3D.indices.push(second + 1, second);
o3D.indices.push(second, first);
o3D.indices.push(first + 1, first);
o3D.indices.push(first + 1, second + 1);
}
}
}
o3D.position = this.position;
o3D.rotation = this.rotation;
// o3D.scale = this.scale;
return o3D;
};
/**
* Creates grid of vertices as new Ayce.Object3D. If splitSquares is true triangles are created as faces without sharing vertices.
* @class
* @constructor
* @param {Number} a
* @param {Number} b
* @param {Number} xSubdivisions
* @param {Number} ySubdivisions
* @param {Boolean} splitSquares
*/
Ayce.Geometry.Plane = function (a, b, xSubdivisions, ySubdivisions, splitSquares) {
Ayce.Geometry.call(this);
this.a = a || 0;
this.b = b || 0;
this.xVertices = xSubdivisions || 2;
this.yVertices = ySubdivisions || 2;
this.splitSquares = splitSquares;
};
Ayce.Geometry.Plane.prototype = new Ayce.Geometry();
/**
* Returns plane geometry as Ayce.Object3D
* @return {Ayce.Object3D} o3D
*/
Ayce.Geometry.Plane.prototype.getO3D = function () {
var o3D = new Ayce.Object3D();
var o = this.offset;
var a = this.a;
var b = this.b;
var xVert = this.xVertices;
var yVert = this.yVertices;
o3D.vertices = [];
var xDist = a/xVert;
var yDist = b/yVert;
var x, y;
if(!this.splitSquares) {
for (y = 0; y < this.yVertices; y++) {
for (x = 0; x < this.xVertices; x++) {
o3D.vertices.push(o.x + x * xDist, o.y + y * yDist, o.z);
}
}
o3D.normals = [];
for (i = 0; i < xVert * yVert; i++) {
o3D.normals.push(0, 0, 1);
}
o3D.indices = [];
for (i = 0; i < xVert * (yVert - 1); i++) {
if ((i + 1) % xVert != 0) {
o3D.indices.push( // square
i + 1, i + xVert, i, // 1st triangle
i + xVert + 1, i + xVert, i + 1); // 2nd triangle
}
}
}else{
for (y = 0; y < this.yVertices - 1; y++) {
for (x = 0; x < this.xVertices - 1; x++) {
o3D.vertices.push(
// first triangle
o.x + x * xDist, o.y + y * yDist, o.z, // origin
o.x + x * xDist + xDist, o.y + y * yDist, o.z, // right of origin
o.x + x * xDist, o.y + y * yDist + yDist, o.z, // top of origin
// second triangle
o.x + x * xDist + xDist, o.y + y * yDist, o.z, // right of origin
o.x + x * xDist + xDist, o.y + y * yDist + yDist, o.z, // top right of origin
o.x + x * xDist, o.y + y * yDist + yDist, o.z // top of origin
);
}
}
o3D.normals = [];
o3D.indices = [];
for (var i = 0; i < o3D.vertices.length / 3; i++) {
o3D.normals.push(0, 0, 1);
o3D.indices.push(i);
}
}
o3D.position = this.position;
o3D.rotation = this.rotation;
o3D.scale = this.scale;
return o3D;
};
/**
* Creates icosahedron with given number of subdivisions
* @class
* @constructor
* @param {Number} subdivisions
*/
Ayce.Geometry.Icosahedron = function (subdivisions) {
this.subdivisions = subdivisions;
Ayce.Geometry.call(this);
};
Ayce.Geometry.Icosahedron.prototype = new Ayce.Geometry();
/**
* Returns icosahedron geometry as Ayce.Object3D
* @return {Ayce.Object3D} o3D
*/
Ayce.Geometry.Icosahedron.prototype.getO3D = function () {
var o3D = new Ayce.Object3D();
var golden = new Ayce.Vector2(0.5, ((1 + Math.sqrt(5)) / 2) - ((1 + Math.sqrt(5)) / 2) / 2);
var a = new Ayce.Vector2(
-golden.x, // left top
golden.y); // -0.5, 0.9
var b = new Ayce.Vector2(
golden.x, // right top
golden.y); // 0.5, 0.9
var c = new Ayce.Vector2(
-golden.x, // left bottom
-golden.y); // -0.5, -0.9
var d = new Ayce.Vector2(
golden.x, // right bottom
-golden.y); // 0.5, -0.9
var unsortedVertices = [];
unsortedVertices.push(
a.x, a.y, 0, // 0 top left
b.x, b.y, 0, // 1 top right
c.x, c.y, 0, // 2 bottom left
d.x, d.y, 0, // 3 bottom right
0, a.x, a.y,// 4 near bottom
0, b.x, b.y,// 5 near top
0, c.x, c.y,// 6 far bottom
0, d.x, d.y,// 7 far top
a.y, 0, a.x,// 8 far right
b.y, 0, b.x,// 9 near right
c.y, 0, c.x,// 10 far left
d.y, 0, d.x // 11 near left
);
o3D.vertices = [
unsortedVertices[0], unsortedVertices[1], unsortedVertices[2],
unsortedVertices[5 * 3], unsortedVertices[5 * 3 + 1], unsortedVertices[5 * 3 + 2],
unsortedVertices[1 * 3], unsortedVertices[1 * 3 + 1], unsortedVertices[1 * 3 + 2],
unsortedVertices[0], unsortedVertices[1], unsortedVertices[2],
unsortedVertices[1 * 3], unsortedVertices[1 * 3 + 1], unsortedVertices[1 * 3 + 2],
unsortedVertices[7 * 3], unsortedVertices[7 * 3 + 1], unsortedVertices[7 * 3 + 2],
unsortedVertices[0], unsortedVertices[1], unsortedVertices[2],
unsortedVertices[10 * 3], unsortedVertices[10 * 3 + 1], unsortedVertices[10 * 3 + 2],
unsortedVertices[11 * 3], unsortedVertices[11 * 3 + 1], unsortedVertices[11 * 3 + 2],
unsortedVertices[0], unsortedVertices[1], unsortedVertices[2],
unsortedVertices[7 * 3], unsortedVertices[7 * 3 + 1], unsortedVertices[7 * 3 + 2],
unsortedVertices[10 * 3], unsortedVertices[10 * 3 + 1], unsortedVertices[10 * 3 + 2],
unsortedVertices[0], unsortedVertices[1], unsortedVertices[2],
unsortedVertices[11 * 3], unsortedVertices[11 * 3 + 1], unsortedVertices[11 * 3 + 2],
unsortedVertices[5 * 3], unsortedVertices[5 * 3 + 1], unsortedVertices[5 * 3 + 2],
unsortedVertices[1 * 3], unsortedVertices[1 * 3 + 1], unsortedVertices[1 * 3 + 2],
unsortedVertices[9 * 3], unsortedVertices[9 * 3 + 1], unsortedVertices[9 * 3 + 2],
unsortedVertices[8 * 3], unsortedVertices[8 * 3 + 1], unsortedVertices[8 * 3 + 2],
unsortedVertices[1 * 3], unsortedVertices[1 * 3 + 1], unsortedVertices[1 * 3 + 2],
unsortedVertices[8 * 3], unsortedVertices[8 * 3 + 1], unsortedVertices[8 * 3 + 2],
unsortedVertices[7 * 3], unsortedVertices[7 * 3 + 1], unsortedVertices[7 * 3 + 2],
unsortedVertices[1 * 3], unsortedVertices[1 * 3 + 1], unsortedVertices[1 * 3 + 2],
unsortedVertices[5 * 3], unsortedVertices[5 * 3 + 1], unsortedVertices[5 * 3 + 2],
unsortedVertices[9 * 3], unsortedVertices[9 * 3 + 1], unsortedVertices[9 * 3 + 2],
unsortedVertices[4 * 3], unsortedVertices[4 * 3 + 1], unsortedVertices[4 * 3 + 2],
unsortedVertices[9 * 3], unsortedVertices[9 * 3 + 1], unsortedVertices[9 * 3 + 2],
unsortedVertices[5 * 3], unsortedVertices[5 * 3 + 1], unsortedVertices[5 * 3 + 2],
unsortedVertices[4 * 3], unsortedVertices[4 * 3 + 1], unsortedVertices[4 * 3 + 2],
unsortedVertices[3 * 3], unsortedVertices[3 * 3 + 1], unsortedVertices[3 * 3 + 2],
unsortedVertices[9 * 3], unsortedVertices[9 * 3 + 1], unsortedVertices[9 * 3 + 2],
unsortedVertices[4 * 3], unsortedVertices[4 * 3 + 1], unsortedVertices[4 * 3 + 2],
unsortedVertices[5 * 3], unsortedVertices[5 * 3 + 1], unsortedVertices[5 * 3 + 2],
unsortedVertices[11 * 3], unsortedVertices[11 * 3 + 1], unsortedVertices[11 * 3 + 2],
unsortedVertices[2 * 3], unsortedVertices[2 * 3 + 1], unsortedVertices[2 * 3 + 2],
unsortedVertices[11 * 3], unsortedVertices[11 * 3 + 1], unsortedVertices[11 * 3 + 2],
unsortedVertices[10 * 3], unsortedVertices[10 * 3 + 1], unsortedVertices[10 * 3 + 2],
unsortedVertices[2 * 3], unsortedVertices[2 * 3 + 1], unsortedVertices[2 * 3 + 2],
unsortedVertices[4 * 3], unsortedVertices[4 * 3 + 1], unsortedVertices[4 * 3 + 2],
unsortedVertices[11 * 3], unsortedVertices[11 * 3 + 1], unsortedVertices[11 * 3 + 2],
unsortedVertices[2 * 3], unsortedVertices[2 * 3 + 1], unsortedVertices[2 * 3 + 2],
unsortedVertices[3 * 3], unsortedVertices[3 * 3 + 1], unsortedVertices[3 * 3 + 2],
unsortedVertices[4 * 3], unsortedVertices[4 * 3 + 1], unsortedVertices[4 * 3 + 2],
unsortedVertices[3 * 3], unsortedVertices[3 * 3 + 1], unsortedVertices[3 * 3 + 2],
unsortedVertices[8 * 3], unsortedVertices[8 * 3 + 1], unsortedVertices[8 * 3 + 2],
unsortedVertices[9 * 3], unsortedVertices[9 * 3 + 1], unsortedVertices[9 * 3 + 2],
unsortedVertices[6 * 3], unsortedVertices[6 * 3 + 1], unsortedVertices[6 * 3 + 2],
unsortedVertices[2 * 3], unsortedVertices[2 * 3 + 1], unsortedVertices[2 * 3 + 2],
unsortedVertices[10 * 3], unsortedVertices[10 * 3 + 1], unsortedVertices[10 * 3 + 2],
unsortedVertices[6 * 3], unsortedVertices[6 * 3 + 1], unsortedVertices[6 * 3 + 2],
unsortedVertices[3 * 3], unsortedVertices[3 * 3 + 1], unsortedVertices[3 * 3 + 2],
unsortedVertices[2 * 3], unsortedVertices[2 * 3 + 1], unsortedVertices[2 * 3 + 2],
unsortedVertices[6 * 3], unsortedVertices[6 * 3 + 1], unsortedVertices[6 * 3 + 2],
unsortedVertices[8 * 3], unsortedVertices[8 * 3 + 1], unsortedVertices[8 * 3 + 2],
unsortedVertices[3 * 3], unsortedVertices[3 * 3 + 1], unsortedVertices[3 * 3 + 2],
unsortedVertices[6 * 3], unsortedVertices[6 * 3 + 1], unsortedVertices[6 * 3 + 2],
unsortedVertices[7 * 3], unsortedVertices[7 * 3 + 1], unsortedVertices[7 * 3 + 2],
unsortedVertices[8 * 3], unsortedVertices[8 * 3 + 1], unsortedVertices[8 * 3 + 2],
unsortedVertices[6 * 3], unsortedVertices[6 * 3 + 1], unsortedVertices[6 * 3 + 2],
unsortedVertices[10 * 3], unsortedVertices[10 * 3 + 1], unsortedVertices[10 * 3 + 2],
unsortedVertices[7 * 3], unsortedVertices[7 * 3 + 1], unsortedVertices[7 * 3 + 2],
];
var radius = Math.sqrt(Math.pow(golden.x, 2) + Math.pow(golden.y, 2));
var unprocessedFaces = [o3D.vertices];
var recursions = this.subdivisions - 1;
a = new Ayce.Vector3(0, 0, 0);
b = new Ayce.Vector3(0, 0, 0);
c = new Ayce.Vector3(0, 0, 0);
var ab = new Ayce.Vector3(0, 0, 0);
var bc = new Ayce.Vector3(0, 0, 0);
var ac = new Ayce.Vector3(0, 0, 0);
var dist;
for(var i = 1; i < recursions + 1; i++){
unprocessedFaces[i] = [];
}
for(i = 0; i < unprocessedFaces.length - 1; i++){ // iterate through rounds
for(var j = 0; j < unprocessedFaces[i].length; j+=9){ //iterate through faces
a.set(
unprocessedFaces[i][j],
unprocessedFaces[i][j + 1],
a.z = unprocessedFaces[i][j + 2]
);
b.set(
unprocessedFaces[i][j + 3],
unprocessedFaces[i][j + 4],
unprocessedFaces[i][j + 5]
);
c.set(
unprocessedFaces[i][j + 6],
unprocessedFaces[i][j + 7],
unprocessedFaces[i][j + 8]
);
ab.set(
(a.x + b.x) / 2,
(a.y + b.y) / 2,
(a.z + b.z) / 2
);
dist = radius / Math.sqrt(ab.x * ab.x + ab.y * ab.y + ab.z * ab.z); // distance between vertex and center (same for all vertices)
ab.x*=dist;
ab.y*=dist;
ab.z*=dist;
bc.set(
(b.x + c.x) / 2 * dist,
(b.y + c.y) / 2 * dist,
(b.z + c.z) / 2 * dist
);
ac.set(
(a.x + c.x) / 2 * dist,
(a.y + c.y) / 2 * dist,
(a.z + c.z) / 2 * dist
);
unprocessedFaces[i + 1].push(
a.x, a.y, a.z, ab.x, ab.y, ab.z, ac.x, ac.y, ac.z,
b.x, b.y, b.z, bc.x, bc.y, bc.z, ab.x, ab.y, ab.z,
c.x, c.y, c.z, ac.x, ac.y, ac.z, bc.x, bc.y, bc.z,
ab.x, ab.y, ab.z, bc.x, bc.y, bc.z, ac.x, ac.y, ac.z
);
if(j == unprocessedFaces[i].length-1){
recursions--;
}
}
}
o3D.vertices = unprocessedFaces[unprocessedFaces.length - 1];
o3D.indices = [];
for(i = 0; i < o3D.vertices.length / 3; i++){
o3D.indices.push(i);
}
var normal;
o3D.normals = [];
for(i = 0; i<o3D.vertices.length; i+=9){
a.set(o3D.vertices[i], o3D.vertices[i + 1], o3D.vertices[i + 2]);
b.set(o3D.vertices[i + 3], o3D.vertices[i + 4], o3D.vertices[i + 5]);
c.set(o3D.vertices[i + 6], o3D.vertices[i + 7], o3D.vertices[i + 8]);
ab = b.subtract(a.x, a.y, a.z);
ac = c.subtract(a.x, a.y, a.z);
normal = ab.crossProduct(ac);
o3D.normals.push(normal.x, normal.y, normal.z, normal.x, normal.y, normal.z, normal.x, normal.y, normal.z);
}
o3D.position = this.position;
o3D.rotation = this.rotation;
o3D.scale = this.scale;
return o3D;
};
Ayce.Geometry.CollisionMath = {};
Ayce.Geometry.CollisionMath.ObjectPool ={
corners1: [
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3()
],
corners2: [
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3()
],
normals: [
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3(),
new Ayce.Vector3()
],
edgeNormalV1: new Ayce.Vector3(),
edgeNormalV2: new Ayce.Vector3()
};
/**
* TODO: Description
* @param {} outputVector
* @param {} boxGeo
* @param {} addA
* @param {} addB
* @param {} addC
*/
Ayce.Geometry.CollisionMath.calcCorner = function (outputVector,boxGeo, addA, addB, addC) {
outputVector.x = addA ? boxGeo.a : 0;
outputVector.y = addB ? boxGeo.b : 0;
outputVector.z = addC ? boxGeo.c : 0;
outputVector.addVector3(boxGeo.offset);
outputVector.multiply(boxGeo.scale.x, boxGeo.scale.y, boxGeo.scale.z);
boxGeo.rotation.getConjugate().rotatePoint(outputVector);
outputVector.addVector3(boxGeo.position);
};
/**
* Description
* @param {} outputVector
* @param {} s
* @param {} u
* @param {} v
*/
Ayce.Geometry.CollisionMath.calcNormal = function (outputVector, s, u, v) {
var x1 = u.x-s.x,
y1 = u.y-s.y,
z1 = u.z-s.z,
x2 = v.x-s.x,
y2 = v.y-s.y,
z2 = v.z-s.z;
outputVector.x = y1*z2 - z1*y2;
outputVector.y = z1*x2 - x1*z2;
outputVector.z = x1*y2 - y1*x2;
outputVector.normalize();
};
/**
* TODO: Description
* @param {} v
* @param {} c1
* @param {} c2
* @param {} sP
*/
Ayce.Geometry.CollisionMath.getEdgeNormal = function (v, c1, c2, sP) {
var v1 = Ayce.Geometry.CollisionMath.ObjectPool.edgeNormalV1;
v1.x = c2.x-c1.x;
v1.y = c2.y-c1.y;
v1.z = c2.z-c1.z;
v1.normalize();
var dP = v1.x*(sP.x-c1.x) + v1.y*(sP.y-c1.y) + v1.z*(sP.z-c1.z);
v.x = v1.x * dP + c1.x - sP.x;
v.y = v1.y * dP + c1.y - sP.y;
v.z = v1.z * dP + c1.z - sP.z;
v.normalize();
};
/**
* TODO: Description
* @param {} box1
* @param {} box2
* @return mtd
*/
Ayce.Geometry.prototype.boxBoxCollision = function (box1, box2) {
var calcCorner = Ayce.Geometry.CollisionMath.calcCorner;
var calcNormal = Ayce.Geometry.CollisionMath.calcNormal;
var corners1 = Ayce.Geometry.CollisionMath.ObjectPool.corners1;
calcCorner(corners1[0], box1, false, false, false);
calcCorner(corners1[1], box1, true, false, false);
calcCorner(corners1[2], box1, false, true, false);
calcCorner(corners1[3], box1, true, true, false);
calcCorner(corners1[4], box1, false, false, true);
calcCorner(corners1[5], box1, true, false, true);
calcCorner(corners1[6], box1, false, true, true);
calcCorner(corners1[7], box1, true, true, true);
var corners2 = Ayce.Geometry.CollisionMath.ObjectPool.corners2;
calcCorner(corners2[0], box2, false, false, false);
calcCorner(corners2[1], box2, true, false, false);
calcCorner(corners2[2], box2, false, true, false);
calcCorner(corners2[3], box2, true, true, false);
calcCorner(corners2[4], box2, false, false, true);
calcCorner(corners2[5], box2, true, false, true);
calcCorner(corners2[6], box2, false, true, true);
calcCorner(corners2[7], box2, true, true, true);
var normals = Ayce.Geometry.CollisionMath.ObjectPool.normals;
var normalsCount = 6;
calcNormal(normals[0], corners1[0], corners1[1], corners1[2]);
calcNormal(normals[1], corners1[0], corners1[4], corners1[2]);
calcNormal(normals[2], corners1[0], corners1[1], corners1[4]);
calcNormal(normals[3], corners2[0], corners2[1], corners2[2]);
calcNormal(normals[4], corners2[0], corners2[4], corners2[2]);
calcNormal(normals[5], corners2[0], corners2[1], corners2[4]);
var i;
var j;
var mtd = null; //Minimum Translation Distance
for (i = 0; i < normalsCount; i++) {
var normal = normals[i];
if (normal.x === 0 && normal.y === 0 && normal.z === 0) continue;
var min1 = null;
var max1 = null;
for (j = 0; j < corners1.length; j++) {
var c = normal.dotProduct(corners1[j]);
if (min1 === null || c < min1) min1 = c;
if (max1 === null || c > max1) max1 = c;
}
var min2 = null;
var max2 = null;
for (j = 0; j < corners2.length; j++) {
var c = normal.dotProduct(corners2[j]);
if (min2 === null || c < min2) min2 = c;
if (max2 === null || c > max2) max2 = c;
}
if (max1 < min2 || min1 > max2) return null;
//Collision Distance
var distance = max1 - min2;
if (Math.abs(max2 - min1) < Math.abs(distance)) distance = max2 - min1;
if (Math.abs(min1 - max2) < Math.abs(distance)) distance = min1 - max2;
if (Math.abs(min2 - max1) < Math.abs(distance)) distance = min2 - max1;
if (min1 > min2) distance = -distance;
var mtdNew = normal.copy().scaleBy(distance);
if ((mtd === null || mtd.getLength() > mtdNew.getLength())) {
mtd = mtdNew;
mtd.normal = normal;
mtd.distance = distance;
}
}
return mtd;
};
/**
* TODO: Description
* @param {} box
* @param {} sphere
* @param {} invert
* @return mtd
*/
Ayce.Geometry.prototype.boxSphereCollision = function (box, sphere, invert) {
if(box.a === 0 || box.b === 0 || box.c === 0)invert = true;//TODO fix...
var calcCorner = Ayce.Geometry.CollisionMath.calcCorner;
var calcNormal = Ayce.Geometry.CollisionMath.calcNormal;
var getEdgeNormal = Ayce.Geometry.CollisionMath.getEdgeNormal;
var corners1 = Ayce.Geometry.CollisionMath.ObjectPool.corners1;
calcCorner(corners1[0], box, false, false, false);
calcCorner(corners1[1], box, true, false, false);
calcCorner(corners1[2], box, false, true, false);
calcCorner(corners1[3], box, true, true, false);
calcCorner(corners1[4], box, false, false, true);
calcCorner(corners1[5], box, true, false, true);
calcCorner(corners1[6], box, false, true, true);
calcCorner(corners1[7], box, true, true, true);
var sP = sphere.position.copy().addVector3(sphere.offset);
var normals = Ayce.Geometry.CollisionMath.ObjectPool.normals;
var normalsCount = 15;
calcNormal(normals[0], corners1[0], corners1[1], corners1[2]);
calcNormal(normals[1], corners1[0], corners1[2], corners1[4]);
calcNormal(normals[2], corners1[0], corners1[4], corners1[1]);
getEdgeNormal(normals[3], corners1[0], corners1[1], sP);
getEdgeNormal(normals[4], corners1[1], corners1[5], sP);
getEdgeNormal(normals[5], corners1[4], corners1[5], sP);
getEdgeNormal(normals[6], corners1[4], corners1[0], sP);
getEdgeNormal(normals[7], corners1[2], corners1[6], sP);
getEdgeNormal(normals[8], corners1[7], corners1[6], sP);
getEdgeNormal(normals[9], corners1[7], corners1[3], sP);
getEdgeNormal(normals[10], corners1[3], corners1[2], sP);
getEdgeNormal(normals[11], corners1[0], corners1[2], sP);
getEdgeNormal(normals[12], corners1[1], corners1[3], sP);
getEdgeNormal(normals[13], corners1[7], corners1[5], sP);
getEdgeNormal(normals[14], corners1[6], corners1[4], sP);
var i;
var j;
var mtd = null; //Minimum Translation Distance
for (i = 0; i < normalsCount; i++) {
var normal = normals[i];
if (normal.x === 0 && normal.y === 0 && normal.z === 0) continue;
var min1 = null;
var max1 = null;
for (j = 0; j < corners1.length; j++) {
var c = normal.dotProduct(corners1[j]);
if (min1 === null || c < min1) min1 = c;
if (max1 === null || c > max1) max1 = c;
}
var p = normal.dotProduct(sP);
var min2 = p - sphere.r;
var max2 = p + sphere.r;
if (max1 < min2 || min1 > max2){return null;}
//Collision Distance
var distance = max1 - min2;
if (Math.abs(max2 - min1) < Math.abs(distance)) distance = max2 - min1;
if (Math.abs(min1 - max2) < Math.abs(distance)) distance = min1 - max2;
if (Math.abs(min2 - max1) < Math.abs(distance)) distance = min2 - max1;
var mtdNew = normal.copy().scaleBy(distance);
if ((invert && min1 > min2) || (!invert && min1 < min2)) mtdNew.negate();
if ((mtd === null || mtd.getLength() > mtdNew.getLength())) {
mtd = mtdNew;
mtd.distance = distance;
mtd.normal = normal;
}
}
return mtd;
};
/**
* TODO: Description
* @param {} sphere1
* @param {} sphere2
* @return Literal
*/
Ayce.Geometry.prototype.sphereSphereCollision = function (sphere1, sphere2) {
var pos1 = sphere1.position.copy().addVector3(sphere1.offset);
var pos2 = sphere2.position.copy().addVector3(sphere2.offset);
var distance = pos1.copy().subtract(pos2.x, pos2.y, pos2.z).getLength();
if (distance < sphere1.r + sphere2.r) {
var p = sphere1.position;
var mtd = sphere2.position.copy().subtract(p.x, p.y, p.z).normalize().scaleBy((sphere1.r + sphere2.r) - distance);
mtd.distance = distance;
mtd.normal = mtd;
return mtd;
}
return null;
};