Skip to content
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

incorrect import of the attached glTF file #2162

Open
vvoovv opened this issue Mar 14, 2024 · 16 comments
Open

incorrect import of the attached glTF file #2162

vvoovv opened this issue Mar 14, 2024 · 16 comments
Labels
bug Something isn't working draco

Comments

@vvoovv
Copy link

vvoovv commented Mar 14, 2024

Describe the bug

Blender's glTF importer can't import the attached glTF file.

The online glTF viewer https://sandbox.babylonjs.com does import the file correctly.

The attached glTF file is a part of Google 3D Tiles.

To Reproduce
Import the attached glTF file and see the odd result.

image

A note. The imported Blender object will be located very far away from the origin:

image

Expected behavior

The online glTF viewer https://sandbox.babylonjs.com does import the attached glTF file correctly.

image

.blend file/ .gltf (mandatory)
problem_tile.zip

Version

  • OS: Windows 11 Home
  • Blender Version: 4.0.1
@julienduroure
Copy link
Collaborator

Hello,
My first thought is that it may be a Draco decoding issue

@julienduroure julienduroure added bug Something isn't working draco labels Mar 14, 2024
@julienduroure
Copy link
Collaborator

I confirm that the bug comes from Draco decompression.
Using

gltf-transform draco /tmp/problem_tile.glb /tmp/problem_tile2.glb

And the new file (still Draco compressed) imports correcly

@vvoovv
Copy link
Author

vvoovv commented Mar 14, 2024

What would be required to fix this problem?

@julienduroure
Copy link
Collaborator

I need to check if we can update Blender Draco lib to latest version, and check if it solves the issue of not

@vvoovv
Copy link
Author

vvoovv commented Mar 26, 2024

Hi @julienduroure

Did the update of the Draco library help to solve the problem?

@julienduroure
Copy link
Collaborator

Helllo,

I didn't check it yet

@vvoovv
Copy link
Author

vvoovv commented May 23, 2024

Hi @julienduroure

Any chance of fixing in Blender 4.3?

Thank you.

@julienduroure
Copy link
Collaborator

Tested on local with Draco 1.5.7, problem is still there :(

@Djdraco93
Copy link

Now unfortunately another person needs a working import of compressed .glb models (edgebreaker and sequential ways). Same problem as above, the geometry does not match what it should contain, but in the browser the browsers work correctly. One is left hoping that the next version of the library will fix this.

@vvoovv
Copy link
Author

vvoovv commented May 28, 2024

@julienduroure

Do you think it makes sense to report the problem to the developers of Draco?

@Djdraco93
Copy link

@julienduroure

Can you or someone push the topic further. I need importing with draco compression madly for my work, without it I can't check files from the client as the requirement is .glb compression on the client's side

@julienduroure
Copy link
Collaborator

So ... I have an answer!

I was looking into Draco, and the answer is probably somewhere else :)
Seems the indices accessor of the primitive is set a component type of 5121 ( UnsignedByte ), so with a max index of 255.

image

But ... the max indice is 314, as we have more than 255 vertices.

The good news is that I identified the root cause of the issue \o/
The bad news: it seems that the problem comes from the file, where you could not trust the indice component type. We will have to find another way to initialize the array type (based on decoded mesh number of points?)

Thanks for your patience waiting a fix :)

@julienduroure
Copy link
Collaborator

diff --git a/addons/io_scene_gltf2/blender/imp/draco_compression_extension.py b/addons/io_scene_gltf2/blender/imp/draco_compression_extension.py
index 94a0e8f3..d06c388b 100644
--- a/addons/io_scene_gltf2/blender/imp/draco_compression_extension.py
+++ b/addons/io_scene_gltf2/blender/imp/draco_compression_extension.py
@@ -15,6 +15,7 @@
 from ctypes import *
 
 from ...io.com.gltf2_io import BufferView
+from ...io.com.constants import ComponentType
 from ...io.imp.gltf2_io_binary import BinaryData
 from ...io.com.draco import dll_path
 
@@ -88,6 +89,16 @@ def decode_primitive(gltf, prim):
         gltf.log.warning(
             'Draco Decoder: Index count of accessor and decoded index count does not match. Updating accessor.')
         index_accessor.count = dll.decoderGetIndexCount(decoder)
+
+    # Recalculate component type based on vertex count.
+    # Because it seems the prim.indices accessor componentType is not always set correctly.
+    if dll.decoderGetVertexCount(decoder) < 255:
+        index_accessor.component_type = ComponentType.UnsignedByte
+    elif dll.decoderGetVertexCount(decoder) < 65535:
+        index_accessor.component_type = ComponentType.UnsignedShort
+    else:
+        index_accessor.component_type = ComponentType.UnsignedInt
+
     if not dll.decoderReadIndices(decoder, index_accessor.component_type):
         gltf.log.error('Draco Decoder: Unable to decode indices. Skipping primitive {}.'.format(name))
         return

