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 a property to specify the CRS of the tileset #504

Closed
lilleyse opened this issue Oct 13, 2021 · 24 comments
Closed

Add a property to specify the CRS of the tileset #504

lilleyse opened this issue Oct 13, 2021 · 24 comments

Comments

@lilleyse
Copy link
Contributor

A long running source of confusion is that 3D Tiles and glTF have different coordinate systems. 3D Tiles uses a generic right-handed cartesian coordinate system where the z-axis can mean different things depending on whether the tileset is in a global or local coordinate system, while glTF is strictly y-up.

This breaks down quickly once you're working with geospatial data that doesn't have an up-axis. This tile here is glTF but it doesn't really have an up axis like a regular game asset would.

Sandcastle

3D Tiles 1.0 is very strict about honoring the glTF up-axis. The spec requires that a y-up to z-up transform is applied on glTF assets, which means that if you have data that is inherently EPSG:4978 you need to include the reverse transform z-up to y-up in the glTF, either as a node or baked into the positions themselves. The transforms section goes into the full details. This behavior has led to much confusion over the years and doesn't feel right.

Now with 3D Tiles Next we have a chance to change this behavior. I think the glTF up axis should be ignored since it doesn't make sense in a geospatial context. Instead the glTF should be considered to be in the tileset's coordinate system. This way no additional transforms need to be applied at runtime or in the glTF.

In order to do this without breaking changes with 1.0 we can define this behavior in 3DTILES_content_gltf. Basically if you have a b3dm you follow the previous rules, but if you have a glTF/glb you follow the new rules (less rules). I would expect the new behavior to be the default in 3D Tiles 2.0.

CC @ptrgags @sanjeetsuhag @donmccurdy @javagl @IanLilleyT

@donmccurdy
Copy link
Contributor

donmccurdy commented Oct 13, 2021

I'm catching up on context so this will probably be more questions than help, but:

Instead the glTF should be considered to be in the tileset's coordinate system.

Would this mean glTF vertex attributes are storing (potentially) WGS84 lat/lng coordinates? Or just take a different Up/Forward convention?

The spec requires that a y-up to z-up transform is applied on glTF assets, which means that if you have data that is inherently EPSG:4978 you need to include the reverse transform z-up to y-up in the glTF...

Plain glTF vertex data that is "inherently EPSG:4978" isn't something I'd want to encourage tools to produce, or at least not without an extension or XMP packet indicating the difference — we wouldn't want to export a photogrammetry capture from Blender in WGS84 given glTF specification being units = meters. Understandably the conversion from e.g. "big photogrammetry GLB" to "3D tileset with optimized 3D tiles" may require a coordinate system conversion somewhere, like in Cesium Ion, is that where the vertex data in other coordinate systems comes in?

Basically if you have a b3dm you follow the previous rules, but if you have a glTF/glb you follow the new rules (less rules)

How would you see this going as a user workflow? In the current state of things you (ideally?) can be confident that the source glTF file is Y=Up, and that conversion to B3DM will put the data into some other known coordinate system. With the change, how might a user bring their photogrammetry GLB into 3D Tiles?

@lilleyse
Copy link
Contributor Author

Just to clear up something, EPSG:4978 is the global cartesian coordinate system (pictured above) not lat/long/height (EPSG:4979). Latitude/longitude/height only shows up in the spec for defining region bounding volumes but that doesn't impact data storage, so vertex attributes would still be cartesian and meters.

The main point is that a lot of geospatial data doesn't even have the concept of an up axis or forward axis because it's captured or processed as EPSG:4978 and lives in this global context.

But if you have data in a local coordinate system, like a glTF outputted from photogrammetry software that spans a small-enough geographic area and is y-up, the user workflow shouldn't change, but the glTF to 3D Tiles converter would create glTF tiles that are now z-up in the local coordinate system... so admittedly that breaks the confidence that the tiled glTF is y-up but the user doesn't have to do anything different with their source glTF which can stay y-up.

But I think the more common case is that a user wants to convert their glTF to 3D Tiles and geolocate the data, in which case the glTF tiles would be EPSG:4978 and we would run into the same problems as before and it's just easier to say "the glTF uses the same coordinate system as the tileset" than try to impose up axis conversions that don't really make sense in the global context.

@donmccurdy
Copy link
Contributor

donmccurdy commented Oct 14, 2021

