-
Notifications
You must be signed in to change notification settings - Fork 295
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
Instance feature metadata #1537
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timoore I tried this out with the instanced version of everybody's favorite model, and it works well. In fact, the existing Metadata level in the Samples can now query instanced models without any changes, which is nice!
However, I also found that that commonality with non-instanced metadata pretty much ends there. As soon as you want to use any of the lower-level, more powerful metadata access Blueprint APIs, we're stick with completely different paths for instanced and non-instanced models.
Now there are certainly details here that I don't understand, but I'm reasonably sure that this doesn't need to be so. For example, Get Feature ID From Hit
looks to me like a concept that works (and is identical) across all types of models. So why do we now have two functions to do this? (confusingly, they have the same name, too)
Well, the immediate reason is that one needs "Primitive Features" and the other needs "Instance Features". But why are those separate? Both are just containers for sets of feature IDs that are resolved in different ways:
- By face -> vertex -> feature ID attribute lookup
- By texture coordinate -> feature ID texture lookup
- And now! By instance ID -> feature ID lookup
In fact, it seems reasonable that a single "hit" could return feature IDs from all three. There could be metadata attached to the instance, the vertex, and the texture.
What do you think, is that achievable?
So that's my main feedback on this PR. I also have some additional small comments below, based on only a partial review of the code so far.
const TSharedPtr<FCesiumInstanceFeatures> pInstanceFeatures = | ||
pInstancedComponent->pInstanceFeatures; | ||
if (!pInstanceFeatures) { | ||
return TMap<FString, FCesiumMetadataValue>(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check looks unnecessary. And also redundant because GetInstanceFeatures
does the same thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking was that this would be a cheap test-and-out if the hit result was not on an instance.
I haven't looked deeply at this PR, but with the way that I also don't see something that disallows I feel like it makes more sense if we use "Instance ID" for |
Hm now that I think about it, "Instance ID" is not an accurate descriptor / is confusing for cases where you're assigning multiple instances the same feature ID. So maybe we have to use terminology like "Instance Feature ID" vs. "Mesh Feature ID" ? |
@j9liu I'm not as well versed in the metadata system as you are, so I very well could be missing something. But I don't understand why an "Instance Feature ID" is fundamentally different from our two other feature IDs we already have: the vertex attribute feature ID, and the texture feature ID. I guess they come from different extensions, but I don't think users know or care about that. They just want to be able to say: what are the metadata properties associated with the thing I just clicked on? And right now, if you want typed metadata (not just strings), that requires coding up (in Blueprint, say) two completely different paths to access the two types of feature IDs. Obviously, if that's unavoidable, then we'll just have to live with it. But it doesn't look unavoidable. As I understand it, a feature ID - no matter which of the three sources provided it - is fundamentally just an index into a property table. |
I agree that functionality wise, they're pretty much the same, and distinctions between them are going to be confusing. And I'm not sure if However, there is also the possibility for multiple feature ID sets in Since there are multiple assignments of feature ID sets, we'd want to have some way for the user to query the one they actually want. So if my memory serves me right, the
It's not unavoidable, but unfortunately there is a level of granularity to these extensions, and abstracting that away can lead to ambiguous behavior. So we just have to be extra careful about documenting the assumptions we make |
|
Ok, I see. That's a good point. We actually already have this problem, though, as it's currently implemented. I think we either need to (1) accept this, and apply it everywhere, meaning that there's just one OR (2) we need to declare this unacceptable and have a separate "namespace" for these two sets of feature ID indices. And if we go this way, I think that It's also possible to start with (1) today, and add (2) in a later version of Cesium for Unreal. But currently this branch has the two separate functions, and I don't think we should ship it that way. Another approach (which doesn't have to replace any of the options already mentioned) is to make it easy to enumerate the feature ID sets, wherever they come from, and then query by reference to one. In other words, avoid the need for feature ID set indices completely. |
@kring Fair enough, I didn't notice that -- I've been arguing at a high level and haven't looked at the code 😅 I think (1) makes sense today. (2) sounds nice for future proofing, and so does the last approach! But I agree that we should just do 1 now and defer the others for later. |
It turns out that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timoore I did a code-only pass for code design, clarity, and quality. We're on Thanksgiving break this week, so if this is supposed to be in by next week's release I ask that you address feedback ASAP so this can make it in!
Also please address @kring 's comments too, I'm seeing that some of them have not been resolved. If you have any questions or want to discuss something please don't hesitate to ask.
Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp
Outdated
Show resolved
Hide resolved
fd4e0f9
to
4f5e3ea
Compare
This is needed because UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute() returns an error for instance attributes. I guess that's reasonable behavior.
Build the functionality into the more general version that works on all primitive types.
Changed the function and its helper getInstancePropertyTableValues() to have less duplicated code. Also, it is now possible for instances to fall back to feature IDs that might be stored in the primitives of an instance.
This collection duplicated all the functionality of FCesiumPrimitiveFeatures, so just that instead.
c2fe821
to
f19130a
Compare
I've removed the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Highlights: Use the default move constructor instead of defining it. Simplify FCesiumPrimitiveFeatures constructor for instances by passing in the Gltf::ExtensionExtInstanceFeatures object.
"Hit merge" and also add more comments if necessary, of course! |
@kring For sure, I'll take a look later today / tomorrow! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just have a few tweaks, but I'm going to push a commit myself to speed things up.
I'm not 100% happy about CesiumPrimitiveFeatures
representing both primitive and instance IDs. Not because we need redundancy with CesiumInstanceFeatures
, but I think the name CesiumPrimitiveFeatures
is now inaccurate.
On the one hand, the node with EXT_mesh_gpu_instancing
gets converted into an instanced mesh primitive under the hood, so it is technically still a primitive. On the other hand, I named CesiumPrimitiveFeatures
after the fact that the EXT_mesh_features
extension is on the glTF primitive. This scheme carries over to EXT_structural_metadata
, where we have CesiumModelMetadata
and CesiumPrimitiveMetadata
to denote the difference.
But not sure what a happy replacement would be. Maybe CesiumGltfFeatures
? Not saying this needs to be resolved -- it's out of scope for this PR. Maybe I'm just abnormally nitpicky about names 🤷
I still notice something that should be addressed, but I will make my own follow-up PR to fix it.
Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp
Outdated
Show resolved
Hide resolved
Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp
Outdated
Show resolved
Hide resolved
Source/CesiumRuntime/Private/CesiumMetadataPickingBlueprintLibrary.cpp
Outdated
Show resolved
Hide resolved
@timoore I should have pointed this out earlier, but if you could add unit tests for your changes in a follow-up PR, that would be great. |
Merging after the Apple builds. I haven't played around with this in action but I assume @kring tested this enough when he reviewed 😛 |
Support for accessing metadata in GPU instances in picking hit results.