This patch seems to fix the issue. But we have to be very careful, and this needs more test / non regression tests / checks

@vvoovv
Copy link
Author

vvoovv commented Nov 6, 2024

This patch seems to fix the issue. But we have to be very careful, and this needs more test / non regression tests / checks

Great news! I'll test the patch.

@julienduroure
Copy link
Collaborator

@donmccurdy You have maybe better understanding of this Draco issue.

the prim.indices of the file have ComponentType 5121, but have more than 255 indices.
Should we ignore this, and always recalculate the ComponentType based on DracoMesh data?

Or is this a bug in this file?
In that case, do you know who I can contact at google to discuss about that?

@donmccurdy
Copy link
Contributor

donmccurdy commented Nov 7, 2024

Copying the JSON header out of the GLB...

problem_tile.glb
{
  "asset":{
    "version":"2.0",
    "generator":"draco_decoder",
    "copyright":"Google"
  },
  "scenes":[
    {
      "nodes":[
        0
      ]
    }
  ],
  "scene":0,
  "nodes":[
    {
      "mesh":0,
      "translation":[
        851227.05319905072,
        4379922.724366514,
        4543783.8765163999
      ]
    }
  ],
  "meshes":[
    {
      "primitives":[
        {
          "attributes":{
            "POSITION":1,
            "TEXCOORD_0":2
          },
          "indices":0,
          "mode":4,
          "material":0,
          "extensions":{
            "KHR_draco_mesh_compression":{
              "bufferView":0,
              "attributes":{
                "POSITION":0,
                "TEXCOORD_0":1
              }
            }
          }
        }
      ]
    }
  ],
  "accessors":[
    {
      "componentType":5121,
      "count":513,
      "type":"SCALAR"
    },
    {
      "componentType":5126,
      "count":314,
      "max":[
        53.494731903076172,
        37.779499053955078,
        -9.2874250411987305
      ],
      "min":[
        -69.238937377929688,
        -95.882095336914062,
        -92.276382446289062
      ],
      "type":"VEC3"
    },
    {
      "componentType":5126,
      "count":314,
      "type":"VEC2"
    }
  ],
  "materials":[
    {
      "pbrMetallicRoughness":{
        "baseColorTexture":{
          "index":0,
          "texCoord":0
        },
        "baseColorFactor":[
          1,
          1,
          1,
          1
        ],
        "metallicFactor":1,
        "roughnessFactor":1
      },
      "emissiveFactor":[
        0,
        0,
        0
      ],
      "alphaMode":"OPAQUE",
      "extensions":{
        "KHR_materials_unlit":{
          
        }
      }
    }
  ],
  "textures":[
    {
      "source":0,
      "sampler":0
    }
  ],
  "samplers":[
    {
      "wrapS":33071,
      "wrapT":33071
    }
  ],
  "images":[
    {
      "bufferView":1,
      "mimeType":"image/jpeg"
    }
  ],
  "bufferViews":[
    {
      "buffer":0,
      "byteOffset":0,
      "byteLength":1108
    },
    {
      "buffer":0,
      "byteOffset":1108,
      "byteLength":3108
    }
  ],
  "buffers":[
    {
      "byteLength":4216
    }
  ],
  "extensionsRequired":[
    "KHR_draco_mesh_compression",
    "KHR_materials_unlit"
  ],
  "extensionsUsed":[
    "KHR_draco_mesh_compression",
    "KHR_materials_unlit"
  ]
}

Indeed, the file has too many vertices for the uint8 indices being used. This is certainly a bug in the software producing the file, it might be good to report the issue at https://github.com/google/draco, but I'm not sure who would be involved in producing 3D Tiles specifically.

As a workaround, detecting this problem in the import process and using uint16 instead of uint8 might work, assuming the encoder has stored the larger indices in the compressed bitstream.

Guessing at what the encoder might have done wrong ... I will note that Draco compression can increase the vertex count slightly, as part of the compression process. If a mesh is near the vertex count limit for uint8 indices, it might be necessary to change the index type if the vertex count increases after compression. I guess the Draco encoder is question has failed to do so. I handle this in glTF Transform with a special case for UNSIGNED_SHORT though it's possible that I need a special case for UNSIGNED_BYTE too. But I don't think glTF Transform was used to produce this file, so that's just an aside.

Related comments and issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working draco
Projects
None yet
Development

No branches or pull requests

4 participants