PolyhedronGeometry.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /**
  2. * @author clockworkgeek / https://github.com/clockworkgeek
  3. * @author timothypratley / https://github.com/timothypratley
  4. * @author WestLangley / http://github.com/WestLangley
  5. */
  6. THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
  7. THREE.Geometry.call( this );
  8. this.type = 'PolyhedronGeometry';
  9. this.parameters = {
  10. vertices: vertices,
  11. indices: indices,
  12. radius: radius,
  13. detail: detail
  14. };
  15. radius = radius || 1;
  16. detail = detail || 0;
  17. var that = this;
  18. for ( var i = 0, l = vertices.length; i < l; i += 3 ) {
  19. prepare( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
  20. }
  21. var midpoints = [], p = this.vertices;
  22. var faces = [];
  23. for ( var i = 0, j = 0, l = indices.length; i < l; i += 3, j ++ ) {
  24. var v1 = p[ indices[ i ] ];
  25. var v2 = p[ indices[ i + 1 ] ];
  26. var v3 = p[ indices[ i + 2 ] ];
  27. faces[ j ] = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
  28. }
  29. var centroid = new THREE.Vector3();
  30. for ( var i = 0, l = faces.length; i < l; i ++ ) {
  31. subdivide( faces[ i ], detail );
  32. }
  33. // Handle case when face straddles the seam
  34. for ( var i = 0, l = this.faceVertexUvs[ 0 ].length; i < l; i ++ ) {
  35. var uvs = this.faceVertexUvs[ 0 ][ i ];
  36. var x0 = uvs[ 0 ].x;
  37. var x1 = uvs[ 1 ].x;
  38. var x2 = uvs[ 2 ].x;
  39. var max = Math.max( x0, Math.max( x1, x2 ) );
  40. var min = Math.min( x0, Math.min( x1, x2 ) );
  41. if ( max > 0.9 && min < 0.1 ) { // 0.9 is somewhat arbitrary
  42. if ( x0 < 0.2 ) uvs[ 0 ].x += 1;
  43. if ( x1 < 0.2 ) uvs[ 1 ].x += 1;
  44. if ( x2 < 0.2 ) uvs[ 2 ].x += 1;
  45. }
  46. }
  47. // Apply radius
  48. for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
  49. this.vertices[ i ].multiplyScalar( radius );
  50. }
  51. // Merge vertices
  52. this.mergeVertices();
  53. this.computeFaceNormals();
  54. this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
  55. // Project vector onto sphere's surface
  56. function prepare( vector ) {
  57. var vertex = vector.normalize().clone();
  58. vertex.index = that.vertices.push( vertex ) - 1;
  59. // Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
  60. var u = azimuth( vector ) / 2 / Math.PI + 0.5;
  61. var v = inclination( vector ) / Math.PI + 0.5;
  62. vertex.uv = new THREE.Vector2( u, 1 - v );
  63. return vertex;
  64. }
  65. // Approximate a curved face with recursively sub-divided triangles.
  66. function make( v1, v2, v3 ) {
  67. var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
  68. that.faces.push( face );
  69. centroid.copy( v1 ).add( v2 ).add( v3 ).divideScalar( 3 );
  70. var azi = azimuth( centroid );
  71. that.faceVertexUvs[ 0 ].push( [
  72. correctUV( v1.uv, v1, azi ),
  73. correctUV( v2.uv, v2, azi ),
  74. correctUV( v3.uv, v3, azi )
  75. ] );
  76. }
  77. // Analytically subdivide a face to the required detail level.
  78. function subdivide( face, detail ) {
  79. var cols = Math.pow(2, detail);
  80. var cells = Math.pow(4, detail);
  81. var a = prepare( that.vertices[ face.a ] );
  82. var b = prepare( that.vertices[ face.b ] );
  83. var c = prepare( that.vertices[ face.c ] );
  84. var v = [];
  85. // Construct all of the vertices for this subdivision.
  86. for ( var i = 0 ; i <= cols; i ++ ) {
  87. v[ i ] = [];
  88. var aj = prepare( a.clone().lerp( c, i / cols ) );
  89. var bj = prepare( b.clone().lerp( c, i / cols ) );
  90. var rows = cols - i;
  91. for ( var j = 0; j <= rows; j ++) {
  92. if ( j == 0 && i == cols ) {
  93. v[ i ][ j ] = aj;
  94. } else {
  95. v[ i ][ j ] = prepare( aj.clone().lerp( bj, j / rows ) );
  96. }
  97. }
  98. }
  99. // Construct all of the faces.
  100. for ( var i = 0; i < cols ; i ++ ) {
  101. for ( var j = 0; j < 2 * (cols - i) - 1; j ++ ) {
  102. var k = Math.floor( j / 2 );
  103. if ( j % 2 == 0 ) {
  104. make(
  105. v[ i ][ k + 1],
  106. v[ i + 1 ][ k ],
  107. v[ i ][ k ]
  108. );
  109. } else {
  110. make(
  111. v[ i ][ k + 1 ],
  112. v[ i + 1][ k + 1],
  113. v[ i + 1 ][ k ]
  114. );
  115. }
  116. }
  117. }
  118. }
  119. // Angle around the Y axis, counter-clockwise when looking from above.
  120. function azimuth( vector ) {
  121. return Math.atan2( vector.z, - vector.x );
  122. }
  123. // Angle above the XZ plane.
  124. function inclination( vector ) {
  125. return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
  126. }
  127. // Texture fixing helper. Spheres have some odd behaviours.
  128. function correctUV( uv, vector, azimuth ) {
  129. if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) uv = new THREE.Vector2( uv.x - 1, uv.y );
  130. if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) uv = new THREE.Vector2( azimuth / 2 / Math.PI + 0.5, uv.y );
  131. return uv.clone();
  132. }
  133. };
  134. THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
  135. THREE.PolyhedronGeometry.prototype.constructor = THREE.PolyhedronGeometry;