FBX Import crashes due to parentship circle (RecursionError) #73790

Open
opened 2020-02-14 03:36:49 +01:00 by Ben · 4 comments

System Information
Operating system: Windows 10
Graphics card: NVIDIA GeForce GTX 1080 Ti

Blender Version
version: 2.81 (sub 16), branch: master, commit date: 2019-12-04 11:32, hash: f1aa4d18d49d, type: Release
build date: 2019-12-04, 14:30:40

Description of error

First of all, sorry for the long post. I thought it may help to quickly track down the issue when I attach some more information of what is going on. To the bug:
It seems like the some parent <-> child relationships get changed during import, which in my case results in an parentship circle and a crash due to recursion depth exceeded:

Traceback (most recent call last):
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\__init__.py", line 216, in execute
    if import_fbx.load(self, context, filepath=path, **keywords) == {'FINISHED'}:
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 2813, in load
    _(); del _
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 2801, in _
    root_helper.collect_armature_meshes()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1923, in collect_armature_meshes
    child.collect_armature_meshes()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1923, in collect_armature_meshes
    child.collect_armature_meshes()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1923, in collect_armature_meshes
    child.collect_armature_meshes()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1916, in collect_armature_meshes
    m.matrix = armature_matrix_inv @ m.get_world_matrix()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1860, in get_world_matrix
    matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1854, in get_world_matrix_as_parent
    matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1854, in get_world_matrix_as_parent
    matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix()
  File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1854, in get_world_matrix_as_parent
    matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix()
  [Previous line repeated 989 more times]
RecursionError: maximum recursion depth exceeded

Jumped into io_scene_fbx/import.fbx and called the FbxImportHelperNode::PrintInfo method before collect_armature_meshes get's called.
This is the hierarchy it spits out (for the fbx attached):

Unknown[root][HBC]
 DummyRoot[HBC]
  rep_inf_ep3trooper[HBC]
   bone_root[armature][HBC]
    root_a_spine[armature][bone][HBC]
     bone_a_spine[bone][HBC]
      bone_b_spine[bone][HBC]
       bone_ribcage[bone][HBC]
        eff_ribcage[bone][HBC]
         root_l_clavicle[bone][HBC]
          bone_l_clavicle[bone][HBC]
           eff_l_clavicle[bone][HBC]
            root_l_upperarm[bone][HBC]
             bone_l_upperarm[bone][HBC]
              bone_l_forearm[bone][HBC]
               eff_l_forearm[bone][HBC]
                root_l_hand[bone][HBC]
                 bone_l_hand[bone][HBC]
                  eff_l_hand[bone]
         root_r_clavicle[bone][HBC]
          bone_r_clavicle[bone][HBC]
           eff_r_clavicle[bone][HBC]
            root_r_upperarm[bone][HBC]
             bone_r_upperarm[bone][HBC]
              bone_r_forearm[bone][HBC]
               eff_r_forearm[bone][HBC]
                root_r_hand[bone][HBC]
                 bone_r_hand[bone][HBC]
                  eff_r_hand[bone]
                  hp_weapons
         root_neck[bone][HBC]
          bone_neck[bone][HBC]
           bone_head[bone][HBC]
            eff_head[bone]
    bone_pelvis[bone][HBC]
     root_r_thigh[bone][HBC]
      bone_r_thigh[bone][HBC]
       bone_r_calf[bone][HBC]
        eff_r_calf[bone][HBC]
         root_r_foot[bone][HBC]
          bone_r_foot[bone][HBC]
           bone_r_toe[bone][HBC]
            eff_r_toe[bone]
     root_l_thigh[bone][HBC]
      bone_l_thigh[bone][HBC]
       bone_l_calf[bone][HBC]
        eff_l_calf[bone][HBC]
         root_l_foot[bone][HBC]
          bone_l_foot[bone][HBC]
           bone_l_toe[bone][HBC]
            eff_l_toe[bone]

This is the exact hierarchy as expected.
Since the error occoured in get_world_matrix_as_parent : 1857, I added two print instructions to see what the child <-> parent relationship at that point is:

    def get_world_matrix_as_parent(self):
        # lets see what's going on here...
        print("self:     " + str(self))
        print("  parent: " + str(self.parent))

        matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix()
        if self.matrix_as_parent:
            matrix = matrix @ self.matrix_as_parent
        return matrix

