Skip to content

Commit

Permalink
Demo update (#346)
Browse files Browse the repository at this point in the history
* Small cleanup

* demo simplification

* Adjust camera position

* Adjust target height

* Remove globe controls
  • Loading branch information
gkjohnson committed Jun 6, 2023
1 parent 9e7048b commit a2b4b31
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 237 deletions.
223 changes: 36 additions & 187 deletions example/googleMapsExample.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,46 @@
import { Ellipsoid, DebugTilesRenderer as TilesRenderer } from '../src/index.js';
import { DebugTilesRenderer as TilesRenderer } from '../src/index.js';
import {
Scene,
DirectionalLight,
AmbientLight,
WebGLRenderer,
PerspectiveCamera,
CameraHelper,
Vector3,
Group,
sRGBEncoding,
Raycaster,
Vector2,
MeshPhongMaterial,
SphereGeometry,
MeshBasicMaterial,
Mesh,
Box3,
} from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import Stats from 'three/examples/jsm/libs/stats.module.js';

import { GlobeOrbitControls } from './GlobeOrbitControls.js';
import { WGS84_RADIUS, WGS84_HEIGHT } from '../src/base/constants.js';
import { EllipsoidRegionHelper } from '../src/index.js';
import { MapControls } from './src/lib/MapControls.js';
import { MapsTilesCredits } from './src/MapsTilesCredits.js';
import { GeoCoord } from './src/GeoCoord.js';
import * as GeoUtils from './src/GeoUtils.js';

const apiOrigin = 'https://tile.googleapis.com';

let camera, controls, scene, renderer, tiles, credits, cameraHelper;
let mainGroup;
let camera, controls, scene, renderer, tiles, credits;
let statsContainer, stats;

const ellipsoid = new Ellipsoid( WGS84_RADIUS, WGS84_RADIUS, WGS84_HEIGHT );
let ellipsoidHelper, ellipsoidInitialised = false;
let surfaceHelper;
const ellipsoid = GeoUtils.WGS84_ELLIPSOID;

Check warning on line 29 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (10.x)

'ellipsoid' is assigned a value but never used

Check warning on line 29 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (12.x)

'ellipsoid' is assigned a value but never used

Check warning on line 29 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (14.x)

'ellipsoid' is assigned a value but never used

const raycaster = new Raycaster();
raycaster.firstHitOnly = true;
const pointer = new Vector2();

Check warning on line 33 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (10.x)

'pointer' is assigned a value but never used

Check warning on line 33 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (12.x)

'pointer' is assigned a value but never used

Check warning on line 33 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (14.x)

'pointer' is assigned a value but never used
const deltaTarget = new Vector3();

Check warning on line 34 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (10.x)

'deltaTarget' is assigned a value but never used

Check warning on line 34 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (12.x)

'deltaTarget' is assigned a value but never used

Check warning on line 34 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (14.x)

'deltaTarget' is assigned a value but never used
const geocoord = new GeoCoord();

let prevDist = 0;

const params = {

'showGlobe': true,
'showGlobeHelper': false,
'showFrustumHelper': false,
'showSurfaceHelper': false,

'enableUpdate': true,
'enableCacheDisplay': false,
'enableRendererStats': false,

'apiKey': 'put-your-api-key-here',
'errorTarget': 6,
'errorThreshold': Infinity,
'maxDepth': Infinity,
'loadSiblings': true,
'stopAtEmptyTiles': true,
'resolutionScale': 1.0,
Expand Down Expand Up @@ -89,7 +70,7 @@ function setupTiles() {
loader.setDRACOLoader( dracoLoader );

tiles.manager.addHandler( /\.gltf$/, loader );
mainGroup.add( tiles.group );
scene.add( tiles.group );

tiles.setResolutionFromRenderer( camera, renderer );
tiles.setCamera( camera );
Expand All @@ -100,7 +81,7 @@ function reinstantiateTiles() {

if ( tiles ) {

mainGroup.remove( tiles.group );
scene.remove( tiles.group );
tiles.dispose();
tiles = null;

Expand Down Expand Up @@ -182,6 +163,8 @@ function reinstantiateTiles() {

};

tiles.parseQueue.maxJobs = 5;
tiles.downloadQueue.maxJobs = 50;
tiles.lruCache.minSize = 3000;
tiles.lruCache.maxSize = 5000;
tiles.group.rotation.x = - Math.PI / 2;
Expand Down Expand Up @@ -210,18 +193,15 @@ function init() {

document.body.appendChild( renderer.domElement );

mainGroup = new Group();
scene.add( mainGroup );

camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 160000000 );
camera.position.set( 7326000, 10279000, - 823000 );
cameraHelper = new CameraHelper( camera );
scene.add( cameraHelper );

// controls
controls = new GlobeOrbitControls( camera, ellipsoid, renderer.domElement );
controls.minDistance = 100;
controls = new MapControls( camera, renderer.domElement );
controls.minDistance = 1;
controls.maxDistance = Infinity;
controls.minPolarAngle = Math.PI / 4;
controls.target.set( 0, 0, 1 );

// lights
const dirLight = new DirectionalLight( 0xffffff );
Expand All @@ -236,29 +216,10 @@ function init() {
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );

// ellipsoid helper
ellipsoidHelper = new EllipsoidRegionHelper( ellipsoid );
ellipsoidHelper.material = new MeshPhongMaterial( { color: 0xff3311 } );
ellipsoidHelper.visible = false;
scene.add( ellipsoidHelper );

// misc helper
const geom = new SphereGeometry( 1, 32, 16 );
const mat = new MeshBasicMaterial( { color: 0x0000ff } );
surfaceHelper = new Mesh( geom, mat );
surfaceHelper.visible = false;
scene.add( surfaceHelper );

// GUI
const gui = new GUI();
gui.width = 300;

const displayOptions = gui.addFolder( 'Display' );
displayOptions.add( params, 'showGlobe' ).onChange( v => mainGroup.visible = v );
displayOptions.add( params, 'showGlobeHelper' ).onChange( v => ellipsoidHelper.visible = v );
displayOptions.add( params, 'showSurfaceHelper' ).onChange( v => surfaceHelper.visible = v );
displayOptions.open();

const mapsOptions = gui.addFolder( 'GMaps' );
mapsOptions.add( params, 'apiKey' );
mapsOptions.add( params, 'reload' );
Expand All @@ -267,9 +228,6 @@ function init() {
const tileOptions = gui.addFolder( 'Tiles Options' );
tileOptions.add( params, 'loadSiblings' );
tileOptions.add( params, 'stopAtEmptyTiles' );
tileOptions.add( params, 'errorTarget' ).min( 0 ).max( 50 );
tileOptions.add( params, 'errorThreshold' );
tileOptions.add( params, 'maxDepth' );

const debug = gui.addFolder( 'Debug Options' );
debug.add( params, 'displayBoxBounds' );
Expand Down Expand Up @@ -303,32 +261,6 @@ function init() {
stats.showPanel( 0 );
document.body.appendChild( stats.dom );

document.addEventListener( 'dblclick', event => {

if ( raycaster ) {

pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

raycaster.setFromCamera( pointer, camera );
const intersections = raycaster.intersectObject( tiles.group, true );
const numIntersections = intersections.length;
if ( numIntersections > 0 ) {

const intersection = intersections[ 0 ];

deltaTarget.subVectors( intersection.point, controls.target );
controls.target.add( deltaTarget );
// TODO: work out how to adjust the camera position so this refocussing
// happens seamlessly (i.e. on a mousemove callback)
// controls.position.add( deltaTarget );

}

}

} );

}

function onWindowResize() {
Expand All @@ -341,98 +273,38 @@ function onWindowResize() {

}

const top = { origin: new Vector3( 0, 1000000000, 0 ), dir: new Vector3( 0, - 1, 0 ) };
const side = { origin: new Vector3( 1000000000, 0, 0 ), dir: new Vector3( - 1, 0, 0 ) };
const temp = new Vector3();

function refineEllipsoid() {

const findSurface = ( query ) => {

raycaster.set( query.origin, query.dir );
const intersections = raycaster.intersectObject( tiles.group, true );
const numIntersections = intersections.length;
if ( numIntersections > 0 ) {

const intersection = intersections[ 0 ];
return intersection.point.length();

} else {

return undefined;
function updateControls() {

}

};
// TODO: add tilting of the camera - keep a frame at the surface to retain the camera orientation

const y = findSurface( top );
const xz = findSurface( side );
const raycaster = new Raycaster();
raycaster.ray.origin.copy( controls.target ).normalize().multiplyScalar( GeoUtils.WGS84_RADIUS * 1.5 );
raycaster.ray.direction.copy( raycaster.ray.origin ).normalize().multiplyScalar( - 1 );
raycaster.firstHitOnly = true;

if ( y !== undefined && xz !== undefined ) {
const hit = raycaster.intersectObject( scene, true )[ 0 ];
if ( hit ) {

ellipsoid.radius.set( xz, y, xz );
controls.target.copy( hit.point );

ellipsoid.getPositionToSurfacePoint( camera.position, temp );

controls.target.copy( temp );
} else {

ellipsoidHelper.update();
ellipsoidInitialised = true;
controls.target.normalize().multiplyScalar( GeoUtils.WGS84_RADIUS );

}
controls.panPlane.copy( controls.target ).normalize();

}

function updateFrustum( dist, raycast = false ) {

// TODO: do we want to raycast like this or just do something simple based
// on surface distance?
if ( raycast ) {

const findSurfaceDistanceScreenSpace = ( x, y ) => {
const dist = camera.position.length();
camera.position.copy( controls.target ).normalize().multiplyScalar( dist );
camera.lookAt( controls.target );
controls.update();

pointer.x = x;
pointer.y = y;

raycaster.setFromCamera( pointer, camera );
const intersections = raycaster.intersectObject( tiles.group, true );
const numIntersections = intersections.length;
if ( numIntersections > 0 ) {

const intersection = intersections[ 0 ];
return intersection.distance;

} else {

return undefined;

}

};

const casts = [];
for ( const [ x, y ] of [[ - 1, 0 ], [ 0, 1 ], [ 1, 0 ], [ 0, - 1 ]] ) {

const distance = findSurfaceDistanceScreenSpace( x, y );
if ( distance !== undefined ) {

camera.getWorldDirection( temp );
casts.push( distance );

}

}

camera.far = casts.length === 4 ? Math.max( ...casts ) : dist;

} else {

camera.far = dist * 2;

}
const box = new Box3();
tiles.getBounds( box );

camera.far = dist;
camera.near = Math.max( 1, dist - Math.max( ...box.min, ...box.max ) );
camera.updateProjectionMatrix();
prevDist = dist;

}

Expand All @@ -442,21 +314,9 @@ function animate() {

if ( ! tiles ) return;

if ( ! ellipsoidInitialised && raycaster ) {

refineEllipsoid();

}

ellipsoid.getPositionToSurfacePoint( camera.position, temp );
surfaceHelper.position.copy( temp );
const surfaceDist = temp.distanceTo( camera.position );
surfaceHelper.scale.setScalar( surfaceDist / 100 );
updateControls();

// update options
tiles.errorTarget = params.errorTarget;
tiles.errorThreshold = params.errorThreshold;
tiles.maxDepth = params.maxDepth;
tiles.loadSiblings = params.loadSiblings;
tiles.stopAtEmptyTiles = params.stopAtEmptyTiles;
tiles.displayActiveTiles = params.displayActiveTiles;
Expand All @@ -468,14 +328,6 @@ function animate() {
tiles.setResolutionFromRenderer( camera, renderer );
tiles.setCamera( camera );

if ( prevDist !== surfaceDist ) {

updateFrustum( surfaceDist );

}

mainGroup.updateMatrixWorld( true );

// update tiles
window.tiles = tiles;
if ( params.enableUpdate ) {
Expand All @@ -492,8 +344,6 @@ function animate() {

function render() {

cameraHelper.visible = false;

// render primary view
renderer.render( scene, camera );

Expand Down Expand Up @@ -525,8 +375,7 @@ function render() {
let count = 0;
geomSet.forEach( g => {

// TODO: resurrect this
count += 0;//BufferGeometryUtils.estimateBytesUsed( g );
count += BufferGeometryUtils.estimateBytesUsed( g );

Check warning on line 378 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (10.x)

'BufferGeometryUtils' is not defined

Check warning on line 378 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (12.x)

'BufferGeometryUtils' is not defined

Check warning on line 378 in example/googleMapsExample.js

View workflow job for this annotation

GitHub Actions / build (14.x)

'BufferGeometryUtils' is not defined

} );
str += `<br/>Cache: ${ ( 100 * cacheFullness ).toFixed( 2 ) }% ~${ ( count / 1000 / 1000 ).toFixed( 2 ) }mb`;
Expand Down
10 changes: 10 additions & 0 deletions example/src/GeoUtils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import { Ellipsoid } from '../../';

export const WGS84_RADIUS = 6378137;

export const WGS84_FLATTENING = 1 / 298.257223563;

export const WGS84_HEIGHT = - ( WGS84_FLATTENING * WGS84_RADIUS - WGS84_RADIUS );

export const WGS84_ELLIPSOID = new Ellipsoid( WGS84_RADIUS, WGS84_RADIUS, WGS84_HEIGHT );

export function swapToGeoFrame( target ) {

const { x, y, z } = target;
Expand Down
Loading

0 comments on commit a2b4b31

Please sign in to comment.