CesiumGS / 3d-tiles-validator

Validator for 3D Tiles :vertical_traffic_light:
https://cesium.com
Apache License 2.0
428 stars 156 forks source link

Tiles not validated with implicit tiling #259

Closed bertt closed 1 year ago

bertt commented 1 year ago

Hi, I noticed that when using implicit tiling in tileset.json the (b3dm) tiles are not validated (only the tileset.json is validated).

javagl commented 1 year ago

It should be validated. Just recently, I took the SparseImplicitQuadree spec/sample data and manipulated one of the B3DM files to become invalid, and it did show up as an error, e.g. like this

Validating tileset Data/SparseImplicitQuadtreeWithError/tileset.json
Validation result:
{
  "date": "2023-01-10T16:36:27.083Z",
  "numErrors": 1,
  "numWarnings": 0,
  "numInfos": 0,
  "issues": [
    {
      "type": "CONTENT_VALIDATION_ERROR",
      "path": "content/content_5__9_28.glb",
      "message": "content/content_5__9_28.glb caused validation errors",
      "severity": "ERROR",
      "causes": [
        {
          "type": "CONTENT_VALIDATION_ERROR",
          "path": "content/content_5__9_28.glb",
          "message": "Content content/content_5__9_28.glb caused validation errors",
          "severity": "ERROR",
          "causes": [
            {
              "type": "CONTENT_VALIDATION_ERROR",
              "message": "Declared length (1232) does not match GLB length (1216).",
              "severity": "ERROR"
            }
          ]
        }
      ]
    }
  ]
}

However, the validation of implicit tilesets in general is not totally trivial. Sometimes it's hard to be sure which error or inconsistency should prevent which further validation step - specifically, which error in an (implicit) tile should prevent further traversal.

Are there any other issues in the tileset or implicit tiles that might force the traversal to stop (i.e. to not reach the point where the actual content data is validated)?

Otherwise: Could you share an example where the validation of the content data is skipped inexplicably?

bertt commented 1 year ago

Hi see https://github.com/bertt/3dtiles_validator_testing, in folder 'implicit_tiling_testing' there are two 2 tilesets, one with implicit tiling and one without.

I run the validation tests with $ npx ts-node src\main.ts --tilesetsDirectory ${directory}

The b3dm is identical in both cases. One option is there is something wrong with the subtree file?

For a complete validation report in both cases see https://github.com/bertt/3dtiles_validator_testing/blob/main/README.md

javagl commented 1 year ago

Thanks for providing that detailed information!

From a first, quick glance, the error

      "path": "/root/implicitTiling/availableLevels",
      "message": "The 'availableLevels' property is required",
      "severity": "ERROR"

is most likely the culprit here: When the traversal does not know how many levels are available, then ... it cannot really traverse anything.

tl;dr with a potentially quick fix: I think that when adding the availableLevels in the implicitTiling definition, then it should work. I'll probably try to allocate some time to try it out, but if this does not solve it, then that's certainly an issue that has to be investigated further and fixed ASAP.


If this was the reason, then that's one of the examples that I referred to: When the "root" is invalid in any way, then every attempt to traverse it could potentially cause seemingly inexplicable other errors. These cases should still not cause crashes. In the worst case, they should show up as an INTERNAL_ERROR. But the when there's the choice between 1. just letting it run, and capture "crashes" as an unspecific INTERNAL_ERROR, or 2. say what exactly was wrong (even if that prevents a further traversal), I'd rather lean towards option 2. There's probably not much value in a message like "Something was wrong when accessing some implicit tile, but I don't know what it is".

There's certainly a trade-off between these approaches. The current implementation tries to validate as much as possible, and when there is an error in one part, it still tries to validate everything that is unaffected by this error. But the question of which parts can really be validated independently is nearly impossible to answer. And there may be cases where the current implementation skips a part of the validation that might still be doable, even when there is a certain error.

(However, in this particular case, I think that skipping the traversal makes sense, when the validator does not know how many levels are available for the traversal...)


An aside: The fact that CesiumJS can still display that data set may seem surprising. One level deeper: I noticed quite a while ago that CesiumJS does not use the ImplicitTileset.availableLevels property at all, and found that surprising as well. But it apparently manages to derive that information from the input data, most likely with a few assumptions about the input data being valid in a particular way.

bertt commented 1 year ago

ah yes, you are correct, when adding availableLevels to ImplicitTiling the b3dm is validated. Still a bit confusing CesiumJS does not use availableLevels , but the validator is.

With this knowledge I think I can create valid tilesets again, thanks!

bertt commented 1 year ago

update: looks like CesiumJS uses (wrongly?) the subtreeLevels as availableLevels... I shall investigate some more.

javagl commented 1 year ago

I've also been browsing over the CesiumJS code right now. I'm curious how accessing this could be avoided. If it generally took availableLevel=subtreeLevels, then I'd suspect rendering issues when there are multiple subtree layers. (But I have to stop looking at that right now due to time constraints)