Spaces:
Running
Running
| /** | |
| * @author mrdoob / http://mrdoob.com/ | |
| * @author alteredq / http://alteredqualia.com/ | |
| */ | |
| THREE.GeometryUtils = { | |
| // Merge two geometries or geometry and geometry from object (using object's transform) | |
| merge: function ( geometry1, geometry2, materialIndexOffset ) { | |
| console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); | |
| var matrix; | |
| if ( geometry2 instanceof THREE.Mesh ) { | |
| geometry2.matrixAutoUpdate && geometry2.updateMatrix(); | |
| matrix = geometry2.matrix; | |
| geometry2 = geometry2.geometry; | |
| } | |
| geometry1.merge( geometry2, matrix, materialIndexOffset ); | |
| }, | |
| // Get random point in triangle (via barycentric coordinates) | |
| // (uniform distribution) | |
| // http://www.cgafaq.info/wiki/Random_Point_In_Triangle | |
| randomPointInTriangle: function () { | |
| var vector = new THREE.Vector3(); | |
| return function ( vectorA, vectorB, vectorC ) { | |
| var point = new THREE.Vector3(); | |
| var a = Math.random(); | |
| var b = Math.random(); | |
| if ( ( a + b ) > 1 ) { | |
| a = 1 - a; | |
| b = 1 - b; | |
| } | |
| var c = 1 - a - b; | |
| point.copy( vectorA ); | |
| point.multiplyScalar( a ); | |
| vector.copy( vectorB ); | |
| vector.multiplyScalar( b ); | |
| point.add( vector ); | |
| vector.copy( vectorC ); | |
| vector.multiplyScalar( c ); | |
| point.add( vector ); | |
| return point; | |
| }; | |
| }(), | |
| // Get random point in face (triangle) | |
| // (uniform distribution) | |
| randomPointInFace: function ( face, geometry ) { | |
| var vA, vB, vC; | |
| vA = geometry.vertices[ face.a ]; | |
| vB = geometry.vertices[ face.b ]; | |
| vC = geometry.vertices[ face.c ]; | |
| return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC ); | |
| }, | |
| // Get uniformly distributed random points in mesh | |
| // - create array with cumulative sums of face areas | |
| // - pick random number from 0 to total area | |
| // - find corresponding place in area array by binary search | |
| // - get random point in face | |
| randomPointsInGeometry: function ( geometry, n ) { | |
| var face, i, | |
| faces = geometry.faces, | |
| vertices = geometry.vertices, | |
| il = faces.length, | |
| totalArea = 0, | |
| cumulativeAreas = [], | |
| vA, vB, vC; | |
| // precompute face areas | |
| for ( i = 0; i < il; i ++ ) { | |
| face = faces[ i ]; | |
| vA = vertices[ face.a ]; | |
| vB = vertices[ face.b ]; | |
| vC = vertices[ face.c ]; | |
| face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC ); | |
| totalArea += face._area; | |
| cumulativeAreas[ i ] = totalArea; | |
| } | |
| // binary search cumulative areas array | |
| function binarySearchIndices( value ) { | |
| function binarySearch( start, end ) { | |
| // return closest larger index | |
| // if exact number is not found | |
| if ( end < start ) | |
| return start; | |
| var mid = start + Math.floor( ( end - start ) / 2 ); | |
| if ( cumulativeAreas[ mid ] > value ) { | |
| return binarySearch( start, mid - 1 ); | |
| } else if ( cumulativeAreas[ mid ] < value ) { | |
| return binarySearch( mid + 1, end ); | |
| } else { | |
| return mid; | |
| } | |
| } | |
| var result = binarySearch( 0, cumulativeAreas.length - 1 ); | |
| return result; | |
| } | |
| // pick random face weighted by face area | |
| var r, index, | |
| result = []; | |
| var stats = {}; | |
| for ( i = 0; i < n; i ++ ) { | |
| r = Math.random() * totalArea; | |
| index = binarySearchIndices( r ); | |
| result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry ); | |
| if ( ! stats[ index ] ) { | |
| stats[ index ] = 1; | |
| } else { | |
| stats[ index ] += 1; | |
| } | |
| } | |
| return result; | |
| }, | |
| randomPointsInBufferGeometry: function ( geometry, n ) { | |
| var i, | |
| vertices = geometry.attributes.position.array, | |
| totalArea = 0, | |
| cumulativeAreas = [], | |
| vA, vB, vC; | |
| // precompute face areas | |
| vA = new THREE.Vector3(); | |
| vB = new THREE.Vector3(); | |
| vC = new THREE.Vector3(); | |
| // geometry._areas = []; | |
| var il = vertices.length / 9; | |
| for ( i = 0; i < il; i ++ ) { | |
| vA.set( vertices[ i * 9 + 0 ], vertices[ i * 9 + 1 ], vertices[ i * 9 + 2 ] ); | |
| vB.set( vertices[ i * 9 + 3 ], vertices[ i * 9 + 4 ], vertices[ i * 9 + 5 ] ); | |
| vC.set( vertices[ i * 9 + 6 ], vertices[ i * 9 + 7 ], vertices[ i * 9 + 8 ] ); | |
| totalArea += THREE.GeometryUtils.triangleArea( vA, vB, vC ); | |
| cumulativeAreas.push( totalArea ); | |
| } | |
| // binary search cumulative areas array | |
| function binarySearchIndices( value ) { | |
| function binarySearch( start, end ) { | |
| // return closest larger index | |
| // if exact number is not found | |
| if ( end < start ) | |
| return start; | |
| var mid = start + Math.floor( ( end - start ) / 2 ); | |
| if ( cumulativeAreas[ mid ] > value ) { | |
| return binarySearch( start, mid - 1 ); | |
| } else if ( cumulativeAreas[ mid ] < value ) { | |
| return binarySearch( mid + 1, end ); | |
| } else { | |
| return mid; | |
| } | |
| } | |
| var result = binarySearch( 0, cumulativeAreas.length - 1 ); | |
| return result; | |
| } | |
| // pick random face weighted by face area | |
| var r, index, | |
| result = []; | |
| for ( i = 0; i < n; i ++ ) { | |
| r = Math.random() * totalArea; | |
| index = binarySearchIndices( r ); | |
| // result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true ); | |
| vA.set( vertices[ index * 9 + 0 ], vertices[ index * 9 + 1 ], vertices[ index * 9 + 2 ] ); | |
| vB.set( vertices[ index * 9 + 3 ], vertices[ index * 9 + 4 ], vertices[ index * 9 + 5 ] ); | |
| vC.set( vertices[ index * 9 + 6 ], vertices[ index * 9 + 7 ], vertices[ index * 9 + 8 ] ); | |
| result[ i ] = THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC ); | |
| } | |
| return result; | |
| }, | |
| // Get triangle area (half of parallelogram) | |
| // http://mathworld.wolfram.com/TriangleArea.html | |
| triangleArea: function () { | |
| var vector1 = new THREE.Vector3(); | |
| var vector2 = new THREE.Vector3(); | |
| return function ( vectorA, vectorB, vectorC ) { | |
| vector1.subVectors( vectorB, vectorA ); | |
| vector2.subVectors( vectorC, vectorA ); | |
| vector1.cross( vector2 ); | |
| return 0.5 * vector1.length(); | |
| }; | |
| }(), | |
| center: function ( geometry ) { | |
| console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); | |
| return geometry.center(); | |
| } | |
| }; | |