Explorar o código

GLTFLoader: Add combined geometry cache

Takahiro %!s(int64=7) %!d(string=hai) anos
pai
achega
d456bf1d0d
Modificáronse 1 ficheiros con 95 adicións e 15 borrados
  1. 95 15
      examples/js/loaders/GLTFLoader.js

+ 95 - 15
examples/js/loaders/GLTFLoader.js

@@ -1318,6 +1318,65 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
+	function getCachedCombinedGeometry( cache, geometries ) {
+
+		for ( var i = 0, il = cache.length; i < il; i ++ ) {
+
+			var entry = cache[ i ];
+
+			if ( geometries.length !== entry.baseGeometries.length ) continue;
+
+			var match = true;
+
+			for ( var j = 0, jl = geometries.length; j < jl; j ++ ) {
+
+				if ( geometries[ j ] !== entry.baseGeometries[ j ] ) {
+
+					match = false;
+					break;
+
+				}
+
+			}
+
+			if ( match ) return entry.geometry;
+
+		}
+
+		return null;
+
+	}
+
+	function getCachedMultiPassGeometry( cache, geometry, primitives ) {
+
+		for ( var i = 0, il = cache.length; i < il; i ++ ) {
+
+			var entry = cache[ i ];
+
+			if ( geometry !== entry.baseGeometry ) continue;
+			if ( primitives.length !== entry.primitives.length ) continue;
+
+			var match = true;
+
+			for ( var j = 0, jl = primitives.length; j < jl; j ++ ) {
+
+				if ( primitives[ j ].indices !== entry.primitives[ j ].indices ) {
+
+					match = false;
+					break;
+
+				}
+
+			}
+
+			if ( match ) return entry.geometry;
+
+		}
+
+		return null;
+
+	}
+
 	function cloneBufferAttribute( attribute ) {
 
 		if ( attribute.isInterleavedBufferAttribute ) {
@@ -1397,6 +1456,8 @@ THREE.GLTFLoader = ( function () {
 
 		// BufferGeometry caching
 		this.primitiveCache = [];
+		this.multiplePrimitivesCache = [];
+		this.multiPassGeometryCache = []
 
 		this.textureLoader = new THREE.TextureLoader( this.options.manager );
 		this.textureLoader.setCrossOrigin( this.options.crossOrigin );
@@ -2098,10 +2159,10 @@ THREE.GLTFLoader = ( function () {
 		var extensions = this.extensions;
 		var cache = this.primitiveCache;
 
-		var isCombinable = isMultiPassGeometry( primitives );
+		var isMultiPass = isMultiPassGeometry( primitives );
 		var originalPrimitives;
 
-		if ( isCombinable ) {
+		if ( isMultiPass ) {
 
 			originalPrimitives = primitives; // save original primitives and use later
 
@@ -2167,18 +2228,25 @@ THREE.GLTFLoader = ( function () {
 
 			return Promise.all( pending ).then( function ( geometries ) {
 
-				if ( isCombinable ) {
+				if ( isMultiPass ) {
+
+					var baseGeometry = geometries[ 0 ];
+
+					// See if we've already created this combined geometry
+					var cache = parser.multiPassGeometryCache;
+					var cached = getCachedMultiPassGeometry( cache, baseGeometry, originalPrimitives );
+
+					if ( cached !== null ) return [ cached.geometry ];
 
 					// Cloning geometry because of index override.
 					// Attributes can be reused so cloning by myself here.
-					var source = geometries[ 0 ];
 					var geometry = new THREE.BufferGeometry();
 
-					geometry.name = source.name;
-					geometry.userData = source.userData;
+					geometry.name = baseGeometry.name;
+					geometry.userData = baseGeometry.userData;
 
-					for ( var key in source.attributes ) geometry.addAttribute( key, source.attributes[ key ] );
-					for ( var key in source.morphAttributes ) geometry.morphAttributes[ key ] = source.morphAttributes[ key ];
+					for ( var key in baseGeometry.attributes ) geometry.addAttribute( key, baseGeometry.attributes[ key ] );
+					for ( var key in baseGeometry.morphAttributes ) geometry.morphAttributes[ key ] = baseGeometry.morphAttributes[ key ];
 
 					var indices = [];
 					var offset = 0;
@@ -2187,11 +2255,7 @@ THREE.GLTFLoader = ( function () {
 
 						var accessor = accessors[ originalPrimitives[ i ].indices ];
 
-						for ( var j = 0, jl = accessor.count; j < jl; j ++ ) {
-
-							indices.push( accessor.array[ j ] );
-
-						}
+						for ( var j = 0, jl = accessor.count; j < jl; j ++ ) indices.push( accessor.array[ j ] );
 
 						geometry.addGroup( offset, accessor.count, i );
 
@@ -2201,6 +2265,8 @@ THREE.GLTFLoader = ( function () {
 
 					geometry.setIndex( indices );
 
+					cache.push( { geometry: geometry, baseGeometry: baseGeometry, primitives: originalPrimitives } );
+
 					return [ geometry ];
 
 				} else if ( geometries.length > 1 && THREE.BufferGeometryUtils !== undefined ) {
@@ -2214,9 +2280,23 @@ THREE.GLTFLoader = ( function () {
 
 					}
 
-					var geometry = THREE.BufferGeometryUtils.mergeBufferGeometries( geometries, true );
+					// See if we've already created this combined geometry
+					var cache = parser.multiplePrimitivesCache;
+					var cached = getCachedCombinedGeometry( cache, geometries );
+
+					if ( cached ) {
 
-					if ( geometry !== null ) return [ geometry ];
+						if ( cached.geometry !== null ) return [ cached.geometry ];
+
+					} else {
+
+						var geometry = THREE.BufferGeometryUtils.mergeBufferGeometries( geometries, true );
+
+						cache.push( { geometry: geometry, baseGeometries: geometries } );
+
+						if ( geometry !== null ) return [ geometry ];
+
+					}
 
 				}