Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial google maps 3D tiles example implementation #330

Merged
merged 12 commits into from May 23, 2023

Conversation

aiden-jeffrey
Copy link
Contributor

@aiden-jeffrey aiden-jeffrey commented May 17, 2023

Example added (googleMapsExample.html) rendering the new google maps tileset.

To use this, you need to get a google api key and add it to the slot in the UI panel (I worked out how to make a free key from the links in the tiles landing page here).

This appears to successfully download a limited (which is expected) number of gltf files from the google maps tile api, however none of them render and there are no error messages for me to know where to start looking. I added a test sphere mesh to the scene just to make sure the camera etc were working correctly.

@aiden-jeffrey aiden-jeffrey changed the title WIP: Aiden/gmaps WIP: Add google maps 3D tiles example May 17, 2023
@gkjohnson
Copy link
Contributor

I'm also noticing some odd rotations of the bounding boxes relative to the tiles, here:

image

It looks like the bounding boxes that converge on the left side should align with the poles 🤔

@hybridherbst
Copy link

hybridherbst commented May 18, 2023

Just wanted to raise a bug that fileType can be "glTF" which is not handled right now as I was looking into 3D Tiles, then I found this PR and it fixes it already. Great that there's already progress here!

@gkjohnson
Copy link
Contributor

gkjohnson commented May 18, 2023

@aiden-jeffrey I've just pushed some changes that removes some of the unused fields from the example page and fixes the rotation bug mentioned above.

Here's what I would try to round the demo out and get a first pass at a more google maps-like experience:

  • Use three.js' MapControls which pans along the camera's "up" direction rather than in screen space.
  • Use the "Ellipsoid" class to derive latitude, longitude, and surface normal from the camera position position so we can adjust the plane the map controls pans on based on the position.
  • Fix the controls target to be the WGS84 ellipsoid surface so we scroll on a reasonable plane.

Longer term:

  • Use raycasting to adjust the camera / controls target height based on loaded geometry / mountains.
  • Adjust MapControls to zoom in to the cursor position.
  • When zooming out transition to an orbital camera
  • Display data copyrights

I'm not sure if three.js' MapControls will do everything we want it to here but it's worth a try. @aiden-jeffrey are you interested in giving some of this a shot?

@aiden-jeffrey
Copy link
Contributor Author

I'm not sure if three.js' MapControls will do everything we want it to here but it's worth a try. @aiden-jeffrey are you interested in giving some of this a shot?

Yes I will work on this today - I got sidetracked this morning onto something else.

@aiden-jeffrey
Copy link
Contributor Author

@gkjohnson - this is getting there - need to tidy it up considerably and rethink the frustum plane contraction, but it sort of works.

@snowzurfer
Copy link

@gkjohnson - this is getting there - need to tidy it up considerably and rethink the frustum plane contraction, but it sort of works.

@aiden-jeffrey id love to help, I've take a look at the latest commit and it looks like it would be useful to be able to zoom into the mouse position and detect the terrain.

What things are already on your radar vs ones I could help with?

@aiden-jeffrey
Copy link
Contributor Author

What things are already on your radar vs ones I could help with?

@snowzurfer - sure, feel free. This is really messy currently, I will spend some time over the weekend getting this into a review-able state. I've added some placeholder functionality similar to what you suggest - if you double click, it will move the orbit camera's target to the position on the globe, under the mouse.

You could take that and have it trigger just on mousemove. I think we probably want to move the camera position by the same amount we move the target though, as the camera behaviour might feel inconsistent otherwise.

The other thing that probably needs rethinking is the frustum correction as we zoom in. When you launch, the frustum is at 0,0,0 (the center of the planet), and as you scroll in, I do a raycast check at the extents of the screen; once I see 4 successful raycast intersections, I take the largest distance (I probably should project the intersections onto the camera direction vector) and use that as the camera.far setting. This works ok when the camera is square on with the surface, but it breaks down once you rotate, and so you end up downloading a load of unneeded tiles.

@andreasrosdal

This comment was marked as off-topic.

@snowzurfer
Copy link

@gkjohnson I'm trying to also understand why it looks like when you're at a given altitude above the earth model, it looks like unless you set loadSiblings to false, the renderer keeps on loading finer and finer tiles, even though it looks like it "shouldn't" as the ones it has already displayed would be enough at that altitude.

I wonder if this is a consequence of this specific 3D tileset being a sphere, rather than just a 3D cartesian infinite plane? I.e. was the AMMOS renderer originally developed to handle tilesets that are just on an infinite 3D cartesian plane VS on a globe, maybe?

Just a guess; in any case, would you know why that's happening? Setting loadSiblings to false seems to stop this "issue" and make the renderer stop loading finer and finer tiles when you're not moving the camera and you're above the earth.

@gkjohnson
Copy link
Contributor

gkjohnson commented May 21, 2023

