MaterialXArchive.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { unzipSync } from '../../libs/fflate.module.js';
  2. const _textDecoder = new TextDecoder();
  3. function normalizePath( path ) {
  4. return path
  5. .split( '\\' ).join( '/' )
  6. .replace( /^\.?\//, '' )
  7. .replace( /^\/+/, '' );
  8. }
  9. function isZipBuffer( buffer ) {
  10. const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer );
  11. return bytes.length >= 4 && bytes[ 0 ] === 0x50 && bytes[ 1 ] === 0x4b;
  12. }
  13. function readMtlxArchive( buffer ) {
  14. const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer );
  15. const archive = unzipSync( bytes );
  16. const fileMap = new Map();
  17. let mtlxPath = null;
  18. for ( const path in archive ) {
  19. const normalizedPath = normalizePath( path );
  20. fileMap.set( normalizedPath, archive[ path ] );
  21. if ( normalizedPath.toLowerCase().endsWith( '.mtlx' ) ) {
  22. if ( mtlxPath !== null ) {
  23. throw new Error( 'THREE.MaterialXLoader: Invalid .mtlx.zip package. Exactly one .mtlx file is required.' );
  24. }
  25. mtlxPath = normalizedPath;
  26. }
  27. }
  28. if ( mtlxPath === null ) {
  29. throw new Error( 'THREE.MaterialXLoader: Invalid .mtlx.zip package. Missing .mtlx file.' );
  30. }
  31. const text = _textDecoder.decode( fileMap.get( mtlxPath ) );
  32. return { text, mtlxPath, files: fileMap };
  33. }
  34. function createArchiveResolver( files ) {
  35. const objectUrlCache = new Map();
  36. const getFile = ( uri ) => {
  37. const normalized = normalizePath( decodeURI( uri ) );
  38. if ( files.has( normalized ) ) return files.get( normalized );
  39. for ( const [ path, bytes ] of files ) {
  40. if ( path.endsWith( normalized ) ) return bytes;
  41. }
  42. return null;
  43. };
  44. const resolve = ( uri ) => {
  45. if ( objectUrlCache.has( uri ) ) return objectUrlCache.get( uri );
  46. const bytes = getFile( uri );
  47. if ( ! bytes ) return null;
  48. const blob = new Blob( [ bytes ], { type: 'application/octet-stream' } );
  49. const objectUrl = URL.createObjectURL( blob );
  50. objectUrlCache.set( uri, objectUrl );
  51. return objectUrl;
  52. };
  53. const dispose = () => {
  54. for ( const objectUrl of objectUrlCache.values() ) {
  55. URL.revokeObjectURL( objectUrl );
  56. }
  57. objectUrlCache.clear();
  58. };
  59. return { resolve, dispose };
  60. }
  61. export { isZipBuffer, readMtlxArchive, createArchiveResolver };
粤ICP备19079148号