donmccurdy / glTF-Transform

glTF 2.0 SDK for JavaScript and TypeScript, on Web and Node.js.
https://gltf-transform.dev
MIT License
1.42k stars 149 forks source link

Draco breaking UV's #976

Closed Samsy closed 1 year ago

Samsy commented 1 year ago

Describe the bug

For some reasons, draco is breaking uv of some models, filling them with [1,1,1,1,1,1,..... ]

I investigated for a while, but got no clues 🧐

To Reproduce Steps to reproduce the behavior:

  1. Download GLB : model
  2. use command => gltf-transform draco already.glb draco.glb
  3. load model
  4. Bottom building got uv's broken

Left is draco model

Screenshot 2023-06-08 at 15 30 15

Uv's are filled with [1,1,.... ]

Screenshot 2023-06-08 at 15 28 01
donmccurdy commented 1 year ago

Hi @Samsy! The cause here is the same as https://github.com/donmccurdy/glTF-Transform/issues/936. The mesh contains a handful of vertices (6) with UVs far outside the [0,1] range, located at [-100000, -100000] instead. Draco — and Meshopt, for that matter — uses quantization to compress data, and extreme outliers affect the precision and the visual result.

I'm not sure how to find or correct those UVs in Blender, but running this script in https://gltf.report would collapse them, and doesn't cause other issues that I can see:

let fixed = 0;

for (const mesh of document.getRoot().listMeshes()) {
    for (const prim of mesh.listPrimitives()){
        const texcoord = prim.getAttribute('TEXCOORD_0');
        const texcoordArray = texcoord.getArray();
        for (let i = 0; i < texcoordArray.length; i++) {
            if (Math.abs(texcoordArray[i]) > 100) {
                texcoordArray[i] = 0;
                fixed++;
            }
        }
        texcoord.setArray(texcoordArray);
    }
}

console.log(`fixed ${fixed / 2} vertices`);

This would be more complex if the model were intentionally using UVs outside of the unit box, with repeating textures for example.

Samsy commented 1 year ago

Got it !

I used your snippet and it corrected it !

Thank you very much

donmccurdy commented 1 year ago

Awesome! I don't have a better idea of how to handle this at the moment — see https://github.com/donmccurdy/glTF-Transform/issues/936#issuecomment-1537230023 — so I'll close this ticket for now. But possibly this is also something that could be reported on the Draco side, or handled by a new/TBD "problem detection mode" at a later date.

forij commented 3 weeks ago

Hi @Samsy! The cause here is the same as #936. The mesh contains a handful of vertices (6) with UVs far outside the [0,1] range, located at [-100000, -100000] instead. Draco — and Meshopt, for that matter — uses quantization to compress data, and extreme outliers affect the precision and the visual result.

I'm not sure how to find or correct those UVs in Blender, but running this script in https://gltf.report would collapse them, and doesn't cause other issues that I can see:

let fixed = 0;

for (const mesh of document.getRoot().listMeshes()) {
  for (const prim of mesh.listPrimitives()){
      const texcoord = prim.getAttribute('TEXCOORD_0');
      const texcoordArray = texcoord.getArray();
      for (let i = 0; i < texcoordArray.length; i++) {
          if (Math.abs(texcoordArray[i]) > 100) {
              texcoordArray[i] = 0;
              fixed++;
          }
      }
      texcoord.setArray(texcoordArray);
  }
}

console.log(`fixed ${fixed / 2} vertices`);

This would be more complex if the model were intentionally using UVs outside of the unit box, with repeating textures for example.

Thanks, your saved my day. I spent 5 hour try to understand why on Macbook Pro m1 ( arm ) draco compressions work fine, but on machine with x86 architecture not all object processed correctly. Your snippet fix this issue.

Again thanks for help.