glTF 2.0 export fails with NaN float value from specific shape key #104989

Closed
opened 2023-11-05 10:20:48 +01:00 by Vectrobe · 7 comments

System Information
Operating system: win10
Graphics card: n/a

Blender Version
Broken: 3.6.5
Worked: unknown

Short description of error
__fix_json(obj) fails at line 114 at int(obj) where obj is a float but with a NaN value, but what float exactly is a complete mistery here since there is zero tracking and no exception catching, to log what part this exception occurred in.
More exact trigger was found after hours of brute force narrowing down, eventually finding that at least shape key "じと目" in this .blend mesh will trigger the stack dump as follows;

Python: Traceback (most recent call last):
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2_init_.py", line 852, in execute
return gltf2_blender_export.save(context, export_settings)
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 34, in save
json, buffer = __export(export_settings)
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 59, in __export
json = __fix_json(exporter.glTF.to_dict())
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 107, in __fix_json
fixed[key] = __fix_json(value)
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 111, in __fix_json
fixed.append(__fix_json(value))
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 107, in __fix_json
fixed[key] = __fix_json(value)
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 111, in __fix_json
fixed.append(__fix_json(value))
File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 114, in __fix_json
if int(obj) == obj:
ValueError: cannot convert float NaN to integer

Exact steps for others to reproduce the error
load the attached .blend and export > glTF 2.0 with the default settings, it should quickly dump the stack in the console

edit; "EyeSquintRight" also seems to be another shape key that will trigger it

**System Information** Operating system: win10 Graphics card: n/a **Blender Version** Broken: 3.6.5 Worked: unknown **Short description of error** __fix_json(obj) fails at line 114 at int(obj) where obj is a float but with a NaN value, but what float exactly is a complete mistery here since there is zero tracking and no exception catching, to log what part this exception occurred in. More exact trigger was found after hours of brute force narrowing down, eventually finding that at least shape key "じと目" in this .blend mesh will trigger the stack dump as follows; > Python: Traceback (most recent call last): File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\__init__.py", line 852, in execute return gltf2_blender_export.save(context, export_settings) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 34, in save json, buffer = __export(export_settings) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 59, in __export json = __fix_json(exporter.glTF.to_dict()) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 107, in __fix_json fixed[key] = __fix_json(value) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 111, in __fix_json fixed.append(__fix_json(value)) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 107, in __fix_json fixed[key] = __fix_json(value) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 111, in __fix_json fixed.append(__fix_json(value)) File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\addons\io_scene_gltf2\blender\exp\gltf2_blender_export.py", line 114, in __fix_json if int(obj) == obj: ValueError: cannot convert float NaN to integer **Exact steps for others to reproduce the error** load the attached .blend and export > glTF 2.0 with the default settings, it should quickly dump the stack in the console edit; "EyeSquintRight" also seems to be another shape key that will trigger it
Vectrobe added the
Status
Needs Triage
Priority
Normal
Type
Report
labels 2023-11-05 10:20:49 +01:00
Member

There's a similar report from NaN in mesh data over at https://github.com/KhronosGroup/glTF-Blender-IO/issues/1446.

It looks like Mesh.validate() doesn't validate shape keys though, so NaN in a shape key can produce the error seen here.

Note than NaN values in model data usually indicate a bug in the steps used to create the model. If you can track down exactly which step caused some values to be set to NaN, then please either report that to Blender or the addon responsible.

In this case, both the じと目 and EyeSquintRight shape keys of the mesh.003 Mesh have a bunch of NaN values on the model's whiskers, backs of the eye balls and the quad inside the chest.

This script will go through all meshes in the .blend file and find any NaN values in shape keys. I included a few lines of code that can be uncommented by removing the # to either select the vertices or to effectively reset the shape key indices that have NaN values.

import bpy
from math import isnan

"""
Run this script from Object mode to find all shape keys that have NaN values and at which indices
"""
for mesh in bpy.data.meshes:
    shape_keys = mesh.shape_keys
    if not shape_keys:
        continue
    for shape_idx, shape in enumerate(shape_keys.key_blocks):
        for i, v in enumerate(shape.data):
            if any(map(isnan, v.co)):
                # Print info to the System Console
                print(f"Shape key [{shape_idx}] '{shape.name}' on mesh '{mesh.name}' has a NaN value at index {i}: {v.co}")
                # Uncomment to select the vertices (enable Vertex Selection Mode in Edit mode first)
                #mesh.vertices[i].select = True

                # Uncomment the following lines to replace the NaN values with no shape key movement
                #if shape.relative_key != shape:
                #    v.co = shape.relative_key.data[i].co
                #else:
                #    v.co = (0, 0, 0)