I see, thanks for clarifying on EPSG:4978 vs EPSG:4979!

If I've understood EPSG:4978 correctly and the coordinate system looks like this, then taking a more concrete example — suppose I have a tileset containing my company's 5,000 wind turbines, which are physically identical, and located around the globe. Would we need 5,000 GLBs to represent this, each having slightly different orientations given "the glTF uses the same coordinate system as the tileset"? Or have I misunderstood, and +Z is instead "up" relative to the WGS84 ellipsoid?

EDIT: Presumably 1 tile = 1 turbine is not a good assumption anyway, so this example isn't really problematic from a data duplication perspective, but it does at least help clarify the differences in my head. :)

I'm a little nervous about phrases like "glTF tiles", and potentially generating lots of GLB files with no (self-contained) indication that they're diverging from the glTF specification's coordinate system. But it's a fair point that up axis conventions don't fully make sense in the global context, and the ecosystem concern is totally solvable with a bit of metadata in the file, a modified file extension (.gltile?), or perhaps other options.

@lilleyse
Copy link
Contributor Author

The wind turbine example is interesting because it highlights the difference between working with geotypical data and geospecific data - geotypical being an authored model, geospecific being a photogrammetry capture of a specific wind turbine; most of my thinking has been about the latter. You definitely wouldn't want to have 5000 versions of the GLB. That was what Instanced 3D Model set ought to solve and what the future vector format is also planning to solve by allowing you to instantiate models wherever there are point features - where each point denotes an x, y, z position and orientation. In that case I think it would be acceptable for the glTF to by y-up since the glTF wouldn't be part of the 3D Tiles payload - the payload would just consist of marker points in a vector tile.

Geospecific models are definitely a bit of an edge case for glTF since glTF was conceived around game assets rather than chunks of the globe. The format is essentially a perfect fit aside from the up-axis specification so if we need to indicate that these files are special I would prefer the bit of metadata route rather than a new file extension or glTF extension. I'm not sure what that would look like though...

@donmccurdy
Copy link
Contributor

Possibly something like one of these:

XMP:

{
  "asset": {
    "version": "2.0",
    "generator": "Cesium Ion v123"
  },
  "extensionsUsed": ["KHR_xmp_json_ld"],
  "extensions": {
    "KHR_xmp_json_ld": {
      "packets": [
        {
          "@context": {"cesium": "https://cesium.com/json-ld/1.0/"},
          "cesium:crs": "EPSG:4978"
        }
      ]
    }
  },
  "scenes": [
    {
      "nodes": [0],
      "extensions": {"KHR_xmp_json_ld": {"packet": 0}}
    }
  ],
  // ...
}

Vendor extension:

{
  "asset": {
    "version": "2.0",
    "generator": "Cesium Ion v123"
  },
  "extensionsUsed": ["CESIUM_scene_crs"],
  "scenes": [
    {
      "nodes": [0],
      "extensions": {"CESIUM_scene_crs": {"crs": "EPSG:4978"}}
    }
  ],
  // ...
}

I don't think it's particularly important that the extension or metadata be standardized as EXT_ or anything, as long as there's something there to indicate the glTF asset was prepared for a specific context.

@lilleyse
Copy link
Contributor Author

We discussed a bit offline, the vendor extension seems like a good way forward here. The crs option opens up the possibility of adding other coordinate reference systems in the future, but limiting it to EPSG:4978 to start is wise since we are only really concerned with geocentric cartesian coordinate systems.

@donmccurdy
Copy link
Contributor

Opened CesiumGS/glTF#39, adding CESIUM_scene_crs.

@jailln
Copy link

jailln commented Oct 26, 2021

Hi,
Since 3D Tiles is an OGC community standard and is implemented in other viewers than Cesium (itowns, deckgl, etc.), shouldn't we remove any references to cesium in the extensions metadata (or replace them by 3dtiles) instead ?

In addition, I think allowing other crs than EPSG:4978 would allow more flexibility in 3D Tiles usage.

@donmccurdy
Copy link
Contributor

The 3DTILES_ prefix is (so far...) not a requested or reserved prefix within the glTF ecosystem — note that this extension would be embedded in a glTF asset, not 3D Tiles. Perhaps a prefix like EXT_ (multi-vendor) or OGC_ would also be appropriate, I'm not sure.

In addition, I think allowing other crs than EPSG:4978 would allow more flexibility in 3D Tiles usage.

