Pārlūkot izejas kodu

Merge pull request #41 from NASA-AMMOS/multiple-camera-support

Add variable resolution per camera
Garrett Johnson 5 gadi atpakaļ
vecāks
revīzija
e218fc54bd
3 mainītis faili ar 127 papildinājumiem un 40 dzēšanām
  1. 32 5
      README.md
  2. 5 5
      example/index.js
  3. 90 30
      src/three/TilesRenderer.js

+ 32 - 5
README.md

@@ -23,8 +23,8 @@ import { TilesRenderer } from '3d-tiles-renderer';
 // ... initialize three scene ...
 
 const tilesRenderer = new TilesRenderer( './path/to/tileset.json' );
-tilesRenderer.camera = camera;
-tilesRenderer.setResolutionFromRenderer( renderer );
+tilesRenderer.setCamera( camera );
+tilesRenderer.setResolutionFromRenderer( camera, renderer );
 scene.add( tilesRenderer.group );
 
 renderLoop();
@@ -33,6 +33,9 @@ function renderLoop() {
 
 	requestAnimationFrame( renderLoop );
 
+	// The camera matrix is expected to be up to date
+	// before calling tilesRenderer.update
+	camera.updateMatrixWorld();
 	tilesRenderer.update();
 	renderer.render( camera, scene );
 
@@ -60,7 +63,7 @@ errorTarget = 6 : Number
 ### .errorThreshold
 
 ```js
-errorThreshold = 6 : Number
+errorThreshold = Infinity : Number
 ```
 
 ### .maxDepth
@@ -99,7 +102,6 @@ parseQueue = new PriorityQueue : PriorityQueue
 
 _NOTE: This cannot be modified once [update](#update) is called for the first time._
 
-
 ### .constructor
 
 ```js
@@ -124,10 +126,35 @@ getBounds( box : Box3 ) : void
 raycast( raycaster : Raycaster, intersects : Array ) : void
 ```
 
+### .hasCamera
+
+```js
+hasCamera( camera : Camera ) : boolean
+```
+
+### .setCamera
+
+```js
+setCamera( camera : Camera ) : boolean
+```
+
+### .deleteCamera
+
+```js
+deleteCamera( camera : Camera ) : boolean
+```
+
+### .setResolution
+
+```js
+setResolution( camera : Camera, resolution : Vector2 ) : boolean
+setResolution( camera : Camera, x : number, y : number ) : boolean
+```
+
 ### .setResolutionFromRenderer
 
 ```js
-setResolutionFromRenderer( renderer : WebGLRenderer )
+setResolutionFromRenderer( camera : Camera, renderer : WebGLRenderer ) : boolean
 ```
 
 # LICENSE

+ 5 - 5
example/index.js

@@ -65,9 +65,6 @@ function reinstantiateTiles() {
 	}
 
 	tiles = new TilesRenderer( url );
-	tiles.camera = camera;
-	tiles.setResolutionFromRenderer( renderer );
-
 	offsetParent.add( tiles.group );
 
 }
@@ -316,10 +313,13 @@ function animate() {
 	tiles.loadSiblings = params.loadSiblings;
 	tiles.displayActiveTiles = params.displayActiveTiles;
 	tiles.maxDepth = params.maxDepth;
-	tiles.camera = params.orthographic ? orthoCamera : camera;
 	tiles.displayBoxBounds = params.displayBoxBounds;
 	tiles.colorMode = parseFloat( params.colorMode );
-	tiles.setResolutionFromRenderer( renderer );
+
+	tiles.setCamera( params.orthographic ? orthoCamera : camera );
+	tiles.setResolutionFromRenderer( orthoCamera, renderer );
+	tiles.setResolutionFromRenderer( camera, renderer );
+	tiles.deleteCamera( params.orthographic ? camera : orthoCamera );
 
 	offsetParent.rotation.set( 0, 0, 0 );
 	if ( params.up === '-Z' ) {

+ 90 - 30
src/three/TilesRenderer.js

@@ -31,25 +31,12 @@ function emptyRaycast() {}
 
 export class TilesRenderer extends TilesRendererBase {
 
-	get camera() {
-
-		return this.cameras[ 0 ];
-
-	}
-
-	set camera( camera ) {
-
-		const cameras = this.cameras;
-		cameras.length = 1;
-		cameras[ 0 ] = camera;
-
-	}
-
 	constructor( ...args ) {
 
 		super( ...args );
 		this.group = new TilesGroup( this );
 		this.cameras = [];
+		this.cameraMap = new Map();
 		this.resolution = new Vector2();
 		this.cameraInfo = [];
 		this.activeTiles = new Set();
@@ -110,11 +97,78 @@ export class TilesRenderer extends TilesRendererBase {
 
 	}
 
-	setResolutionFromRenderer( renderer ) {
+	hasCamera( camera ) {
+
+		return this.cameraMap.has( camera );
+
+	}
+
+	setCamera( camera ) {
+
+		const cameras = this.cameras;
+		const cameraMap = this.cameraMap;
+		if ( ! cameraMap.has( camera ) ) {
+
+			cameraMap.set( camera, new Vector2() );
+			cameras.push( camera );
+			return true;
+
+		}
+		return false;
+
+	}
+
+	setResolution( camera, xOrVec, y ) {
 
-		const resolution = this.resolution;
+		const cameraMap = this.cameraMap;
+		if ( ! cameraMap.has( camera ) ) {
+
+			return false;
+
+		}
+
+		if ( xOrVec instanceof Vector2 ) {
+
+			cameraMap.get( camera ).copy( xOrVec );
+
+		} else {
+
+			cameraMap.get( camera ).set( xOrVec, y );
+
+		}
+		return true;
+
+	}
+
+	setResolutionFromRenderer( camera, renderer ) {
+
+		const cameraMap = this.cameraMap;
+		if ( ! cameraMap.has( camera ) ) {
+
+			return false;
+
+		}
+
+		const resolution = cameraMap.get( camera );
 		renderer.getSize( resolution );
 		resolution.multiplyScalar( renderer.getPixelRatio() );
+		return true;
+
+	}
+
+	deleteCamera( camera ) {
+
+		const cameras = this.cameras;
+		const cameraMap = this.cameraMap;
+		if ( cameraMap.has( camera ) ) {
+
+			const index = cameras.indexOf( camera );
+			cameras.splice( index, 1 );
+			cameraMap.delete( camera );
+			return true;
+
+		}
+		return false;
 
 	}
 
@@ -123,19 +177,12 @@ export class TilesRenderer extends TilesRendererBase {
 
 		const group = this.group;
 		const cameras = this.cameras;
+		const cameraMap = this.cameraMap;
 		const cameraInfo = this.cameraInfo;
-		const resolution = this.resolution;
 
 		if ( cameras.length === 0 ) {
 
-			console.warn( 'TilesRenderer: no cameras to use are defined. Cannot update 3d tiles.' );
-			return;
-
-		}
-
-		if ( resolution.width === 0 || resolution.height === 0 ) {
-
-			console.warn( 'TilesRenderer: resolution for error calculation is not set. Cannot updated 3d tiles.' );
+			console.warn( 'TilesRenderer: no cameras defined. Cannot update 3d tiles.' );
 			return;
 
 		}
@@ -155,11 +202,13 @@ export class TilesRenderer extends TilesRendererBase {
 				sseDenominator: - 1,
 				position: new Vector3(),
 				invScale: - 1,
+				pixelSize: 0,
 
 			} );
 
 		}
 
+		// extract scale of group container
 		tempMat2.getInverse( group.matrixWorld );
 
 		let invScale;
@@ -179,6 +228,13 @@ export class TilesRenderer extends TilesRendererBase {
 			const info = cameraInfo[ i ];
 			const frustum = info.frustum;
 			const position = info.position;
+			const resolution = cameraMap.get( camera );
+
+			if ( resolution.width === 0 || resolution.height === 0 ) {
+
+				console.warn( 'TilesRenderer: resolution for camera error calculation is not set.' );
+
+			}
 
 			if ( camera.isPerspectiveCamera ) {
 
@@ -186,6 +242,14 @@ export class TilesRenderer extends TilesRendererBase {
 
 			}
 
+			if ( camera.isOrthographicCamera ) {
+
+				const w = camera.right - camera.left;
+				const h = camera.top - camera.bottom;
+				info.pixelSize = Math.max( h / resolution.height, w / resolution.width );
+
+			}
+
 			info.invScale = invScale;
 
 			tempMat.copy( group.matrixWorld );
@@ -520,8 +584,6 @@ export class TilesRenderer extends TilesRendererBase {
 
 		// TODO: Use the content bounding volume here?
 		const boundingVolume = tile.boundingVolume;
-		const resolution = this.resolution;
-
 		if ( 'box' in boundingVolume ) {
 
 			const boundingBox = cached.box;
@@ -543,9 +605,7 @@ export class TilesRenderer extends TilesRendererBase {
 				let error;
 				if ( camera.isOrthographicCamera ) {
 
-					const w = camera.right - camera.left;
-					const h = camera.top - camera.bottom;
-					const pixelSize = Math.max( h / resolution.height, w / resolution.width );
+					const pixelSize = info.pixelSize;
 					error = tile.geometricError / ( pixelSize * invScale );
 
 				} else {