Pārlūkot izejas kodu

Added EdgeSplitModifier module

Max Godefroy (Clyde) 4 gadi atpakaļ
vecāks
revīzija
02966652f4

+ 8 - 0
examples/jsm/modifiers/EdgeSplitModifier.d.ts

@@ -0,0 +1,8 @@
+import { BufferGeometry, Geometry } from "../../../src/Three";
+
+export class EdgeSplitModifier {
+
+	constructor();
+	modify( geometry: Geometry, cutOffPoint: number ): BufferGeometry;
+
+}

+ 191 - 0
examples/jsm/modifiers/EdgeSplitModifier.js

@@ -0,0 +1,191 @@
+import { BufferAttribute, BufferGeometry, Vector3 } from "../../../build/three.module.js";
+import { BufferGeometryUtils } from "../utils/BufferGeometryUtils.js";
+
+
+export function EdgeSplitModifier() {
+
+	const A = new Vector3();
+	const B = new Vector3();
+	const C = new Vector3();
+
+	let positions, normals;
+	let indexes;
+	let pointToIndexMap, splitIndexes;
+
+
+	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 ] );
+
+	}
+
+
+	this.modify = function ( geometry, cutOffAngle ) {
+
+		if ( ! geometry.isBufferGeometry ) {
+
+			geometry = new BufferGeometry().fromGeometry( geometry );
+
+		}
+
+
+		if ( geometry.index == null )
+			geometry = BufferGeometryUtils.mergeVertices( geometry );
+
+
+		indexes = geometry.index.array;
+		positions = geometry.getAttribute( "position" ).array;
+
+		computeNormals();
+
+
+		mapPositionsToIndexes();
+
+
+		splitIndexes = [];
+
+		for ( const vertexIndexes of pointToIndexMap )
+			edgeSplit( vertexIndexes, Math.cos( cutOffAngle ) - 0.001 );
+
+
+		const newPositions = new Float32Array( positions.length + 3 * splitIndexes.length );
+		newPositions.set( positions );
+		const offset = positions.length;
+
+		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 ];
+
+			newPositions[ offset + 3 * i ] = positions[ 3 * index ];
+			newPositions[ offset + 3 * i + 1 ] = positions[ 3 * index + 1 ];
+			newPositions[ offset + 3 * i + 2 ] = positions[ 3 * index + 2 ];
+
+			for ( const j of split.indexes )
+				newIndexes[ j ] = offset / 3 + i;
+
+		}
+
+		geometry = new BufferGeometry();
+		geometry.setAttribute( 'position', new BufferAttribute( newPositions, 3, true ) );
+		geometry.setIndex( new BufferAttribute( newIndexes, 1 ) );
+
+		return geometry;
+
+	};
+
+}