The intention is to allow glTF content to match the tileset containing it, and not to impose new expectations on clients to have to transform content from an arbitrary source CRS. Since the tileset could indeed have another CRS, perhaps it's better to (a) put a more generic identifier in the glTF asset like {"CESIUM_scene_crs": {"inherit": true}}, or (b) allow any CRS with the restriction that the content must end up in the CRS of the tileset after tile.transform is applied.

@jailln
Copy link

jailln commented Oct 27, 2021

Thanks for the precision, I thought the Vendor extension was for 3D Tiles (the syntax is similar to 3D Tiles extensions).

Regarding the prefix, would it be possible to add 3DTILES_ to the gltf ecosystem ? Otherwise I think OGC_ would be a good alternative.

Regarding the CRS, 3D Tiles tilesets may indeed be in a certain CRS but if I'm not mistaken there is no currently no property in the 3D Tiles spec to declare it (I will open an issue on the subject).

My point was that we should remove all references to cesium from the properties names of the extension. Based on your proposal, and assuming that we take 3DTILES_ as a prefix (may be replaced by `` or EXT_), I propose:

XMP:

{
  "asset": {
    "version": "2.0",
    "generator": "Cesium Ion v123"
  },
  "extensionsUsed": ["KHR_xmp_json_ld"],
  "extensions": {
    "KHR_xmp_json_ld": {
      "packets": [
        {
          "@context": {"3dtiles": "https://www.ogc.org/standards/3DTiles"},
          "3dtiles:crs": "EPSG:4978"
        }
      ]
    }
  },
  "scenes": [
    {
      "nodes": [0],
      "extensions": {"KHR_xmp_json_ld": {"packet": 0}}
    }
  ],
  // ...
}

Vendor extension:

{
  "asset": {
    "version": "2.0",
    "generator": "Cesium Ion v123"
  },
  "extensionsUsed": ["3DTILES_scene_crs"],
  "scenes": [
    {
      "nodes": [0],
      "extensions": {"3DTILES_scene_crs": {"crs": "EPSG:4978"}}
    }
  ],
  // ...
}

What do you think ?

@lilleyse
Copy link
Contributor Author

Regarding the CRS, 3D Tiles tilesets may indeed be in a certain CRS but if I'm not mistaken there is no currently no property in the 3D Tiles spec to declare it (I will open an issue on the subject).

Yes this is a good point that we had discussed a bit offline. There should be a way for a tileset to declare its CRS and if that property/extension exists then glTF contents should also have an extension that declares a CRS and it must match the tileset's CRS.

@donmccurdy
Copy link
Contributor

Regarding the prefix, would it be possible to add 3DTILES_ to the gltf ecosystem?

This sounds totally reasonable to me. My only hesitation is that I'm not sure whether using the same prefix for 3D Tiles extensions, and for glTF extensions related to 3D Tiles, is a good symmetry or just confusing. 😅

@jailln
Copy link

jailln commented Oct 28, 2021

Mmmh that's a good point :) I would keep the symmetry but no strong opinion on this

@javagl
Copy link
Contributor

javagl commented Oct 29, 2021

I think this may be related to an ancient issue: #286

@lilleyse lilleyse changed the title Fixing the 3D Tiles and glTF coordinate system mismatch Add a property to specify the CRS of the tileset Nov 15, 2021
@lilleyse
Copy link
Contributor Author

Draft of what this might look like for 3D Tiles

{
  "asset": {
    "version": "1.0"
  },
  "extensions": {
    "3DTILES_coordinate_reference_system": {
      "crs": "EPSG:4978"
    }
  }
}

CRS would be either [EPSG:4978 or local] where EPSG:4978 is the geocentric coordinate system based on the WGS84 ellipsoid and local is a local right-handed Z-up cartesian coordinate system (described here).

This extension would redefine the transformation behavior in 3D Tiles, which is much easier to do if we ignore b3dm, i3dm, pnts, cmpt and omit the glTF y-up to z-up conversion.

Essentially it is a simple scene graph where T0, T1, etc are tile transforms and N0, N1, etc are glTF node transforms. After transforms are applied a vertex is expected to be in the tileset's coordinate system.

image

@jailln
Copy link

jailln commented Nov 18, 2021

Nice thanks :)
I propose that we allow any EPSG code for the crs attribute though (instead than limiting it to EPSG:4978). What's your opinion on this ?

