Mr.doob преди 4 години
родител
ревизия
d7e25f3135

+ 312 - 1
examples/js/utils/BufferGeometryUtils.js

@@ -744,7 +744,6 @@ THREE.BufferGeometryUtils = {
 						newIndices.push( index.getX( i + 1 ) );
 						newIndices.push( index.getX( i + 2 ) );
 
-
 					} else {
 
 						newIndices.push( index.getX( i + 2 ) );
@@ -778,6 +777,318 @@ THREE.BufferGeometryUtils = {
 
 		}
 
+	},
+
+	/**
+	 * Calculates the morphed attributes of a morphed/skinned BufferGeometry.
+	 * Helpful for Raytracing or Decals.
+	 * @param {Object3D} object
+	 * @return {Object} An Object with original position/normal attributes and morphed ones.
+	 */
+	computeMorphedBufferGeometry: function ( object ) {
+
+		if ( ! object ) {
+
+			console.error( 'Please provide an object' );
+			return null;
+
+		}
+
+		if ( ! object.geometry ) {
+
+			console.error( 'Please provide an object with a geometry' );
+			return null;
+
+		}
+
+		if ( ! object.geometry.isBufferGeometry ) {
+
+			console.error( 'Geometry is not a BufferGeometry' );
+			return null;
+
+		}
+
+		var _vA = new THREE.Vector3();
+		var _vB = new THREE.Vector3();
+		var _vC = new THREE.Vector3();
+
+		var _tempA = new THREE.Vector3();
+		var _tempB = new THREE.Vector3();
+		var _tempC = new THREE.Vector3();
+
+		var _morphA = new THREE.Vector3();
+		var _morphB = new THREE.Vector3();
+		var _morphC = new THREE.Vector3();
+
+		function _calculateMorphedAttributeData(
+			object,
+			material,
+			attribute,
+			morphAttribute,
+			morphTargetsRelative,
+			a,
+			b,
+			c,
+			modifiedAttributeArray
+		) {
+
+			_vA.fromBufferAttribute( attribute, a );
+			_vB.fromBufferAttribute( attribute, b );
+			_vC.fromBufferAttribute( attribute, c );
+
+			var morphInfluences = object.morphTargetInfluences;
+
+			if ( material.morphTargets && morphAttribute && morphInfluences ) {
+
+				_morphA.set( 0, 0, 0 );
+				_morphB.set( 0, 0, 0 );
+				_morphC.set( 0, 0, 0 );
+
+				for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {
+
+					var influence = morphInfluences[ i ];
+					var morphAttribute = morphAttribute[ i ];
+
+					if ( influence === 0 ) continue;
+
+					_tempA.fromBufferAttribute( morphAttribute, a );
+					_tempB.fromBufferAttribute( morphAttribute, b );
+					_tempC.fromBufferAttribute( morphAttribute, c );
+
+					if ( morphTargetsRelative ) {
+
+						_morphA.addScaledVector( _tempA, influence );
+						_morphB.addScaledVector( _tempB, influence );
+						_morphC.addScaledVector( _tempC, influence );
+
+					} else {
+
+						_morphA.addScaledVector( _tempA.sub( _vA ), influence );
+						_morphB.addScaledVector( _tempB.sub( _vB ), influence );
+						_morphC.addScaledVector( _tempC.sub( _vC ), influence );
+
+					}
+
+				}
+
+				_vA.add( _morphA );
+				_vB.add( _morphB );
+				_vC.add( _morphC );
+
+			}
+
+			if ( object.isSkinnedMesh ) {
+
+				object.boneTransform( a, _vA );
+				object.boneTransform( b, _vB );
+				object.boneTransform( c, _vC );
+
+			}
+
+			modifiedAttributeArray[ a * 3 + 0 ] = _vA.x;
+			modifiedAttributeArray[ a * 3 + 1 ] = _vA.y;
+			modifiedAttributeArray[ a * 3 + 2 ] = _vA.z;
+			modifiedAttributeArray[ b * 3 + 0 ] = _vB.x;
+			modifiedAttributeArray[ b * 3 + 1 ] = _vB.y;
+			modifiedAttributeArray[ b * 3 + 2 ] = _vB.z;
+			modifiedAttributeArray[ c * 3 + 0 ] = _vC.x;
+			modifiedAttributeArray[ c * 3 + 1 ] = _vC.y;
+			modifiedAttributeArray[ c * 3 + 2 ] = _vC.z;
+
+		}
+
+		var geometry = object.geometry;
+		var material = object.material;
+
+		var a, b, c;
+		var index = geometry.index;
+		var positionAttribute = geometry.attributes.position;
+		var morphPosition = geometry.morphAttributes.position;
+		var morphTargetsRelative = geometry.morphTargetsRelative;
+		var normalAttribute = geometry.attributes.normal;
+		var morphNormal = geometry.morphAttributes.position;
+
+		var groups = geometry.groups;
+		var drawRange = geometry.drawRange;
+		var i, j, il, jl;
+		var group, groupMaterial;
+		var start, end;
+
+		var modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize );
+		var modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize );
+
+		if ( index !== null ) {
+
+			// indexed buffer geometry
+
+			if ( Array.isArray( material ) ) {
+
+				for ( i = 0, il = groups.length; i < il; i ++ ) {
+
+					group = groups[ i ];
+					groupMaterial = material[ group.materialIndex ];
+
+					start = Math.max( group.start, drawRange.start );
+					end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
+
+					for ( j = start, jl = end; j < jl; j += 3 ) {
+
+						a = index.getX( j );
+						b = index.getX( j + 1 );
+						c = index.getX( j + 2 );
+
+						_calculateMorphedAttributeData(
+							object,
+							groupMaterial,
+							positionAttribute,
+							morphPosition,
+							morphTargetsRelative,
+							a, b, c,
+							modifiedPosition
+						);
+
+						_calculateMorphedAttributeData(
+							object,
+							groupMaterial,
+							normalAttribute,
+							morphNormal,
+							morphTargetsRelative,
+							a, b, c,
+							modifiedNormal
+						);
+
+					}
+
+				}
+
+			} else {
+
+				start = Math.max( 0, drawRange.start );
+				end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
+
+				for ( i = start, il = end; i < il; i += 3 ) {
+
+					a = index.getX( i );
+					b = index.getX( i + 1 );
+					c = index.getX( i + 2 );
+
+					_calculateMorphedAttributeData(
+						object,
+						material,
+						positionAttribute,
+						morphPosition,
+						morphTargetsRelative,
+						a, b, c,
+						modifiedPosition
+					);
+
+					_calculateMorphedAttributeData(
+						object,
+						material,
+						normalAttribute,
+						morphNormal,
+						morphTargetsRelative,
+						a, b, c,
+						modifiedNormal
+					);
+
+				}
+
+			}
+
+		} else if ( positionAttribute !== undefined ) {
+
+			// non-indexed buffer geometry
+
+			if ( Array.isArray( material ) ) {
+
+				for ( i = 0, il = groups.length; i < il; i ++ ) {
+
+					group = groups[ i ];
+					groupMaterial = material[ group.materialIndex ];
+
+					start = Math.max( group.start, drawRange.start );
+					end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
+
+					for ( j = start, jl = end; j < jl; j += 3 ) {
+
+						a = j;
+						b = j + 1;
+						c = j + 2;
+
+						_calculateMorphedAttributeData(
+							object,
+							groupMaterial,
+							positionAttribute,
+							morphPosition,
+							morphTargetsRelative,
+							a, b, c,
+							modifiedPosition
+						);
+
+						_calculateMorphedAttributeData(
+							object,
+							groupMaterial,
+							normalAttribute,
+							morphNormal,
+							morphTargetsRelative,
+							a, b, c,
+							modifiedNormal
+						);
+
+					}
+
+				}
+
+			} else {
+
+				start = Math.max( 0, drawRange.start );
+				end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
+
+				for ( i = start, il = end; i < il; i += 3 ) {
+
+					a = i;
+					b = i + 1;
+					c = i + 2;
+
+					_calculateMorphedAttributeData(
+						object,
+						material,
+						positionAttribute,
+						morphPosition,
+						morphTargetsRelative,
+						a, b, c,
+						modifiedPosition
+					);
+
+					_calculateMorphedAttributeData(
+						object,
+						material,
+						normalAttribute,
+						morphNormal,
+						morphTargetsRelative,
+						a, b, c,
+						modifiedNormal
+					);
+
+				}
+
+			}
+
+		}
+
+		var morphedPositionAttribute = new THREE.Float32BufferAttribute( modifiedPosition, 3 );
+		var morphedNormalAttribute = new THREE.Float32BufferAttribute( modifiedNormal, 3 );
+
+		return {
+
+			positionAttribute: positionAttribute,
+			normalAttribute: normalAttribute,
+			morphedPositionAttribute: morphedPositionAttribute,
+			morphedNormalAttribute: morphedNormalAttribute
+
+		};
+
 	}
 
 };

