kcoley / gltf2usd

command-line utility for converting glTF 2.0 models to USD
MIT License
263 stars 39 forks source link

IndexError: tuple index out of range #97

Closed ghost closed 5 years ago

ghost commented 5 years ago

I started getting:

converted usd file extension from .usdz to .usdc: /var/app/current/tmp/d1a2b68740f1789264028e52919e1ac625cbd560cd0c894a4701205cefa4b4f4/usdz/dist.usdc
Traceback (most recent call last):
  File "/usr/local/gltf2usd/Source/gltf2usd.py", line 808, in <module>
    convert_to_usd(os.path.expanduser(args.gltf_file), os.path.abspath(os.path.expanduser(args.usd_file)), args.fps, args.scale, args.arkit, args.verbose, args.use_euler_rotation)
  File "/usr/local/gltf2usd/Source/gltf2usd.py", line 757, in convert_to_usd
    usd = GLTF2USD(gltf_file=gltf_file, usd_file=usd_file, fps=fps, scale=scale, verbose=verbose, use_euler_rotation=use_euler_rotation)
  File "/usr/local/gltf2usd/Source/gltf2usd.py", line 74, in __init__
    self.convert()
  File "/usr/local/gltf2usd/Source/gltf2usd.py", line 727, in convert
    self._convert_materials_to_preview_surface_new()
  File "/usr/local/gltf2usd/Source/gltf2usd.py", line 440, in _convert_materials_to_preview_surface_new
    usd_material.convert_material_to_usd_preview_surface(material, self.output_dir)
  File "/usr/local/gltf2usd/Source/_gltf2usd/usd_material.py", line 21, in convert_material_to_usd_preview_surface
    usd_preview_surface = USDPreviewSurface(self._stage, gltf_material, self, output_directory)
  File "/usr/local/gltf2usd/Source/_gltf2usd/usd_material.py", line 41, in __init__
    self._initialize_from_gltf_material(gltf_material)
  File "/usr/local/gltf2usd/Source/_gltf2usd/usd_material.py", line 101, in _initialize_from_gltf_material
    self._set_normal_texture(gltf_material)
  File "/usr/local/gltf2usd/Source/_gltf2usd/usd_material.py", line 113, in _set_normal_texture
    destination = normal_texture.write_to_directory(self._output_directory, GLTFImage.ImageColorChannels.RGB)
  File "/usr/local/gltf2usd/Source/_gltf2usd/gltf2/Material.py", line 33, in write_to_directory
    return self._image.write_to_directory(output_directory, channels, texture_prefix)
  File "/usr/local/gltf2usd/Source/_gltf2usd/gltf2/GLTFImage.py", line 49, in write_to_directory
    img = Image.merge('RGB', (img_channels[0], img_channels[1], img_channels[2]))
IndexError: tuple index out of range

This is the GLTF failing:

