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

Consider a function to automatically assign IDs to mesh primitives #125

Open
javagl opened this issue May 6, 2024 · 1 comment
Open

Comments

@javagl
Copy link
Contributor

javagl commented May 6, 2024

The main use case of the EXT_mesh_features extension is to identify "individual things" (like buildings or trees) within a glTF asset. And I could imagine that many glTF assets already do have a structure that reflects this: In many cases, a single mesh or mesh.primitive will be "a building" or "a tree".

In rendering engines like CesiumJS, these parts can often no longer be distinguished. Whatever is loaded from the GLB counts as "one thing", and diving into the glTF scene graph- and mesh structures is not necessarily offered on an API level.

It could be useful to introduce a functionality to just automatically assign consecutive IDs to all meshes or mesh primitives that are contained in a glTF asset. There are some obvious degrees of freedom, like

  • should the IDs be assigned to meshes or to mesh primitives?
  • should the IDs be in [0,...numElements-1], or should it be possible to specify the range, so that different sets of IDs can be assigned to different glTFs that are then loaded together in the runtime engine?
  • should there be other mechanisms for conveying which ID should be assigned to which element?
  • (the resulting glTF should probably use compression by default, because there's no point of storing the same ID value, 10000 times, for a primitive with 10000 vertices...)
    • many more

But in the most basic case, and in terms of implementation effort, this could be a really low-hanging fruit. And it would already allow a systematic way of identifying the former elements after the glTF was loaded into the runtime engine.

@javagl
Copy link
Contributor Author

javagl commented May 19, 2024

I started drafting a few possible approaches here. At the moment, this is rather experimental, recreational, brainstorming, ... "let's see how this could be done". And I think that a green-field approach for the task to 'do something', is to define an interface SomethingDoer, and fill it with life, refining it iteratively.

So in the current state, there is an interface

export interface FeatureIdAssigner {
  processDocuments(documents: { [key: string]: Document }): Promise<void>;
}

This can receive a bunch of documents, and assign feature IDs to the mesh primitives.

Static factories exist for creating different types of feature ID assigners. So for simple patterns, the "surface area of the API" is close to zero:

const documents: { [key: string]: Document } = { ... }; // The input documents
const featureIdAssigner = FeatureIdAssigners.perMesh();
await featureIdAssigner.processDocuments(documents);

That's it. It will assign consecutive feature ID values [0,...n) to the primitives of the n meshes that are found in these documents. Similarly, there is FeatureIdAssigners.perPrimitive() that will just assign consecutive IDs to the primitives.

Now, there are a million possible ways of how this could be configured on a more fine-grained level. (Some of them are listed in the first post here). But one important configuration hook is to determine...

  • what the actual values of the feature IDs are
  • which primitive will receive which ID value

So... when there's the goal to provide a feature ID value for a certain primitive of a certain mesh of a certain document, then... there can be an interface (type definition) like this:

export type FeatureIdValueProvider = (
  document: Document,
  mesh: Mesh,
  primitive: Primitive
) => number;

An instance of this can be passed to the static factory methods, and allow determining the actual feature ID values.

There are some details about the nullFeatureId, or the question of whether/how to determine that a certain primitive should not receive a feature ID at all. But a draft of how this could be used is shown here:

const nullFeatureId = 999;
const featureIdAssigner = FeatureIdAssigners.customPerPrimitive(
  (document: Document, mesh: Mesh, primitive: Primitive) => {
    if (primitive.getName() === "EXAMPLE_NAME_A") return 123;
    if (primitive.getName() === "EXAMPLE_NAME_B") return nullFeatureId;
    return undefined;
  },
  nullFeatureId
);

This feature ID assigner will assign the ID value 123 to mesh primitives that have a certain name, or the given nullFeatureId to mesh primitives that have another specific name. Primitives that are not handled here will receive consecutive ID values. This obviously has to be refined further (for the case that there are 999 primitives in these documents and such...). But for some cases, this could already be useful.

(Maybe I'll open a draft PR for a demo, but for now, this comment might be enough...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant