three-stdlib
Version:
stand-alone library of threejs examples
244 lines (243 loc) • 8.65 kB
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