Browse Source

Added ion loading

Petter 4 năm trước cách đây
mục cha
commit
26ef6ae9c6
3 tập tin đã thay đổi với 174 bổ sung7 xóa
  1. 1 1
      src/base/TilesRendererBase.d.ts
  2. 104 4
      src/base/TilesRendererBase.js
  3. 69 2
      src/three/TilesRenderer.js

+ 1 - 1
src/base/TilesRendererBase.d.ts

@@ -19,7 +19,7 @@ export class TilesRendererBase {
 	parseQueue : PriorityQueue;
 	downloadQueue : PriorityQueue;
 
-	constructor( url : String );
+	constructor( url : String, ionAccessToken : String );
 	update() : void;
 	traverse(
 		beforeCb : ( ( tile : Object, parent : Object, depth : Number ) => Boolean ) | null,

+ 104 - 4
src/base/TilesRendererBase.js

@@ -8,6 +8,8 @@ import { UNLOADED, LOADING, PARSING, LOADED, FAILED } from './constants.js';
 // Function for sorting the evicted LRU items. We should evict the shallowest depth first.
 const priorityCallback = tile => 1 / ( tile.__depthFromRenderedParent + 1 );
 
+const defaultIonToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlNzMyOGZjZC1jMWUzLTQxNDctOGQxYi03YTYyZDQ1OTIxMjkiLCJpZCI6MjU5LCJpYXQiOjE2MDE1Njk1NDN9.X1a0DCM6F539g9MDSs_ldZ0gwgruxLAZiBl60JwG1ck';
+
 export class TilesRendererBase {
 
 	get rootTileSet() {
@@ -32,13 +34,18 @@ export class TilesRendererBase {
 
 	}
 
-	constructor( url ) {
+	//The url can be:
+	//A plain url to the tileset json file
+	//A Cesium Ion asset number with access token
+	//A url to the Cesium Ion json file with bearer token as the ionAccessToken. This needs to be fetched from the Ion endpoint separately
+	constructor( url, ionAccessToken = defaultIonToken ) {
 
 		// state
 		this.tileSets = {};
-		this.rootURL = url;
 		this.fetchOptions = {};
 
+		this.setupUrlTokens( url, ionAccessToken );
+
 		const lruCache = new LRUCache();
 		lruCache.unloadPriorityCallback = priorityCallback;
 
@@ -74,6 +81,73 @@ export class TilesRendererBase {
 
 	}
 
+	setupUrlTokens( url, ionToken ) {
+
+		this.ionAssetId = this.isInt( url ) ? url : null;
+		this.ionAccessToken = ionToken;
+		this.fetchOptions.headers = {};
+
+		if ( ! this.ionAssetId ) {
+
+			this.rootURL = url;
+			if ( this.isIonJsonUrl( url ) ) {
+
+				this.ionAssetId = url.split( "/" )[ 3 ];
+				this.ionJsonUrl = new URL( url );
+				this.ionVersion = this.ionJsonUrl.searchParams.get( 'v' );
+				this.fetchOptions.headers.Authorization = `Bearer ${ionToken}`;
+				this.rootURL = this.ionJsonUrl;
+
+			}
+			return;
+
+		} else {
+
+			this.ionEndpointUrl = new URL( `https://api.cesium.com/v1/assets/${this.ionAssetId}/endpoint` );
+			this.ionEndpointUrl.searchParams.append( 'access_token', ionToken );
+
+		}
+
+	}
+
+	isInt( input ) {
+
+		return ( typeof input === 'string' ) ? ! isNaN( input ) && ! isNaN( parseFloat( input, 10 ) ) && Number.isInteger( parseFloat( input, 10 ) ) : Number.isInteger( input );
+
+	}
+	isIonJsonUrl( input ) {
+
+		return input.includes( '://assets.cesium.com/' ) && input.includes( '/tileset.json' );
+
+	}
+
+	getIonAssetJson( url ) {
+
+		return fetch( url, this.fetchOptions )
+			.then( res => {
+
+				if ( res.ok ) {
+
+					return res.json();
+
+				} else {
+
+					return Promise.reject( `${res.status} : ${res.statusText}` );
+
+				}
+
+			} )
+			.then( json => {
+
+				this.ionJsonUrl = new URL( json.url );
+				this.ionVersion = this.ionJsonUrl.searchParams.get( 'v' );
+				this.fetchOptions.headers.Authorization = `Bearer ${json.accessToken}`;
+				this.rootURL = this.ionJsonUrl;
+
+			} );
+
+	}
+
 	traverse( beforecb, aftercb ) {
 
 		const tileSets = this.tileSets;
@@ -93,6 +167,18 @@ export class TilesRendererBase {
 		const rootTileSet = tileSets[ this.rootURL ];
 		if ( ! ( this.rootURL in tileSets ) ) {
 
+			if ( this.ionAssetId && ! this.ionJsonUrl ) {
+
+				if ( this.ionJsonUrl == undefined ) {
+
+					this.ionJsonUrl = false; // Can't use promise to block update loop, hence this hack
+					this.getIonAssetJson( this.ionEndpointUrl ).catch( err => console.error( `TilesRenderer: Failed to load ION endpoint "${this.ionEndpointUrl}" with error: ${err}` ) );
+
+				}
+				return;
+
+			}
+
 			this.loadRootTileSet( this.rootURL );
 			return;
 
@@ -427,7 +513,14 @@ export class TilesRendererBase {
 
 				}
 
-				return this.fetchTileSet( tile.content.uri, Object.assign( { signal }, this.fetchOptions ), tile );
+				let uri = tile.content.uri;
+				if ( this.ionAssetId ) {
+
+					uri = new URL( tile.content.uri );
+					uri.searchParams.append( 'v', this.ionVersion );
+
+				}
+				return this.fetchTileSet( uri, Object.assign( { signal }, this.fetchOptions ), tile );
 
 			} )
 				.then( json => {
@@ -457,8 +550,15 @@ export class TilesRendererBase {
 					return Promise.resolve();
 
 				}
+				let uri = tile.content.uri;
+				if ( this.ionAssetId ) {
+
+					uri = new URL( tile.content.uri );
+					uri.searchParams.append( 'v', this.ionVersion );
+
+				}
 
-				return fetch( tile.content.uri, Object.assign( { signal }, this.fetchOptions ) );
+				return fetch( uri, Object.assign( { signal }, this.fetchOptions ) );
 
 			} )
 				.then( res => {

+ 69 - 2
src/three/TilesRenderer.js

@@ -10,6 +10,7 @@ import {
 	Sphere,
 	Vector3,
 	Vector2,
+	Quaternion,
 	Math as MathUtils,
 	Frustum,
 	LoadingManager,
@@ -213,6 +214,20 @@ export class TilesRenderer extends TilesRendererBase {
 
 	}
 
+	rotationBetweenDirections( dir1, dir2 ) {
+
+		const rotation = new Quaternion();
+		const a = new Vector3().crossVectors( dir1, dir2 );
+		rotation.x = a.x;
+		rotation.y = a.y;
+		rotation.z = a.z;
+		rotation.w = 1 + dir1.clone().dot( dir2 );
+		rotation.normalize();
+
+		return rotation;
+
+	}
+
 	deleteCamera( camera ) {
 
 		const cameras = this.cameras;
@@ -247,12 +262,55 @@ export class TilesRenderer extends TilesRendererBase {
 				} );
 
 			}
+			Promise.resolve().then( () => {
+
+				if ( this.ionAssetId ) {
+
+					const transform = this.root.cached.boxTransform;
+					let position = new Vector3().setFromMatrixPosition( transform );
+					let distance = position.length();
+
+					const surfaceDir = position.normalize();
+
+					const rotation = this.rotationBetweenDirections( surfaceDir, new Vector3( 0, 1, 0 ) );
+
+					// Rotate tiles to the north pole around the Earth
+					this.group.quaternion.x = rotation.x;
+					this.group.quaternion.y = rotation.y;
+					this.group.quaternion.z = rotation.z;
+					this.group.quaternion.w = rotation.w;
+
+					//Move tiles to the center of the Earth
+					this.group.position.y = -distance;
+
+				}
+
+			} );
 
 		} );
 		return pr;
 
 	}
 
+	/** set projection matrix to frustum for legacy versions of three.js */
+	setFromProjectionMatrix( frustum, m ) {
+
+		var planes = frustum.planes;
+		var me = m.elements;
+		var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
+		var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
+		var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
+		var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
+
+		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
+		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
+		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
+		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
+		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
+		planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
+
+	}
+
 	update() {
 
 		const group = this.group;
@@ -336,7 +394,16 @@ export class TilesRenderer extends TilesRendererBase {
 			tempMat.copy( group.matrixWorld );
 			tempMat.premultiply( camera.matrixWorldInverse );
 			tempMat.premultiply( camera.projectionMatrix );
-			frustum.setFromProjectionMatrix( tempMat );
+
+			if ( typeof frustum.setFromProjectionMatrix === 'function' ) {
+
+				frustum.setFromProjectionMatrix( tempMat );
+
+			} else {
+
+				this.setFromProjectionMatrix( frustum, tempMat );
+
+			}
 
 			// get transform position in group root frame
 			position.set( 0, 0, 0 );
@@ -529,7 +596,7 @@ export class TilesRenderer extends TilesRendererBase {
 
 			}
 
-			scene.updateMatrix();
+			//scene.updateMatrix();
 			scene.matrix.premultiply( cachedTransform );
 			scene.matrix.decompose( scene.position, scene.quaternion, scene.scale );
 			scene.traverse( c => {