Skip to content

Commit

Permalink
fix: add workaround for non-weighted skinned mesh export error
Browse files Browse the repository at this point in the history
  • Loading branch information
saturday06 committed Dec 10, 2024
1 parent 40f06fc commit a47a0d2
Showing 1 changed file with 58 additions and 3 deletions.
61 changes: 58 additions & 3 deletions src/io_scene_vrm/exporter/vrm1_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2260,7 +2260,19 @@ def assign_export_custom_properties(
material.pop(self.extras_material_name_key, None)

@staticmethod
def gltf_export_armature_object_remove(context: Context) -> bool:
def gltf_export_armature_object_remove(
context: Context, mesh_object_names: Sequence[str]
) -> bool:
"""export_armature_object_removeを有効にするかどうかを返す.
export_armature_object_removeは非常に便利でぜひ使いたいが、
バグも多いので、そのバグの影響を受けない場合のみ有効にする。
"""
if bpy.app.version < (4, 2):
return False

# ルートボーンにnot use_deformのものがあったらFalse
# https://github.com/KhronosGroup/glTF-Blender-IO/issues/2394
for selected_object in context.selected_objects:
if selected_object.type != "ARMATURE":
continue
Expand All @@ -2270,9 +2282,50 @@ def gltf_export_armature_object_remove(context: Context) -> bool:
for bone in armature.bones:
if bone.parent:
continue
# https://github.com/KhronosGroup/glTF-Blender-IO/issues/2394
if not bone.use_deform:
return False

# Armatureモディファイアがついていて、ウエイトがついていない頂点があったらFalse
# https://github.com/KhronosGroup/glTF-Blender-IO/issues/2436
for mesh_object_name in mesh_object_names:
mesh_object = context.blend_data.objects.get(mesh_object_name)
if not mesh_object:
continue
if mesh_object.type != "MESH":
continue
mesh = mesh_object.data
if not isinstance(mesh, Mesh):
continue

vertex_group_names_sequence: Sequence[set[str]] = [
{
mesh_object.vertex_groups[group.group].name
for group in vertex.groups
if group.weight > 0
and 0 <= group.group < len(mesh_object.vertex_groups)
}
for vertex in mesh.vertices
]

for modifier in mesh_object.modifiers:
if modifier.type != "ARMATURE":
continue
if not isinstance(modifier, ArmatureModifier):
continue
armature_object = modifier.object
if not armature_object:
continue
armature_data = armature_object.data
if not isinstance(armature_data, Armature):
continue
bone_names = set(armature_data.bones.keys())
for vertex_group_names in vertex_group_names_sequence:
if all(
vertex_group_name not in bone_names
for vertex_group_name in vertex_group_names
):
return False

return True

def export_vrm(self) -> Optional[bytes]:
Expand Down Expand Up @@ -2316,7 +2369,9 @@ def export_vrm(self) -> Optional[bytes]:
use_active_scene=True,
export_animations=True,
export_armature_object_remove=(
self.gltf_export_armature_object_remove(self.context)
self.gltf_export_armature_object_remove(
self.context, mesh_compat_object_names
)
),
export_rest_position_armature=False,
export_apply=False,
Expand Down

0 comments on commit a47a0d2

Please sign in to comment.