Turns out, at some point rep_inf_ep3trooperis no longer parented to DummyRoot, but root_a_spine (Log output):

self:     rep_inf_ep3trooper Model
  parent: DummyRoot Model
self:     DummyRoot Model
  parent: None
self:     None
  parent: None
self:     bone_root Model
  parent: rep_inf_ep3trooper Model
self:     rep_inf_ep3trooper Model
  parent: DummyRoot Model
self:     DummyRoot Model
  parent: None
self:     None
  parent: None
self:     DummyRoot Model
  parent: None
self:     None
  parent: None
self:     root_a_spine Model
  parent: bone_root Model
self:     bone_root Model
  parent: rep_inf_ep3trooper Model
self:     rep_inf_ep3trooper Model
  parent: root_a_spine Model
self:     root_a_spine Model
  parent: bone_root Model
self:     bone_root Model
  parent: rep_inf_ep3trooper Model
self:     rep_inf_ep3trooper Model
  parent: root_a_spine Model

Which of course results in a parentship circle.
Went back to the collect_armature_meshes method and removed the #70244 fix (maybe the fix introduced this?). Import was successfull, but no amature and no mesh imported...

Tried something else, commented out m.parent = self in import_fbx.py : 1919, everything imports (yay!), but my animations are broken.

            for m in meshes:
                old_matrix = m.matrix
                m.matrix = armature_matrix_inv @ m.get_world_matrix()
                m.anim_compensation_matrix = old_matrix.inverted_safe() @ m.matrix
                m.is_global_animation = True
                #m.parent = self   # no no

So I don't know where to go from here. Thought I should share my results, so that some developer can fix this properly (better than simply commenting out a line that's probably there for a reason).
Respective FBX file is attached. Note that it works just fine in Maya, Autodesk FBX Review and Unity.

Exact steps for others to reproduce the error
Import the fbx file attached{F8338792}