+ 0 - 430
examples/jsm/modifiers/SubdivisionModifier.js

@@ -1,430 +0,0 @@
-import {
-	BufferGeometry,
-	Face3,
-	Vector2,
-	Vector3
-} from '../../../build/three.module.js';
-
-/**
- *	Subdivision Geometry Modifier
- *		using Loop Subdivision Scheme
- *
- *	References:
- *		http://graphics.stanford.edu/~mdfisher/subdivision.html
- *		http://www.holmes3d.net/graphics/subdivision/
- *		http://www.cs.rutgers.edu/~decarlo/readings/subdiv-sg00c.pdf
- *
- *	Known Issues:
- *		- currently doesn't handle "Sharp Edges"
- */
-
-var SubdivisionModifier = function ( subdivisions ) {
-
-	this.subdivisions = ( subdivisions === undefined ) ? 1 : subdivisions;
-
-};
-
-// Applies the "modify" pattern
-SubdivisionModifier.prototype.modify = function ( geometry ) {
-
-	var isBufferGeometry = geometry.isBufferGeometry;
-
-	if ( isBufferGeometry ) {
-
-		geometry = new Geometry().fromBufferGeometry( geometry );
-
-	} else {
-
-		geometry = geometry.clone();
-
-	}
-
-	geometry.mergeVertices( 6 );
-
-	var repeats = this.subdivisions;
-
-	while ( repeats -- > 0 ) {
-
-		this.smooth( geometry );
-
-	}
-
-	geometry.computeFaceNormals();
-	geometry.computeVertexNormals();
-
-	if ( isBufferGeometry ) {
-
-		return new BufferGeometry().fromGeometry( geometry );
-
-	} else {
-
-		return geometry;
-
-	}
-
-};
-
-( function () {
-
-	// Some constants
-	var ABC = [ 'a', 'b', 'c' ];
-
-
-	function getEdge( a, b, map ) {
-
-		var vertexIndexA = Math.min( a, b );
-		var vertexIndexB = Math.max( a, b );
-
-		var key = vertexIndexA + '_' + vertexIndexB;
-
-		return map[ key ];
-
-	}
-
-
-	function processEdge( a, b, vertices, map, face, metaVertices ) {
-
-		var vertexIndexA = Math.min( a, b );
-		var vertexIndexB = Math.max( a, b );
-
-		var key = vertexIndexA + '_' + vertexIndexB;
-
-		var edge;
-
-		if ( key in map ) {
-
-			edge = map[ key ];
-
-		} else {
-
-			var vertexA = vertices[ vertexIndexA ];
-			var vertexB = vertices[ vertexIndexB ];
-
-			edge = {
-
-				a: vertexA, // pointer reference
-				b: vertexB,
-				newEdge: null,
-				// aIndex: a, // numbered reference
-				// bIndex: b,
-				faces: [] // pointers to face
-
-			};
-
-			map[ key ] = edge;
-
-		}
-
-		edge.faces.push( face );
-
-		metaVertices[ a ].edges.push( edge );
-		metaVertices[ b ].edges.push( edge );
-
-
-	}
-
-	function generateLookups( vertices, faces, metaVertices, edges ) {
-
-		var i, il, face;
-
-		for ( i = 0, il = vertices.length; i < il; i ++ ) {
-
-			metaVertices[ i ] = { edges: [] };
-
-		}
-
-		for ( i = 0, il = faces.length; i < il; i ++ ) {
-
-			face = faces[ i ];
-
-			processEdge( face.a, face.b, vertices, edges, face, metaVertices );
-			processEdge( face.b, face.c, vertices, edges, face, metaVertices );
-			processEdge( face.c, face.a, vertices, edges, face, metaVertices );
-
-		}
-
-	}
-
-	function newFace( newFaces, a, b, c, materialIndex ) {
-
-		newFaces.push( new Face3( a, b, c, undefined, undefined, materialIndex ) );
-
-	}
-
-	function midpoint( a, b ) {
-
-		return ( Math.abs( b - a ) / 2 ) + Math.min( a, b );
-
-	}
-
-	function newUv( newUvs, a, b, c ) {
-
-		newUvs.push( [ a.clone(), b.clone(), c.clone() ] );
-
-	}
-
-	/////////////////////////////
-
-	// Performs one iteration of Subdivision
-	SubdivisionModifier.prototype.smooth = function ( geometry ) {
-
-		var tmp = new Vector3();
-
-		var oldVertices, oldFaces, oldUvs;
-		var newVertices, newFaces, newUVs = [];
-
-		var n, i, il, j, k;
-		var metaVertices, sourceEdges;
-
-		// new stuff.
-		var sourceEdges, newEdgeVertices, newSourceVertices;
-
-		oldVertices = geometry.vertices; // { x, y, z}
-		oldFaces = geometry.faces; // { a: oldVertex1, b: oldVertex2, c: oldVertex3 }
-		oldUvs = geometry.faceVertexUvs;
-
-		var hasUvs = oldUvs[ 0 ] !== undefined && oldUvs[ 0 ].length > 0;
-
-		if ( hasUvs ) {
-
-			for ( var j = 0; j < oldUvs.length; j ++ ) {
-
-				newUVs.push( [] );
-
-			}
-
-		}
-
-		/******************************************************
-		 *
-		 * Step 0: Preprocess Geometry to Generate edges Lookup
-		 *
-		 *******************************************************/
-
-		metaVertices = new Array( oldVertices.length );
-		sourceEdges = {}; // Edge => { oldVertex1, oldVertex2, faces[]  }
-
-		generateLookups( oldVertices, oldFaces, metaVertices, sourceEdges );
-
-
-		/******************************************************
-		 *
-		 *	Step 1.
-		 *	For each edge, create a new Edge Vertex,
-		 *	then position it.
-		 *
-		 *******************************************************/
-
-		newEdgeVertices = [];
-		var other, currentEdge, newEdge, face;
-		var edgeVertexWeight, adjacentVertexWeight, connectedFaces;
-
-		for ( i in sourceEdges ) {
-
-			currentEdge = sourceEdges[ i ];
-			newEdge = new Vector3();
-
-			edgeVertexWeight = 3 / 8;
-			adjacentVertexWeight = 1 / 8;
-
-			connectedFaces = currentEdge.faces.length;
-
-			// check how many linked faces. 2 should be correct.
-			if ( connectedFaces != 2 ) {
-
-				// if length is not 2, handle condition
-				edgeVertexWeight = 0.5;
-				adjacentVertexWeight = 0;
-
-				if ( connectedFaces != 1 ) {
-
-					// console.warn( 'Subdivision Modifier: Number of connected faces != 2, is: ', connectedFaces, currentEdge );
-
-				}
-
-			}
-
-			newEdge.addVectors( currentEdge.a, currentEdge.b ).multiplyScalar( edgeVertexWeight );
-
-			tmp.set( 0, 0, 0 );
-
-			for ( j = 0; j < connectedFaces; j ++ ) {
-
-				face = currentEdge.faces[ j ];
-
-				for ( k = 0; k < 3; k ++ ) {
-
-					other = oldVertices[ face[ ABC[ k ] ] ];
-					if ( other !== currentEdge.a && other !== currentEdge.b ) break;
-
-				}
-
-				tmp.add( other );
-
-			}
-
-			tmp.multiplyScalar( adjacentVertexWeight );
-			newEdge.add( tmp );
-
-			currentEdge.newEdge = newEdgeVertices.length;
-			newEdgeVertices.push( newEdge );
-
-			// console.log(currentEdge, newEdge);
-
-		}
-
-		/******************************************************
-		 *
-		 *	Step 2.
-		 *	Reposition each source vertices.
-		 *
-		 *******************************************************/
-
-		var beta, sourceVertexWeight, connectingVertexWeight;
-		var connectingEdge, connectingEdges, oldVertex, newSourceVertex;
-		newSourceVertices = [];
-
-		for ( i = 0, il = oldVertices.length; i < il; i ++ ) {
-
-			oldVertex = oldVertices[ i ];
-
-			// find all connecting edges (using lookupTable)
-			connectingEdges = metaVertices[ i ].edges;
-			n = connectingEdges.length;
-
-			if ( n == 3 ) {
-
-				beta = 3 / 16;
-
-			} else if ( n > 3 ) {
-
-				beta = 3 / ( 8 * n ); // Warren's modified formula
-
-			}
-
-			// Loop's original beta formula
-			// beta = 1 / n * ( 5/8 - Math.pow( 3/8 + 1/4 * Math.cos( 2 * Math. PI / n ), 2) );
-
-			sourceVertexWeight = 1 - n * beta;
-			connectingVertexWeight = beta;
-
-			if ( n <= 2 ) {
-
-				// crease and boundary rules
-				// console.warn('crease and boundary rules');
-
-				if ( n == 2 ) {
-
-					// console.warn( '2 connecting edges', connectingEdges );
-					sourceVertexWeight = 3 / 4;
-					connectingVertexWeight = 1 / 8;
-
-					// sourceVertexWeight = 1;
-					// connectingVertexWeight = 0;
-
-				} else if ( n == 1 ) {
-
-					// console.warn( 'only 1 connecting edge' );
-
-				} else if ( n == 0 ) {
-
-					// console.warn( '0 connecting edges' );
-
-				}
-
-			}
-
-			newSourceVertex = oldVertex.clone().multiplyScalar( sourceVertexWeight );
-
-			tmp.set( 0, 0, 0 );
-
-			for ( j = 0; j < n; j ++ ) {
-
-				connectingEdge = connectingEdges[ j ];
-				other = connectingEdge.a !== oldVertex ? connectingEdge.a : connectingEdge.b;
-				tmp.add( other );
-
-			}
-
-			tmp.multiplyScalar( connectingVertexWeight );
-			newSourceVertex.add( tmp );
-
-			newSourceVertices.push( newSourceVertex );
-
-		}
-
-
-		/******************************************************
-		 *
-		 *	Step 3.
-		 *	Generate Faces between source vertices
-		 *	and edge vertices.
-		 *
-		 *******************************************************/
-
-		newVertices = newSourceVertices.concat( newEdgeVertices );
-		var sl = newSourceVertices.length, edge1, edge2, edge3;
-		newFaces = [];
-
-		var uv, x0, x1, x2;
-		var x3 = new Vector2();
-		var x4 = new Vector2();
-		var x5 = new Vector2();
-
-		for ( i = 0, il = oldFaces.length; i < il; i ++ ) {
-
-			face = oldFaces[ i ];
-
-			// find the 3 new edges vertex of each old face
-
-			edge1 = getEdge( face.a, face.b, sourceEdges ).newEdge + sl;
-			edge2 = getEdge( face.b, face.c, sourceEdges ).newEdge + sl;
-			edge3 = getEdge( face.c, face.a, sourceEdges ).newEdge + sl;
-
-			// create 4 faces.
-
-			newFace( newFaces, edge1, edge2, edge3, face.materialIndex );
-			newFace( newFaces, face.a, edge1, edge3, face.materialIndex );
-			newFace( newFaces, face.b, edge2, edge1, face.materialIndex );
-			newFace( newFaces, face.c, edge3, edge2, face.materialIndex );
-
-			// create 4 new uv's
-
-			if ( hasUvs ) {
-
-				for ( var j = 0; j < oldUvs.length; j ++ ) {
-
-					uv = oldUvs[ j ][ i ];
-
-					x0 = uv[ 0 ];
-					x1 = uv[ 1 ];
-					x2 = uv[ 2 ];
-
-					x3.set( midpoint( x0.x, x1.x ), midpoint( x0.y, x1.y ) );
-					x4.set( midpoint( x1.x, x2.x ), midpoint( x1.y, x2.y ) );
-					x5.set( midpoint( x0.x, x2.x ), midpoint( x0.y, x2.y ) );
-
-					newUv( newUVs[ j ], x3, x4, x5 );
-					newUv( newUVs[ j ], x0, x3, x5 );
-
-					newUv( newUVs[ j ], x1, x4, x3 );
-					newUv( newUVs[ j ], x2, x5, x4 );
-
-				}
-
-			}
-
-		}
-
-		// Overwrite old arrays
-		geometry.vertices = newVertices;
-		geometry.faces = newFaces;
-		if ( hasUvs ) geometry.faceVertexUvs = newUVs;
-
-		// console.log('done');
-
-	};
-
-} )();
-
-export { SubdivisionModifier };