@lilleyse
Copy link
Contributor Author

I do see the benefit of bringing 3D Tiles spatial subdivision to other coordinate reference systems, but I don't think it would fit with 3D Tiles goal of being runtime efficient. Clients would need a projection library and access to grid shift files in order to transform positions for the GPU. Plus there's just a nice simplicity that 3D Tiles only supports cartesian coordinate systems.

@donmccurdy
Copy link
Contributor

Perhaps a distinction worth making between "the extension allows >1 CRS" and "clients must implement >1 CRS". I would certainly not expect most clients to implement support for more than a couple EPSG codes. Whether this means others should be prohibited at the spec level, I'm not sure.

If we do think it's preferable to allow only EPSG:4978, perhaps we rename the extension from 3DTILES_coordinate_reference_system to 3DTILES_epsg_4978 or similar? Then at least there is a cleaner path to allowing more in the future than 3DTILES_coordinate_reference_system_v2,3,4,....

@lilleyse
Copy link
Contributor Author

For comparison I3S supports two global CRS - EPSG:4326 and EPSG:4490 - and any number of local CRS

I3S Coordinate Reference Sytstems

All I3S profiles support writing 3D content in two modes: global and local. In global mode, only the geographic CRS WGS84, as identified by its EPSG code 4326, and GCS China Geodetic Coordinate System 2000, as identified by its EPSG code 4490, are supported for both index and vertex positions. It is represented using longitude, latitude and elevation. In local mode, all other geodetic CRS, including projected coordinate systems, are allowed.

@lilleyse
Copy link
Contributor Author

Going along with the idea of 3DTILES_epsg_4978, sometimes it's important to know the realization and epoch of the WGS84 model. These could be included in the schema as optional properties.

EPSG Code Realization Year published Epoch Notes Accuracy compared to ITRF
4326 WGS84 1987 Identical to NAD83 1-2 meters
4326 WGS84 (G730) 1994 1994.0 Based on ITRF91 10 cm/component rms
4326 WGS84 (G873) 1997 1997.0 Based on ITRF94 5 cm/component rms
4326 WGS84 (G1150) 2002 2001.0 Based on ITRF2000 1cm/component rms
4326 WGS84 (G1674) 2012 2005.0 Based on ITRF2008 <1cm/component rms
4326 WGS84 (G1762) 2013 2005.0 Based on ITRF2008 <1cm/component rms

@jailln
Copy link

jailln commented Nov 19, 2021

I agree with @donmccurdy that allowing it in the extension doesn't mean that every client should support this extension neither that it should support it fully. Allowing more than one CRS however gives more flexibility to tilesets creators and clients.

In addition, 3D Tiles in other CRS than 4978 are already created / displayed but their CRS is not explicitly stored in the tileset. For instance:

  • py3dtiles support creating 3D Tiles in many CRS (with --srs_in and --srs_out options)
  • the 3D Tiles ecosystem for mapbox/maplibre (mapbox-3dtiles and pg2b3dm work in EPSG:3857 since it was the only CRS supported by mapbox until very recently
  • itowns can read and display 3D tiles in many CRS
  • RhinoCity software also allows to produce 3D Tiles in many CRS
  • ...

One might ask what a 3D dataset into a 2D projected coordinate system means, and if we should provide this possibility in 3D Tiles... Nevertheless it is currently quite used and generally it just means geolocalizing the 3D objects in this 2D coordinate system for using it in clients that don't support other CRS or for combination with datasets in local projections that cannot or should not be reprojected.

@jerstlouis
Copy link

jerstlouis commented Nov 24, 2021

It might be a good idea to consider the new TileSet metadata specification, which is intended to also support 3D use cases.
Perhaps its schema could be integrated here, and we could extend it to handle 3D data types?

@donmccurdy
Copy link
Contributor

^This got me thinking about the extension vs. metadata distinction, and I wrote up some thoughts in #600. In the end I didn't come up with a preference on the suggestion though. 😅

@lilleyse
Copy link
Contributor Author

lilleyse commented Mar 4, 2022

#633 added the ability to provide the geocentric CRS and coordinate epoch.

Some of the other discussion in this issue related to up-axis conventions has not been addressed yet, but #587 seems to be a promising direction.

@lilleyse lilleyse closed this as completed Mar 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants