浏览代码

Merge pull request #154 from NASA-AMMOS/fix-cmpt

Fix I3DM files not correctly loading external assets
Garrett Johnson 4 年之前
父节点
当前提交
e8668004df

+ 1 - 0
src/base/CMPTLoaderBase.d.ts

@@ -15,6 +15,7 @@ export interface CMPTBaseResult {
 
 export class CMPTLoaderBase {
 
+	workingPath : string;
 	load( url : String ) : Promise< CMPTBaseResult >;
 	parse( buffer : ArrayBuffer ) : CMPTBaseResult;
 

+ 14 - 1
src/base/CMPTLoaderBase.js

@@ -6,6 +6,7 @@ export class CMPTLoaderBase {
 	constructor() {
 
 		this.fetchOptions = {};
+		this.workingPath = '';
 
 	}
 
@@ -22,7 +23,19 @@ export class CMPTLoaderBase {
 				return res.arrayBuffer();
 
 			} )
-			.then( buffer => this.parse( buffer ) );
+			.then( buffer => {
+
+				if ( this.workingPath === '' ) {
+
+					const splits = url.split( /\\\//g );
+					splits.pop();
+					this.workingPath = splits.join( '/' );
+
+				}
+
+				return this.parse( buffer );
+
+			} );
 
 	}
 

+ 3 - 0
src/base/I3DMLoaderBase.d.ts

@@ -11,6 +11,9 @@ export interface I3DMBaseResult {
 
 export class I3DMLoaderBase {
 
+	workingPath : string;
+
+	resolveExternalURL( url : string ) : string;
 	load( url : string ) : Promise< I3DMBaseResult >;
 	parse( buffer : ArrayBuffer ) : Promise< I3DMBaseResult >;
 

+ 40 - 3
src/base/I3DMLoaderBase.js

@@ -9,6 +9,21 @@ export class I3DMLoaderBase {
 	constructor() {
 
 		this.fetchOptions = {};
+		this.workingPath = '';
+
+	}
+
+	resolveExternalURL( url ) {
+
+		if ( /^[^\\/]/ ) {
+
+			return this.workingPath + '/' + url;
+
+		} else {
+
+			return url;
+
+		}
 
 	}
 
@@ -25,7 +40,19 @@ export class I3DMLoaderBase {
 				return res.arrayBuffer();
 
 			} )
-			.then( buffer => this.parse( buffer ) );
+			.then( buffer => {
+
+				if ( this.workingPath === '' ) {
+
+					const splits = url.split( /\\\//g );
+					splits.pop();
+					this.workingPath = splits.join( '/' );
+
+				}
+
+				return this.parse( buffer );
+
+			} );
 
 	}
 
@@ -108,9 +135,19 @@ export class I3DMLoaderBase {
 
 		} else {
 
-			const externalUri = arrayToString( bodyBytes );
+			const externalUri = this.resolveExternalURL( arrayToString( bodyBytes ) );
 			promise = fetch( externalUri, this.fetchOptions )
-				.then( res => res.buffer )
+				.then( res => {
+
+					if ( ! res.ok ) {
+
+						throw new Error( `I3DMLoaderBase : Failed to load file "${ externalUri }" with status ${ res.status } : ${ res.statusText }` );
+
+					}
+
+					return res.arrayBuffer();
+
+				} )
 				.then( buffer => {
 
 					glbBytes = new Uint8Array( buffer );

+ 5 - 1
src/three/CMPTLoader.js

@@ -56,7 +56,11 @@ export class CMPTLoader extends CMPTLoaderBase {
 				case 'i3dm': {
 
 					const slicedBuffer = buffer.slice();
-					const promise = new I3DMLoader( manager )
+					const loader = new I3DMLoader( manager );
+					loader.workingPath = this.workingPath;
+					loader.fetchOptions = this.fetchOptions;
+
+					const promise = loader
 						.parse( slicedBuffer.buffer )
 						.then( res => {
 

+ 6 - 0
src/three/I3DMLoader.js

@@ -15,6 +15,12 @@ export class I3DMLoader extends I3DMLoaderBase {
 
 	}
 
+	resolveExternalURL( url ) {
+
+		return this.manager.resolveURL( super.resolveExternalURL( url ) );
+
+	}
+
 	parse( buffer ) {
 
 		return super

+ 39 - 5
src/three/TilesRenderer.js

@@ -82,7 +82,21 @@ export class TilesRenderer extends TilesRendererBase {
 		this.onLoadModel = null;
 		this.onDisposeModel = null;
 
-		this.manager = new LoadingManager();
+		const manager = new LoadingManager();
+		manager.setURLModifier( url => {
+
+			if ( this.preprocessURL ) {
+
+				return this.preprocessURL( url );
+
+			} else {
+
+				return url;
+
+			}
+
+		} );
+		this.manager = manager;
 
 	}
 
@@ -495,6 +509,12 @@ export class TilesRenderer extends TilesRendererBase {
 		tile._loadIndex = tile._loadIndex || 0;
 		tile._loadIndex ++;
 
+		const uri = tile.content.uri;
+		const uriSplits = uri.split( /[\\\/]/g );
+		uriSplits.pop();
+		const workingPath = uriSplits.join( '/' );
+		const fetchOptions = this.fetchOptions;
+
 		const manager = this.manager;
 		const loadIndex = tile._loadIndex;
 		let promise = null;
@@ -511,18 +531,32 @@ export class TilesRenderer extends TilesRendererBase {
 				promise = Promise.resolve( new PNTSLoader( manager ).parse( buffer ).scene );
 				break;
 
-			case 'i3dm':
-				promise = new I3DMLoader( manager )
+			case 'i3dm': {
+
+				const loader = new I3DMLoader( manager );
+				loader.workingPath = workingPath;
+				loader.fetchOptions = fetchOptions;
+				promise = loader
 					.parse( buffer )
 					.then( res => res.scene );
+
 				break;
 
-			case 'cmpt':
-				promise = new CMPTLoader( manager )
+			}
+
+			case 'cmpt': {
+
+				const loader = new CMPTLoader( manager );
+				loader.workingPath = workingPath;
+				loader.fetchOptions = fetchOptions;
+				promise = loader
 					.parse( buffer )
 					.then( res => res.scene	);
+
 				break;
 
+			}
+
 			default:
 				console.warn( `TilesRenderer: Content type "${ extension }" not supported.` );
 				promise = Promise.resolve( null );