+ 0 - 1
examples/jsm/modifiers/TessellateModifier.js

@@ -2,7 +2,6 @@ import {
 	BufferGeometry,
 	Color,
 	Float32BufferAttribute,
-	Geometry,
 	Vector2,
 	Vector3
 } from '../../../build/three.module.js';

+ 12 - 11
examples/jsm/utils/BufferGeometryUtils.js

@@ -1,6 +1,7 @@
 import {
 	BufferAttribute,
 	BufferGeometry,
+	Float32BufferAttribute,
 	InterleavedBuffer,
 	InterleavedBufferAttribute,
 	TriangleFanDrawMode,
@@ -820,17 +821,17 @@ var BufferGeometryUtils = {
 
 		}
 
-		var _vA = new THREE.Vector3();
-		var _vB = new THREE.Vector3();
-		var _vC = new THREE.Vector3();
+		var _vA = new Vector3();
+		var _vB = new Vector3();
+		var _vC = new Vector3();
 
-		var _tempA = new THREE.Vector3();
-		var _tempB = new THREE.Vector3();
-		var _tempC = new THREE.Vector3();
+		var _tempA = new Vector3();
+		var _tempB = new Vector3();
+		var _tempC = new Vector3();
 
-		var _morphA = new THREE.Vector3();
-		var _morphB = new THREE.Vector3();
-		var _morphC = new THREE.Vector3();
+		var _morphA = new Vector3();
+		var _morphB = new Vector3();
+		var _morphC = new Vector3();
 
 		function _calculateMorphedAttributeData(
 			object,
@@ -1089,8 +1090,8 @@ var BufferGeometryUtils = {
 
 		}
 
-		var morphedPositionAttribute = new THREE.Float32BufferAttribute( modifiedPosition, 3 );
-		var morphedNormalAttribute = new THREE.Float32BufferAttribute( modifiedNormal, 3 );
+		var morphedPositionAttribute = new Float32BufferAttribute( modifiedPosition, 3 );
+		var morphedNormalAttribute = new Float32BufferAttribute( modifiedNormal, 3 );
 
 		return {