ami-cjs.js
Version:
<p align="center"> <img src="https://cloud.githubusercontent.com/assets/214063/23213764/78ade038-f90c-11e6-8208-4fcade5f3832.png" width="60%"> </p>
475 lines (395 loc) • 15.4 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _core = require('./core.utils');
var _core2 = _interopRequireDefault(_core);
var _core3 = require('./core.validators');
var _core4 = _interopRequireDefault(_core3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Compute/test intersection between different objects.
*
* @module core/intersections
*/
var Intersections = function () {
function Intersections() {
_classCallCheck(this, Intersections);
}
_createClass(Intersections, null, [{
key: 'aabbPlane',
/**
* Compute intersection between oriented bounding box and a plane.
*
* Returns intersection in plane's space.
*
* Should return at least 3 intersections. If not, the plane and the box do not
* intersect.
*
* @param {Object} aabb - Axe Aligned Bounding Box representation.
* @param {THREE.Vector3} aabb.halfDimensions - Half dimensions of the box.
* @param {THREE.Vector3} aabb.center - Center of the box.
* @param {THREE.Matrix4} aabb.toAABB - Transform to go from plane space to box space.
* @param {Object} plane - Plane representation
* @param {THREE.Vector3} plane.position - position of normal which describes the plane.
* @param {THREE.Vector3} plane.direction - Direction of normal which describes the plane.
*
* @returns {Array<THREE.Vector3>} List of all intersections in plane's space.
* @returns {boolean} false is invalid input provided.
*
* @example
* //Returns array with intersection N intersections
* let aabb = {
* center: new THREE.Vector3(150, 150, 150),
* halfDimensions: new THREE.Vector3(50, 60, 70),
* toAABB: new THREE.Matrix4()
* }
* let plane = {
* position: new THREE.Vector3(110, 120, 130),
* direction: new THREE.Vector3(1, 0, 0)
* }
*
* let intersections = CoreIntersections.aabbPlane(aabb, plane);
* // intersections ==
* //[ { x : 110, y : 90, z : 80 },
* // { x : 110, y : 210, z : 220 },
* // { x : 110, y : 210, z : 80 },
* // { x : 110, y : 90, z : 220 } ]
*
* //Returns empty array with 0 intersections
* let aabb = {
*
* }
* let plane = {
*
* }
*
* let intersections = VJS.Core.Validators.matrix4(new THREE.Vector3());
*
* //Returns false if invalid input?
*
*/
value: function aabbPlane(aabb, plane) {
//
// obb = { halfDimensions, orientation, center, toAABB }
// plane = { position, direction }
//
//
// LOGIC:
//
// Test intersection of each edge of the Oriented Bounding Box with the Plane
//
// ALL EDGES
//
// .+-------+
// .' | .'|
// +---+---+' |
// | | | |
// | ,+---+---+
// |.' | .'
// +-------+'
//
// SPACE ORIENTATION
//
// +
// j |
// |
// | i
// k ,+-------+
// .'
// +
//
//
// 1- Move Plane position and orientation in IJK space
// 2- Test Edges/ IJK Plane intersections
// 3- Return intersection Edge/ IJK Plane if it touches the Oriented BBox
var intersections = [];
if (!(this.validateAabb(aabb) && this.validatePlane(plane))) {
window.console.log('Invalid aabb or plane provided.');
return false;
}
// invert space matrix
var fromAABB = new THREE.Matrix4();
fromAABB.getInverse(aabb.toAABB);
var t1 = plane.direction.clone().applyMatrix4(aabb.toAABB);
var t0 = new THREE.Vector3(0, 0, 0).applyMatrix4(aabb.toAABB);
var planeAABB = this.posdir(plane.position.clone().applyMatrix4(aabb.toAABB), new THREE.Vector3(t1.x - t0.x, t1.y - t0.y, t1.z - t0.z).normalize());
var bbox = _core2.default.bbox(aabb.center, aabb.halfDimensions);
var orientation = new THREE.Vector3(new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1));
// 12 edges (i.e. ray)/plane intersection tests
// RAYS STARTING FROM THE FIRST CORNER (0, 0, 0)
//
// +
// |
// |
// |
// ,+---+---+
// .'
// +
var ray = this.posdir(new THREE.Vector3(aabb.center.x - aabb.halfDimensions.x, aabb.center.y - aabb.halfDimensions.y, aabb.center.z - aabb.halfDimensions.z), orientation.x);
this.rayPlaneInBBox(ray, planeAABB, bbox, intersections);
ray.direction = orientation.y;
this.rayPlaneInBBox(ray, planeAABB, bbox, intersections);
ray.direction = orientation.z;
this.rayPlaneInBBox(ray, planeAABB, bbox, intersections);
// RAYS STARTING FROM THE LAST CORNER
//
// +
// .'
// +-------+'
// |
// |
// |
// +
//
var ray2 = this.posdir(new THREE.Vector3(aabb.center.x + aabb.halfDimensions.x, aabb.center.y + aabb.halfDimensions.y, aabb.center.z + aabb.halfDimensions.z), orientation.x);
this.rayPlaneInBBox(ray2, planeAABB, bbox, intersections);
ray2.direction = orientation.y;
this.rayPlaneInBBox(ray2, planeAABB, bbox, intersections);
ray2.direction = orientation.z;
this.rayPlaneInBBox(ray2, planeAABB, bbox, intersections);
// RAYS STARTING FROM THE SECOND CORNER
//
// +
// |
// |
// |
// +
// .'
// +'
var ray3 = this.posdir(new THREE.Vector3(aabb.center.x + aabb.halfDimensions.x, aabb.center.y - aabb.halfDimensions.y, aabb.center.z - aabb.halfDimensions.z), orientation.y);
this.rayPlaneInBBox(ray3, planeAABB, bbox, intersections);
ray3.direction = orientation.z;
this.rayPlaneInBBox(ray3, planeAABB, bbox, intersections);
// RAYS STARTING FROM THE THIRD CORNER
//
// .+-------+
// .'
// +
//
//
//
//
var ray4 = this.posdir(new THREE.Vector3(aabb.center.x - aabb.halfDimensions.x, aabb.center.y + aabb.halfDimensions.y, aabb.center.z - aabb.halfDimensions.z), orientation.x);
this.rayPlaneInBBox(ray4, planeAABB, bbox, intersections);
ray4.direction = orientation.z;
this.rayPlaneInBBox(ray4, planeAABB, bbox, intersections);
// RAYS STARTING FROM THE FOURTH CORNER
//
//
//
// +
// |
// |
// |
// +-------+
var ray5 = this.posdir(new THREE.Vector3(aabb.center.x - aabb.halfDimensions.x, aabb.center.y - aabb.halfDimensions.y, aabb.center.z + aabb.halfDimensions.z), orientation.x);
this.rayPlaneInBBox(ray5, planeAABB, bbox, intersections);
ray5.direction = orientation.y;
this.rayPlaneInBBox(ray5, planeAABB, bbox, intersections);
// @todo make sure objects are unique...
// back to original space
intersections.map(function (element) {
return element.applyMatrix4(fromAABB);
});
return intersections;
}
/**
* Compute intersection between a ray and a plane.
*
* @memberOf this
* @public
*
* @param {Object} ray - Ray representation.
* @param {THREE.Vector3} ray.position - position of normal which describes the ray.
* @param {THREE.Vector3} ray.direction - Direction of normal which describes the ray.
* @param {Object} plane - Plane representation
* @param {THREE.Vector3} plane.position - position of normal which describes the plane.
* @param {THREE.Vector3} plane.direction - Direction of normal which describes the plane.
*
* @returns {THREE.Vector3|null} Intersection between ray and plane or null.
*/
}, {
key: 'rayPlane',
value: function rayPlane(ray, plane) {
// ray: {position, direction}
// plane: {position, direction}
if (ray.direction.dot(plane.direction) !== 0) {
//
// not parallel, move forward
//
// LOGIC:
//
// Ray equation: P = P0 + tV
// P = <Px, Py, Pz>
// P0 = <ray.position.x, ray.position.y, ray.position.z>
// V = <ray.direction.x, ray.direction.y, ray.direction.z>
//
// Therefore:
// Px = ray.position.x + t*ray.direction.x
// Py = ray.position.y + t*ray.direction.y
// Pz = ray.position.z + t*ray.direction.z
//
//
//
// Plane equation: ax + by + cz + d = 0
// a = plane.direction.x
// b = plane.direction.y
// c = plane.direction.z
// d = -( plane.direction.x*plane.position.x +
// plane.direction.y*plane.position.y +
// plane.direction.z*plane.position.z )
//
//
// 1- in the plane equation, we replace x, y and z by Px, Py and Pz
// 2- find t
// 3- replace t in Px, Py and Pz to get the coordinate of the intersection
//
var t = (plane.direction.x * (plane.position.x - ray.position.x) + plane.direction.y * (plane.position.y - ray.position.y) + plane.direction.z * (plane.position.z - ray.position.z)) / (plane.direction.x * ray.direction.x + plane.direction.y * ray.direction.y + plane.direction.z * ray.direction.z);
var intersection = new THREE.Vector3(ray.position.x + t * ray.direction.x, ray.position.y + t * ray.direction.y, ray.position.z + t * ray.direction.z);
return intersection;
}
return null;
}
/**
* Compute intersection between a ray and a box
* @param {Object} ray
* @param {Object} box
* @return {Array}
*/
}, {
key: 'rayBox',
value: function rayBox(ray, box) {
// should also do the space transforms here
// ray: {position, direction}
// box: {halfDimensions, center}
var intersections = [];
var bbox = _core2.default.bbox(box.center, box.halfDimensions);
// window.console.log(bbox);
// X min
var plane = this.posdir(new THREE.Vector3(bbox.min.x, box.center.y, box.center.z), new THREE.Vector3(-1, 0, 0));
this.rayPlaneInBBox(ray, plane, bbox, intersections);
// X max
plane = this.posdir(new THREE.Vector3(bbox.max.x, box.center.y, box.center.z), new THREE.Vector3(1, 0, 0));
this.rayPlaneInBBox(ray, plane, bbox, intersections);
// Y min
plane = this.posdir(new THREE.Vector3(box.center.x, bbox.min.y, box.center.z), new THREE.Vector3(0, -1, 0));
this.rayPlaneInBBox(ray, plane, bbox, intersections);
// Y max
plane = this.posdir(new THREE.Vector3(box.center.x, bbox.max.y, box.center.z), new THREE.Vector3(0, 1, 0));
this.rayPlaneInBBox(ray, plane, bbox, intersections);
// Z min
plane = this.posdir(new THREE.Vector3(box.center.x, box.center.y, bbox.min.z), new THREE.Vector3(0, 0, -1));
this.rayPlaneInBBox(ray, plane, bbox, intersections);
// Z max
plane = this.posdir(new THREE.Vector3(box.center.x, box.center.y, bbox.max.z), new THREE.Vector3(0, 0, 1));
this.rayPlaneInBBox(ray, plane, bbox, intersections);
return intersections;
}
/**
* Intersection between ray and a plane that are in a box.
* @param {*} ray
* @param {*} planeAABB
* @param {*} bbox
* @param {*} intersections
*/
}, {
key: 'rayPlaneInBBox',
value: function rayPlaneInBBox(ray, planeAABB, bbox, intersections) {
var intersection = this.rayPlane(ray, planeAABB);
// window.console.log(intersection);
if (intersection && this.inBBox(intersection, bbox)) {
if (!intersections.find(this.findIntersection(intersection))) {
intersections.push(intersection);
}
}
}
/**
* Find intersection in array
* @param {*} myintersection
*/
}, {
key: 'findIntersection',
value: function findIntersection(myintersection) {
return function found(element, index, array) {
if (myintersection.x === element.x && myintersection.y === element.y && myintersection.z === element.z) {
return true;
}
return false;
};
}
/**
* Is point in box.
* @param {Object} point
* @param {Object} bbox
* @return {Boolean}
*/
}, {
key: 'inBBox',
value: function inBBox(point, bbox) {
//
var epsilon = 0.0001;
if (point && point.x >= bbox.min.x - epsilon && point.y >= bbox.min.y - epsilon && point.z >= bbox.min.z - epsilon && point.x <= bbox.max.x + epsilon && point.y <= bbox.max.y + epsilon && point.z <= bbox.max.z + epsilon) {
return true;
}
return false;
}
}, {
key: 'posdir',
value: function posdir(position, direction) {
return { position: position, direction: direction };
}
}, {
key: 'validatePlane',
value: function validatePlane(plane) {
//
if (plane === null) {
window.console.log('Invalid plane.');
window.console.log(plane);
return false;
}
if (!_core4.default.vector3(plane.position)) {
window.console.log('Invalid plane.position.');
window.console.log(plane.position);
return false;
}
if (!_core4.default.vector3(plane.direction)) {
window.console.log('Invalid plane.direction.');
window.console.log(plane.direction);
return false;
}
return true;
}
}, {
key: 'validateAabb',
value: function validateAabb(aabb) {
//
if (aabb === null) {
window.console.log('Invalid aabb.');
window.console.log(aabb);
return false;
}
if (!_core4.default.matrix4(aabb.toAABB)) {
window.console.log('Invalid aabb.toAABB: ');
window.console.log(aabb.toAABB);
return false;
}
if (!_core4.default.vector3(aabb.center)) {
window.console.log('Invalid aabb.center.');
window.console.log(aabb.center);
return false;
}
if (!(_core4.default.vector3(aabb.halfDimensions) && aabb.halfDimensions.x >= 0 && aabb.halfDimensions.y >= 0 && aabb.halfDimensions.z >= 0)) {
window.console.log('Invalid aabb.halfDimensions.');
window.console.log(aabb.halfDimensions);
return false;
}
return true;
}
}]);
return Intersections;
}();
exports.default = Intersections;
module.exports = exports['default'];