-
Notifications
You must be signed in to change notification settings - Fork 220
Support Google Photorealistic 3D Tiles in iTwin.js #8104
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
base: master
Are you sure you want to change the base?
Conversation
…tion. redo UI in DTA.
Thanks for your effort on this. Unrelated to this PR but I'm surprised that GeometricError is not enabled by default. Would we get a performance improvement for reality mesh as well? |
Yes, at the expense of drawing much lower-resolution tiles for the vast majority of reality models used with iTwins. |
Doing everything in We could just put all of this code in I also hesitate to throw all of this into I generally agree that the proper handling of all of this stuff should eventually also go into other source implementations that parse 3d Tiles format tiles, probably getting combined into one implementation. Should that work be in a followup PR? (This current fix is not 100% proper, it just gets GP3DT up and running). Edit: we could tag this implementation Edit: there is also a concern that altering the core logic of |
The url gets stored in the display style JSON. People will not want to store their Google 3D Tiles API key in there. The primary job of the various map and reality data "provider" objects is to handle authentication and format URLs. Shouldn't your provider implement those similarly to |
Agree. |
@markschlosseratbentley I added attributions ordered by number of occurrences. If there are copyright properties in the tiles but the tree provider is not I also started working on adding the logo as a decorator on top of the view itself. |
* A registry of RealityDataFormats identified by their unique format IDs. The registry can be accessed via [[IModelApp.realityDataFormatRegistry]]. | ||
* @alpha | ||
*/ | ||
export class RealityDataFormatRegistry { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a provider registry not format - google's tiles are in the same format as ION's, Context Capture's, etc - what differs is the provider logic (authentication, url formatting, etc). That would match with RealityDataSourceKey.provider
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't appear to expose any way for apps / other packages to register their own providers. All it seems to do is provide a place to register and later look up a google API key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My takeaways from this feedback:
- Make this be
RealityDataProviderRegistry
. - Add something like this to
RealityDataOptions
.
Is there something further you are thinking of? It does just basically wrap an auth key right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the crucial thing your registry is missing compared to MapLayerFormatRegistry
is the register
function. The "config" thing with key-value pairs IMO is not great in either registry; it'd make more sense to me for somebody to instantiate a Google3DTilesProvider
, passing it the API key and whatever else it needs, and then register that provider with your registry. When we encounter a RealityDataSourceKey
we'd look up the provider in the registry by its name and go from there. This implies that we'd also register an ION provider etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we already have RealityDataSourceProvider, is this roughly what you are envisioning? (overview, this code is not meant to include everything it would need)
export class RealityDataSourceGP3DTProvider implements RealityDataSourceProvider {
private _apiKey: string;
// api key would be passed into RealityDataSourceGP3DTImpl or something
// to use it in query params, auth header, etc.
public async createRealityDataSource(key: RealityDataSourceKey, iTwinId: GuidString | undefined): Promise<RealityDataSource | undefined> {
return RealityDataSourceGP3DTImpl.createFromKey(key, iTwinId);
}
public constructor(apiKey: string) {
this._apiKey = apiKey;
}
}
// Usage:
IModelApp.realityDataSourceProviders.register("GP3DT", new RealityDataSourceGP3DTProvider("my api key"));
If so, is clarity for how to pass in the API key the main purpose? We are already automatically registering the source like this, but the approach in this snippet would force the user to set their API key in the provider instead of elsewhere.
common/api/core-frontend.api.md
Outdated
} | ||
|
||
// @alpha | ||
export interface RealityDataKey { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For our use case, authorization will be provided via authorization header instead of api key. Could we add support for authorization header as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What kind of authorization - like a bearer token, and from what service (Bentley IMS/other)? And can this replace the API key? From what I understand, the API key is required for all the Google 3D Tiles requests, so I'm not sure how they would be accessed without the user providing one.
Maybe this is also relevant to @aruniverse's comment below. I don't think the Google Photorealistic 3D Tiles allow you to use a session token in the same way as the 2D Map Tiles. I don't see a mention of sessions in the 3D Tiles docs, and see this in the 2D Tiles:
Note: You need to use session tokens for getting 2D Tiles and Street View Tiles, but not for getting 3D Tiles.
Let me know if we're missing a puzzle piece here though, and there's another service that can provide auth/sessions in this context
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes a Bearer token in the authorization header. ref: https://developers.google.com/maps/documentation/tile/oauth_token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for clarifying. In this commit I added an option so when the provider is created, the user can pass in a function that returns an authorization token. That function is called to provide the token for the authorization header when the google tiles are requested.
Working on cleaning this up to make the API key optional (I assume it won't be required in the auth header case?) and add documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if this pr is actually ready for review, and still needs to be cleaned up to not cut corners like paul mentioned elsewhere. adding a few minor comments.
if not ready, please draft
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you would need to copy the assets this decorator needs from map-layers-fromats into core-frontend
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks, good catch. I guess this didn't show up as an error DTA because the assets were also included from map-layers-formats?
core/frontend/src/tile/Tile.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert whitespace polluting diff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
*/ | ||
export interface RealityDataProviderOptions { | ||
/** Access key for Google Photorealistic 3D Tiles in the format `{ key: "key", value: "your-gp3dt-key" }`. */ | ||
gp3dt?: RealityDataProviderKey; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we be hardcoding these in core-frontend?
also take into account those who will not be providing an access token/key, but has to interface with a service to obtain a session token. you should look at what was done for google 2d tiles
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on earlier feedback (and now your feedback as well), we are in the process of changing the way this works. New approach:
- User can create a GP3DT provider (new API class)
- User can register that provider themselves if they want to use it. (The RealityDataProviderOptions / related structures will go away).
- User will be responsible for passing in a valid key, if desired.
- An alternate using a session token / authorization header will be available - but we need to develop this.
Stay tuned for further code updates in these areas (the first three of these are done; we need to clean up old classes still).
@@ -221,6 +229,11 @@ export namespace RealityDataSource { | |||
* is invoked to produce the reality data source. | |||
* @alpha | |||
*/ | |||
|
|||
// TODO extend this for GP3DT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how applicable are these todos still?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RealityDataSourceGP3DTProvider
is still technically WIP so I reverted this to draft
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reverting to draft, @eringram. Thanks @aruniverse for the feedback - we were unsure how fast we would try to push this through until we had some more discussions.
// Only add another logo card if the tiles have copyright | ||
if (copyrightMap.size > 0) { | ||
// Order by most occurances to least | ||
// See https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
based off of this, i wonder if we need an additional / clickable data attributions
thats always visible on the vp and when clicked also shows the logo card
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference; more details about attribution requirements are discussed here: #8036 (comment)
Related to #8036.
iTwin.js can already attach tilesets from a variety of sources. Google Photorealistic 3d Tiles are in the common 3D Tiles format so in theory should work in iTwin.js. However, a few hurdles were found which this PR works around.
This PR adds a new
RealityDataSourceG3DTImpl
implementation ofRealityDataSource
which can be used to request and process Google Photorealistic 3D Tiles if you have a valid key to access them. ThisRealityDataSourceGP3DTImpl
implementation does the following:usesGeometricError
astrue
which tells iTwin.js to use the geometric errors found inside the GP3DT tileset, which is crucial for good performance.RealityDataSourceTilesetUrlImpl
did not handle properly.IModelApp.realityDataFormatRegistry
.Other changes:
GoogleMapDecorator.ts
frommap-layers-formats
to thecore-frontend
package, to use the decorator to display the logo in the bottom left of the viewport when the Google Photorealistic 3d Tiles are visiblecopyright
property when reading glTF files, which is passed intoRealityModelTileTree
and used to display attributions in accordance with Google's policyAttributions screenshot:
To use this implementation, attach a reality model to your
ViewState
in the following manner:Alternatively, you can test this implementation using
display-test-app
after setting theIMJS_GP3DT_KEY
environment variable to a proper value.Enable the GP3DT tiles by toggling off Background Map and toggling on Google Photorealistic 3D Tiles in the view settings dialog:
TODO:
G3DT
for Google Photorealistic 3d Tiles. Should we useGP3DT
instead? I have seen both forms used. We have now decided to useGP3DT
and this change has been pushed.RealityDataSourceTilesetUrlImpl
? It should not. We should keep this separate for now, IMO. We need special handling for the GP3DT case including special auth handling that theTilesetUrl
implementation does not handle.copyright
is currently in theTile
class - is this okay?gp3dtKey
ontoTileAdmin
, look into implementing something similar toMapLayerFormatRegistry.ts
.TODO (later PRs):