Skip to content

Add 3DTILES_time_dynamic extension#817

Draft
lilleyse wants to merge 1 commit intomainfrom
3DTILES_time_dynamic
Draft

Add 3DTILES_time_dynamic extension#817
lilleyse wants to merge 1 commit intomainfrom
3DTILES_time_dynamic

Conversation

@lilleyse
Copy link
Collaborator

@lilleyse lilleyse commented Jun 30, 2025

This extension adds support for time-dynamic 3D Tiles through two new content metadata semantics:

Semantic Type Description
CONTENT_TIMESTAMP_START Type: STRING The start time (inclusive) as ISO 8601 string.
CONTENT_TIMESTAMP_STOP Type: STRING The stop time (exclusive) as ISO 8601 string.

Together CONTENT_TIMESTAMP_START and CONTENT_TIMESTAMP_STOP form a time interval during which the content should appear.

This is one of three extension for supporting time-dynamic 3D Tiles: #102 (comment)

To do:

  • Make github links relative paths
  • Link to CesiumJS implementation

Copy link
Collaborator

@weegeekps weegeekps left a comment

Choose a reason for hiding this comment

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

This looks good, but you may want to add to your todo list a comprehensive sample in the sample repo that includes both time dynamic tiles and level of detail.

Copy link
Contributor

@javagl javagl left a comment

Choose a reason for hiding this comment

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

This was "bumped" by another comment, and I saw that I had two pending nitpicks here. Beyond that, I posted some thoughts at #102 (comment)

"timestampStop": "2024-11-03T00:00:00Z"
}
}, {
"uri": "content/day_1.glb",
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be day_2, probably

"region": [-1.318, 0.697, -1.319, 0.698, 0, 20]
},
"refine": "ADD",
"geometricError": 5000,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be smaller than that of the root

@bjornblissing
Copy link
Contributor

