未验证 提交 b4ac5c5e 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #15431 from nextbitlabs/feature/#15321-improve-gtlf-loader-cache

#15321: use object as cache for GTLF loader instead of array
......@@ -1362,8 +1362,10 @@ THREE.GLTFLoader = ( function () {
var accessor = target.POSITION !== undefined
? parser.getDependency( 'accessor', target.POSITION )
.then( function ( accessor ) {
// Cloning not to pollute original accessor below
return cloneBufferAttribute( accessor );
} )
: geometry.attributes.position;
......@@ -1377,7 +1379,9 @@ THREE.GLTFLoader = ( function () {
var accessor = target.NORMAL !== undefined
? parser.getDependency( 'accessor', target.NORMAL )
.then( function ( accessor ) {
return cloneBufferAttribute( accessor );
} )
: geometry.attributes.normal;
......@@ -1515,30 +1519,6 @@ THREE.GLTFLoader = ( function () {
}
}
function isPrimitiveEqual( a, b ) {
var dracoExtA = a.extensions ? a.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] : undefined;
var dracoExtB = b.extensions ? b.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] : undefined;
if ( dracoExtA && dracoExtB ) {
if ( dracoExtA.bufferView !== dracoExtB.bufferView ) return false;
return isObjectEqual( dracoExtA.attributes, dracoExtB.attributes );
}
if ( a.indices !== b.indices ) {
return false;
}
return isObjectEqual( a.attributes, b.attributes );
}
function isObjectEqual( a, b ) {
if ( Object.keys( a ).length !== Object.keys( b ).length ) return false;
......@@ -1553,59 +1533,68 @@ THREE.GLTFLoader = ( function () {
}
function isArrayEqual( a, b ) {
function createPrimitiveKey( primitiveDef ) {
if ( a.length !== b.length ) return false;
var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
var geometryKey;
for ( var i = 0, il = a.length; i < il; i ++ ) {
if ( dracoExtension ) {
geometryKey = 'draco:' + dracoExtension.bufferView
+ ':' + dracoExtension.indices
+ ':' + createAttributesKey( dracoExtension.attributes );
if ( a[ i ] !== b[ i ] ) return false;
} else {
geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;
}
return true;
return geometryKey;
}
function getCachedGeometry( cache, newPrimitive ) {
function createAttributesKey( attributes ) {
var attributesKey = '';
for ( var i = 0, il = cache.length; i < il; i ++ ) {
var keys = Object.keys( attributes ).sort();
var cached = cache[ i ];
for ( var i = 0, il = keys.length; i < il; i ++ ) {
if ( isPrimitiveEqual( cached.primitive, newPrimitive ) ) return cached.promise;
attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';
}
return null;
return attributesKey;
}
function getCachedCombinedGeometry( cache, geometries ) {
function createArrayKeyBufferGeometry( a ) {
for ( var i = 0, il = cache.length; i < il; i ++ ) {
var arrayKey = '';
var cached = cache[ i ];
for ( var i = 0, il = a.length; i < il; i ++ ) {
if ( isArrayEqual( geometries, cached.baseGeometries ) ) return cached.geometry;
arrayKey += ':' + a[ i ].uuid;
}
return null;
return arrayKey;
}
function getCachedMultiPassGeometry( cache, geometry, primitives ) {
function createMultiPassGeometryKey( geometry, primitives ) {
for ( var i = 0, il = cache.length; i < il; i ++ ) {
var key = geometry.uuid;
var cached = cache[ i ];
for ( var i = 0, il = primitives.length; i < il; i ++ ) {
if ( geometry === cached.baseGeometry && isArrayEqual( primitives, cached.primitives ) ) return cached.geometry;
key += i + createPrimitiveKey( primitives[ i ] );
}
return null;
return key;
}
......@@ -1688,9 +1677,9 @@ THREE.GLTFLoader = ( function () {
this.cache = new GLTFRegistry();
// BufferGeometry caching
this.primitiveCache = [];
this.multiplePrimitivesCache = [];
this.multiPassGeometryCache = [];
this.primitiveCache = {};
this.multiplePrimitivesCache = {};
this.multiPassGeometryCache = {};
this.textureLoader = new THREE.TextureLoader( this.options.manager );
this.textureLoader.setCrossOrigin( this.options.crossOrigin );
......@@ -2534,14 +2523,15 @@ THREE.GLTFLoader = ( function () {
for ( var i = 0, il = primitives.length; i < il; i ++ ) {
var primitive = primitives[ i ];
var cacheKey = createPrimitiveKey( primitive );
// See if we've already created this geometry
var cached = getCachedGeometry( cache, primitive );
var cached = cache[ cacheKey ];
if ( cached ) {
// Use the cached geometry if it exists
pending.push( cached );
pending.push( cached.promise );
} else {
......@@ -2560,7 +2550,7 @@ THREE.GLTFLoader = ( function () {
}
// Cache this geometry
cache.push( { primitive: primitive, promise: geometryPromise } );
cache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };
pending.push( geometryPromise );
......@@ -2576,7 +2566,8 @@ THREE.GLTFLoader = ( function () {
// See if we've already created this combined geometry
var cache = parser.multiPassGeometryCache;
var cached = getCachedMultiPassGeometry( cache, baseGeometry, originalPrimitives );
var cacheKey = createMultiPassGeometryKey( baseGeometry, originalPrimitives );
var cached = cache[ cacheKey ];
if ( cached !== null ) return [ cached.geometry ];
......@@ -2617,7 +2608,7 @@ THREE.GLTFLoader = ( function () {
geometry.setIndex( indices );
cache.push( { geometry: geometry, baseGeometry: baseGeometry, primitives: originalPrimitives } );
cache[ cacheKey ] = { geometry: geometry, baseGeometry: baseGeometry, primitives: originalPrimitives };
return [ geometry ];
......@@ -2636,7 +2627,8 @@ THREE.GLTFLoader = ( function () {
// See if we've already created this combined geometry
var cache = parser.multiplePrimitivesCache;
var cached = getCachedCombinedGeometry( cache, geometries );
var cacheKey = createArrayKeyBufferGeometry( geometries );
var cached = cache[ cacheKey ];
if ( cached ) {
......@@ -2646,7 +2638,7 @@ THREE.GLTFLoader = ( function () {
var geometry = THREE.BufferGeometryUtils.mergeBufferGeometries( geometries, true );
cache.push( { geometry: geometry, baseGeometries: geometries } );
cache[ cacheKey ] = { geometry: geometry, baseGeometries: geometries };
if ( geometry !== null ) return [ geometry ];
......@@ -3335,7 +3327,7 @@ THREE.GLTFLoader = ( function () {
mesh.bind( new THREE.Skeleton( bones, boneInverses ), mesh.matrixWorld );
};
}
return node;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册