sgillespie / haskell-gltf-loader

High level GlTF Haskell loader
MIT License
4 stars 2 forks source link

32bit unsigned-integer encoded vertex indices seem to be decoded as 16bit #3

Closed mrehayden1 closed 9 months ago

mrehayden1 commented 9 months ago

When loading the model below vertex indices for the mesh primitive are loaded as the correct values padded with alternating zeroes causing it to be corrupted when rendered, while the model loads correctly in other GlTF viewers.

https://sketchfab.com/3d-models/reference-frame-7b41e02853134b04b460b257951cd653

P.S. Great project!

mrehayden1 commented 9 months ago

Seeing how things work at the moment, maybe the decoders:

-- | Decode vertex indices
vertexIndices :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector Word16
vertexIndices = readBufferWithGet getIndices

-- | Decode vertex positions
vertexPositions :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
vertexPositions = readBufferWithGet getPositions

-- | Decode vertex normals
vertexNormals :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
vertexNormals = readBufferWithGet getNormals

-- | Decode texture coordinates. Note that we only use the first one.
vertexTexCoords :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V2 Float)
vertexTexCoords = readBufferWithGet getTexCoords

-- | Decode vertex colors
vertexColors :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V4 Word16)
vertexColors = readBufferWithGet getColors

should use generalised getters that are aware of the byteStride from the BufferView (used in the case of interleaved, non-tightly-packed vertex attributes) and also the componentType from the Accessor for the data it's decoding from the binary chunk.

mrehayden1 commented 9 months ago

Having done more digging, the 32-bit encoding of indices is the nature of the Sketchfab automatic conversion of uploaded models.

A good work-around I've found is importing to and exporting from Blender, which re-encodes the indices as 16-bit unsigned integers.

sgillespie commented 9 months ago

Having done more digging, the 32-bit encoding of indices is the nature of the Sketchfab automatic conversion of uploaded models.

A good work-around I've found is importing to and exporting from Blender, which re-encodes the indices as 16-bit unsigned integers.

Unfortunately, I've only been testing on Blender, so I appreciate the report. If you can post a gltf file somewhere for reference, I can poke around

mrehayden1 commented 9 months ago

Hey!

Try downloading this file as a GlTF. That's the one I've been using. https://sketchfab.com/3d-models/reference-frame-7b41e02853134b04b460b257951cd653

sgillespie commented 9 months ago

I can see the difference. Sketchfab:

    {
      "bufferView": 0,
      "componentType": 5125,
      "count": 2232,
      "type": "SCALAR"
    }

vs Blender:

        {
            "bufferView":3,
            "componentType":5123,
            "count":2232,
            "type":"SCALAR"
        }

So you are right that it is using 32bit unsigned integers (vs 16 from blender)

mrehayden1 commented 9 months ago

Yeah, that's what I was seeing.

There are workarounds so I thought I would document the issue in case any tripped up on it too.

sgillespie commented 9 months ago

Should be fixed by https://github.com/sgillespie/haskell-gltf-loader/commit/d133575a007d524da5bad68fc492a8591834c828

mrehayden1 commented 9 months ago

All working.