Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three /src /geometries /PolyhedronGeometry.js
| import { BufferGeometry } from '../core/BufferGeometry.js'; | |
| import { Float32BufferAttribute } from '../core/BufferAttribute.js'; | |
| import { Vector3 } from '../math/Vector3.js'; | |
| import { Vector2 } from '../math/Vector2.js'; | |
| class PolyhedronGeometry extends BufferGeometry { | |
| constructor( vertices = [], indices = [], radius = 1, detail = 0 ) { | |
| super(); | |
| this.type = 'PolyhedronGeometry'; | |
| this.parameters = { | |
| vertices: vertices, | |
| indices: indices, | |
| radius: radius, | |
| detail: detail | |
| }; | |
| // default buffer data | |
| const vertexBuffer = []; | |
| const uvBuffer = []; | |
| // the subdivision creates the vertex buffer data | |
| subdivide( detail ); | |
| // all vertices should lie on a conceptual sphere with a given radius | |
| applyRadius( radius ); | |
| // finally, create the uv data | |
| generateUVs(); | |
| // build non-indexed geometry | |
| this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); | |
| this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); | |
| this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); | |
| if ( detail === 0 ) { | |
| this.computeVertexNormals(); // flat normals | |
| } else { | |
| this.normalizeNormals(); // smooth normals | |
| } | |
| // helper functions | |
| function subdivide( detail ) { | |
| const a = new Vector3(); | |
| const b = new Vector3(); | |
| const c = new Vector3(); | |
| // iterate over all faces and apply a subdivision with the given detail value | |
| for ( let i = 0; i < indices.length; i += 3 ) { | |
| // get the vertices of the face | |
| getVertexByIndex( indices[ i + 0 ], a ); | |
| getVertexByIndex( indices[ i + 1 ], b ); | |
| getVertexByIndex( indices[ i + 2 ], c ); | |
| // perform subdivision | |
| subdivideFace( a, b, c, detail ); | |
| } | |
| } | |
| function subdivideFace( a, b, c, detail ) { | |
| const cols = detail + 1; | |
| // we use this multidimensional array as a data structure for creating the subdivision | |
| const v = []; | |
| // construct all of the vertices for this subdivision | |
| for ( let i = 0; i <= cols; i ++ ) { | |
| v[ i ] = []; | |
| const aj = a.clone().lerp( c, i / cols ); | |
| const bj = b.clone().lerp( c, i / cols ); | |
| const rows = cols - i; | |
| for ( let j = 0; j <= rows; j ++ ) { | |
| if ( j === 0 && i === cols ) { | |
| v[ i ][ j ] = aj; | |
| } else { | |
| v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); | |
| } | |
| } | |
| } | |
| // construct all of the faces | |
| for ( let i = 0; i < cols; i ++ ) { | |
| for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { | |
| const k = Math.floor( j / 2 ); | |
| if ( j % 2 === 0 ) { | |
| pushVertex( v[ i ][ k + 1 ] ); | |
| pushVertex( v[ i + 1 ][ k ] ); | |
| pushVertex( v[ i ][ k ] ); | |
| } else { | |
| pushVertex( v[ i ][ k + 1 ] ); | |
| pushVertex( v[ i + 1 ][ k + 1 ] ); | |
| pushVertex( v[ i + 1 ][ k ] ); | |
| } | |
| } | |
| } | |
| } | |
| function applyRadius( radius ) { | |
| const vertex = new Vector3(); | |
| // iterate over the entire buffer and apply the radius to each vertex | |
| for ( let i = 0; i < vertexBuffer.length; i += 3 ) { | |
| vertex.x = vertexBuffer[ i + 0 ]; | |
| vertex.y = vertexBuffer[ i + 1 ]; | |
| vertex.z = vertexBuffer[ i + 2 ]; | |
| vertex.normalize().multiplyScalar( radius ); | |
| vertexBuffer[ i + 0 ] = vertex.x; | |
| vertexBuffer[ i + 1 ] = vertex.y; | |
| vertexBuffer[ i + 2 ] = vertex.z; | |
| } | |
| } | |
| function generateUVs() { | |
| const vertex = new Vector3(); | |
| for ( let i = 0; i < vertexBuffer.length; i += 3 ) { | |
| vertex.x = vertexBuffer[ i + 0 ]; | |
| vertex.y = vertexBuffer[ i + 1 ]; | |
| vertex.z = vertexBuffer[ i + 2 ]; | |
| const u = azimuth( vertex ) / 2 / Math.PI + 0.5; | |
| const v = inclination( vertex ) / Math.PI + 0.5; | |
| uvBuffer.push( u, 1 - v ); | |
| } | |
| correctUVs(); | |
| correctSeam(); | |
| } | |
| function correctSeam() { | |
| // handle case when face straddles the seam, see #3269 | |
| for ( let i = 0; i < uvBuffer.length; i += 6 ) { | |
| // uv data of a single face | |
| const x0 = uvBuffer[ i + 0 ]; | |
| const x1 = uvBuffer[ i + 2 ]; | |
| const x2 = uvBuffer[ i + 4 ]; | |
| const max = Math.max( x0, x1, x2 ); | |
| const min = Math.min( x0, x1, x2 ); | |
| // 0.9 is somewhat arbitrary | |
| if ( max > 0.9 && min < 0.1 ) { | |
| if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; | |
| if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; | |
| if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; | |
| } | |
| } | |
| } | |
| function pushVertex( vertex ) { | |
| vertexBuffer.push( vertex.x, vertex.y, vertex.z ); | |
| } | |
| function getVertexByIndex( index, vertex ) { | |
| const stride = index * 3; | |
| vertex.x = vertices[ stride + 0 ]; | |
| vertex.y = vertices[ stride + 1 ]; | |
| vertex.z = vertices[ stride + 2 ]; | |
| } | |
| function correctUVs() { | |
| const a = new Vector3(); | |
| const b = new Vector3(); | |
| const c = new Vector3(); | |
| const centroid = new Vector3(); | |
| const uvA = new Vector2(); | |
| const uvB = new Vector2(); | |
| const uvC = new Vector2(); | |
| for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { | |
| a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); | |
| b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); | |
| c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); | |
| uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); | |
| uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); | |
| uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); | |
| centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); | |
| const azi = azimuth( centroid ); | |
| correctUV( uvA, j + 0, a, azi ); | |
| correctUV( uvB, j + 2, b, azi ); | |
| correctUV( uvC, j + 4, c, azi ); | |
| } | |
| } | |
| function correctUV( uv, stride, vector, azimuth ) { | |
| if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { | |
| uvBuffer[ stride ] = uv.x - 1; | |
| } | |
| if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { | |
| uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; | |
| } | |
| } | |
| // 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 ) ) ); | |
| } | |
| } | |
| copy( source ) { | |
| super.copy( source ); | |
| this.parameters = Object.assign( {}, source.parameters ); | |
| return this; | |
| } | |
| static fromJSON( data ) { | |
| return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); | |
| } | |
| } | |
| export { PolyhedronGeometry }; | |
Xet Storage Details
- Size:
- 6.44 kB
- Xet hash:
- 70e1d85e293ea846c24639d1da9f5f40f8f20a5afbd2668c3cbce4936e850b0c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.