Open javagl opened 6 months ago
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...
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...)
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 singlemesh
ormesh.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
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.