123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- /**
- * @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();
- },
- /**
- * Generates 2D-Coordinates in a very fast way.
- *
- * @author Dylan Grafmyre
- *
- * Based on work by:
- * @author Thomas Diewald
- * @link http://www.openprocessing.org/sketch/15493
- *
- * @param center Center of Hilbert curve.
- * @param size Total width of Hilbert curve.
- * @param iterations Number of subdivisions.
- * @param v0 Corner index -X, -Z.
- * @param v1 Corner index -X, +Z.
- * @param v2 Corner index +X, +Z.
- * @param v3 Corner index +X, -Z.
- */
- hilbert2D: function ( center, size, iterations, v0, v1, v2, v3 ) {
- // Default Vars
- var center = center !== undefined ? center : new THREE.Vector3( 0, 0, 0 ),
- size = size !== undefined ? size : 10,
- half = size / 2,
- iterations = iterations !== undefined ? iterations : 1,
- v0 = v0 !== undefined ? v0 : 0,
- v1 = v1 !== undefined ? v1 : 1,
- v2 = v2 !== undefined ? v2 : 2,
- v3 = v3 !== undefined ? v3 : 3
- ;
- var vec_s = [
- new THREE.Vector3( center.x - half, center.y, center.z - half ),
- new THREE.Vector3( center.x - half, center.y, center.z + half ),
- new THREE.Vector3( center.x + half, center.y, center.z + half ),
- new THREE.Vector3( center.x + half, center.y, center.z - half )
- ];
- var vec = [
- vec_s[ v0 ],
- vec_s[ v1 ],
- vec_s[ v2 ],
- vec_s[ v3 ]
- ];
- // Recurse iterations
- if ( 0 <= -- iterations ) {
- var tmp = [];
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 0 ], half, iterations, v0, v3, v2, v1 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 1 ], half, iterations, v0, v1, v2, v3 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 2 ], half, iterations, v0, v1, v2, v3 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 3 ], half, iterations, v2, v1, v0, v3 ) );
- // Return recursive call
- return tmp;
- }
- // Return complete Hilbert Curve.
- return vec;
- },
- /**
- * Generates 3D-Coordinates in a very fast way.
- *
- * @author Dylan Grafmyre
- *
- * Based on work by:
- * @author Thomas Diewald
- * @link http://www.openprocessing.org/visuals/?visualID=15599
- *
- * @param center Center of Hilbert curve.
- * @param size Total width of Hilbert curve.
- * @param iterations Number of subdivisions.
- * @param v0 Corner index -X, +Y, -Z.
- * @param v1 Corner index -X, +Y, +Z.
- * @param v2 Corner index -X, -Y, +Z.
- * @param v3 Corner index -X, -Y, -Z.
- * @param v4 Corner index +X, -Y, -Z.
- * @param v5 Corner index +X, -Y, +Z.
- * @param v6 Corner index +X, +Y, +Z.
- * @param v7 Corner index +X, +Y, -Z.
- */
- hilbert3D: function ( center, size, iterations, v0, v1, v2, v3, v4, v5, v6, v7 ) {
- // Default Vars
- var center = center !== undefined ? center : new THREE.Vector3( 0, 0, 0 ),
- size = size !== undefined ? size : 10,
- half = size / 2,
- iterations = iterations !== undefined ? iterations : 1,
- v0 = v0 !== undefined ? v0 : 0,
- v1 = v1 !== undefined ? v1 : 1,
- v2 = v2 !== undefined ? v2 : 2,
- v3 = v3 !== undefined ? v3 : 3,
- v4 = v4 !== undefined ? v4 : 4,
- v5 = v5 !== undefined ? v5 : 5,
- v6 = v6 !== undefined ? v6 : 6,
- v7 = v7 !== undefined ? v7 : 7
- ;
- var vec_s = [
- new THREE.Vector3( center.x - half, center.y + half, center.z - half ),
- new THREE.Vector3( center.x - half, center.y + half, center.z + half ),
- new THREE.Vector3( center.x - half, center.y - half, center.z + half ),
- new THREE.Vector3( center.x - half, center.y - half, center.z - half ),
- new THREE.Vector3( center.x + half, center.y - half, center.z - half ),
- new THREE.Vector3( center.x + half, center.y - half, center.z + half ),
- new THREE.Vector3( center.x + half, center.y + half, center.z + half ),
- new THREE.Vector3( center.x + half, center.y + half, center.z - half )
- ];
- var vec = [
- vec_s[ v0 ],
- vec_s[ v1 ],
- vec_s[ v2 ],
- vec_s[ v3 ],
- vec_s[ v4 ],
- vec_s[ v5 ],
- vec_s[ v6 ],
- vec_s[ v7 ]
- ];
- // Recurse iterations
- if ( -- iterations >= 0 ) {
- var tmp = [];
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
- Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) );
- // Return recursive call
- return tmp;
- }
- // Return complete Hilbert Curve.
- return vec;
- }
- };
|