123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /**
- * @author clockworkgeek / https://github.com/clockworkgeek
- * @author timothypratley / https://github.com/timothypratley
- * @author WestLangley / http://github.com/WestLangley
- */
- THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
- THREE.Geometry.call( this );
- this.type = 'PolyhedronGeometry';
- this.parameters = {
- vertices: vertices,
- indices: indices,
- radius: radius,
- detail: detail
- };
- radius = radius || 1;
- detail = detail || 0;
- var that = this;
- for ( var i = 0, l = vertices.length; i < l; i += 3 ) {
- prepare( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
- }
- var midpoints = [], p = this.vertices;
- var faces = [];
- for ( var i = 0, j = 0, l = indices.length; i < l; i += 3, j ++ ) {
- var v1 = p[ indices[ i ] ];
- var v2 = p[ indices[ i + 1 ] ];
- var v3 = p[ indices[ i + 2 ] ];
- faces[ j ] = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
- }
- var centroid = new THREE.Vector3();
- for ( var i = 0, l = faces.length; i < l; i ++ ) {
- subdivide( faces[ i ], detail );
- }
- // Handle case when face straddles the seam
- for ( var i = 0, l = this.faceVertexUvs[ 0 ].length; i < l; i ++ ) {
- var uvs = this.faceVertexUvs[ 0 ][ i ];
- var x0 = uvs[ 0 ].x;
- var x1 = uvs[ 1 ].x;
- var x2 = uvs[ 2 ].x;
- var max = Math.max( x0, Math.max( x1, x2 ) );
- var min = Math.min( x0, Math.min( x1, x2 ) );
- if ( max > 0.9 && min < 0.1 ) { // 0.9 is somewhat arbitrary
- if ( x0 < 0.2 ) uvs[ 0 ].x += 1;
- if ( x1 < 0.2 ) uvs[ 1 ].x += 1;
- if ( x2 < 0.2 ) uvs[ 2 ].x += 1;
- }
- }
- // Apply radius
- for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
- this.vertices[ i ].multiplyScalar( radius );
- }
- // Merge vertices
- this.mergeVertices();
- this.computeFaceNormals();
- this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
- // Project vector onto sphere's surface
- function prepare( vector ) {
- var vertex = vector.normalize().clone();
- vertex.index = that.vertices.push( vertex ) - 1;
- // Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
- var u = azimuth( vector ) / 2 / Math.PI + 0.5;
- var v = inclination( vector ) / Math.PI + 0.5;
- vertex.uv = new THREE.Vector2( u, 1 - v );
- return vertex;
- }
- // Approximate a curved face with recursively sub-divided triangles.
- function make( v1, v2, v3 ) {
- var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
- that.faces.push( face );
- centroid.copy( v1 ).add( v2 ).add( v3 ).divideScalar( 3 );
- var azi = azimuth( centroid );
- that.faceVertexUvs[ 0 ].push( [
- correctUV( v1.uv, v1, azi ),
- correctUV( v2.uv, v2, azi ),
- correctUV( v3.uv, v3, azi )
- ] );
- }
- // Analytically subdivide a face to the required detail level.
- function subdivide( face, detail ) {
- var cols = Math.pow(2, detail);
- var cells = Math.pow(4, detail);
- var a = prepare( that.vertices[ face.a ] );
- var b = prepare( that.vertices[ face.b ] );
- var c = prepare( that.vertices[ face.c ] );
- var v = [];
- // Construct all of the vertices for this subdivision.
- for ( var i = 0 ; i <= cols; i ++ ) {
- v[ i ] = [];
- var aj = prepare( a.clone().lerp( c, i / cols ) );
- var bj = prepare( b.clone().lerp( c, i / cols ) );
- var rows = cols - i;
- for ( var j = 0; j <= rows; j ++) {
- if ( j == 0 && i == cols ) {
- v[ i ][ j ] = aj;
- } else {
- v[ i ][ j ] = prepare( aj.clone().lerp( bj, j / rows ) );
- }
- }
- }
- // Construct all of the faces.
- for ( var i = 0; i < cols ; i ++ ) {
- for ( var j = 0; j < 2 * (cols - i) - 1; j ++ ) {
- var k = Math.floor( j / 2 );
- if ( j % 2 == 0 ) {
- make(
- v[ i ][ k + 1],
- v[ i + 1 ][ k ],
- v[ i ][ k ]
- );
- } else {
- make(
- v[ i ][ k + 1 ],
- v[ i + 1][ k + 1],
- v[ i + 1 ][ k ]
- );
- }
- }
- }
- }
- // Angle around the Y axis, counter-clockwise when looking from above.
- function azimuth( vector ) {
- return Math.atan2( vector.z, - vector.x );
- }
- // Angle above the XZ plane.
- function inclination( vector ) {
- return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
- }
- // Texture fixing helper. Spheres have some odd behaviours.
- function correctUV( uv, vector, azimuth ) {
- if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) uv = new THREE.Vector2( uv.x - 1, uv.y );
- if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) uv = new THREE.Vector2( azimuth / 2 / Math.PI + 0.5, uv.y );
- return uv.clone();
- }
- };
- THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
- THREE.PolyhedronGeometry.prototype.constructor = THREE.PolyhedronGeometry;
|