CesiumGS / cesium-native

Apache License 2.0
402 stars 205 forks source link

Add a few helpful functions to `Model` and `GltfUtilities`. #857

Closed kring closed 4 months ago

kring commented 4 months ago

This builds on #853 so merge that first.

j9liu commented 4 months ago

Merging now. Thanks @kring !

javagl commented 4 months ago

The combination of removeUnusedBufferViews and compactBuffers will break the alignment requirements in certain cases.

Here is an archive of a glTF and the resulting output:

NastyAlignmentTest.zip

The glTF has a single buffer, where

Accessor 0 is unused (but it might very well be used - this is just for demonstation). Buffer view 1 has an offset of 3 and a length of 3, and is unused.

So these are the ranges of the 44 bytes that are occupied by the respective buffer views 0, 1, and 2:


          1         2         3         4   4
0       8 0         0         0         0   4
--------------------------------------------
000
   111  
        222222222222222222222222222222222222

This is valid.

Running removeUnusedBufferViews/compactBuffers on this will detect that the range 3...8 is unused, and remove it, resulting in


          1         2         3         4   4
0       8 0         0         0         0   4
--------------------------------------------
000
   1111111111111111111111111111111111111

where the buffer view 1 has an offset of 3, but the accessor that refers to it requires an alignment of 4.

kring commented 4 months ago

Thanks @javagl. And I guess the problem is that we can't tell what alignment is required by only looking at the bufferView? We have to also look at the accessors (or whatever else uses the bufferView, e.g., metadata).

If I have that right, I think we can still deal with it relatively easily just be being conservative about it. If a bufferView is originally aligned to 2 or 4 bytes, whether it needs to be or not, we make sure we preserve that alignment by deleting slightly fewer bytes than we otherwise would. Are there any bufferViews that need to be aligned to 8 bytes?

timoore commented 4 months ago

Thanks @javagl. And I guess the problem is that we can't tell what alignment is required by only looking at the bufferView? We have to also look at the accessors (or whatever else uses the bufferView, e.g., metadata).

If I have that right, I think we can still deal with it relatively easily just be being conservative about it. If a bufferView is originally aligned to 2 or 4 bytes, whether it needs to be or not, we make sure we preserve that alignment by deleting slightly fewer bytes than we otherwise would. Are there any bufferViews that need to be aligned to 8 bytes?

You are safe if new buffer view offset = old buffer view offset mod 4. I think it's true that the alignment of a buffer view determines the maximum alignment of possible accessors; the accessor offset must be "a multiple of the size of the accessor’s component type," so the accessor's offset can't "realign" a misaligned buffer view.

The maximum component size in glTF 2.0 -- and therefore the maximum alignment -- is 4 bytes. I don't know if any extension specifies an 8 byte component type.

javagl commented 4 months ago

Responded in https://github.com/CesiumGS/cesium-native/issues/862#issuecomment-2061074914