Skip to content
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

Bim 272 converter packed metadata from gltfpack and output metadata file #1

Conversation

pirlande-fw
Copy link

@pirlande-fw pirlande-fw commented Aug 28, 2024

BIM-272 | Packed metadata from gltfpack

This PR aims at generating an additional output file from the gltfpack utility to keep track of the meshes that are merged together.

The aim is to optionally use this information on our mobile apps to show objects properties. Using gltfpack is very helpful as it reduces the draw count by merging meshes together, which makes complex models viewable on mobile. The caveat is that we lose the meshes metadata information.

How it is done

There are several key pieces that follow the order of commits:

  • at parsing time (in parsegltf.cpp), we first retrieve the parent node from meshes, as parent nodes carry out the name used to retrieve properties. But a parent node can have several mesh child nodes, so we also keep the index of the mesh from its parent node. Both pieces of information are stores into the main Mesh struct.
  • at processing time (in gltfpack.cpp), we disable one optimization using a new option named -kmpn (for keep mesh parent nodes). This option makes sure the merged mesh's parent nodes are kept as they are the ones that carry out the names used to retrieve properties. At the end, we have the same number of parent nodes as merges meshes. Their names are generated dynamically, from the information retrieved at parsing time, and we write them into the merged mesh's parent nodes.
  • the key step is the merging one (in mesh.cpp), where a source mesh is merged into a target mesh. At this step, we keep two pieces of information into the target mesh:
    • the parent node name of the source mesh
    • the index_offset where the triangle vertice positions of the source mesh are copied over into the target mesh
  • finally, we print the metadata information into an output file, using a new option named -mmi (for merge mesh information). Here, we just iterate over the merged meshes, and format the useful information stored at the previous step.

To illustrate, let's take this GLTF file example:

 "meshes": [
    /* mesh with 12 indices */
    {
      "primitives": [
        ...
      ]
    },
    /* mesh with 36 indices that will be merged into the first one */
    {
      "primitives": [
        ...
      ]
    },
    /* mesh with 9 indices that will be merged into the first one */
    {
      "primitives": [
        ...
      ]
    },
  ],
  "nodes": [
    {
      "mesh": 0,
    },
    {
      "mesh": 1,
    },
    {
      "mesh": 2,
    },
    {
      "name": "0yiBM2NAH96xSSnOnrhhld",
      "children": [0, 1]
    },
    {
      "name": "3j913Y4av3qOaiLIYT4b6p",
      "children": [2]
    }
  ]

The output metadata file should contain:

{
  "0yiBM2NAH96xSSnOnrhhld_0": {   // note the _0 that indicates the first child mesh of 0yiBM2NAH96xSSnOnrhhld
    "0": "0yiBM2NAH96xSSnOnrhhld", // for the 2 first meshes (12+36=48 indices)
    "48": "3j913Y4av3qOaiLIYT4b6p"  //  3rd mesh
}

On the client side, when the merged mesh 0yiBM2NAH96xSSnOnrhhld_0 is touched, we'll need to retrieve the triangle that was selected in the mesh. From the triangle, we can retrieve its vertices, then its corresponding indices. If we find indices 51, 52, 53 for example, we know that it's after 48, so that's the initial 3rd mesh that was selected. We get 3j913Y4av3qOaiLIYT4b6p and can display the corresponding property 🙌.

How to read

Read by commit

How to test

  • To build, follow instructions at the end of this page.
  • Take an input glb file and run this command line:
./gltfpack -i input.glb -o packed.glb -vp 16 -vn 16 -vc 16 -vpf -cc -v -kmpn -mmi metadata.json
  • See the produced output.json file

@pirlande-fw
Copy link
Author

@tsanghrajka @mehulshinde I'm not sure how familiar you are with C++.
Happy to go through this PR live as needed.

Copy link

@tsanghrajka tsanghrajka left a comment

Choose a reason for hiding this comment

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

Looks great overall!
Thanks for the detailed description and explanation @pirlande-fw 🙏 🙌

Copy link

@mehulshinde mehulshinde left a comment

Choose a reason for hiding this comment

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

Thank you for the detailed explanation @pirlande-fw. Looks good 👏👏 Left some super nit around bracket style.

@@ -183,6 +189,70 @@ static void printImageStats(const std::vector<BufferView>& views, TextureKind ki
printf("stats: image %s: %d bytes in %d images\n", name, int(bytes), int(count));
}

static bool printMergeMetadata(const char* path, const std::vector<Mesh>& meshes) {

Choose a reason for hiding this comment

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

nit: I think the default style of these cpp files is to follow Allman style for curly brackets. Although I am team K&R, might want to keep things consistent. This is super minor so feel free to disregard this and other instances of this.

Copy link
Author

Choose a reason for hiding this comment

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

Thx, I did not even realize!
Addressed all comments in 538a003

@@ -555,11 +625,17 @@ static void process(cgltf_data* data, const char* input_path, const char* output
{
const Mesh& mesh = meshes[i];

std::string mesh_name = std::string();
if (settings.keep_mesh_parent_nodes) {

Choose a reason for hiding this comment

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

nit: Allman style brackets

// skip all meshes that we've written in this iteration
assert(pi > i);
i = pi - 1;
if (!settings.keep_mesh_parent_nodes) {

Choose a reason for hiding this comment

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

nit: Allman style brackets

gltf/mesh.cpp Outdated
@@ -257,11 +257,15 @@ static void mergeMeshes(Mesh& target, const Mesh& mesh)

size_t index_count = mesh.indices.size();

for (size_t i = 0; i < index_count; ++i)
for (size_t i = 0; i < index_count; ++i) {

Choose a reason for hiding this comment

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

nit: Allman

@@ -186,6 +205,12 @@ static void parseMeshesGltf(cgltf_data* data, std::vector<Mesh>& meshes, std::ve

size_t vertex_count = primitive.attributes_count ? primitive.attributes[0].data->count : 0;

// save the parent node info to the mesh
if (nodes_to_child_meshes_map_it != nodes_to_child_meshes_map.end()) {

Choose a reason for hiding this comment

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

nit: Allman

gltf/write.cpp Outdated
{
comma(json);
append(json, "{\"mesh\":");
append(json, mesh_offset);
if (!name.empty()) {

Choose a reason for hiding this comment

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

nit: Allman

@pirlande-fw pirlande-fw merged commit 8c9fa1b into master Aug 30, 2024
@pirlande-fw pirlande-fw deleted the BIM-272-converter-packed-metadata-from-gltfpack-and-output-metadata-file branch August 30, 2024 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants