mirror of https://gitee.com/cf-fz/WebCAD.git
parent
6896067527
commit
7efa25ea7d
@ -1,15 +1,249 @@
|
||||
import { Vector3, Matrix4 } from 'three';
|
||||
|
||||
import { Matrix3, Matrix4, Vector3 } from 'three';
|
||||
import { OBB } from "three/examples/jsm/math/OBB";
|
||||
// Quote from:
|
||||
// https://github.com/Mugen87/yume/blob/master/src/javascript/engine/etc/OBB.js
|
||||
// 即obb.js(本项目中已存在)
|
||||
|
||||
/**
|
||||
* @param ocs 坐标系
|
||||
* @param size 尺寸
|
||||
* @returns OBB
|
||||
*/
|
||||
export function GetObbFromOcsSize(ocs: Matrix4, size: Vector3): OBB
|
||||
// Reference material:
|
||||
//https://stackoverflow.com/questions/28499800/oriented-box-intersection-in-threejs
|
||||
//http://www.cnblogs.com/iamzhanglei/archive/2012/06/07/2539751.html
|
||||
//https://github.com/Mugen87/yume/blob/master/src/javascript/engine/etc/OBB.js
|
||||
|
||||
export class OBB
|
||||
{
|
||||
size = size.clone().multiplyScalar(0.5);
|
||||
let center = size.clone().applyMatrix4(ocs);
|
||||
return new OBB(center, size, new Matrix3().setFromMatrix4(ocs));
|
||||
_EPSILON = 1e-3;
|
||||
|
||||
public center: Vector3;
|
||||
|
||||
constructor(public ocs: Matrix4, public halfSizes: Vector3)
|
||||
{
|
||||
this.center = halfSizes.clone().applyMatrix4(ocs);
|
||||
}
|
||||
|
||||
intersectsOBB(obb: OBB, is2D?: boolean, ucsInv?: Matrix4): boolean
|
||||
{
|
||||
let newCenter: Vector3;
|
||||
let newObbCenter: Vector3;
|
||||
let cs: Matrix4;
|
||||
let obbcs: Matrix4;
|
||||
if (is2D)
|
||||
{
|
||||
let mtx1 = new Matrix4().multiplyMatrices(ucsInv, this.ocs);
|
||||
let mtx2 = new Matrix4().multiplyMatrices(ucsInv, obb.ocs);
|
||||
cs = mtx1;
|
||||
obbcs = mtx2;
|
||||
cs.elements[14] = 0;
|
||||
obbcs.elements[14] = 0;
|
||||
newCenter = this.halfSizes.clone().applyMatrix4(cs);
|
||||
newObbCenter = obb.halfSizes.clone().applyMatrix4(obbcs);
|
||||
}
|
||||
let xAxisA = new Vector3();
|
||||
let yAxisA = new Vector3();
|
||||
let zAxisA = new Vector3();
|
||||
|
||||
let xAxisB = new Vector3();
|
||||
let yAxisB = new Vector3();
|
||||
let zAxisB = new Vector3();
|
||||
|
||||
let translation = new Vector3();
|
||||
|
||||
let vector = new Vector3();
|
||||
|
||||
let axisA: Vector3[] = [];
|
||||
let axisB: Vector3[] = [];
|
||||
let rotationMatrix = [[], [], []];
|
||||
let rotationMatrixAbs = [[], [], []];
|
||||
|
||||
let halfSizeA: number, halfSizeB: number;
|
||||
let t: number, i: number;
|
||||
|
||||
// extract each axis
|
||||
(cs ?? this.ocs).extractBasis(xAxisA, yAxisA, zAxisA);
|
||||
(obbcs ?? obb.ocs).extractBasis(xAxisB, yAxisB, zAxisB);
|
||||
|
||||
// push basis vectors into arrays, so you can access them via indices
|
||||
axisA.push(xAxisA, yAxisA, zAxisA);
|
||||
axisB.push(xAxisB, yAxisB, zAxisB);
|
||||
|
||||
// get displacement vector
|
||||
vector.subVectors(newObbCenter ?? obb.center, newCenter ?? this.center);
|
||||
|
||||
// express the translation vector in the coordinate frame of the current
|
||||
// OBB (this)
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
translation.setComponent(i, vector.dot(axisA[i]));
|
||||
}
|
||||
|
||||
// generate a rotation matrix that transforms from world space to the
|
||||
// OBB's coordinate space
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (let j = 0; j < 3; j++)
|
||||
{
|
||||
rotationMatrix[i][j] = axisA[i].dot(axisB[j]);
|
||||
rotationMatrixAbs[i][j] = Math.abs(rotationMatrix[i][j]) + this._EPSILON;
|
||||
}
|
||||
}
|
||||
|
||||
// test the three major axes of this OBB
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
vector.set(rotationMatrixAbs[i][0], rotationMatrixAbs[i][1], rotationMatrixAbs[i][2]);
|
||||
|
||||
halfSizeA = this.halfSizes.getComponent(i);
|
||||
halfSizeB = obb.halfSizes.dot(vector);
|
||||
|
||||
if (Math.abs(translation.getComponent(i)) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// test the three major axes of other OBB
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
vector.set(rotationMatrixAbs[0][i], rotationMatrixAbs[1][i], rotationMatrixAbs[2][i]);
|
||||
|
||||
halfSizeA = this.halfSizes.dot(vector);
|
||||
halfSizeB = obb.halfSizes.getComponent(i);
|
||||
|
||||
vector.set(rotationMatrix[0][i], rotationMatrix[1][i], rotationMatrix[2][i]);
|
||||
t = translation.dot(vector);
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// test the 9 different cross-axes
|
||||
|
||||
// A.x <cross> B.x
|
||||
halfSizeA = this.halfSizes.y * rotationMatrixAbs[2][0] + this.halfSizes.z * rotationMatrixAbs[1][0];
|
||||
halfSizeB = obb.halfSizes.y * rotationMatrixAbs[0][2] + obb.halfSizes.z * rotationMatrixAbs[0][1];
|
||||
|
||||
t = translation.z * rotationMatrix[1][0] - translation.y * rotationMatrix[2][0];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.x < cross> B.y
|
||||
halfSizeA = this.halfSizes.y * rotationMatrixAbs[2][1] + this.halfSizes.z * rotationMatrixAbs[1][1];
|
||||
halfSizeB = obb.halfSizes.x * rotationMatrixAbs[0][2] + obb.halfSizes.z * rotationMatrixAbs[0][0];
|
||||
|
||||
t = translation.z * rotationMatrix[1][1] - translation.y * rotationMatrix[2][1];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.x <cross> B.z
|
||||
halfSizeA = this.halfSizes.y * rotationMatrixAbs[2][2] + this.halfSizes.z * rotationMatrixAbs[1][2];
|
||||
halfSizeB = obb.halfSizes.x * rotationMatrixAbs[0][1] + obb.halfSizes.y * rotationMatrixAbs[0][0];
|
||||
|
||||
t = translation.z * rotationMatrix[1][2] - translation.y * rotationMatrix[2][2];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.y <cross> B.x
|
||||
halfSizeA = this.halfSizes.x * rotationMatrixAbs[2][0] + this.halfSizes.z * rotationMatrixAbs[0][0];
|
||||
halfSizeB = obb.halfSizes.y * rotationMatrixAbs[1][2] + obb.halfSizes.z * rotationMatrixAbs[1][1];
|
||||
|
||||
t = translation.x * rotationMatrix[2][0] - translation.z * rotationMatrix[0][0];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.y <cross> B.y
|
||||
halfSizeA = this.halfSizes.x * rotationMatrixAbs[2][1] + this.halfSizes.z * rotationMatrixAbs[0][1];
|
||||
halfSizeB = obb.halfSizes.x * rotationMatrixAbs[1][2] + obb.halfSizes.z * rotationMatrixAbs[1][0];
|
||||
|
||||
t = translation.x * rotationMatrix[2][1] - translation.z * rotationMatrix[0][1];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.y <cross> B.z
|
||||
halfSizeA = this.halfSizes.x * rotationMatrixAbs[2][2] + this.halfSizes.z * rotationMatrixAbs[0][2];
|
||||
halfSizeB = obb.halfSizes.x * rotationMatrixAbs[1][1] + obb.halfSizes.y * rotationMatrixAbs[1][0];
|
||||
|
||||
t = translation.x * rotationMatrix[2][2] - translation.z * rotationMatrix[0][2];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.z <cross> B.x
|
||||
halfSizeA = this.halfSizes.x * rotationMatrixAbs[1][0] + this.halfSizes.y * rotationMatrixAbs[0][0];
|
||||
halfSizeB = obb.halfSizes.y * rotationMatrixAbs[2][2] + obb.halfSizes.z * rotationMatrixAbs[2][1];
|
||||
|
||||
t = translation.y * rotationMatrix[0][0] - translation.x * rotationMatrix[1][0];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.z <cross> B.y
|
||||
halfSizeA = this.halfSizes.x * rotationMatrixAbs[1][1] + this.halfSizes.y * rotationMatrixAbs[0][1];
|
||||
halfSizeB = obb.halfSizes.x * rotationMatrixAbs[2][2] + obb.halfSizes.z * rotationMatrixAbs[2][0];
|
||||
|
||||
t = translation.y * rotationMatrix[0][1] - translation.x * rotationMatrix[1][1];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A.z <cross> B.z
|
||||
halfSizeA = this.halfSizes.x * rotationMatrixAbs[1][2] + this.halfSizes.y * rotationMatrixAbs[0][2];
|
||||
halfSizeB = obb.halfSizes.x * rotationMatrixAbs[2][1] + obb.halfSizes.y * rotationMatrixAbs[2][0];
|
||||
|
||||
t = translation.y * rotationMatrix[0][2] - translation.x * rotationMatrix[1][2];
|
||||
|
||||
if (Math.abs(t) > halfSizeA + halfSizeB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// no separating axis exists, so the two OBB don't intersect
|
||||
return true;
|
||||
}
|
||||
|
||||
// setFromObject(obj: THREE.Mesh): OBB;
|
||||
// setFromAABB(aabb: THREE.Box3): OBB;
|
||||
|
||||
// setFromSphere(sphere: THREE.Shape): OBB;
|
||||
|
||||
// closestPoint(point: THREE.Vector3): THREE.Vector3
|
||||
// isPointContained(point: THREE.Vector3): boolean
|
||||
// isAABBContained(aabb: THREE.Box3): boolean
|
||||
// isLineContained(line: THREE.Line3): boolean
|
||||
// isTriangleContained(tarianlg: THREE.Triangle): boolean
|
||||
// intersectsAABB(box: THREE.Box3): boolean
|
||||
// intersectsSphere(sphere: THREE.Sphere): boolean
|
||||
// intersectsOBB(box: OBB): boolean;
|
||||
// intersectsPlane(plane: Plane): boolean
|
||||
// intersectsRay(ray: Ray): boolean
|
||||
// intersectRay(ray: Ray): Vector3
|
||||
// intersectSphere(sphere: Sphere): Vector3
|
||||
// size(optionalTarget: Vector3): Vector3
|
||||
|
||||
// translate(offset: Vector3): OBB
|
||||
|
||||
// copy(obb: OBB): OBB
|
||||
// clone(obb: OBB): OBB
|
||||
|
||||
}
|
||||
|
Loading…
Reference in new issue