There's a similar report from NaN in mesh data over at https://github.com/KhronosGroup/glTF-Blender-IO/issues/1446. It looks like `Mesh.validate()` doesn't validate shape keys though, so NaN in a shape key can produce the error seen here. Note than NaN values in model data usually indicate a bug in the steps used to create the model. If you can track down exactly which step caused some values to be set to NaN, then please either report that to Blender or the addon responsible. In this case, both the `じと目` and `EyeSquintRight` shape keys of the `mesh.003` Mesh have a bunch of NaN values on the model's whiskers, backs of the eye balls and the quad inside the chest. This script will go through all meshes in the .blend file and find any NaN values in shape keys. I included a few lines of code that can be uncommented by removing the `#` to either select the vertices or to effectively reset the shape key indices that have NaN values. ```py import bpy from math import isnan """ Run this script from Object mode to find all shape keys that have NaN values and at which indices """ for mesh in bpy.data.meshes: shape_keys = mesh.shape_keys if not shape_keys: continue for shape_idx, shape in enumerate(shape_keys.key_blocks): for i, v in enumerate(shape.data): if any(map(isnan, v.co)): # Print info to the System Console print(f"Shape key [{shape_idx}] '{shape.name}' on mesh '{mesh.name}' has a NaN value at index {i}: {v.co}") # Uncomment to select the vertices (enable Vertex Selection Mode in Edit mode first) #mesh.vertices[i].select = True # Uncomment the following lines to replace the NaN values with no shape key movement #if shape.relative_key != shape: # v.co = shape.relative_key.data[i].co #else: # v.co = (0, 0, 0) ```
Member

Hello,

So the question is: Should I/O manage these check on their own, or should consistency of mesh be centralized by mesh module (by extension of validate() to shape keys?

Hello, So the question is: Should I/O manage these check on their own, or should consistency of mesh be centralized by mesh module (by extension of _validate()_ to shape keys?
Author

well we can break this down into 4 parts;

1; bug-0, the origin of the NaN values, however I have no clue where this bug exists and this model was not made by me, so for now we just have to ignore this

2; sanity, blender at no point catches that NaN values exist in any of the shape keys, nothing is ever logged and manually editing the shape keys fails to show or change any abnormalies

3; export safety, at no point does exporting check for sanity, this possibly affects more than just glTF as other formats I have exported to also seem to be corrupted in different ways, but I have not fully confirmed this

4; glTF export lacks exception catching to log at what point exactly something has failed and why, this is the big one since the user is completely unable to figure out why this stack dump even occurs, unless they so happen to also be a python coder and can edit the export script directly

extra 5th point; the blender UI does not work well during this, the mouse cursor becomes corrupted, blender itself locks up for a while, and then the python stack dump flashes on screen for only one frame and dissappears, but I expect this is already reported

well we can break this down into 4 parts; 1; bug-0, the origin of the NaN values, however I have no clue where this bug exists and this model was not made by me, so for now we just have to ignore this 2; sanity, blender at no point catches that NaN values exist in any of the shape keys, nothing is ever logged and manually editing the shape keys fails to show or change any abnormalies 3; export safety, at no point does exporting check for sanity, this possibly affects more than just glTF as other formats I have exported to also seem to be corrupted in different ways, but I have not fully confirmed this 4; glTF export lacks exception catching to log at what point exactly something has failed and why, this is the big one since the user is completely unable to figure out why this stack dump even occurs, unless they so happen to also be a python coder and can edit the export script directly extra 5th point; the blender UI does not work well during this, the mouse cursor becomes corrupted, blender itself locks up for a while, and then the python stack dump flashes on screen for only one frame and dissappears, but I expect this is already reported

It seems good to extend mesh validate to include shape keys too. But I would also expect exporters/importers to be robust to NaN values, and either preserve them or set them to zero.

It seems good to extend mesh validate to include shape keys too. But I would also expect exporters/importers to be robust to NaN values, and either preserve them or set them to zero.
Member

Here is the PR for glTF exporter.
https://github.com/KhronosGroup/glTF-Blender-IO/pull/2045/files

Will apply it to main, as we are close to 4.0 release, and this is not a regression

Here is the PR for glTF exporter. https://github.com/KhronosGroup/glTF-Blender-IO/pull/2045/files Will apply it to main, as we are close to 4.0 release, and this is not a regression
Julien Duroure self-assigned this 2023-11-06 10:41:50 +01:00
Julien Duroure added
Status
Confirmed
Type
Bug
and removed
Status
Needs Triage
Type
Report
labels 2023-11-06 10:42:15 +01:00

It seems good to extend mesh validate to include shape keys too. But I would also expect exporters/importers to be robust to NaN values, and either preserve them or set them to zero.

That's a bit knew to me... so far official position afaik was that NaN values in meshes was data corruption/bug, and we never expected exporters to be resilient to these (iirc we still have these NaN values creeping in UV maps sometimes too, which breaks FBX exporter e.g.)?

> It seems good to extend mesh validate to include shape keys too. But I would also expect exporters/importers to be robust to NaN values, and either preserve them or set them to zero. That's a bit knew to me... so far official position afaik was that NaN values in meshes was data corruption/bug, and we never expected exporters to be resilient to these (iirc we still have these NaN values creeping in UV maps sometimes too, which breaks FBX exporter e.g.)?

Built-in Blender operators don't crash or stop working on NaN values, I would expect operators in add-ons to do the same. The result might not be as expected, but they can still output something.

Built-in Blender operators don't crash or stop working on NaN values, I would expect operators in add-ons to do the same. The result might not be as expected, but they can still output something.
Blender Bot added
Status
Resolved
and removed
Status
Confirmed
labels 2023-11-19 10:28:04 +01:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender-addons#104989
No description provided.