-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Allow external tilesets in multiple contents #12440
Conversation
Thank you for the pull request, @javagl! ✅ We can confirm we have a CLA on file for you. |
Yes, given the depth of possible implications, I think that it could be worthwhile to review the approach itself, with scrutiny, by someone who might come up with ideas of what might go wrong in areas where I couldn't zoom to the "bottom". Updating the specs could then be simple: There are four failing specs right now. The ones that expected the error to be thrown could be changed to just not expect the error to be thrown. One talks about color - that could be a fluke. The one at https://github.com/CesiumGS/cesium/actions/runs/12836753145/job/35799051528?pr=12440#step:6:43 warrants another look. It is about refinement, which might be a side-effect of the changes here (although not immediately obvious). |
The failing test was setting Specifically, this had the effect that this call to So this "mocking" relied on the very intricate implementation of |
The spec that just said Now, the remaining failing ones are 🤞 only the ones where the expectation has to be changed from 'expecting an error' to 'expecting no error'. Futher specs should be considered - like one that checks that this external tileset actually is traversed. But I'd address that when the general approach is confirmed. |
Bump @lilleyse, would you have time to take a pass on this? |
@ggetz yes, should have a chance this week. |
The specs update here had still been pending. Although it might not make its way into the next release, I wanted to wrap this up, in doubt so that it may be merged shortly after the release and undergo some sort of additional "implicit testing" before the next one. The specs update consisted of these two steps: The spec The spec This spec uses the tileset that was added in the issue. It renders the following (debug canvas): and checks that 4 tiles are selected and visited (the root of the main tileset, and the three roots of the external tilesets). |
…ts-in-multiple-contents
Should Otherwise, the approach makes sense. I'm less worried about the case where there's a mix of renderable content and external tilesets. It's harder to reason about but also less likely to occur in practice (I think). |
I think that this should make sense, and I considered it at one point. The reasons why I did not implement this initially:
The latter refers to the fact that it generates some promises, waits for them, and eventually has an array of
For now, I took the second approach: There now is a One caveat: There might be cases where an inner content is cancelled, failed, or its loading is interrupted, and depending on where exactly that can happen, it's hard to say whether this counter reflects the truth. If you think that the more invasive, wide-ranging, but somehow "safer" approach of keeping track of an (I also added a spec for this case, based on the existing one, by just wrapping the red cube into another tileset) |
I prefer the second approach (the one you took). Just update |
…ts-in-multiple-contents
Done. |
Addresses #11960
Description
It removes the check that previously did throw a
RuntimeError
with the messagewhen trying to load a tileset where an external tileset was found in the (multiple)
contents
array.Detailed description
The relevant part of the "trace" that leads to this point is drafted here:
Cesium3DTileset.requestContent
for a certain tileCesium3DTile.requestContent
. When the tile contained thecontents
array, this delegates toCesium3DTile.requestMultipleContents
Multiple3DTileContent
on which it callsrequestInnerContents
. This callsrequestInnerContent
for each content, then callscreateInnerContents
which waits for the requests, and then callscreateInnerContent
for each response.Multiple3DTileContent.createInnerContent
did throw the error when it found that the content type wasEXTERNAL_TILESET
.The place that originally threw up can in fact handle the creation of external tileset content. By just commenting out the check, the issue was fixed, and it "worked": It just used the
Cesium3DTileContentFactory
to create the content., which then was just aTileset3DTileContent
.Caveats....
For single-content external tilesets, an external tileset caused the
tile.hasTilesetContent = true;
to be set. And thishasTilesetContent
is checked in various places.In most places, it seems to be used in the meaning that there are some children to traverse. For example, when
contentExpired
turnstrue
, it causesdestroySubtree
to be called. This should be fine.In
getPriorityReverseScreenSpaceError
, it is taken into account in a non-obvious way. I don't see a reasonable way to understand the implications of this flag at this point, but hope that having it beingtrue
there is fine as well.The
Cesium3DTile#hasRenderableContent
may be the most critical one. It was implemented asA somewhat shallow way of putting it is: With multiple contents, the tile may have renderable content even though it has a tileset content!
So I tried to examine that more thoroughly. And the
hasRenderableContent
is checked in various places:true
fortile.contentAvailable
to ever betrue
true
fortile.hasUnloadedRenderableContent
to betrue
. ThehasUnloadedRenderableContent
is checked in various places. It has effects on loading, often in the context of expiration.true
fortile.unloadContent
to do anything(!)applyDebugSettings
The effect of
hasRenderableContent
(and its dependent,hasUnloadedRenderableContent
) are scattered and not obvious. They usually appear in private (aka undocumented) functions. I had to stop "zooming" into this at some point.Trying to deal with the caveats...
The change here revolves around two assumptions:
hasTilesetContent
also has to be set totrue
when the external tileset is one of multiple contents.hasRenderableContent
must usually betrue
, except for the case of 1. empty content, 2. single external, 3. single implicitSo made
hasRenderableContent
an explicit variable (not just a getter that returns the&&
-result of three others). This has to be set totrue
orfalse
, consistent with its previous behavior and the assumptions.Previously,
hasRenderableContent
depended onhasEmptyContent
,hasTilesetContent
, andhasImplicitContent
. What makes this more difficult are the comments inhasTilesetContent
andhasImplicitContent
that sayThis is <code>false</code> until the tile's (implicit) content is loaded.
meaning that the return value of
hasRenderableContent
would change through the loading process. What's even more quirky: When nothing is loaded yet, thenhasRenderableContent
will returntrue
by default. Ouch.So what is done here:
hasRenderableContent
is a variable that starts astrue
except for empty contentfalse
when encountering a single content that is an external tileset or implicit contentIssue number and link
#11960
Testing plan
I tried out the test case that was posted in the issue, and other tilesets that involve external tilesets. For (somewhat helpless) testing, I inserted a brutal
this._cache.trim();
inCesium3DTileset.postPassesUpdate
, to basically "force" the unloading/reloading in each frame, and then played with moving the tileset out of the viewport and back in again, to ensure that it is properly reloaded each time.Beyond that, the difficulty of really testing this is why I added so many "Details" above.
In terms of "specs": There are currently two distinct specs:
Theoretically, only the second one should keep throwing.
But in practice, nobody is ever going to use
3DTILES_multiple_contents
, any more, and if someone uses it for external tilesets (i.e. not compliant to the spec), and this happens to work in CesiumJS, that could be OK.(Otherwise, we'd have to carry along the information of whether something was created from
3DTILES_multiple_contents
or 3D Tiles 1.1, just to throw an "unnecessary" error at the right place ...)The specs are not updated yet. I have no idea why the tests are currently passing.
I'll have to investigate that. Hey. Passing tests being wrong. That's new 🙂Update: It looks like they are failing now. That's good.
Author checklist
CONTRIBUTORS.md
CHANGES.md
with a short summary of my change