"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