Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three /examples /jsm /modifiers /EdgeSplitModifier.js
| import { | |
| BufferAttribute, | |
| BufferGeometry, | |
| Vector3 | |
| } from 'three'; | |
| import * as BufferGeometryUtils from '../utils/BufferGeometryUtils.js'; | |
| const _A = new Vector3(); | |
| const _B = new Vector3(); | |
| const _C = new Vector3(); | |
| class EdgeSplitModifier { | |
| modify( geometry, cutOffAngle, tryKeepNormals = true ) { | |
| function computeNormals() { | |
| normals = new Float32Array( indexes.length * 3 ); | |
| for ( let i = 0; i < indexes.length; i += 3 ) { | |
| let index = indexes[ i ]; | |
| _A.set( | |
| positions[ 3 * index ], | |
| positions[ 3 * index + 1 ], | |
| positions[ 3 * index + 2 ] ); | |
| index = indexes[ i + 1 ]; | |
| _B.set( | |
| positions[ 3 * index ], | |
| positions[ 3 * index + 1 ], | |
| positions[ 3 * index + 2 ] ); | |
| index = indexes[ i + 2 ]; | |
| _C.set( | |
| positions[ 3 * index ], | |
| positions[ 3 * index + 1 ], | |
| positions[ 3 * index + 2 ] ); | |
| _C.sub( _B ); | |
| _A.sub( _B ); | |
| const normal = _C.cross( _A ).normalize(); | |
| for ( let j = 0; j < 3; j ++ ) { | |
| normals[ 3 * ( i + j ) ] = normal.x; | |
| normals[ 3 * ( i + j ) + 1 ] = normal.y; | |
| normals[ 3 * ( i + j ) + 2 ] = normal.z; | |
| } | |
| } | |
| } | |
| function mapPositionsToIndexes() { | |
| pointToIndexMap = Array( positions.length / 3 ); | |
| for ( let i = 0; i < indexes.length; i ++ ) { | |
| const index = indexes[ i ]; | |
| if ( pointToIndexMap[ index ] == null ) { | |
| pointToIndexMap[ index ] = []; | |
| } | |
| pointToIndexMap[ index ].push( i ); | |
| } | |
| } | |
| function edgeSplitToGroups( indexes, cutOff, firstIndex ) { | |
| _A.set( normals[ 3 * firstIndex ], normals[ 3 * firstIndex + 1 ], normals[ 3 * firstIndex + 2 ] ).normalize(); | |
| const result = { | |
| splitGroup: [], | |
| currentGroup: [ firstIndex ] | |
| }; | |
| for ( const j of indexes ) { | |
| if ( j !== firstIndex ) { | |
| _B.set( normals[ 3 * j ], normals[ 3 * j + 1 ], normals[ 3 * j + 2 ] ).normalize(); | |
| if ( _B.dot( _A ) < cutOff ) { | |
| result.splitGroup.push( j ); | |
| } else { | |
| result.currentGroup.push( j ); | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| function edgeSplit( indexes, cutOff, original = null ) { | |
| if ( indexes.length === 0 ) return; | |
| const groupResults = []; | |
| for ( const index of indexes ) { | |
| groupResults.push( edgeSplitToGroups( indexes, cutOff, index ) ); | |
| } | |
| let result = groupResults[ 0 ]; | |
| for ( const groupResult of groupResults ) { | |
| if ( groupResult.currentGroup.length > result.currentGroup.length ) { | |
| result = groupResult; | |
| } | |
| } | |
| if ( original != null ) { | |
| splitIndexes.push( { | |
| original: original, | |
| indexes: result.currentGroup | |
| } ); | |
| } | |
| if ( result.splitGroup.length ) { | |
| edgeSplit( result.splitGroup, cutOff, original || result.currentGroup[ 0 ] ); | |
| } | |
| } | |
| let hadNormals = false; | |
| let oldNormals = null; | |
| if ( geometry.attributes.normal ) { | |
| hadNormals = true; | |
| geometry = geometry.clone(); | |
| if ( tryKeepNormals === true && geometry.index !== null ) { | |
| oldNormals = geometry.attributes.normal.array; | |
| } | |
| geometry.deleteAttribute( 'normal' ); | |
| } | |
| if ( geometry.index == null ) { | |
| geometry = BufferGeometryUtils.mergeVertices( geometry ); | |
| } | |
| const indexes = geometry.index.array; | |
| const positions = geometry.getAttribute( 'position' ).array; | |
| let normals; | |
| let pointToIndexMap; | |
| computeNormals(); | |
| mapPositionsToIndexes(); | |
| const splitIndexes = []; | |
| for ( const vertexIndexes of pointToIndexMap ) { | |
| edgeSplit( vertexIndexes, Math.cos( cutOffAngle ) - 0.001 ); | |
| } | |
| const newAttributes = {}; | |
| for ( const name of Object.keys( geometry.attributes ) ) { | |
| const oldAttribute = geometry.attributes[ name ]; | |
| const newArray = new oldAttribute.array.constructor( ( indexes.length + splitIndexes.length ) * oldAttribute.itemSize ); | |
| newArray.set( oldAttribute.array ); | |
| newAttributes[ name ] = new BufferAttribute( newArray, oldAttribute.itemSize, oldAttribute.normalized ); | |
| } | |
| const newIndexes = new Uint32Array( indexes.length ); | |
| newIndexes.set( indexes ); | |
| for ( let i = 0; i < splitIndexes.length; i ++ ) { | |
| const split = splitIndexes[ i ]; | |
| const index = indexes[ split.original ]; | |
| for ( const attribute of Object.values( newAttributes ) ) { | |
| for ( let j = 0; j < attribute.itemSize; j ++ ) { | |
| attribute.array[ ( indexes.length + i ) * attribute.itemSize + j ] = | |
| attribute.array[ index * attribute.itemSize + j ]; | |
| } | |
| } | |
| for ( const j of split.indexes ) { | |
| newIndexes[ j ] = indexes.length + i; | |
| } | |
| } | |
| geometry = new BufferGeometry(); | |
| geometry.setIndex( new BufferAttribute( newIndexes, 1 ) ); | |
| for ( const name of Object.keys( newAttributes ) ) { | |
| geometry.setAttribute( name, newAttributes[ name ] ); | |
| } | |
| if ( hadNormals ) { | |
| geometry.computeVertexNormals(); | |
| if ( oldNormals !== null ) { | |
| const changedNormals = new Array( oldNormals.length / 3 ).fill( false ); | |
| for ( const splitData of splitIndexes ) | |
| changedNormals[ splitData.original ] = true; | |
| for ( let i = 0; i < changedNormals.length; i ++ ) { | |
| if ( changedNormals[ i ] === false ) { | |
| for ( let j = 0; j < 3; j ++ ) | |
| geometry.attributes.normal.array[ 3 * i + j ] = oldNormals[ 3 * i + j ]; | |
| } | |
| } | |
| } | |
| } | |
| return geometry; | |
| } | |
| } | |
| export { EdgeSplitModifier }; | |
Xet Storage Details
- Size:
- 5.3 kB
- Xet hash:
- 6a9cb0e4e6ca037795caaa5a320162606a42bec2afbcb2944459844b6a22f61f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.