Просмотр исходного кода

BatchedMesh: Add `optimize()`. (#29527)

* Add support for "deleteGeometry"

* Add docs, fix mistype

* BatchedMesh: Add an "optimize" function

* Fix index offset

* Add docs

* Update BatchedMesh.html

* Update BatchedMesh.html
Garrett Johnson 1 год назад
Родитель
Сommit
7ede9aa986
2 измененных файлов с 80 добавлено и 0 удалено
  1. 8 0
      docs/api/en/objects/BatchedMesh.html
  2. 72 0
      src/objects/BatchedMesh.js

+ 8 - 0
docs/api/en/objects/BatchedMesh.html

@@ -301,6 +301,14 @@
 			Calling this will change all instances that are rendering that geometry.
 			Calling this will change all instances that are rendering that geometry.
 		</p>
 		</p>
 
 
+
+		<h3>
+			[method:this optimize]()
+		</h3>
+		<p>
+			Repacks the sub geometries in [name] to remove any unused space remaining from previously deleted geometry, freeing up space to add new geometry.
+		</p>
+
 		<!--
 		<!--
 		<h3>
 		<h3>
 			[method:Integer getInstanceCountAt]( [param:Integer index] )
 			[method:Integer getInstanceCountAt]( [param:Integer index] )

+ 72 - 0
src/objects/BatchedMesh.js

@@ -674,6 +674,78 @@ class BatchedMesh extends Mesh {
 
 
 	}
 	}
 
 
+	optimize() {
+
+		// track the next indices to copy data to
+		let nextVertexStart = 0;
+		let nextIndexStart = 0;
+
+		// iterate over all geometry ranges
+		const drawRanges = this._drawRanges;
+		const reservedRanges = this._reservedRanges;
+		const geometry = this.geometry;
+		for ( let i = 0, l = drawRanges.length; i < l; i ++ ) {
+
+			// if a geometry range is inactive then don't copy anything
+			const drawRange = drawRanges[ i ];
+			const reservedRange = reservedRanges[ i ];
+			if ( drawRange.active === false ) {
+
+				continue;
+
+			}
+
+			// if a geometry contains an index buffer then shift it, as well
+			if ( geometry.index !== null && reservedRange.indexStart !== nextIndexStart ) {
+
+				const { indexStart, indexCount } = reservedRange;
+				const index = geometry.index;
+				const array = index.array;
+
+				// shift the index pointers based on how the vertex data will shift
+				// adjusting the index must happen first so the original vertex start value is available
+				const elementDelta = nextVertexStart - reservedRange.vertexStart;
+				for ( let j = indexStart; j < indexStart + indexCount; j ++ ) {
+
+					array[ j ] = array[ j ] + elementDelta;
+
+				}
+
+				index.array.copyWithin( nextIndexStart, indexStart, indexStart + indexCount );
+				index.addUpdateRange( nextIndexStart, indexCount );
+
+				reservedRange.indexStart = nextIndexStart;
+				nextIndexStart += reservedRange.indexCount;
+
+			}
+
+			// if a geometry needs to be moved then copy attribute data to overwrite unused space
+			if ( reservedRange.vertexStart !== nextVertexStart ) {
+
+				const { vertexStart, vertexCount } = reservedRange;
+				const attributes = geometry.attributes;
+				for ( const key in attributes ) {
+
+					const attribute = attributes[ key ];
+					const { array, itemSize } = attribute;
+					array.copyWithin( nextVertexStart * itemSize, vertexStart * itemSize, ( vertexStart + vertexCount ) * itemSize );
+					attribute.addUpdateRange( nextVertexStart * itemSize, vertexCount * itemSize );
+
+				}
+
+				reservedRange.vertexStart = nextVertexStart;
+				nextVertexStart += reservedRange.vertexCount;
+
+			}
+
+			drawRange.start = geometry.index ? reservedRange.indexStart : reservedRange.vertexStart;
+
+		}
+
+		return this;
+
+	}
+
 	// get bounding box and compute it if it doesn't exist
 	// get bounding box and compute it if it doesn't exist
 	getBoundingBoxAt( geometryId, target ) {
 	getBoundingBoxAt( geometryId, target ) {
 
 

粤ICP备19079148号