Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three-mesh-bvh /src /math /OrientedBox.js
| import { Vector3, Matrix4, Line3 } from 'three'; | |
| import { SeparatingAxisBounds } from './SeparatingAxisBounds.js'; | |
| import { ExtendedTriangle } from './ExtendedTriangle.js'; | |
| import { closestPointsSegmentToSegment } from './MathUtilities.js'; | |
| export class OrientedBox { | |
| constructor( min, max, matrix ) { | |
| this.isOrientedBox = true; | |
| this.min = new Vector3(); | |
| this.max = new Vector3(); | |
| this.matrix = new Matrix4(); | |
| this.invMatrix = new Matrix4(); | |
| this.points = new Array( 8 ).fill().map( () => new Vector3() ); | |
| this.satAxes = new Array( 3 ).fill().map( () => new Vector3() ); | |
| this.satBounds = new Array( 3 ).fill().map( () => new SeparatingAxisBounds() ); | |
| this.alignedSatBounds = new Array( 3 ).fill().map( () => new SeparatingAxisBounds() ); | |
| this.needsUpdate = false; | |
| if ( min ) this.min.copy( min ); | |
| if ( max ) this.max.copy( max ); | |
| if ( matrix ) this.matrix.copy( matrix ); | |
| } | |
| set( min, max, matrix ) { | |
| this.min.copy( min ); | |
| this.max.copy( max ); | |
| this.matrix.copy( matrix ); | |
| this.needsUpdate = true; | |
| } | |
| copy( other ) { | |
| this.min.copy( other.min ); | |
| this.max.copy( other.max ); | |
| this.matrix.copy( other.matrix ); | |
| this.needsUpdate = true; | |
| } | |
| } | |
| OrientedBox.prototype.update = ( function () { | |
| return function update() { | |
| const matrix = this.matrix; | |
| const min = this.min; | |
| const max = this.max; | |
| const points = this.points; | |
| for ( let x = 0; x <= 1; x ++ ) { | |
| for ( let y = 0; y <= 1; y ++ ) { | |
| for ( let z = 0; z <= 1; z ++ ) { | |
| const i = ( ( 1 << 0 ) * x ) | ( ( 1 << 1 ) * y ) | ( ( 1 << 2 ) * z ); | |
| const v = points[ i ]; | |
| v.x = x ? max.x : min.x; | |
| v.y = y ? max.y : min.y; | |
| v.z = z ? max.z : min.z; | |
| v.applyMatrix4( matrix ); | |
| } | |
| } | |
| } | |
| const satBounds = this.satBounds; | |
| const satAxes = this.satAxes; | |
| const minVec = points[ 0 ]; | |
| for ( let i = 0; i < 3; i ++ ) { | |
| const axis = satAxes[ i ]; | |
| const sb = satBounds[ i ]; | |
| const index = 1 << i; | |
| const pi = points[ index ]; | |
| axis.subVectors( minVec, pi ); | |
| sb.setFromPoints( axis, points ); | |
| } | |
| const alignedSatBounds = this.alignedSatBounds; | |
| alignedSatBounds[ 0 ].setFromPointsField( points, 'x' ); | |
| alignedSatBounds[ 1 ].setFromPointsField( points, 'y' ); | |
| alignedSatBounds[ 2 ].setFromPointsField( points, 'z' ); | |
| this.invMatrix.copy( this.matrix ).invert(); | |
| this.needsUpdate = false; | |
| }; | |
| } )(); | |
| OrientedBox.prototype.intersectsBox = ( function () { | |
| const aabbBounds = new SeparatingAxisBounds(); | |
| return function intersectsBox( box ) { | |
| // TODO: should this be doing SAT against the AABB? | |
| if ( this.needsUpdate ) { | |
| this.update(); | |
| } | |
| const min = box.min; | |
| const max = box.max; | |
| const satBounds = this.satBounds; | |
| const satAxes = this.satAxes; | |
| const alignedSatBounds = this.alignedSatBounds; | |
| aabbBounds.min = min.x; | |
| aabbBounds.max = max.x; | |
| if ( alignedSatBounds[ 0 ].isSeparated( aabbBounds ) ) return false; | |
| aabbBounds.min = min.y; | |
| aabbBounds.max = max.y; | |
| if ( alignedSatBounds[ 1 ].isSeparated( aabbBounds ) ) return false; | |
| aabbBounds.min = min.z; | |
| aabbBounds.max = max.z; | |
| if ( alignedSatBounds[ 2 ].isSeparated( aabbBounds ) ) return false; | |
| for ( let i = 0; i < 3; i ++ ) { | |
| const axis = satAxes[ i ]; | |
| const sb = satBounds[ i ]; | |
| aabbBounds.setFromBox( axis, box ); | |
| if ( sb.isSeparated( aabbBounds ) ) return false; | |
| } | |
| return true; | |
| }; | |
| } )(); | |
| OrientedBox.prototype.intersectsTriangle = ( function () { | |
| const saTri = new ExtendedTriangle(); | |
| const pointsArr = new Array( 3 ); | |
| const cachedSatBounds = new SeparatingAxisBounds(); | |
| const cachedSatBounds2 = new SeparatingAxisBounds(); | |
| const cachedAxis = new Vector3(); | |
| return function intersectsTriangle( triangle ) { | |
| if ( this.needsUpdate ) { | |
| this.update(); | |
| } | |
| if ( ! triangle.isExtendedTriangle ) { | |
| saTri.copy( triangle ); | |
| saTri.update(); | |
| triangle = saTri; | |
| } else if ( triangle.needsUpdate ) { | |
| triangle.update(); | |
| } | |
| const satBounds = this.satBounds; | |
| const satAxes = this.satAxes; | |
| pointsArr[ 0 ] = triangle.a; | |
| pointsArr[ 1 ] = triangle.b; | |
| pointsArr[ 2 ] = triangle.c; | |
| for ( let i = 0; i < 3; i ++ ) { | |
| const sb = satBounds[ i ]; | |
| const sa = satAxes[ i ]; | |
| cachedSatBounds.setFromPoints( sa, pointsArr ); | |
| if ( sb.isSeparated( cachedSatBounds ) ) return false; | |
| } | |
| const triSatBounds = triangle.satBounds; | |
| const triSatAxes = triangle.satAxes; | |
| const points = this.points; | |
| for ( let i = 0; i < 3; i ++ ) { | |
| const sb = triSatBounds[ i ]; | |
| const sa = triSatAxes[ i ]; | |
| cachedSatBounds.setFromPoints( sa, points ); | |
| if ( sb.isSeparated( cachedSatBounds ) ) return false; | |
| } | |
| // check crossed axes | |
| for ( let i = 0; i < 3; i ++ ) { | |
| const sa1 = satAxes[ i ]; | |
| for ( let i2 = 0; i2 < 4; i2 ++ ) { | |
| const sa2 = triSatAxes[ i2 ]; | |
| cachedAxis.crossVectors( sa1, sa2 ); | |
| cachedSatBounds.setFromPoints( cachedAxis, pointsArr ); | |
| cachedSatBounds2.setFromPoints( cachedAxis, points ); | |
| if ( cachedSatBounds.isSeparated( cachedSatBounds2 ) ) return false; | |
| } | |
| } | |
| return true; | |
| }; | |
| } )(); | |
| OrientedBox.prototype.closestPointToPoint = ( function () { | |
| return function closestPointToPoint( point, target1 ) { | |
| if ( this.needsUpdate ) { | |
| this.update(); | |
| } | |
| target1 | |
| .copy( point ) | |
| .applyMatrix4( this.invMatrix ) | |
| .clamp( this.min, this.max ) | |
| .applyMatrix4( this.matrix ); | |
| return target1; | |
| }; | |
| } )(); | |
| OrientedBox.prototype.distanceToPoint = ( function () { | |
| const target = new Vector3(); | |
| return function distanceToPoint( point ) { | |
| this.closestPointToPoint( point, target ); | |
| return point.distanceTo( target ); | |
| }; | |
| } )(); | |
| OrientedBox.prototype.distanceToBox = ( function () { | |
| const xyzFields = [ 'x', 'y', 'z' ]; | |
| const segments1 = new Array( 12 ).fill().map( () => new Line3() ); | |
| const segments2 = new Array( 12 ).fill().map( () => new Line3() ); | |
| const point1 = new Vector3(); | |
| const point2 = new Vector3(); | |
| // early out if we find a value below threshold | |
| return function distanceToBox( box, threshold = 0, target1 = null, target2 = null ) { | |
| if ( this.needsUpdate ) { | |
| this.update(); | |
| } | |
| if ( this.intersectsBox( box ) ) { | |
| if ( target1 || target2 ) { | |
| box.getCenter( point2 ); | |
| this.closestPointToPoint( point2, point1 ); | |
| box.closestPointToPoint( point1, point2 ); | |
| if ( target1 ) target1.copy( point1 ); | |
| if ( target2 ) target2.copy( point2 ); | |
| } | |
| return 0; | |
| } | |
| const threshold2 = threshold * threshold; | |
| const min = box.min; | |
| const max = box.max; | |
| const points = this.points; | |
| // iterate over every edge and compare distances | |
| let closestDistanceSq = Infinity; | |
| // check over all these points | |
| for ( let i = 0; i < 8; i ++ ) { | |
| const p = points[ i ]; | |
| point2.copy( p ).clamp( min, max ); | |
| const dist = p.distanceToSquared( point2 ); | |
| if ( dist < closestDistanceSq ) { | |
| closestDistanceSq = dist; | |
| if ( target1 ) target1.copy( p ); | |
| if ( target2 ) target2.copy( point2 ); | |
| if ( dist < threshold2 ) return Math.sqrt( dist ); | |
| } | |
| } | |
| // generate and check all line segment distances | |
| let count = 0; | |
| for ( let i = 0; i < 3; i ++ ) { | |
| for ( let i1 = 0; i1 <= 1; i1 ++ ) { | |
| for ( let i2 = 0; i2 <= 1; i2 ++ ) { | |
| const nextIndex = ( i + 1 ) % 3; | |
| const nextIndex2 = ( i + 2 ) % 3; | |
| // get obb line segments | |
| const index = i1 << nextIndex | i2 << nextIndex2; | |
| const index2 = 1 << i | i1 << nextIndex | i2 << nextIndex2; | |
| const p1 = points[ index ]; | |
| const p2 = points[ index2 ]; | |
| const line1 = segments1[ count ]; | |
| line1.set( p1, p2 ); | |
| // get aabb line segments | |
| const f1 = xyzFields[ i ]; | |
| const f2 = xyzFields[ nextIndex ]; | |
| const f3 = xyzFields[ nextIndex2 ]; | |
| const line2 = segments2[ count ]; | |
| const start = line2.start; | |
| const end = line2.end; | |
| start[ f1 ] = min[ f1 ]; | |
| start[ f2 ] = i1 ? min[ f2 ] : max[ f2 ]; | |
| start[ f3 ] = i2 ? min[ f3 ] : max[ f2 ]; | |
| end[ f1 ] = max[ f1 ]; | |
| end[ f2 ] = i1 ? min[ f2 ] : max[ f2 ]; | |
| end[ f3 ] = i2 ? min[ f3 ] : max[ f2 ]; | |
| count ++; | |
| } | |
| } | |
| } | |
| // check all the other boxes point | |
| for ( let x = 0; x <= 1; x ++ ) { | |
| for ( let y = 0; y <= 1; y ++ ) { | |
| for ( let z = 0; z <= 1; z ++ ) { | |
| point2.x = x ? max.x : min.x; | |
| point2.y = y ? max.y : min.y; | |
| point2.z = z ? max.z : min.z; | |
| this.closestPointToPoint( point2, point1 ); | |
| const dist = point2.distanceToSquared( point1 ); | |
| if ( dist < closestDistanceSq ) { | |
| closestDistanceSq = dist; | |
| if ( target1 ) target1.copy( point1 ); | |
| if ( target2 ) target2.copy( point2 ); | |
| if ( dist < threshold2 ) return Math.sqrt( dist ); | |
| } | |
| } | |
| } | |
| } | |
| for ( let i = 0; i < 12; i ++ ) { | |
| const l1 = segments1[ i ]; | |
| for ( let i2 = 0; i2 < 12; i2 ++ ) { | |
| const l2 = segments2[ i2 ]; | |
| closestPointsSegmentToSegment( l1, l2, point1, point2 ); | |
| const dist = point1.distanceToSquared( point2 ); | |
| if ( dist < closestDistanceSq ) { | |
| closestDistanceSq = dist; | |
| if ( target1 ) target1.copy( point1 ); | |
| if ( target2 ) target2.copy( point2 ); | |
| if ( dist < threshold2 ) return Math.sqrt( dist ); | |
| } | |
| } | |
| } | |
| return Math.sqrt( closestDistanceSq ); | |
| }; | |
| } )(); | |
Xet Storage Details
- Size:
- 9.27 kB
- Xet hash:
- 559fea21f1b4f1275c973a041d3bda1ccecc301bd3f03bdaf792cde4bba0874f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.