Should there be a requirement that child tiles must have their time range within the time range of its parent?
(Similar to how a child's bounding volume must be within is parents bounding volume).

@javagl
Copy link
Contributor

javagl commented Sep 18, 2025

Similar to how a child's bounding volume must be within is parents bounding volume

This is not a requirement in 3D Tiles. The requirement is that the content of each child must be contained in the bounding volume of the parent. The bounding volume of the child does not have to be fully contained in the bounding volume of the parent.

But ... a ~"requirement like this" could certainly make sense. I could imagine this being referred to as temporal coherence, similar to the spatial coherence of 3D Tiles.

There have been some internal discussions, and some thoughts have been added at #102 (comment). (I might be that there will not be "ranges" of times, but this is not yet decided upon - even if there are no "ranges", then there could still be a "coherence constraint" that requires child tiles to have a set of "keys" that is a subset of the parent keys).

@bjornblissing
Copy link
Contributor

I am also not sure about the naming. Linking tile content to specific date/time ranges doesn't seem very dynamic to me.

My counter proposal would rather be something like 3DTILES_temporal_content, since the intention seems to be to specify temporal validity/visibility periods for tile content.

@bjornblissing
Copy link
Contributor

Instead of using the metadata tag inside the tile content node the extension notation should be used:

{
  "asset": {
    "version": "1.1"
  },
  "schema": "schema.json",
  "geometricError": 1000,
  "root": {
    "boundingVolume": {
      "region": [-1.318, 0.697, -1.319, 0.698, 0, 20]
    },
    "refine": "ADD",
    "geometricError": 0,
    "contents": [{
        "uri": "content/phase_1.glb",
        "extensions": {
          "3DTILES_temporal_content": {
            "name": "Construction Phase 1",
            "validFrom": "2020-01-01T00:00:00Z",
            "validTo": "2021-06-30T23:59:59Z"
          }
        }
      }, {
        "uri": "content/phase_2.glb",
        "extensions": {
          "3DTILES_temporal_content": {
            "name": "Construction Phase 2",
            "validFrom": "2021-07-01T00:00:00Z",
            "validTo": "2023-12-31T23:59:59Z"
          }
        }
      }
    ]
  },
  "extensionsUsed": ["3DTILES_temporal_content"],
  "extensionsRequired": ["3DTILES_temporal_content"]
}

@bjornblissing
Copy link
Contributor

There have been some internal discussions, and some thoughts have been added at #102 (comment). (I might be that there will not be "ranges" of times, but this is not yet decided upon - even if there are no "ranges", then there could still be a "coherence constraint" that requires child tiles to have a set of "keys" that is a subset of the parent keys).

Yes, this is not as clear-cut as the spatial coherence requirement.

Should open ranges be allowed? I.e. only specifying a start date/time or only an end date/time?

Should ranges inside a ´contents` node be allowed to overlap? If so, should there be a rendering priority order when multiple contents are "valid" at the same time?

@javagl
Copy link
Contributor

javagl commented Sep 19, 2025

Instead of using the metadata tag inside the tile content node the extension notation should be used:

This is pretty similar to what I posted in the linked comment (at least regarding the basic idea, of not shoehorning the "multiple contents" extension into this use-case, but using real extension objects instead)

Should open ranges be allowed? I.e. only specifying a start date/time or only an end date/time?

Should ranges inside a ´contents` node be allowed to overlap?

These are exactly the questions that I raised in the linked comment(s) as well, for example

  • What if there are contents that have no timeStampStart and no timeStampEnd?
    • Could be disallowed by the spec (?)
      ...
  • What if there is no time stamp range that contains the current time?
    • (No content will be shown?)
  • What if the time ranges overlap, and there are multiple ranges that contain the current time?
    • (All contents that contain the time will be shown?)

I know, these comments are long and cover a broad range of aspects, so they are not well structured for transporting a mental model, but rather tracking the process of (me) trying to build a mental model. Despite that issue having been opened in 2016, apparently, nobody ever asked these questions, but they have to be answered (pretty soon now).

Specifically:

If so, should there be a rendering priority order when multiple contents are "valid" at the same time?

The current idea is to allow multiple contents to be "active" at the same time (or disregarding time: 'unter certain conditions'). Whether zero, one, or many contents are displayed at a certain time is solely in the responsibility of the data creator, and there are realistic scenarios where each of them should be possible in runtime engines.

@bjornblissing
Copy link
Contributor

This is pretty similar to what I posted in the linked comment

Great minds think alike. 🙂

Another thought that you touched upon in the other thread is the time point format being specified as ISO 8601.
While ISO 8601 works well in our modern age. ISO 8601 dates are not suitable for describing historical dates or periods:

  • Gregorian bias – ISO 8601 assumes the Gregorian calendar, extended backwards uniformly. This erases the real historical complexity of calendar systems (Julian, local/regional calendars, calendar reforms). (https://www.timeanddate.com/date/february-30.html)
  • Inability to capture uncertainty – Historical dates are often approximate (“circa 1200”, “late 5th century”), ranges, or fuzzy periods. ISO 8601 only encodes precise instants, durations, and intervals.
  • Ambiguity of eras – ISO 8601 encodes BCE only through signed years and lacks explicit “eras.” This is unsuitable not only for historical BCE/CE notation but also for geological eras (e.g., Jurassic, Holocene), which are not tied to calendar years at all and require named stratigraphic periods.

@javagl
Copy link
Contributor

javagl commented Sep 19, 2025

I think that ISO8601 is used so ubiquitously and is so well supported that it's justifiable to use it as a baseline. It's the "least ambiguous and most agreed-upon" way of representing a time stamp as a string. (And it has to boil down to a string. Related: https://community.cesium.com/t/date-time-in-ext-structural-metadata/29293 )

For points 1. and 3. of your list, I wouldn't have a clear idea about how to solve that technically. It might already be alleviated to some extent, by the approach that is described in the linked comment, which plays down the role of "time" a little bit, suggesting that it might eventually become "one dimension (among others)". The example there was that there might be keys like revision0, revision1, revision2. Similarly, non-ISO8601-representable times yould just be keys yesterday, today, tomorrow. (That's a first shot, of course - the exact way about how ~"key sets" and ~"dimensions" are supposed to be specified is still being fleshed out).

The second point, uncertainty, is a veeery broad one. It can refer to almost everything - even geometric properties, like ~"we don't know exactly how high this building is", or "We know that our LIDAR scanner measurements are in +/- 5cm or the real distance". Trying to cleany pour that into a data model raises all sorts of questions, about units, processing steps, accumulation (from multiple sources) of uncertainty. And I don't know how exactly it should be taken into account for the (time) dynamic 3D Tiles. In some way, using a range already can capture a form of "uncertainty" (even though the latest drafts do no longer make that "range" explicit). Did you have a specific form or approach in mind here?

@bjornblissing
Copy link
Contributor

I think that ISO8601 is used so ubiquitously and is so well supported that it's justifiable to use it as a baseline.

I agree, and ISO8601 will probably be the proper reference to use for most applications and should be the default.
But supporting other more fuzzy time ranges could be supported by having user defined time references. Maybe just the addition of supporting named time periods which are listed with a ordinal numbering to support switching between timepoints.

For example, letting an archeological visualization define a ordinal list of labels such as ["Stone-age", "Bronze-age", "Iron-age"] and then let the content be valid for one or more ordinal numbers.

@javagl
Copy link
Contributor

javagl commented Sep 21, 2025

I think that this is already somewhat anticipated in the thoughts from #102 (comment) , as part of one aspect that I consider to be important: There has to be "top-level" (tileset JSON-level) information about the valid time stamps/ranges.

The example there drafted that as a top-level / tileset JSON level(!) extension object like this

{
  "3DTILES_dynamic": {
    "dimensions": [
      {
        "name": "exampleTimeStamp",
        "keySet": [ "2024-11-01T00:00:00Z", "2024-11-02T00:00:00Z", "2024-11-03T00:00:00Z" ]
      }, 
   ...

This defines the "dimensions", like that exampleTimeStamp, and the set of valid keys. So that keySet could also be
["Stone-age", "Bronze-age", "Iron-age"]


There's still be open question of whether there should be type information about these dimensions. In its original form, the type information for that exampleTimeStamp could be some
type: "isoString"
info, while for your example, it would be only
type: "string"
But whether or not that type information is necessary (and where and how it will be included) is not decided yet.

@chris-little
Copy link

Dear Cesium temporal enthusiasts,
Before you venture too far into the temporal quagmire (I am not sure ISO8601 is well supported, though supported - yes) can I point you to https://docs.ogc.org/as/23-049/23-049.html to help clarify your thinking?
I come from a community where we side-stepped a lot of the issues by having a temporal CRS like T+00, T+12, T+24, T+36, T+48 for weather forecasts. The datum/epoch may be in ISO8601 (or IETF RFC 3339 subset), but the other times, and UoM, are more like spatial CRSs. HTH.

@javagl
Copy link
Contributor

javagl commented Sep 25, 2025

Scio me nihil scire. That said: While certainly interesting (for nerds like me), I don't see how this is applicable (or should just be taken into account) for temporal tiles.

The quote from Table 1 captures it nicely: People are often far too casually talking about date and time, and think that they know what they are talking about. But there are different levels on which one can astonish them. I'm occasionally asking people "Which years are leap years?", and people are surprised that "Every fourth year" is wrong. I ask them "What was on 10th of October 1582 in Rome?", and people are surprised that this date simply does not exist. There are more subtle gotchas that became famous in some ways. Time zones, leap seconds, daylight saving, or the disagreement of whether "01-02-2023" is in January (US) or February (rest of the world) are some other interesting trivia. There's the urban legend that some database administrator spent hours of debugging, only to find out that one customer was actually born on 01-01-1970.

So formalizing any of that, in any way (and particularly in a way so that it works for machines and algorithms) is a whole different story.

Some obvious, important questions are often just looked over when it comes to code and implementations. I followed some of the developments in specific areas. For example, the famously broken Date class in Java that was later replaced by JSR-310. I used this in a library that dealt with "Time Series processing and visualization". And in that context, I also went down the formal road quite a bit, in terms of data types: You can have a time series, with time stamps, and that time stamp may be "whatever" - but when you want to do any form of processing, it immediately raises the question about whether it's possible to even (sensibly) represent the difference between two time stamps. Whatever the (mathematical) domain, or "data type" of the time stamps is: The domain for differences is a different one, and this is where it gets messy pretty quickly.


Some of the questions that are brought up in that document have already been raised here. For example: If the temporal tiles are supposed to be defined by a time range, then the behavior - c.f. the "Allen Operators" - has to be strictly defined for all cases. The question of whether the time scale should be discrete or continuous was also brought up (with the claim that defining the ranges is just one form of discretization).

But after all: The goal of this extension is not to answer the question "Quid ergo tempus?". The goal is to offer users an option to say something like
tileset.displayTheTilesFor(someTimeStamp);
And this has to be accessible (we cannot point users to that OGC document when instructing them how to call that function). And (importantly): All this has to be serialized into JSON, i.e. into strings. And the only really agreed-upon way of "serializing time stamps into strings" is ISO8601. It's not perfect, but ... the "least bad" solution that we could agree on until now.


Unrelated: There seems to be a broken image reference in point 2 of https://docs.ogc.org/as/23-049/23-049.html#_d9780ef6-0feb-1ed8-34a3-8878ac7fc5b0

@weegeekps
Copy link
Collaborator

Relying solely on ISO8601 will significantly hamper the flexibility of this extension to fully handle all representations of time, especially when there is significant uncertainty involved. It seems to me to be a much better approach to take a more abstract approach here for each of the time slices given that this extension essentially only represents discrete slices of time.

As a thought experiment, something like this could be done:

  • Add an extension body for 3DTILES_time_dynamic to the tileset.json that contains an enum named type that can contain values iso8601, offset, or custom.
    • iso8601 is a timestamp.
    • offset is just a pure T+n offset. All we store is an integer for n.
    • custom is for uncertain times. (i.e. Bronze Age, Paleolithic Era, etc.)
  • Times are defined in an array of "time objects" named times. The time objects can have a start time and an end time. Each of these time objects corresponds with a zero-indexed time index.
  • Instead of relying on the start and end timestamps in the metadata for selection, use the time index instead. The timestamps can still be included in the metadata for display, but it's up to the developer to decide if this is the label they want or if they need another one for their application.
  • Retrieving time slices can still function in a similar manner to tileset.displayTheTilesFor(someTimestamp), but the underlying logic is different depending on the method used.
    • For iso8601 and offset, comparisons are performed to find the correct time index.
    • For custom, an explicit value must be provided to find the correct time index. If it doesn't exist, it errors out and selects no new tiles.

I don't think this is a perfect solution, but it seems to get us closer to an abstraction that may handle almost every case.

@javagl
Copy link
Contributor

javagl commented Sep 25, 2025

I'd like to point to the comments starting at #102 (comment) which are already covering some of this. (Yes, they are long, but I think that it can be useful to pose questions (sometimes devil's advocate), lay out the options and their pros and cons, and explain the thought process behind some (final) JSON structure).

Specifically, the currently last comment already contains a draft of something that defines the structure of the dimensions (where time is just one possible dimension):

      {
        "name": "exampleTimeStamp",

        // Define a type (number, date, string...?)
        "type": "isoDate",

        "keySet": {
          // Explicitly list values
          "values": [ "2024-11-01T00:00:00Z", "2024-11-02T00:00:00Z", "2024-11-03T00:00:00Z" ],

          // OR define a range (min/max inclusive/exclusive? Yeah...)
          "range": {
            "min": "2024-11-01T00:00:00Z",
            "max": "2024-11-03T00:00:00Z",
          }
        } 
      }

The exact structure and level of detail remain to be decided, but the general idea is: There is something that can be a plain string, or (defined to be) an "ISO date". And this 'thing' is essentially used for "indexing" into an array of contents.

@GatorScott
Copy link

I know they're complicated, but the OGC and related ISO standards cover temporal reference systems which could be used as guidance.

@javagl
Copy link
Contributor

javagl commented Nov 4, 2025

@GatorScott If you have specific ideas about where and how these standards and reference systems come into play here, it might be worth adding your thoughts in #102 . (Note that "time" will probably no longer play a special role in this extension, but the details are in the process of being sorted out, and additional perspectives can be helpful for doing exactly that)

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.

6 participants