123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /**
- * @author qiao / https://github.com/qiao
- * @fileoverview This is a convex hull generator using the incremental method.
- * The complexity is O(n^2) where n is the number of vertices.
- * O(nlogn) algorithms do exist, but they are much more complicated.
- *
- * Benchmark:
- *
- * Platform: CPU: P7350 @2.00GHz Engine: V8
- *
- * Num Vertices Time(ms)
- *
- * 10 1
- * 20 3
- * 30 19
- * 40 48
- * 50 107
- */
- THREE.ConvexGeometry = function( vertices ) {
- THREE.Geometry.call( this );
- var faces = [ [ 0, 1, 2 ], [ 0, 2, 1 ] ];
- for ( var i = 3; i < vertices.length; i ++ ) {
- addPoint( i );
- }
- function addPoint( vertexId ) {
- var vertex = vertices[ vertexId ].clone();
- var mag = vertex.length();
- vertex.x += mag * randomOffset();
- vertex.y += mag * randomOffset();
- vertex.z += mag * randomOffset();
- var hole = [];
- for ( var f = 0; f < faces.length; ) {
- var face = faces[ f ];
- // for each face, if the vertex can see it,
- // then we try to add the face's edges into the hole.
- if ( visible( face, vertex ) ) {
- for ( var e = 0; e < 3; e ++ ) {
- var edge = [ face[ e ], face[ ( e + 1 ) % 3 ] ];
- var boundary = true;
- // remove duplicated edges.
- for ( var h = 0; h < hole.length; h ++ ) {
- if ( equalEdge( hole[ h ], edge ) ) {
- hole[ h ] = hole[ hole.length - 1 ];
- hole.pop();
- boundary = false;
- break;
- }
- }
- if ( boundary ) {
- hole.push( edge );
- }
- }
- // remove faces[ f ]
- faces[ f ] = faces[ faces.length - 1 ];
- faces.pop();
- } else {
- // not visible
- f ++;
- }
- }
- // construct the new faces formed by the edges of the hole and the vertex
- for ( var h = 0; h < hole.length; h ++ ) {
- faces.push( [
- hole[ h ][ 0 ],
- hole[ h ][ 1 ],
- vertexId
- ] );
- }
- }
- /**
- * Whether the face is visible from the vertex
- */
- function visible( face, vertex ) {
- var va = vertices[ face[ 0 ] ];
- var vb = vertices[ face[ 1 ] ];
- var vc = vertices[ face[ 2 ] ];
- var n = normal( va, vb, vc );
- // distance from face to origin
- var dist = n.dot( va );
- return n.dot( vertex ) >= dist;
- }
- /**
- * Face normal
- */
- function normal( va, vb, vc ) {
- var cb = new THREE.Vector3();
- var ab = new THREE.Vector3();
- cb.subVectors( vc, vb );
- ab.subVectors( va, vb );
- cb.cross( ab );
- cb.normalize();
- return cb;
- }
- /**
- * Detect whether two edges are equal.
- * Note that when constructing the convex hull, two same edges can only
- * be of the negative direction.
- */
- function equalEdge( ea, eb ) {
- return ea[ 0 ] === eb[ 1 ] && ea[ 1 ] === eb[ 0 ];
- }
- /**
- * Create a random offset between -1e-6 and 1e-6.
- */
- function randomOffset() {
- return ( Math.random() - 0.5 ) * 2 * 1e-6;
- }
- // Push vertices into `this.vertices`, skipping those inside the hull
- var id = 0;
- var newId = new Array( vertices.length ); // map from old vertex id to new id
- for ( var i = 0; i < faces.length; i ++ ) {
- var face = faces[ i ];
- for ( var j = 0; j < 3; j ++ ) {
- if ( newId[ face[ j ] ] === undefined ) {
- newId[ face[ j ] ] = id ++;
- this.vertices.push( vertices[ face[ j ] ] );
- }
- face[ j ] = newId[ face[ j ] ];
- }
- }
- // Convert faces into instances of THREE.Face3
- for ( var i = 0; i < faces.length; i ++ ) {
- this.faces.push( new THREE.Face3(
- faces[ i ][ 0 ],
- faces[ i ][ 1 ],
- faces[ i ][ 2 ]
- ) );
- }
- this.computeFaceNormals();
- // Compute flat vertex normals
- for ( var i = 0; i < this.faces.length; i ++ ) {
- var face = this.faces[ i ];
- var normal = face.normal;
- face.vertexNormals[ 0 ] = normal.clone();
- face.vertexNormals[ 1 ] = normal.clone();
- face.vertexNormals[ 2 ] = normal.clone();
- }
- };
- THREE.ConvexGeometry.prototype = Object.create( THREE.Geometry.prototype );
- THREE.ConvexGeometry.prototype.constructor = THREE.ConvexGeometry;
|