{
  "accessors": [
    {
      "name": "Plane_1_0_positions",
      "componentType": 5126,
      "count": 4,
      "min": [
        -0.7204229235649109,
        0,
        -0.7204229235649109
      ],
      "max": [
        0.7204229235649109,
        0,
        0.7204229235649109
      ],
      "type": "VEC3",
      "bufferView": 0,
      "byteOffset": 0
    },
    {
      "name": "Plane_1_0_normals",
      "componentType": 5126,
      "count": 4,
      "min": [
        0,
        1,
        0
      ],
      "max": [
        0,
        1,
        0
      ],
      "type": "VEC3",
      "bufferView": 1,
      "byteOffset": 0
    },
    {
      "name": "Plane_1_0_texcoords",
      "componentType": 5126,
      "count": 4,
      "min": [
        0.010928000323474407,
        0.02456897497177124
      ],
      "max": [
        0.9900990128517151,
        0.9900990128517151
      ],
      "type": "VEC2",
      "bufferView": 2,
      "byteOffset": 0
    },
    {
      "name": "Plane_1_0_indices",
      "componentType": 5123,
      "count": 6,
      "min": [
        0
      ],
      "max": [
        3
      ],
      "type": "SCALAR",
      "bufferView": 3,
      "byteOffset": 0
    },
    {
      "name": "Stoppers_1_0_positions",
      "componentType": 5126,
      "count": 1177,
      "min": [
        -0.25344064831733704,
        0.0000019999999949504854,
        -0.23678182065486908
      ],
      "max": [
        0.2547532320022583,
        0.006404059939086437,
        0.223549023270607
      ],
      "type": "VEC3",
      "bufferView": 4,
      "byteOffset": 0
    },
    {
      "name": "Stoppers_1_0_normals",
      "componentType": 5126,
      "count": 1177,
      "min": [
        -0.9999967813491821,
        -0.9999879002571106,
        -0.9999811053276062
      ],
      "max": [
        1,
        0.35328805446624756,
        1
      ],
      "type": "VEC3",
      "bufferView": 5,
      "byteOffset": 0
    },
    {
      "name": "Stoppers_1_0_texcoords",
      "componentType": 5126,
      "count": 1177,
      "min": [
        0,
        0
      ],
      "max": [
        1.0312999486923218,
        1
      ],
      "type": "VEC2",
      "bufferView": 6,
      "byteOffset": 0
    },
    {
      "name": "Stoppers_1_0_indices",
      "componentType": 5123,
      "count": 2877,
      "min": [
        0
      ],
      "max": [
        1176
      ],
      "type": "SCALAR",
      "bufferView": 7,
      "byteOffset": 0
    },
    {
      "name": "Legs_1_0_positions",
      "componentType": 5126,
      "count": 7037,
      "min": [
        -0.2604827582836151,
        0.0050951396115124226,
        -0.24131372570991516
      ],
      "max": [
        0.26179325580596924,
        0.43977487087249756,
        0.2259734719991684
      ],
      "type": "VEC3",
      "bufferView": 8,
      "byteOffset": 0
    },
    {
      "name": "Legs_1_0_normals",
      "componentType": 5126,
      "count": 7037,
      "min": [
        -0.9999845027923584,
        -0.9999834895133972,
        -0.9999822378158569
      ],
      "max": [
        0.9999923706054688,
        0.9999653697013855,
        0.9999979734420776
      ],
      "type": "VEC3",
      "bufferView": 9,
      "byteOffset": 0
    },
    {
      "name": "Legs_1_0_texcoords",
      "componentType": 5126,
      "count": 7037,
      "min": [
        0.007799999788403511,
        0.20800000429153442
      ],
      "max": [
        0.9868999719619751,
        0.934499979019165
      ],
      "type": "VEC2",
      "bufferView": 10,
      "byteOffset": 0
    },
    {
      "name": "Legs_1_0_indices",
      "componentType": 5123,
      "count": 28650,
      "min": [
        0
      ],
      "max": [
        7036
      ],
      "type": "SCALAR",
      "bufferView": 11,
      "byteOffset": 0
    },
    {
      "name": "Seat_1_0_positions",
      "componentType": 5126,
      "count": 6961,
      "min": [
        -0.29365548491477966,
        0.4196036458015442,
        -0.2498132586479187
      ],
      "max": [
        0.29496803879737854,
        0.8004719614982605,
        0.2498132586479187
      ],
      "type": "VEC3",
      "bufferView": 12,
      "byteOffset": 0
    },
    {
      "name": "Seat_1_0_normals",
      "componentType": 5126,
      "count": 6961,
      "min": [
        -0.9998460412025452,
        -1,
        -0.9999814629554749
      ],
      "max": [
        0.9999666810035706,
        0.999976634979248,
        0.9999750852584839
      ],
      "type": "VEC3",
      "bufferView": 13,
      "byteOffset": 0
    },
    {
      "name": "Seat_1_0_texcoords",
      "componentType": 5126,
      "count": 6961,
      "min": [
        0.000699999975040555,
        0.0012000203132629395
      ],
      "max": [
        0.5627999901771545,
        0.9994999766349792
      ],
      "type": "VEC2",
      "bufferView": 14,
      "byteOffset": 0
    },
    {
      "name": "Seat_1_0_indices",
      "componentType": 5123,
      "count": 40782,
      "min": [
        0
      ],
      "max": [
        6960
      ],
      "type": "SCALAR",
      "bufferView": 15,
      "byteOffset": 0
    }
  ],
  "asset": {
    "generator": "obj2gltf",
    "version": "2.0"
  },
  "buffers": [
    {
      "name": "uzeMRRS8nxw4ltvfzGiB4P9Z7mU_fixed",
      "byteLength": 140,
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/852/38e6b194dfbc0811c99357347c559516de36ec8ae5a9fadf7e54c7a8c6df5837-original.bin"
    },
    {
      "name": "DiGjTke8ftERP58o__COrk1__8s_fixed",
      "byteLength": 43420,
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/851/af4901f84f06f5e2793053951322ce3c721069f03ecaf109ff589940f69edfe4-original.bin"
    },
    {
      "name": "XGsiwyrHOE4fFc_5WCnIwzd2Pno_fixed",
      "byteLength": 282484,
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/855/a66a071623c32d77535d08cbbde7385b2209d535792ad61d63a70977fc0536ca-original.bin"
    },
    {
      "name": "dm56xNreILSsNsvHWx2Lzx4fxes_fixed",
      "byteLength": 304316,
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/858/3f8c210e9c849fd2c3fb6f77a98cbd8a542be4675139b6cef7000e8a4f19c539-original.bin"
    }
  ],
  "bufferViews": [
    {
      "name": "bufferView_0",
      "buffer": 0,
      "byteLength": 48,
      "byteOffset": 0,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_1",
      "buffer": 0,
      "byteLength": 48,
      "byteOffset": 48,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_2",
      "buffer": 0,
      "byteLength": 32,
      "byteOffset": 96,
      "byteStride": 8,
      "target": 34962
    },
    {
      "name": "bufferView_3",
      "buffer": 0,
      "byteLength": 12,
      "byteOffset": 128,
      "target": 34963
    },
    {
      "name": "bufferView_0",
      "buffer": 1,
      "byteLength": 14124,
      "byteOffset": 0,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_1",
      "buffer": 1,
      "byteLength": 14124,
      "byteOffset": 14124,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_2",
      "buffer": 1,
      "byteLength": 9416,
      "byteOffset": 28248,
      "byteStride": 8,
      "target": 34962
    },
    {
      "name": "bufferView_3",
      "buffer": 1,
      "byteLength": 5756,
      "byteOffset": 37664,
      "target": 34963
    },
    {
      "name": "bufferView_0",
      "buffer": 2,
      "byteLength": 84444,
      "byteOffset": 0,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_1",
      "buffer": 2,
      "byteLength": 84444,
      "byteOffset": 84444,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_2",
      "buffer": 2,
      "byteLength": 56296,
      "byteOffset": 168888,
      "byteStride": 8,
      "target": 34962
    },
    {
      "name": "bufferView_3",
      "buffer": 2,
      "byteLength": 57300,
      "byteOffset": 225184,
      "target": 34963
    },
    {
      "name": "bufferView_0",
      "buffer": 3,
      "byteLength": 83532,
      "byteOffset": 0,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_1",
      "buffer": 3,
      "byteLength": 83532,
      "byteOffset": 83532,
      "byteStride": 12,
      "target": 34962
    },
    {
      "name": "bufferView_2",
      "buffer": 3,
      "byteLength": 55688,
      "byteOffset": 167064,
      "byteStride": 8,
      "target": 34962
    },
    {
      "name": "bufferView_3",
      "buffer": 3,
      "byteLength": 81564,
      "byteOffset": 222752,
      "target": 34963
    }
  ],
  "materials": [
    {
      "extras": {
        "sayduck": {
          "uuid": "678c3080-c4da-0136-1b99-762176b07bc8"
        }
      },
      "name": "Shadow Plane",
      "pbrMetallicRoughness": {
        "baseColorFactor": [
          1,
          1,
          1,
          1
        ],
        "roughnessFactor": 1,
        "metallicFactor": 0,
        "baseColorTexture": {
          "index": 0
        }
      },
      "emissiveFactor": [
        0,
        0,
        0
      ],
      "alphaMode": "BLEND",
      "doubleSided": false
    },
    {
      "extras": {
        "sayduck": {
          "uuid": "68325f00-c4da-0136-758f-762176b07bc8"
        }
      },
      "name": "Glossy White",
      "pbrMetallicRoughness": {
        "baseColorFactor": [
          1,
          1,
          1,
          1
        ],
        "roughnessFactor": 0,
        "metallicFactor": 0
      },
      "emissiveFactor": [
        0,
        0,
        0
      ],
      "alphaMode": "BLEND",
      "doubleSided": false
    },
    {
      "extras": {
        "sayduck": {
          "uuid": "6795f3d0-c4da-0136-280e-762176b07bc8"
        }
      },
      "name": "Legs Soap Treated Oak",
      "pbrMetallicRoughness": {
        "baseColorFactor": [
          1,
          1,
          1,
          1
        ],
        "roughnessFactor": 0.7,
        "metallicFactor": 0,
        "baseColorTexture": {
          "index": 1
        }
      },
      "emissiveFactor": [
        0,
        0,
        0
      ],
      "alphaMode": "BLEND",
      "doubleSided": false,
      "normalTexture": {
        "index": 3
      },
      "occlusionTexture": {
        "index": 4
      }
    },
    {
      "extras": {
        "sayduck": {
          "uuid": "67c26100-c4da-0136-6c86-762176b07bc8"
        }
      },
      "name": "Seat White",
      "pbrMetallicRoughness": {
        "baseColorFactor": [
          1,
          1,
          0.9803921568627451,
          1
        ],
        "roughnessFactor": 0.7,
        "metallicFactor": 0
      },
      "emissiveFactor": [
        0,
        0,
        0
      ],
      "alphaMode": "BLEND",
      "doubleSided": false,
      "normalTexture": {
        "index": 6
      },
      "occlusionTexture": {
        "index": 7
      }
    }
  ],
  "meshes": [
    {
      "name": "Plane_1",
      "primitives": [
        {
          "attributes": {
            "POSITION": 0,
            "NORMAL": 1,
            "TEXCOORD_0": 2
          },
          "indices": 3,
          "material": 0,
          "mode": 4
        }
      ],
      "extras": {
        "sayduck": {
          "uuid": "67891470-c4da-0136-0b8c-762176b07bc8"
        }
      }
    },
    {
      "name": "Stoppers_1",
      "primitives": [
        {
          "attributes": {
            "POSITION": 4,
            "NORMAL": 5,
            "TEXCOORD_0": 6
          },
          "indices": 7,
          "material": 1,
          "mode": 4
        }
      ],
      "extras": {
        "sayduck": {
          "uuid": "6782aa10-c4da-0136-5d3c-762176b07bc8"
        }
      }
    },
    {
      "name": "Legs_1",
      "primitives": [
        {
          "attributes": {
            "POSITION": 8,
            "NORMAL": 9,
            "TEXCOORD_0": 10
          },
          "indices": 11,
          "material": 2,
          "mode": 4
        }
      ],
      "extras": {
        "sayduck": {
          "uuid": "677bda40-c4da-0136-6f01-762176b07bc8"
        }
      }
    },
    {
      "name": "Seat_1",
      "primitives": [
        {
          "attributes": {
            "POSITION": 12,
            "NORMAL": 13,
            "TEXCOORD_0": 14
          },
          "indices": 15,
          "material": 3,
          "mode": 4
        }
      ],
      "extras": {
        "sayduck": {
          "uuid": "67775020-c4da-0136-dde5-762176b07bc8"
        }
      }
    }
  ],
  "nodes": [
    {
      "name": "Plane",
      "mesh": 0
    },
    {
      "name": "Stoppers",
      "mesh": 1
    },
    {
      "name": "Legs",
      "mesh": 2
    },
    {
      "name": "Seat",
      "mesh": 3
    }
  ],
  "scene": 0,
  "scenes": [
    {
      "nodes": [
        0,
        1,
        2,
        3
      ]
    }
  ],
  "samplers": [
    {
      "magFilter": 9729,
      "minFilter": 9986,
      "wrapS": 10497,
      "wrapT": 10497
    },
    {
      "magFilter": 9729,
      "minFilter": 9986,
      "wrapS": 10497,
      "wrapT": 10497
    },
    {
      "magFilter": 9729,
      "minFilter": 9986,
      "wrapS": 10497,
      "wrapT": 10497
    },
    {
      "magFilter": 9729,
      "minFilter": 9986,
      "wrapS": 10497,
      "wrapT": 10497
    }
  ],
  "textures": [
    {
      "name": "albedo",
      "sampler": 0,
      "source": 0
    },
    {
      "name": "albedo",
      "sampler": 2,
      "source": 1
    },
    {
      "name": "occlusion",
      "sampler": 2,
      "source": 2
    },
    {
      "name": "normal",
      "sampler": 2,
      "source": 3
    },
    {
      "name": "occlusion_roughness_metallic",
      "sampler": 2,
      "source": 4
    },
    {
      "name": "occlusion",
      "sampler": 3,
      "source": 5
    },
    {
      "name": "normal",
      "sampler": 3,
      "source": 6
    },
    {
      "name": "occlusion_roughness_metallic",
      "sampler": 3,
      "source": 7
    }
  ],
  "images": [
    {
      "name": "albedo",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/826/a3e8bca121afa5a7f1fc67c938a11d4205918fbc0ddcb699708d8999f38ebdce-optimized_texture_jpg_1024.jpg"
    },
    {
      "name": "albedo",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/827/b80c583699c2af15871a6fa893399d961dc3e0fdfb957324539ee8df7fadc1c2-optimized_texture_jpg_2048.jpg"
    },
    {
      "name": "occlusion",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/828/562fac8f9496fcecccf264158f539834b832cf18ae66ab7959c64fc493c9552a-optimized_texture_jpg_2048.jpg"
    },
    {
      "name": "normal",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/829/fda8dd8cb6880ec0e153aa6bc06be273e0a2728fcc1c4e5176471964e10541c1-optimized_texture_jpg_2048.jpg"
    },
    {
      "name": "occlusion_roughness_metallic",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/861/7670097a4e97dcca24e04767d91a2f6c038f5b4976f680946a202b41f4749923-optimized_texture_jpg_2048.jpg"
    },
    {
      "name": "occlusion",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/832/4607e122e124ecff8b099a70ba4d1c4c60209dbed7a89391c00151a0a7493f33-optimized_texture_jpg_2048.jpg"
    },
    {
      "name": "normal",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/833/45959dc29e97ca35f17709bdd318a18a347ec68f0b49bd8d67464fb67e8a29df-optimized_texture_jpg_512.jpg"
    },
    {
      "name": "occlusion_roughness_metallic",
      "uri": "https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/862/8e4216c11041c38bc421a173577616960195bf12f090e57cc516903655221d5e-optimized_texture_jpg_2048.jpg"
    }
  ]
}

