244 lines
8.4 KiB
JavaScript
244 lines
8.4 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
const THREE = require("three");
|
|
const a = {
|
|
c: null,
|
|
// center
|
|
u: [/* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3()],
|
|
// basis vectors
|
|
e: []
|
|
// half width
|
|
};
|
|
const b = {
|
|
c: null,
|
|
// center
|
|
u: [/* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3()],
|
|
// basis vectors
|
|
e: []
|
|
// half width
|
|
};
|
|
const R = [[], [], []];
|
|
const AbsR = [[], [], []];
|
|
const t = [];
|
|
const xAxis = /* @__PURE__ */ new THREE.Vector3();
|
|
const yAxis = /* @__PURE__ */ new THREE.Vector3();
|
|
const zAxis = /* @__PURE__ */ new THREE.Vector3();
|
|
const v1 = /* @__PURE__ */ new THREE.Vector3();
|
|
const size = /* @__PURE__ */ new THREE.Vector3();
|
|
const closestPoint = /* @__PURE__ */ new THREE.Vector3();
|
|
const rotationMatrix = /* @__PURE__ */ new THREE.Matrix3();
|
|
const aabb = /* @__PURE__ */ new THREE.Box3();
|
|
const matrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
const inverse = /* @__PURE__ */ new THREE.Matrix4();
|
|
const localRay = /* @__PURE__ */ new THREE.Ray();
|
|
class OBB {
|
|
constructor(center = new THREE.Vector3(), halfSize = new THREE.Vector3(), rotation = new THREE.Matrix3()) {
|
|
this.center = center;
|
|
this.halfSize = halfSize;
|
|
this.rotation = rotation;
|
|
}
|
|
set(center, halfSize, rotation) {
|
|
this.center = center;
|
|
this.halfSize = halfSize;
|
|
this.rotation = rotation;
|
|
return this;
|
|
}
|
|
copy(obb2) {
|
|
this.center.copy(obb2.center);
|
|
this.halfSize.copy(obb2.halfSize);
|
|
this.rotation.copy(obb2.rotation);
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
getSize(result) {
|
|
return result.copy(this.halfSize).multiplyScalar(2);
|
|
}
|
|
/**
|
|
* Reference: Closest Point on OBB to Point in Real-Time Collision Detection
|
|
* by Christer Ericson (chapter 5.1.4)
|
|
*/
|
|
clampPoint(point, result) {
|
|
const halfSize = this.halfSize;
|
|
v1.subVectors(point, this.center);
|
|
this.rotation.extractBasis(xAxis, yAxis, zAxis);
|
|
result.copy(this.center);
|
|
const x = THREE.MathUtils.clamp(v1.dot(xAxis), -halfSize.x, halfSize.x);
|
|
result.add(xAxis.multiplyScalar(x));
|
|
const y = THREE.MathUtils.clamp(v1.dot(yAxis), -halfSize.y, halfSize.y);
|
|
result.add(yAxis.multiplyScalar(y));
|
|
const z = THREE.MathUtils.clamp(v1.dot(zAxis), -halfSize.z, halfSize.z);
|
|
result.add(zAxis.multiplyScalar(z));
|
|
return result;
|
|
}
|
|
containsPoint(point) {
|
|
v1.subVectors(point, this.center);
|
|
this.rotation.extractBasis(xAxis, yAxis, zAxis);
|
|
return Math.abs(v1.dot(xAxis)) <= this.halfSize.x && Math.abs(v1.dot(yAxis)) <= this.halfSize.y && Math.abs(v1.dot(zAxis)) <= this.halfSize.z;
|
|
}
|
|
intersectsBox3(box3) {
|
|
return this.intersectsOBB(obb.fromBox3(box3));
|
|
}
|
|
intersectsSphere(sphere) {
|
|
this.clampPoint(sphere.center, closestPoint);
|
|
return closestPoint.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius;
|
|
}
|
|
/**
|
|
* Reference: OBB-OBB Intersection in Real-Time Collision Detection
|
|
* by Christer Ericson (chapter 4.4.1)
|
|
*
|
|
*/
|
|
intersectsOBB(obb2, epsilon = Number.EPSILON) {
|
|
a.c = this.center;
|
|
a.e[0] = this.halfSize.x;
|
|
a.e[1] = this.halfSize.y;
|
|
a.e[2] = this.halfSize.z;
|
|
this.rotation.extractBasis(a.u[0], a.u[1], a.u[2]);
|
|
b.c = obb2.center;
|
|
b.e[0] = obb2.halfSize.x;
|
|
b.e[1] = obb2.halfSize.y;
|
|
b.e[2] = obb2.halfSize.z;
|
|
obb2.rotation.extractBasis(b.u[0], b.u[1], b.u[2]);
|
|
for (let i = 0; i < 3; i++) {
|
|
for (let j = 0; j < 3; j++) {
|
|
R[i][j] = a.u[i].dot(b.u[j]);
|
|
}
|
|
}
|
|
v1.subVectors(b.c, a.c);
|
|
t[0] = v1.dot(a.u[0]);
|
|
t[1] = v1.dot(a.u[1]);
|
|
t[2] = v1.dot(a.u[2]);
|
|
for (let i = 0; i < 3; i++) {
|
|
for (let j = 0; j < 3; j++) {
|
|
AbsR[i][j] = Math.abs(R[i][j]) + epsilon;
|
|
}
|
|
}
|
|
let ra, rb;
|
|
for (let i = 0; i < 3; i++) {
|
|
ra = a.e[i];
|
|
rb = b.e[0] * AbsR[i][0] + b.e[1] * AbsR[i][1] + b.e[2] * AbsR[i][2];
|
|
if (Math.abs(t[i]) > ra + rb)
|
|
return false;
|
|
}
|
|
for (let i = 0; i < 3; i++) {
|
|
ra = a.e[0] * AbsR[0][i] + a.e[1] * AbsR[1][i] + a.e[2] * AbsR[2][i];
|
|
rb = b.e[i];
|
|
if (Math.abs(t[0] * R[0][i] + t[1] * R[1][i] + t[2] * R[2][i]) > ra + rb)
|
|
return false;
|
|
}
|
|
ra = a.e[1] * AbsR[2][0] + a.e[2] * AbsR[1][0];
|
|
rb = b.e[1] * AbsR[0][2] + b.e[2] * AbsR[0][1];
|
|
if (Math.abs(t[2] * R[1][0] - t[1] * R[2][0]) > ra + rb)
|
|
return false;
|
|
ra = a.e[1] * AbsR[2][1] + a.e[2] * AbsR[1][1];
|
|
rb = b.e[0] * AbsR[0][2] + b.e[2] * AbsR[0][0];
|
|
if (Math.abs(t[2] * R[1][1] - t[1] * R[2][1]) > ra + rb)
|
|
return false;
|
|
ra = a.e[1] * AbsR[2][2] + a.e[2] * AbsR[1][2];
|
|
rb = b.e[0] * AbsR[0][1] + b.e[1] * AbsR[0][0];
|
|
if (Math.abs(t[2] * R[1][2] - t[1] * R[2][2]) > ra + rb)
|
|
return false;
|
|
ra = a.e[0] * AbsR[2][0] + a.e[2] * AbsR[0][0];
|
|
rb = b.e[1] * AbsR[1][2] + b.e[2] * AbsR[1][1];
|
|
if (Math.abs(t[0] * R[2][0] - t[2] * R[0][0]) > ra + rb)
|
|
return false;
|
|
ra = a.e[0] * AbsR[2][1] + a.e[2] * AbsR[0][1];
|
|
rb = b.e[0] * AbsR[1][2] + b.e[2] * AbsR[1][0];
|
|
if (Math.abs(t[0] * R[2][1] - t[2] * R[0][1]) > ra + rb)
|
|
return false;
|
|
ra = a.e[0] * AbsR[2][2] + a.e[2] * AbsR[0][2];
|
|
rb = b.e[0] * AbsR[1][1] + b.e[1] * AbsR[1][0];
|
|
if (Math.abs(t[0] * R[2][2] - t[2] * R[0][2]) > ra + rb)
|
|
return false;
|
|
ra = a.e[0] * AbsR[1][0] + a.e[1] * AbsR[0][0];
|
|
rb = b.e[1] * AbsR[2][2] + b.e[2] * AbsR[2][1];
|
|
if (Math.abs(t[1] * R[0][0] - t[0] * R[1][0]) > ra + rb)
|
|
return false;
|
|
ra = a.e[0] * AbsR[1][1] + a.e[1] * AbsR[0][1];
|
|
rb = b.e[0] * AbsR[2][2] + b.e[2] * AbsR[2][0];
|
|
if (Math.abs(t[1] * R[0][1] - t[0] * R[1][1]) > ra + rb)
|
|
return false;
|
|
ra = a.e[0] * AbsR[1][2] + a.e[1] * AbsR[0][2];
|
|
rb = b.e[0] * AbsR[2][1] + b.e[1] * AbsR[2][0];
|
|
if (Math.abs(t[1] * R[0][2] - t[0] * R[1][2]) > ra + rb)
|
|
return false;
|
|
return true;
|
|
}
|
|
/**
|
|
* Reference: Testing Box Against Plane in Real-Time Collision Detection
|
|
* by Christer Ericson (chapter 5.2.3)
|
|
*/
|
|
intersectsPlane(plane) {
|
|
this.rotation.extractBasis(xAxis, yAxis, zAxis);
|
|
const r = this.halfSize.x * Math.abs(plane.normal.dot(xAxis)) + this.halfSize.y * Math.abs(plane.normal.dot(yAxis)) + this.halfSize.z * Math.abs(plane.normal.dot(zAxis));
|
|
const d = plane.normal.dot(this.center) - plane.constant;
|
|
return Math.abs(d) <= r;
|
|
}
|
|
/**
|
|
* Performs a ray/OBB intersection test and stores the intersection point
|
|
* to the given 3D vector. If no intersection is detected, *null* is returned.
|
|
*/
|
|
intersectRay(ray, result) {
|
|
this.getSize(size);
|
|
aabb.setFromCenterAndSize(v1.set(0, 0, 0), size);
|
|
matrix.setFromMatrix3(this.rotation);
|
|
matrix.setPosition(this.center);
|
|
inverse.copy(matrix).invert();
|
|
localRay.copy(ray).applyMatrix4(inverse);
|
|
if (localRay.intersectBox(aabb, result)) {
|
|
return result.applyMatrix4(matrix);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
/**
|
|
* Performs a ray/OBB intersection test. Returns either true or false if
|
|
* there is a intersection or not.
|
|
*/
|
|
intersectsRay(ray) {
|
|
return this.intersectRay(ray, v1) !== null;
|
|
}
|
|
fromBox3(box3) {
|
|
box3.getCenter(this.center);
|
|
box3.getSize(this.halfSize).multiplyScalar(0.5);
|
|
this.rotation.identity();
|
|
return this;
|
|
}
|
|
equals(obb2) {
|
|
return obb2.center.equals(this.center) && obb2.halfSize.equals(this.halfSize) && obb2.rotation.equals(this.rotation);
|
|
}
|
|
applyMatrix4(matrix2) {
|
|
const e = matrix2.elements;
|
|
let sx = v1.set(e[0], e[1], e[2]).length();
|
|
const sy = v1.set(e[4], e[5], e[6]).length();
|
|
const sz = v1.set(e[8], e[9], e[10]).length();
|
|
const det = matrix2.determinant();
|
|
if (det < 0)
|
|
sx = -sx;
|
|
rotationMatrix.setFromMatrix4(matrix2);
|
|
const invSX = 1 / sx;
|
|
const invSY = 1 / sy;
|
|
const invSZ = 1 / sz;
|
|
rotationMatrix.elements[0] *= invSX;
|
|
rotationMatrix.elements[1] *= invSX;
|
|
rotationMatrix.elements[2] *= invSX;
|
|
rotationMatrix.elements[3] *= invSY;
|
|
rotationMatrix.elements[4] *= invSY;
|
|
rotationMatrix.elements[5] *= invSY;
|
|
rotationMatrix.elements[6] *= invSZ;
|
|
rotationMatrix.elements[7] *= invSZ;
|
|
rotationMatrix.elements[8] *= invSZ;
|
|
this.rotation.multiply(rotationMatrix);
|
|
this.halfSize.x *= sx;
|
|
this.halfSize.y *= sy;
|
|
this.halfSize.z *= sz;
|
|
v1.setFromMatrixPosition(matrix2);
|
|
this.center.add(v1);
|
|
return this;
|
|
}
|
|
}
|
|
const obb = /* @__PURE__ */ new OBB();
|
|
exports.OBB = OBB;
|
|
//# sourceMappingURL=OBB.cjs.map
|