Implicit tiling bounding volume issue

Hi, I’m currently trying to make a tileset with some simple Quadtree implicit tiling, however I’m having a lot of issues regarding (what I’m assuming is) the bounding volumes of the sub-tiles. As shown in the GIF, it seems to be culling tiles that are clearly still within the view frustrum and does so in both levels of the implicit tiling.

The normal tiles at the highest level (that contains the “ImplicitTiling” object) does not have this problem; it seems to only be the tiles made from the implicit tiling object. Any idea what could be causing this?

CesiumBoundsError

Here’s an example of what the tiles look like:

{
  "geometricError": 100000.0,
  "asset": {
    "version": "1.0",
    "tilesetVersion": "GmbH.v1.0"
  },
  "root": {
    "boundingVolume": {
      "box": [
        3257782.0332075045, 1076229.418252235, 5358702.152881364,
        422.85164062306285, -1279.1426711131353, 0.0, 2007.8094336986542,
        663.2928651347756, -1344.2004600726068, -2.5477726673707366,
        -0.8416732202749699, -4.219056840986013
      ]
    },
    "geometricError": 200.0,
    "refine": "REPLACE",
    "content": {
      "uri": "content_0_0/content_{level}__{x}_{y}.gltf"
    },
    "implicitTiling": {
      "subdivisionScheme": "QUADTREE",
      "availableLevels": 3,
      "subtreeLevels": 1,
      "subtrees": {
        "uri": "subtrees0_0/{level}.{x}.{y}.subtree"
      }
    }
  }
}

Edited for formatting

It’s possible that there is something wrong with the culling, but it’s hard to be sure (or even investigate this) for a specific case, only based on the tileset JSON.

Could you attach tileset JSON and the associated .subtree files (as a ZIP) here?

Ideally, this ZIP could also include the .gltf files, but if the glTFs cannot be shared (because they are too large or proprietary), maybe I can create some “dummy” glTF files to substitute them for further tests.

Hello Marco, thanks for the response!

I’ve attached a file containing the tilesets, subtrees and glTFs, although without the textures.

CesiumCulling.zip (2.6 MB)

Having the actual data may be helpful if the @cesium-nativeruntime team wants to do additional tests. The data in the given form did not have textures. Here is the same data with a “dummy texture” inserted:

CesiumCulling_DummyTexture.zip (2.7 MB)

However, I did some tests in CesiumJS. And this took me way more time than I’d like to admit. But it seemed to be related enough to ongoing efforts ( CesiumJS ignores bounding volume metadata for implicit tilesets · Issue #13195 · CesiumGS/cesium · GitHub, Bounding volume generalizations by javagl · Pull Request #189 · CesiumGS/3d-tiles-tools · GitHub , Bounding volume validation by javagl · Pull Request #359 · CesiumGS/3d-tiles-validator · GitHub ) so that I can justify that. Based on these investigations, I’m reasonably sure that I found the issue:

The bounding volumes of the tileset are wrong.


The tileset uses multiple external tilesets, where each external tileset uses implicit tiling. That’s unusual, but of course, it should work. (There is certainly a lack of test coverage for this. I should create some test data for that). I spent a few hours trying to figure out what exactly is wrong. I converted the implcit tilesets into explicit ones, and combined them into one large tileset, but of course, each step could hide the original issue (or introduce new errors).

However, eventually, I noticed one thing, when loading only one of the implicit tilesets (namely, Tile_0x0.json):

Cesium Forum 45313 culling 0001

:light_bulb:

The bounding volumes in that tileset are “reversed”! One could think that in a “center-and-half-axes” representation, this should not really make a difference, but it does. In fact, I also checked it with the SparseImplicitQuadtree sample. Changing the bounding box from
[ 0.5, 0.5, 0.00625, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.00625 ] to
[ 0.5, 0.5, 0.00625, -0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.00625 ]
(i.e. just negating the x- and y-half-axes) shows the same behavior:

Cesium Forum 45313 culling 0003

The (dark blue) tiles are disappearing, even though only their “negated counterparts” on the other side went out of view!

I therefore re-computed the bounding volumes of the tilesets. But apparently, my local toolchain for doing this (some mix of JglTF and a private project called J3DTiles) doesn’t do this perfectly either. I tweaked it with some additional, manual fixes, but that was a bit tedious for 16 external tilesets.

So the following is a version of that tileset where most of the bounding volumes are fixed, but not all of them!!!

CesiumCulling_NewBvs_Manual.zip (2.7 MB)

Again: This may appear to work (much better, at least), but some bounding volumes are still wrong, and some tiles may still disappear in certain view configurations! I’ll have to update my local tools to get this right. (And so do you :slight_smile: ).

The main point is: The bounding volumes and their half-axes have to match the extent of the tile content, in the right coordinate system. For example, using the bounding volume of the ‘SparseImplicitQuadtree’ above, the bounding volumes of
[ 0.5, 0.5, 0.00625, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.00625 ] and
[ 0.5, 0.5, 0.00625, -0.5, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.00625 ]
do technically describe the same bounding volume (a unit rectangle with a tiny height). But with the wrong axis directions, the second one causes a wrong culling behavior. The computation of the child bounding volumes for the implicit tiles relies on the axis describing the extents along the “positive” axes.

(Aside: I think that some of this is not really obvious, and I’m wondering whether and how that could be made clearer in the specification…)

Thanks for the detailed answer, its much appreciated! Also, if I’m understanding you right, this is only affected by the x and y bounds and not by z? I would imagine an octotree would be affected by the z bound in a similar manner if that is the case?

That’s my understanding as well, including the (important) point that the z-axis would be relevant for an octree.

And I had another look at the Tile Coordinates section of the Implicit Tiling specification: It does contain this table:

Coordinate Positive Direction
x Along the +x axis of the bounding box
y Along the +y axis of the bounding box
z Along the +z axis of the bounding box

These short statements of “Along the …-axis of the bounding box” are the requirement that is currently violated by the given tileset. (To my understanding…)

As I said: I think that this could be pointed out more explicitly.

Even if it was pointed out: I had a hard time fixing the given tileset to meet this requirement. I can compute the bounding volume of the tile contents, but there is no easy way to derive the right orientation. The only way of computing that bounding volume with the right orientation (in hindsight, only based on the contents) would probably be to compute the bounding volume of the tiles at (0,0), (1,0), and (0,1), and derive the x- and y-axis directions from that. But that’s a bit complicated and brittle (you cannot be sure that these tiles even have content - it could be that there is no tile with content along one axis, in one “row”…)

I think that it’s far easier to fix this at the point where the implicit tileset is actually generated.