Any idea from where this could come?

ghost commented 5 years ago

Could it be because of the asset https://s3.us-east-1.amazonaws.com/sayduck-production/a/shared_assets/files/000/010/829/fda8dd8cb6880ec0e153aa6bc06be273e0a2728fcc1c4e5176471964e10541c1-optimized_texture_jpg_2048.jpg ?

It seems to be a grayscale image.

kcoley commented 5 years ago

Hi @sayduck-daniel , yeah seems to be the case. Is this texture being used as a normal map? I believe glTF expects it to be an RGB texture, similar to this: https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Material/Textures/Normal_Plane.png

ghost commented 5 years ago

Yes, it's a normal map. But it seems greyscale normal maps work with gltf.

Do you think it would be out of the scope of this project to implement a safeguard in case a texture is in grayscale perhaps?

We are importing models from another system and it happens we used a lot of maps in greyscale.

kcoley commented 5 years ago

@sayduck-daniel sure we could do that, have the grayscale values duplicated to the RGB channels

kcoley commented 5 years ago

@sayduck-daniel actually, duplicating the grayscale isn't really a normal map and would yield the wrong results. This would probably involve generating a new normal map from a sobel filter, which might be better handled with a separate tool. I'll look into how difficult this might be or if there is already a tool out there.

ghost commented 5 years ago

Yes that is correct.

One thing in favor of having the convert in there for me is the fact sometimes an user uploads a RGB map and somehow this map gets converted to grayscale by ImageMagick in our side.

ImageMagick seems to take the decision that if there is nothing on 2 channels it should be set to grayscale.

I tried to counter this behavior but so far nothing conclusive. On top of that, glTF renders as normal with this map in greyscale.

ghost commented 5 years ago

If someone stumbles upon this problem there is what we did:

After further investigation, we realised that ImageMagick is smart enough to automatically convert an image to grayscale if the image is an actual grayscale:

convert my_image_created_with_photoshop_and_set_to_RGB_with_3_channels.jpg imagemagik_image.jpg

This will result in a grayscale if it detects only grey!!!

To avoid that, we are now using only RGB and use the parameters -type truecolor -colorspace RGB for JPG and -define png:bit-depth=8 -define png:color-type=6 -colorspace RGB for PNG.

kcoley commented 5 years ago

@sayduck-daniel I merged a change for this to copy the single channel grayscale to the RGB channels: https://github.com/kcoley/gltf2usd/pull/98

Feel free to re-open if this still causes issues