-
Notifications
You must be signed in to change notification settings - Fork 42
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
More edge cases for interleaved buffer views #563
Comments
Babylon isn't ignoring unused UVs as users may add textures after loading. It seems the math works out fine in Babylon so I think it's a bug in three.js and the sample viewer? But even if the math turns out to be bad for typed arrays, the Babylon glTF loader allows invalid typed array offset/length combinations due to backwards compatibility since at some point it worked out of the box.
We avoid putting edge cases that ideally should not exist. Otherwise, the matrix of cases get unwieldly rapidly. I'm not sure there is a reasonable case for this one. Maybe we can add as a negative test case, but it will blur the definition a bit. If we come up with a reasonable case, I'm all for it. |
The data layout is unusual, at least, and I can imagine that some tools choke on that. (One of my utilities reported an error: "The accessorModel has an offset of 0 and 5 elements with a byte stride of 44, requiring 220 bytes, but the buffer view has only 208 bytes" - which sounds like a reasonable error message, but I assume that I just messed up the error check here. Or conversely: It seems very unlikely that such an error wasn't covered by the validator if it was really invalid...) Looking at the JSON, this refers to this accessor
and this buffer view
It might still be valid, considering that the fifth element in this case is only a The The full JSON from the model, maybe someone wants to have a look... bloc.gltf
|
That was exactly my mistake, and probably the mistake of glTF-Sample-Viewer too. 😇 The spec actually does spell this out, I just wasn't looking for it;
Visually, here's the problem. Suppose byteStride were 8 bytes, with two attributes, and 4 vertices. Each vertex is 4 bytes, let's say that's 3 bytes + 1 byte of padding.
My implementation assumed it would encounter the first attribute (X) in the buffer first, and it constructs a TypedArray then. When we encounter attribute X first, that's fine — the length of the buffer is exactly However, I'd be willing to bet my implementation would also break in a much more reasonable situation, where all attributes are in the same bufferView, but they're listed under
By luck, that's not something exporters are very likely to do, but I do think it might be a reasonable enough situation to test for here. |
(Not sure how I overlooked that part of the spec - I did several CTRL+F passes with the related keywords...) Here's an image of the actual data layout of the asset. Even if this case is not dedicatedly handled by the asset generator, maybe the model could be added as one of the "simpler test models" in the glTF Sample Models repo (along with the "interleaved cube"), so that importers are aware of that case. |
It's not a good data layout — it'd very likely cause the engine to lose the benefits of interleaving — so I wouldn't want to put it in glTF-Sample-Models personally. If we find a "good" model that hits the same issue then we should include it either there or here.
I thought this would break, but it didn't — both three.js and the sample viewer do handle this correctly. So I guess they're just broken in the more pathological case of the original model. I'm not sure whether any action is necessary, in that case. I understand @bghgary's preference to not host edge cases that shouldn't exist... is this enough of an edge case that we should put an implementation note or even a bugfix in the spec? /cc @lexaknyazev |
I'd have to take some time to wrap my heads about the details, but if I understood that correctly, then the main issue is (very roughly speaking) that a straightforward implementation of a viewer would upload the 4 buffer views to the GPU, even though they contain the same data, causing some redundant redundancies. (The viewer could figure that out, but it would be complicated, so no viewer would do that by default) I wonder whether we could find a way to more precisely say what the term "good data layout" means. A quick search on the spec shows that it does not contain the word |
This model was reported as not working in three.js, and it doesn't appear to work in the Sample Viewer either. The buffer layout has a single mesh primitive with several vertex attributes, which are interleaved, but each attribute accessor has its own buffer view — rather than setting
byteOffset
on each accessor, abyteOffset
is assigned to the accessor's unique buffer view.This passes the validator, and seems valid according to the spec too. It's not a data layout I'd want to encourage, but the bug it identified in three.js could technically happen in some reasonable cases too, so maybe it's worth including a test case here.
It appears to work in BabylonJS already, although the accessor three.js failed on was (by chance) an unused UV set, so if BabylonJS ignores unused UVs it might have dodged the issue entirely that way.
bloc1.glb.zip
donmccurdy/three-gltf-viewer#202
The text was updated successfully, but these errors were encountered: