Dies ist das Repository meines kleinen Portfolios.
Im Hintergrund läuft eine Planetensimulation, geschrieben in JavaScript und Three.js.
Die zu sehenden Texturen stammen von:
https://www.solarsystemscope.com/textures/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
5.5 KiB
271 lines
5.5 KiB
( function () { |
|
|
|
const _A = new THREE.Vector3(); |
|
|
|
const _B = new THREE.Vector3(); |
|
|
|
const _C = new THREE.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 ] ); |
|
|
|
} |
|
|
|
} |
|
|
|
if ( geometry.isGeometry === true ) { |
|
|
|
console.error( 'THREE.EdgeSplitModifier no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' ); |
|
return; |
|
|
|
} |
|
|
|
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 ) { |
|
|
|
if ( THREE.BufferGeometryUtils === undefined ) { |
|
|
|
throw 'THREE.EdgeSplitModifier relies on THREE.BufferGeometryUtils'; |
|
|
|
} |
|
|
|
geometry = THREE.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 THREE.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 THREE.BufferGeometry(); |
|
geometry.setIndex( new THREE.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; |
|
|
|
} |
|
|
|
} |
|
|
|
THREE.EdgeSplitModifier = EdgeSplitModifier; |
|
|
|
} )();
|
|
|