Best practices for tileset and glTF structure and embedding metadata

Firstly, thank you so much for your time and your extensive answer, @Marco13 !

You are absolutely right regarding “best practices” and maybe getting some guidance would have been more on point ; )
Nonetheless your brainstorming/input was very helpful!

A starting point for that could be the Terrain Clipping Planes sandcastle.

That looks promising at first glance. Thank you.

Regarding your questions:

What is the total data size of all the geometry? (Roughly: The sum of the sizes of all glTF assets)

To be honest, right now it is hard to tell, since we are not quite sure if and in which detail we are going to model interior and the front of the building. But most likely the first version will have no interior and most of the buildings will have no modelled front.

Also it is not clear yet how many buildings we are going to have. We have listed around 300 buildings, but in some the university has only one or a few room(s).
If I had to, I’d estimate we will have 180-220 3D buildings with 3-4 floors average but very varying number of rooms per floor. If this is already a crucial amount and thus the question needs to be answered in more detail, I could try to get more information on this.

One relevant question here is: Where is the metadata coming from, and how is the metadata currently assigned to the elements of the glTF asset?

We have a GIS database containing floor plans and metadata of the buildings/rooms. We import this as shapefiles in Blender (using BlenderGIS plugin). The plugin allows to import as separate objects while giving the opportunity to assign the data stored in the shapefile and also naming the Blender object after a data field (e.g. the id). When exporting from Blender there is an option to export the assigned metadata within the glTF.

Depending on how exactly the data is structured, it might not even be necessary to assign metadata to elements of a glTF asset. It might be sufficient to associate the metadata to the “glTF asset as a whole” (namely, to the tile that refers to that asset via its content.uri).

Considering the amount of buildings and their rooms and our workflow in which we can assign the metadata to the glTF assets with no extra work, we would like to store the metadata in the tileset using a (semi-)automatic way. So roughly speaking something along the lines of: Loop threw the glTF; get the metadata; create a tileset; store the metadata in the tileset; clean up the glTF

You could assign metadata to these elements, as 3D Tiles Metadata, directly in the tileset JSON. Possible drawbacks could be: When it is really a lot of fine-grained data, then this could cause an overhead. But if you have roughly ~“50 buildings, with 5 floors, with 10 rooms per floor, with 1 KB of metadata each”, this would still only be in the range of 2.5MB, which shouldn’t be prohibitively large.

Honestly this sounds like the perfect way for us to handle the metadata, since we could automate a lot. As mentioned above we have more buildings though. But on the bright side, we really only need to store two metadata properties per each room, floor and building. We could leverage metadata groups then we’d probably only need one property each.
This is because we only need the relevant IDs to query the detailed and up-to-date data from our backend plus information which object is on which floor.

What I take away as possible approach (at least for now):

From the perspective of our workflow and the requirements regarding which parts need to be selectable, I think that something along the lines of your suggested ‘fine-grained’ approach would be a good fit for us.

Though for a better overview we would have a separate tileset for each building referenced in a ‘master’ tileset. Expressed in pseudocode:

// 'master' tileset
root {
  schema {
    ...
  }
  ...
  children: [
    {
       content: {
         uri: "building-a-tileset.json"
       }
       metadata: {
        buildingId
       }
    }
    ...
    {
      content: {
        uri: "building-n-tileset.json"
      }
      metadata: {
        buildingId
      }
    }
  ]
}

// a building's tileset
root {
  ...
  // each floor would equal one children
  children: [
    // floor 1 
    {
      metadata: {
        floorNumber
      }
      children: [
        {
          content: {
            // We have all walls, stairs etc. combined and rooms are only defined threw a room's floor
            uri: "walls-etc.gltf"
          }
          metadata: {
            floorNumber //if not inherited 
          }
        {
          content: {
            uri: "room-a.gltf"
          }
          metadata: {
            floorNumber //if not inherited 
            roomId
          }
        }
        ...
        {
          content: {
            uri: "room-n.gltf"
          }
          metadata: {
            floorNumber //if not inherited 
            roomId
          }
        }
      ]
    }
    // floor 2
    {
      ...
    }
    // floor n
    {
      ...
    }
  ]
}

After (hopefully) clarifying your questions, would you consider the above or a similar approach as fitting for our use case?

On more practical notes:

(hoping that the above approach will be considered by you as appropriate ; )

  • Do child tilesets inherit the schema of the parent tileset, so we’d only need to define a schema in the ‘master’ tileset? Or if not, can a tileset’s schema be imported or does it have to be explicitly written in every tileset using it?
  • I found the samples repo, which is very helpful! But I can not get the MetadataGranularities sample to work. Since the picked variable in line 67 yields undefined. Do you see what the problem is?
    (Also in the tileset sometimes ‘contents’ instead of ‘content’ is used, but I think the latter is correct? And some children have no content property at all. But this is unrelated to the aforementioned undefined picked.)
  • Is metadata a property of content or a ‘standalone’ property?

Lastly thank you again!