diff --git a/core/import_pmx.py b/core/import_pmx.py index 764979f..19595ee 100644 --- a/core/import_pmx.py +++ b/core/import_pmx.py @@ -200,39 +200,77 @@ def read_bone(file: BufferedReader, string_build, byte_size): print(f"Current file position: {file.tell()}") raise +def set_bone_local_axis(bone, local_x, local_z): + # Convert from MMD to Blender coordinate system + x_axis = Vector(local_x).xzy + z_axis = Vector(local_z).xzy + y_axis = z_axis.cross(x_axis) + + # Create rotation matrix from axes + matrix = Matrix([x_axis, y_axis, z_axis]).transposed() + bone.matrix_local = matrix.to_4x4() + +def finalize_armature(armature_obj): + # Apply MMD to Blender space conversion + armature_obj.rotation_euler[0] = 1.5708 # 90 degrees in radians + armature_obj.rotation_euler[2] = 3.14159 # 180 degrees in radians + + # Apply scale to armature + armature_obj.scale = (scale, scale, scale) + + # Apply transforms + bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) + def create_bones(armature_obj, bones_data, scale=0.08): bpy.context.view_layer.objects.active = armature_obj bpy.ops.object.mode_set(mode='EDIT') edit_bones = [] - for bone_data in bones_data: - bone = armature_obj.data.edit_bones.new(bone_data[0]) - # Scale the head position - bone.head = Vector(bone_data[2]).xzy * scale + for i, bone_data in enumerate(bones_data): + try: + print(f"Creating bone {i}: {bone_data[0]}") + bone = armature_obj.data.edit_bones.new(bone_data[0]) + + # Convert and scale head position + head_pos = Vector(bone_data[2]).xzy * scale + bone.head = head_pos + + # Handle tail position + if bone_data[6][0] is not None: + tail_pos = Vector(bone_data[6]).xzy * scale + bone.tail = tail_pos + print(f"Using defined tail position for bone {bone_data[0]}") + else: + # Set a default tail position if not provided + bone.tail = head_pos + Vector((0, 0.1, 0)) * scale + print(f"Using default tail position for bone {bone_data[0]}") + + # Set parent if exists + if bone_data[3] != -1: + parent_bone = armature_obj.data.edit_bones[bones_data[bone_data[3]][0]] + bone.parent = parent_bone + print(f"Parented bone {bone_data[0]} to {parent_bone.name}") + + edit_bones.append(bone) + + except Exception as e: + print(f"Error creating bone {i}: {str(e)}") + continue - # Handle tail position with scale - if isinstance(bone_data[6], int) and bone_data[6] != -1: - target_pos = Vector(bones_data[bone_data[6]][2]).xzy * scale - bone.tail = target_pos - else: - offset = Vector(bone_data[6]).xzy * scale - bone.tail = bone.head + offset - - if bone.length < 0.001: - bone.tail = bone.head + Vector((0, 0, 0.001)) - - edit_bones.append(bone) - - # Set parent relationships + # Set bone hierarchy for i, bone_data in enumerate(bones_data): if bone_data[3] != -1: edit_bones[i].parent = edit_bones[bone_data[3]] + # Apply final transforms bpy.ops.object.mode_set(mode='OBJECT') + armature_obj.rotation_euler[0] = 1.5708 + armature_obj.rotation_euler[2] = 3.14159 + armature_obj.select_set(True) + bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) + return edit_bones - - def read_morph(file: BufferedReader, morph_struct, morph_bytesize, vertex_struct, vertex_size, bone_struct, bone_size, material_struct, material_size, rigid_struct, rigid_size): morph_name = str(file.read(struct.unpack('