kcoley / gltf2usd

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

KHR_texture_transform texture generation crashes (source_image_pixels goes out of range) #131

Closed silvainSayduck closed 5 years ago

silvainSayduck commented 5 years ago

Hi @kcoley,

I just pulled the latest version which should support the KHR_texture_transform extension. However, when processing a glTF using that extension, I get the following error.

Traceback (most recent call last):
  File "/.../gltf2usd/Source/gltf2usd.py", line 822, 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, args.optimize_textures)
  File "/.../gltf2usd/Source/gltf2usd.py", line 770, 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, optimize_textures=optimize_textures)
  File "/.../gltf2usd/Source/gltf2usd.py", line 74, in __init__
    self.convert()
  File "/.../gltf2usd/Source/gltf2usd.py", line 740, in convert
    self._convert_materials_to_preview_surface_new()
  File "/.../gltf2usd/Source/gltf2usd.py", line 453, in _convert_materials_to_preview_surface_new
    usd_material.convert_material_to_usd_preview_surface(material, self.output_dir)
  File "/.../gltf2usd/Source/_gltf2usd/usd_material.py", line 22, in convert_material_to_usd_preview_surface
    usd_preview_surface = USDPreviewSurface(self._stage, gltf_material, self, output_directory)
  File "/.../gltf2usd/Source/_gltf2usd/usd_material.py", line 42, in __init__
    self._initialize_from_gltf_material(gltf_material)
  File "/.../gltf2usd/Source/_gltf2usd/usd_material.py", line 105, in _initialize_from_gltf_material
    self._set_khr_material_pbr_specular_glossiness(gltf_material)
  File "/.../gltf2usd/Source/_gltf2usd/usd_material.py", line 167, in _set_khr_material_pbr_specular_glossiness
    self._set_pbr_metallic_roughness(gltf_material)
  File "/.../gltf2usd/Source/_gltf2usd/usd_material.py", line 160, in _set_pbr_metallic_roughness
    self._set_pbr_base_color(pbr_metallic_roughness, gltf_material.alpha_mode)
  File "/.../gltf2usd/Source/_gltf2usd/usd_material.py", line 243, in _set_pbr_base_color
    destination = base_color_texture.write_to_directory(self._output_directory, GLTFImage.ImageColorChannels.RGBA)
  File "/.../gltf2usd/Source/_gltf2usd/gltf2/Material.py", line 48, in write_to_directory
    return self._image.write_to_directory(output_directory, channels, texture_prefix, self._tt_offset, self._tt_scale, self._tt_rotation)
  File "/.../gltf2usd/Source/_gltf2usd/gltf2/GLTFImage.py", line 95, in write_to_directory
    img = self._transform_image(img, translate=offset, scale=scale, rotation=rotation)
  File "/.../gltf2usd/Source/_gltf2usd/gltf2/GLTFImage.py", line 175, in _transform_image
    pixel = source_image_pixels[r * width + c]
IndexError: image index out of range

I've tried to investigate, but I'm not sure how the crashing block of code is supposed to work:

for col in range(new_img.size[0]):
    for row in range(new_img.size[1]):
        res = np.matmul(texture_transform_matrix, np.array([col/float(img.width),row/float(img.height),1]))

        c = int(round(_normalized_texcoord(res[0,0]) * height))
        r = int(round(_normalized_texcoord(res[0,1]) * width))
        pixel = source_image_pixels[r * width + c]
        pixels[col, row] = pixel

At least, height == 2048, width == 2048 and len(source_image_pixels) == 2048 * 2048 which is correct. The thing is that r == 2048 too, so the source_image_pixels array goes out of range...

kcoley commented 5 years ago

@silvainSayduck just merged a fix for this: https://github.com/kcoley/gltf2usd/pull/132 Thanks for flagging!

silvainSayduck commented 5 years ago

Awesome, thanks a lot! Testing it now :)

[EDIT] Works perfectly fine! Thanks for the awesome work :)