**System Information** Operating system: Windows 10 Graphics card: NVIDIA GeForce GTX 1080 Ti **Blender Version** version: 2.81 (sub 16), branch: master, commit date: 2019-12-04 11:32, hash: f1aa4d18d49d, type: Release build date: 2019-12-04, 14:30:40 **Description of error** First of all, sorry for the long post. I thought it may help to quickly track down the issue when I attach some more information of what is going on. To the bug: It seems like the some parent <-> child relationships get changed during import, which in my case results in an parentship circle and a crash due to *recursion depth exceeded*: ``` Traceback (most recent call last): File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\__init__.py", line 216, in execute if import_fbx.load(self, context, filepath=path, **keywords) == {'FINISHED'}: File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 2813, in load _(); del _ File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 2801, in _ root_helper.collect_armature_meshes() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1923, in collect_armature_meshes child.collect_armature_meshes() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1923, in collect_armature_meshes child.collect_armature_meshes() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1923, in collect_armature_meshes child.collect_armature_meshes() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1916, in collect_armature_meshes m.matrix = armature_matrix_inv @ m.get_world_matrix() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1860, in get_world_matrix matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1854, in get_world_matrix_as_parent matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1854, in get_world_matrix_as_parent matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() File "F:\blender-2.81a-windows64\2.81\scripts\addons\io_scene_fbx\import_fbx.py", line 1854, in get_world_matrix_as_parent matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() [Previous line repeated 989 more times] RecursionError: maximum recursion depth exceeded ``` Jumped into io_scene_fbx/import.fbx and called the *FbxImportHelperNode::PrintInfo* method before *collect_armature_meshes* get's called. This is the hierarchy it spits out (for the fbx attached): ``` Unknown[root][HBC] DummyRoot[HBC] rep_inf_ep3trooper[HBC] bone_root[armature][HBC] root_a_spine[armature][bone][HBC] bone_a_spine[bone][HBC] bone_b_spine[bone][HBC] bone_ribcage[bone][HBC] eff_ribcage[bone][HBC] root_l_clavicle[bone][HBC] bone_l_clavicle[bone][HBC] eff_l_clavicle[bone][HBC] root_l_upperarm[bone][HBC] bone_l_upperarm[bone][HBC] bone_l_forearm[bone][HBC] eff_l_forearm[bone][HBC] root_l_hand[bone][HBC] bone_l_hand[bone][HBC] eff_l_hand[bone] root_r_clavicle[bone][HBC] bone_r_clavicle[bone][HBC] eff_r_clavicle[bone][HBC] root_r_upperarm[bone][HBC] bone_r_upperarm[bone][HBC] bone_r_forearm[bone][HBC] eff_r_forearm[bone][HBC] root_r_hand[bone][HBC] bone_r_hand[bone][HBC] eff_r_hand[bone] hp_weapons root_neck[bone][HBC] bone_neck[bone][HBC] bone_head[bone][HBC] eff_head[bone] bone_pelvis[bone][HBC] root_r_thigh[bone][HBC] bone_r_thigh[bone][HBC] bone_r_calf[bone][HBC] eff_r_calf[bone][HBC] root_r_foot[bone][HBC] bone_r_foot[bone][HBC] bone_r_toe[bone][HBC] eff_r_toe[bone] root_l_thigh[bone][HBC] bone_l_thigh[bone][HBC] bone_l_calf[bone][HBC] eff_l_calf[bone][HBC] root_l_foot[bone][HBC] bone_l_foot[bone][HBC] bone_l_toe[bone][HBC] eff_l_toe[bone] ``` This is the exact hierarchy as expected. Since the error occoured in *get_world_matrix_as_parent : 1857*, I added two print instructions to see what the child <-> parent relationship at that point is: ``` def get_world_matrix_as_parent(self): # lets see what's going on here... print("self: " + str(self)) print(" parent: " + str(self.parent)) matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() if self.matrix_as_parent: matrix = matrix @ self.matrix_as_parent return matrix ``` Turns out, at some point *rep_inf_ep3trooper*is no longer parented to *DummyRoot*, but *root_a_spine* (Log output): ``` self: rep_inf_ep3trooper Model parent: DummyRoot Model self: DummyRoot Model parent: None self: None parent: None self: bone_root Model parent: rep_inf_ep3trooper Model self: rep_inf_ep3trooper Model parent: DummyRoot Model self: DummyRoot Model parent: None self: None parent: None self: DummyRoot Model parent: None self: None parent: None self: root_a_spine Model parent: bone_root Model self: bone_root Model parent: rep_inf_ep3trooper Model self: rep_inf_ep3trooper Model parent: root_a_spine Model self: root_a_spine Model parent: bone_root Model self: bone_root Model parent: rep_inf_ep3trooper Model self: rep_inf_ep3trooper Model parent: root_a_spine Model ``` Which of course results in a parentship circle. Went back to the *collect_armature_meshes* method and removed the #70244 fix (maybe the fix introduced this?). Import was successfull, but no amature and no mesh imported... Tried something else, commented out *m.parent = self* in *import_fbx.py : 1919*, everything imports (yay!), but my animations are broken. ``` for m in meshes: old_matrix = m.matrix m.matrix = armature_matrix_inv @ m.get_world_matrix() m.anim_compensation_matrix = old_matrix.inverted_safe() @ m.matrix m.is_global_animation = True #m.parent = self # no no ``` So I don't know where to go from here. Thought I should share my results, so that some developer can fix this properly (better than simply commenting out a line that's probably there for a reason). Respective FBX file is attached. Note that it works just fine in Maya, Autodesk FBX Review and Unity. **Exact steps for others to reproduce the error** Import the fbx file attached{[F8338792](https://archive.blender.org/developer/F8338792/rep_inf_ep3trooper.fbx)}
Author

Added subscriber: @Ben1138

Added subscriber: @Ben1138
Member

Added subscriber: @lichtwerk

Added subscriber: @lichtwerk
Member

Changed status from 'Needs Triage' to: 'Confirmed'

Changed status from 'Needs Triage' to: 'Confirmed'
Member

could be related to {#47344}? (in that the root bone is itself parented? not sure though...)

could be related to {#47344}? (in that the root bone is itself parented? not sure though...)
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 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#73790
No description provided.