three
Version:
JavaScript 3D library
109 lines (61 loc) • 2.22 kB
JavaScript
import { unzipSync } from '../../libs/fflate.module.js';
const _textDecoder = new TextDecoder();
function normalizePath( path ) {
return path
.split( '\\' ).join( '/' )
.replace( /^\.?\//, '' )
.replace( /^\/+/, '' );
}
function isZipBuffer( buffer ) {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer );
return bytes.length >= 4 && bytes[ 0 ] === 0x50 && bytes[ 1 ] === 0x4b;
}
function readMtlxArchive( buffer ) {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer );
const archive = unzipSync( bytes );
const fileMap = new Map();
let mtlxPath = null;
for ( const path in archive ) {
const normalizedPath = normalizePath( path );
fileMap.set( normalizedPath, archive[ path ] );
if ( normalizedPath.toLowerCase().endsWith( '.mtlx' ) ) {
if ( mtlxPath !== null ) {
throw new Error( 'THREE.MaterialXLoader: Invalid .mtlx.zip package. Exactly one .mtlx file is required.' );
}
mtlxPath = normalizedPath;
}
}
if ( mtlxPath === null ) {
throw new Error( 'THREE.MaterialXLoader: Invalid .mtlx.zip package. Missing .mtlx file.' );
}
const text = _textDecoder.decode( fileMap.get( mtlxPath ) );
return { text, mtlxPath, files: fileMap };
}
function createArchiveResolver( files ) {
const objectUrlCache = new Map();
const getFile = ( uri ) => {
const normalized = normalizePath( decodeURI( uri ) );
if ( files.has( normalized ) ) return files.get( normalized );
for ( const [ path, bytes ] of files ) {
if ( path.endsWith( normalized ) ) return bytes;
}
return null;
};
const resolve = ( uri ) => {
if ( objectUrlCache.has( uri ) ) return objectUrlCache.get( uri );
const bytes = getFile( uri );
if ( ! bytes ) return null;
const blob = new Blob( [ bytes ], { type: 'application/octet-stream' } );
const objectUrl = URL.createObjectURL( blob );
objectUrlCache.set( uri, objectUrl );
return objectUrl;
};
const dispose = () => {
for ( const objectUrl of objectUrlCache.values() ) {
URL.revokeObjectURL( objectUrl );
}
objectUrlCache.clear();
};
return { resolve, dispose };
}
export { isZipBuffer, readMtlxArchive, createArchiveResolver };