Buckets:
| import { Vector3 } from './Vector3.js'; | |
| import { Vector4 } from './Vector4.js'; | |
| const _v0 = /*@__PURE__*/ new Vector3(); | |
| const _v1 = /*@__PURE__*/ new Vector3(); | |
| const _v2 = /*@__PURE__*/ new Vector3(); | |
| const _v3 = /*@__PURE__*/ new Vector3(); | |
| const _vab = /*@__PURE__*/ new Vector3(); | |
| const _vac = /*@__PURE__*/ new Vector3(); | |
| const _vbc = /*@__PURE__*/ new Vector3(); | |
| const _vap = /*@__PURE__*/ new Vector3(); | |
| const _vbp = /*@__PURE__*/ new Vector3(); | |
| const _vcp = /*@__PURE__*/ new Vector3(); | |
| const _v40 = /*@__PURE__*/ new Vector4(); | |
| const _v41 = /*@__PURE__*/ new Vector4(); | |
| const _v42 = /*@__PURE__*/ new Vector4(); | |
| /** | |
| * A geometric triangle as defined by three vectors representing its three corners. | |
| */ | |
| class Triangle { | |
| /** | |
| * Constructs a new triangle. | |
| * | |
| * @param {Vector3} [a=(0,0,0)] - The first corner of the triangle. | |
| * @param {Vector3} [b=(0,0,0)] - The second corner of the triangle. | |
| * @param {Vector3} [c=(0,0,0)] - The third corner of the triangle. | |
| */ | |
| constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { | |
| /** | |
| * The first corner of the triangle. | |
| * | |
| * @type {Vector3} | |
| */ | |
| this.a = a; | |
| /** | |
| * The second corner of the triangle. | |
| * | |
| * @type {Vector3} | |
| */ | |
| this.b = b; | |
| /** | |
| * The third corner of the triangle. | |
| * | |
| * @type {Vector3} | |
| */ | |
| this.c = c; | |
| } | |
| /** | |
| * Computes the normal vector of a triangle. | |
| * | |
| * @param {Vector3} a - The first corner of the triangle. | |
| * @param {Vector3} b - The second corner of the triangle. | |
| * @param {Vector3} c - The third corner of the triangle. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {Vector3} The triangle's normal. | |
| */ | |
| static getNormal( a, b, c, target ) { | |
| target.subVectors( c, b ); | |
| _v0.subVectors( a, b ); | |
| target.cross( _v0 ); | |
| const targetLengthSq = target.lengthSq(); | |
| if ( targetLengthSq > 0 ) { | |
| return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); | |
| } | |
| return target.set( 0, 0, 0 ); | |
| } | |
| /** | |
| * Computes a barycentric coordinates from the given vector. | |
| * Returns `null` if the triangle is degenerate. | |
| * | |
| * @param {Vector3} point - A point in 3D space. | |
| * @param {Vector3} a - The first corner of the triangle. | |
| * @param {Vector3} b - The second corner of the triangle. | |
| * @param {Vector3} c - The third corner of the triangle. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {?Vector3} The barycentric coordinates for the given point | |
| */ | |
| static getBarycoord( point, a, b, c, target ) { | |
| // based on: http://www.blackpawn.com/texts/pointinpoly/default.html | |
| _v0.subVectors( c, a ); | |
| _v1.subVectors( b, a ); | |
| _v2.subVectors( point, a ); | |
| const dot00 = _v0.dot( _v0 ); | |
| const dot01 = _v0.dot( _v1 ); | |
| const dot02 = _v0.dot( _v2 ); | |
| const dot11 = _v1.dot( _v1 ); | |
| const dot12 = _v1.dot( _v2 ); | |
| const denom = ( dot00 * dot11 - dot01 * dot01 ); | |
| // collinear or singular triangle | |
| if ( denom === 0 ) { | |
| target.set( 0, 0, 0 ); | |
| return null; | |
| } | |
| const invDenom = 1 / denom; | |
| const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; | |
| const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; | |
| // barycentric coordinates must always sum to 1 | |
| return target.set( 1 - u - v, v, u ); | |
| } | |
| /** | |
| * Returns `true` if the given point, when projected onto the plane of the | |
| * triangle, lies within the triangle. | |
| * | |
| * @param {Vector3} point - The point in 3D space to test. | |
| * @param {Vector3} a - The first corner of the triangle. | |
| * @param {Vector3} b - The second corner of the triangle. | |
| * @param {Vector3} c - The third corner of the triangle. | |
| * @return {boolean} Whether the given point, when projected onto the plane of the | |
| * triangle, lies within the triangle or not. | |
| */ | |
| static containsPoint( point, a, b, c ) { | |
| // if the triangle is degenerate then we can't contain a point | |
| if ( this.getBarycoord( point, a, b, c, _v3 ) === null ) { | |
| return false; | |
| } | |
| return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 ); | |
| } | |
| /** | |
| * Computes the value barycentrically interpolated for the given point on the | |
| * triangle. Returns `null` if the triangle is degenerate. | |
| * | |
| * @param {Vector3} point - Position of interpolated point. | |
| * @param {Vector3} p1 - The first corner of the triangle. | |
| * @param {Vector3} p2 - The second corner of the triangle. | |
| * @param {Vector3} p3 - The third corner of the triangle. | |
| * @param {Vector3} v1 - Value to interpolate of first vertex. | |
| * @param {Vector3} v2 - Value to interpolate of second vertex. | |
| * @param {Vector3} v3 - Value to interpolate of third vertex. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {?Vector3} The interpolated value. | |
| */ | |
| static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { | |
| if ( this.getBarycoord( point, p1, p2, p3, _v3 ) === null ) { | |
| target.x = 0; | |
| target.y = 0; | |
| if ( 'z' in target ) target.z = 0; | |
| if ( 'w' in target ) target.w = 0; | |
| return null; | |
| } | |
| target.setScalar( 0 ); | |
| target.addScaledVector( v1, _v3.x ); | |
| target.addScaledVector( v2, _v3.y ); | |
| target.addScaledVector( v3, _v3.z ); | |
| return target; | |
| } | |
| /** | |
| * Computes the value barycentrically interpolated for the given attribute and indices. | |
| * | |
| * @param {BufferAttribute} attr - The attribute to interpolate. | |
| * @param {number} i1 - Index of first vertex. | |
| * @param {number} i2 - Index of second vertex. | |
| * @param {number} i3 - Index of third vertex. | |
| * @param {Vector3} barycoord - The barycoordinate value to use to interpolate. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {Vector3} The interpolated attribute value. | |
| */ | |
| static getInterpolatedAttribute( attr, i1, i2, i3, barycoord, target ) { | |
| _v40.setScalar( 0 ); | |
| _v41.setScalar( 0 ); | |
| _v42.setScalar( 0 ); | |
| _v40.fromBufferAttribute( attr, i1 ); | |
| _v41.fromBufferAttribute( attr, i2 ); | |
| _v42.fromBufferAttribute( attr, i3 ); | |
| target.setScalar( 0 ); | |
| target.addScaledVector( _v40, barycoord.x ); | |
| target.addScaledVector( _v41, barycoord.y ); | |
| target.addScaledVector( _v42, barycoord.z ); | |
| return target; | |
| } | |
| /** | |
| * Returns `true` if the triangle is oriented towards the given direction. | |
| * | |
| * @param {Vector3} a - The first corner of the triangle. | |
| * @param {Vector3} b - The second corner of the triangle. | |
| * @param {Vector3} c - The third corner of the triangle. | |
| * @param {Vector3} direction - The (normalized) direction vector. | |
| * @return {boolean} Whether the triangle is oriented towards the given direction or not. | |
| */ | |
| static isFrontFacing( a, b, c, direction ) { | |
| _v0.subVectors( c, b ); | |
| _v1.subVectors( a, b ); | |
| // strictly front facing | |
| return ( _v0.cross( _v1 ).dot( direction ) < 0 ) ? true : false; | |
| } | |
| /** | |
| * Sets the triangle's vertices by copying the given values. | |
| * | |
| * @param {Vector3} a - The first corner of the triangle. | |
| * @param {Vector3} b - The second corner of the triangle. | |
| * @param {Vector3} c - The third corner of the triangle. | |
| * @return {Triangle} A reference to this triangle. | |
| */ | |
| set( a, b, c ) { | |
| this.a.copy( a ); | |
| this.b.copy( b ); | |
| this.c.copy( c ); | |
| return this; | |
| } | |
| /** | |
| * Sets the triangle's vertices by copying the given array values. | |
| * | |
| * @param {Array<Vector3>} points - An array with 3D points. | |
| * @param {number} i0 - The array index representing the first corner of the triangle. | |
| * @param {number} i1 - The array index representing the second corner of the triangle. | |
| * @param {number} i2 - The array index representing the third corner of the triangle. | |
| * @return {Triangle} A reference to this triangle. | |
| */ | |
| setFromPointsAndIndices( points, i0, i1, i2 ) { | |
| this.a.copy( points[ i0 ] ); | |
| this.b.copy( points[ i1 ] ); | |
| this.c.copy( points[ i2 ] ); | |
| return this; | |
| } | |
| /** | |
| * Sets the triangle's vertices by copying the given attribute values. | |
| * | |
| * @param {BufferAttribute} attribute - A buffer attribute with 3D points data. | |
| * @param {number} i0 - The attribute index representing the first corner of the triangle. | |
| * @param {number} i1 - The attribute index representing the second corner of the triangle. | |
| * @param {number} i2 - The attribute index representing the third corner of the triangle. | |
| * @return {Triangle} A reference to this triangle. | |
| */ | |
| setFromAttributeAndIndices( attribute, i0, i1, i2 ) { | |
| this.a.fromBufferAttribute( attribute, i0 ); | |
| this.b.fromBufferAttribute( attribute, i1 ); | |
| this.c.fromBufferAttribute( attribute, i2 ); | |
| return this; | |
| } | |
| /** | |
| * Returns a new triangle with copied values from this instance. | |
| * | |
| * @return {Triangle} A clone of this instance. | |
| */ | |
| clone() { | |
| return new this.constructor().copy( this ); | |
| } | |
| /** | |
| * Copies the values of the given triangle to this instance. | |
| * | |
| * @param {Triangle} triangle - The triangle to copy. | |
| * @return {Triangle} A reference to this triangle. | |
| */ | |
| copy( triangle ) { | |
| this.a.copy( triangle.a ); | |
| this.b.copy( triangle.b ); | |
| this.c.copy( triangle.c ); | |
| return this; | |
| } | |
| /** | |
| * Computes the area of the triangle. | |
| * | |
| * @return {number} The triangle's area. | |
| */ | |
| getArea() { | |
| _v0.subVectors( this.c, this.b ); | |
| _v1.subVectors( this.a, this.b ); | |
| return _v0.cross( _v1 ).length() * 0.5; | |
| } | |
| /** | |
| * Computes the midpoint of the triangle. | |
| * | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {Vector3} The triangle's midpoint. | |
| */ | |
| getMidpoint( target ) { | |
| return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); | |
| } | |
| /** | |
| * Computes the normal of the triangle. | |
| * | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {Vector3} The triangle's normal. | |
| */ | |
| getNormal( target ) { | |
| return Triangle.getNormal( this.a, this.b, this.c, target ); | |
| } | |
| /** | |
| * Computes a plane the triangle lies within. | |
| * | |
| * @param {Plane} target - The target vector that is used to store the method's result. | |
| * @return {Plane} The plane the triangle lies within. | |
| */ | |
| getPlane( target ) { | |
| return target.setFromCoplanarPoints( this.a, this.b, this.c ); | |
| } | |
| /** | |
| * Computes a barycentric coordinates from the given vector. | |
| * Returns `null` if the triangle is degenerate. | |
| * | |
| * @param {Vector3} point - A point in 3D space. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {?Vector3} The barycentric coordinates for the given point | |
| */ | |
| getBarycoord( point, target ) { | |
| return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); | |
| } | |
| /** | |
| * Computes the value barycentrically interpolated for the given point on the | |
| * triangle. Returns `null` if the triangle is degenerate. | |
| * | |
| * @param {Vector3} point - Position of interpolated point. | |
| * @param {Vector3} v1 - Value to interpolate of first vertex. | |
| * @param {Vector3} v2 - Value to interpolate of second vertex. | |
| * @param {Vector3} v3 - Value to interpolate of third vertex. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {?Vector3} The interpolated value. | |
| */ | |
| getInterpolation( point, v1, v2, v3, target ) { | |
| return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); | |
| } | |
| /** | |
| * Returns `true` if the given point, when projected onto the plane of the | |
| * triangle, lies within the triangle. | |
| * | |
| * @param {Vector3} point - The point in 3D space to test. | |
| * @return {boolean} Whether the given point, when projected onto the plane of the | |
| * triangle, lies within the triangle or not. | |
| */ | |
| containsPoint( point ) { | |
| return Triangle.containsPoint( point, this.a, this.b, this.c ); | |
| } | |
| /** | |
| * Returns `true` if the triangle is oriented towards the given direction. | |
| * | |
| * @param {Vector3} direction - The (normalized) direction vector. | |
| * @return {boolean} Whether the triangle is oriented towards the given direction or not. | |
| */ | |
| isFrontFacing( direction ) { | |
| return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); | |
| } | |
| /** | |
| * Returns `true` if this triangle intersects with the given box. | |
| * | |
| * @param {Box3} box - The box to intersect. | |
| * @return {boolean} Whether this triangle intersects with the given box or not. | |
| */ | |
| intersectsBox( box ) { | |
| return box.intersectsTriangle( this ); | |
| } | |
| /** | |
| * Returns the closest point on the triangle to the given point. | |
| * | |
| * @param {Vector3} p - The point to compute the closest point for. | |
| * @param {Vector3} target - The target vector that is used to store the method's result. | |
| * @return {Vector3} The closest point on the triangle. | |
| */ | |
| closestPointToPoint( p, target ) { | |
| const a = this.a, b = this.b, c = this.c; | |
| let v, w; | |
| // algorithm thanks to Real-Time Collision Detection by Christer Ericson, | |
| // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., | |
| // under the accompanying license; see chapter 5.1.5 for detailed explanation. | |
| // basically, we're distinguishing which of the voronoi regions of the triangle | |
| // the point lies in with the minimum amount of redundant computation. | |
| _vab.subVectors( b, a ); | |
| _vac.subVectors( c, a ); | |
| _vap.subVectors( p, a ); | |
| const d1 = _vab.dot( _vap ); | |
| const d2 = _vac.dot( _vap ); | |
| if ( d1 <= 0 && d2 <= 0 ) { | |
| // vertex region of A; barycentric coords (1, 0, 0) | |
| return target.copy( a ); | |
| } | |
| _vbp.subVectors( p, b ); | |
| const d3 = _vab.dot( _vbp ); | |
| const d4 = _vac.dot( _vbp ); | |
| if ( d3 >= 0 && d4 <= d3 ) { | |
| // vertex region of B; barycentric coords (0, 1, 0) | |
| return target.copy( b ); | |
| } | |
| const vc = d1 * d4 - d3 * d2; | |
| if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { | |
| v = d1 / ( d1 - d3 ); | |
| // edge region of AB; barycentric coords (1-v, v, 0) | |
| return target.copy( a ).addScaledVector( _vab, v ); | |
| } | |
| _vcp.subVectors( p, c ); | |
| const d5 = _vab.dot( _vcp ); | |
| const d6 = _vac.dot( _vcp ); | |
| if ( d6 >= 0 && d5 <= d6 ) { | |
| // vertex region of C; barycentric coords (0, 0, 1) | |
| return target.copy( c ); | |
| } | |
| const vb = d5 * d2 - d1 * d6; | |
| if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { | |
| w = d2 / ( d2 - d6 ); | |
| // edge region of AC; barycentric coords (1-w, 0, w) | |
| return target.copy( a ).addScaledVector( _vac, w ); | |
| } | |
| const va = d3 * d6 - d5 * d4; | |
| if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { | |
| _vbc.subVectors( c, b ); | |
| w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); | |
| // edge region of BC; barycentric coords (0, 1-w, w) | |
| return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC | |
| } | |
| // face region | |
| const denom = 1 / ( va + vb + vc ); | |
| // u = va * denom | |
| v = vb * denom; | |
| w = vc * denom; | |
| return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); | |
| } | |
| /** | |
| * Returns `true` if this triangle is equal with the given one. | |
| * | |
| * @param {Triangle} triangle - The triangle to test for equality. | |
| * @return {boolean} Whether this triangle is equal with the given one. | |
| */ | |
| equals( triangle ) { | |
| return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); | |
| } | |
| } | |
| export { Triangle }; | |
Xet Storage Details
- Size:
- 15.2 kB
- Xet hash:
- 612523e19ec1044b38be9aa4eed4d3eac66605850c58533904d08f8416a91e1b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.