I'm trying to also understand why it looks like when you're at a given altitude above the earth model, it looks like unless you set loadSiblings to false, the renderer keeps on loading finer and finer tiles, even though it looks like it "shouldn't" as the ones it has already displayed would be enough at that altitude.

You'll have to provide numbers and camera positions otherwise I can't see what you're referring to.

I.e. was the AMMOS renderer originally developed to handle tilesets that are just on an infinite 3D cartesian plane VS on a globe, maybe?

No it just treats the tiles as a series of bounding volumes and computes distances and geometric error to determine whether to load data. The one thing relevant to a globe that's not necessarily fully supported with closest distance computation and frustum culling is ellipsoid / region volumes - instead spheres and box bounds are generated to use, which are less precise. If anyone is interested in taking on improving that it would be great!

const xz = findSurface( side );

if ( y !== undefined && xz !== undefined ) {
ellipsoid.radius.set( xz, y, xz );
Copy link

@dbuck dbuck May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use the WGS constants to start from?

import { WGS84_RADIUS, WGS84_HEIGHT } from '../src/base/constants.js';
let ellipsoid = new Ellipsoid(WGS84_RADIUS, WGS84_RADIUS, WGS84_HEIGHT);

It's not perfect depending on the elevation of the area you're looking at, but should be good enough to initialize the camera controls if that was the main thing you're trying to do?

@gkjohnson
Copy link
Contributor

How do we feel about merging this so others can start making PRs into the example to get it polished? We can make an issue to track some of the action items if people want to take them on.

Comment on lines 24 to 25
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
Copy link

@mrdoob mrdoob May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two imports are unused.

// Note the DRACO compression files need to be supplied via an explicit source.
// We use unpkg here but in practice should be provided by the application.
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath( 'https://unpkg.com/three@0.123.0/examples/js/libs/draco/gltf/' );
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For anyone trying to use this with the latest three.js this should be:

dracoLoader.setDecoderPath( 'https://unpkg.com/three@0.152.0/examples/jsm/libs/draco/' );

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we should update the three.js version used for demos in the project.

<br/>
</div>
</div>
<script src="./googleMapsExample.js"></script>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For anyone trying to run this without having to deal with bundlers... 😇

<script type="importmap">
	{
	  "imports": {
		"three": "https://unpkg.com/three@0.152.0/build/three.module.js",
		"three/": "https://unpkg.com/three@0.152.0/"
	  }
	}
</script>   
<script type="module" src="./googleMapsExample.js"></script>

@aiden-jeffrey
Copy link
Contributor Author

How do we feel about merging this so others can start making PRs into the example to get it polished? We can make an issue to track some of the action items if people want to take them on.

OK. Give me a couple of hours with it.

@aiden-jeffrey aiden-jeffrey changed the title WIP: Add google maps 3D tiles example Add initial google maps 3D tiles example implementation May 23, 2023
@aiden-jeffrey aiden-jeffrey marked this pull request as ready for review May 23, 2023 10:50
@aiden-jeffrey
Copy link
Contributor Author

I ended up forking the three.js OrbitControls; the way it's written, it's hard to override / extend some of the internal functions (like the panUp|Left or rotate functions).

The big TODOs I see are:

  1. Add in the attributions detailed here: https://developers.google.com/maps/documentation/tile/create-renderer (I couldn't work out which callback to use to access the raw tile response)
  2. Adapt the GlobeOrbitCamera to use ellipsoid surface normal as the rotation axis (again, I tried and failed to do this - some TODOs / commented out code left in)
  3. The rest of the longer term goals laid out by @gkjohnson above
  4. Find a better strategy for updating the frustum plane

@aiden-jeffrey
Copy link
Contributor Author

@gkjohnson - I'm going to try and use this for my own project now. I only want to display tiles within some radius of a given lat/long, and to a given detail depth (i.e. independent of camera position). Is this use case already supported in your API?

@aiden-jeffrey
Copy link
Contributor Author

@gkjohnson - I'm going to try and use this for my own project now. I only want to display tiles within some radius of a given lat/long, and to a given detail depth (i.e. independent of camera position). Is this use case already supported in your API?

Do I have to setCamera with a dummy fixed camera?

@gkjohnson
Copy link
Contributor

Thanks @aiden-jeffrey! The camera still needs a bit of work but it's good to have a starting point - hopefully we can remove the need to create a completely custom control scheme. Can you fix the lint issues and we can get this fixed?

I only want to display tiles within some radius of a given lat/long, and to a given detail depth (i.e. independent of camera position)

You can't limit which tiles will be loaded to a specific region. But you can limit the where the camera looks and can move to.

@gkjohnson gkjohnson merged commit 5e20756 into NASA-AMMOS:master May 23, 2023
3 checks passed
@gkjohnson
Copy link
Contributor

I've made a new issue for those who want to help refine and polish the demo page further in #331. Feel free to chime in and claim a feature or subset of one it would be great!

@gkjohnson gkjohnson added this to the v0.3.19 milestone May 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants