FlailingFog / KK-Blender-Porter-Pack

Plugin pack for exporting Koikatsu characters to Blender.
310 stars 29 forks source link

Keep original bone structure. #29

Closed MediaMoots closed 2 years ago

MediaMoots commented 2 years ago

As you may have noticed, the current workflow (PMX and CATS) completely nukes the original bone structure, making retargeting animations taken from Koikatsu very time consuming.

One workflow I used was to, use the PMX model, not fix the bones through CATS and manually delete all the extra bones (while comparing the bone structure to GME's fbx export)

This works well but takes an awfully long time.

Since GMEs armature has issues with scale, we also can't use the exported fbx.

Any ideas? Thanks.

FlailingFog commented 2 years ago

Looking back, I kind of forgot what is gained by using CATS to fix the model... I've always it used as part of the process because it nicely connects the main bones together but like you said, using it at all wrecks the bone structure. The plugin code expects the bone changes CATS makes, so currently you're forced to use CATS if you want to use the plugin.

It'd probably be easy to copy their code to do just the bone connections, and if that were done then I think CATS could be dropped and the armature could be preserved to match the one in koikatsu. Though, now that this plugin advertises CATS export compatibility + Unity compatibility, I'd have to check what exactly CATS does so nothing is broken by not using it.

(Also, I'm looking into using the fbx files now, even with the scaling issues. I was originally going to make the fbx files match the pmx files then send it through CATS, but maybe this could be a good opportunity to move away from CATS instead...)

MediaMoots commented 2 years ago

It'd probably be easy to copy their code to do just the bone connections, and if that were done then I think CATS could be dropped and the armature could be preserved to match the one in koikatsu. Though, now that this plugin advertises CATS export compatibility + Unity compatibility, I'd have to check what exactly CATS does so nothing is broken by not using it.

What sort of bone connection/correction does it (CATS) do?

One idea I had for a scripted workflow is this:

  1. Import the PMX model
  2. Import and get a list of bones from GME's FBX
  3. Rename some bones manually (scripted) in the PMX model to match GME (Such as 上半身 -> cf_j_spine01)
  4. Get the list from earlier and iterate through PMX's bones, deleting the ones not in the list.
  5. Profit (I think, haha)

This workflow would remove the need for CATS aside from importing and exporting (which works flawlessly with the workflow from my original comment).

Is there anything else that CATS is necessary for? image Even disabling all the options here, renames all bones and structure.

MediaMoots commented 2 years ago

More info.

GME root bone vs KK animation root bone

GME: image

KK: image

Note the extra BodyTop bone and the different naming of the p_cf_body_bone

MediaMoots commented 2 years ago

Conversion list. (It should all be correct, if not please let me know)

Source:

全ての親
センター
上半身
上半身2
左AH1
左AH2
右AH1
右AH2
左肩
左腕
左ひじ
左手首
左人指1
左人指2
左人指3
左小指1
左小指2
左小指3
左中指1
左中指2
左中指3
左薬指1
左薬指2
左薬指3
左親指0
左親指1
左親指2
右肩
右腕
右ひじ
右手首
右人指1
右人指2
右人指3
右小指1
右小指2
右小指3
右中指1
右中指2
右中指3
右薬指1
右薬指2
右薬指3
右親指0
右親指1
右親指2
首
頭
両目x
_dummy_左目x
_dummy_右目x
左目x
右目x
_shadow_左目x
_shadow_右目x
胸親
左胸操作
右胸操作
下半身
左足
左ひざ
左足首
左つま先
右足
右ひざ
右足首
右つま先
左足IK
左つま先IK
右足IK
右つま先IK

Converted:

X
X
cf_j_spine01
cf_j_spine02
cf_j_bust02_L
X
cf_j_bust02_R
X
cf_d_shoulder02_L
cf_j_arm00_L
cf_j_forearm01_L
cf_j_hand_L
cf_j_index01_L
cf_j_index02_L
cf_j_index03_L
cf_j_little01_L
cf_j_little02_L
cf_j_little03_L
cf_j_middle01_L
cf_j_middle02_L
cf_j_middle03_L
cf_j_ring01_L
cf_j_ring02_L
cf_j_ring03_L
cf_j_thumb01_L
cf_j_thumb02_L
cf_j_thumb03_L
cf_d_shoulder02_R
cf_j_arm00_R
cf_j_forearm01_R
cf_j_hand_R
cf_j_index01_R
cf_j_index02_R
cf_j_index03_R
cf_j_little01_R
cf_j_little02_R
cf_j_little03_R
cf_j_middle01_R
cf_j_middle02_R
cf_j_middle03_R
cf_j_ring01_R
cf_j_ring02_R
cf_j_ring03_R
cf_j_thumb01_R
cf_j_thumb02_R
cf_j_thumb03_R
cf_j_neck
cf_j_head
X
X
X
cf_J_hitomi_tx_L
cf_J_hitomi_tx_R
X
X
X
X
X
cf_j_waist01
cf_j_thigh00_L
cf_j_leg01_L
cf_j_foot_L
X
cf_j_thigh00_R
cf_j_leg01_R
cf_j_foot_R
X
X
X
X
X

A useful tool https://wtools.io/convert-list-to-json-array (X means: Can be removed)

Both of the cf_jfoot(L/R) bones need to be reparented to cf_jleg03(L/R)

MediaMoots commented 2 years ago

Here's a script that does all the above.

All you need to do is:

  1. Import the PMX model through CATS with the following settings image

  2. Import the FBX model from GME

  3. Run the script

  4. Profit

import re
import bpy
import fnmatch

pmx = bpy.data.objects['Model_arm']
gme = bpy.data.objects['Armature']

pmxCJKBoneNames = ["全ての親","センター","上半身","上半身2","左AH1","左AH2","右AH1","右AH2","左肩","左腕","左ひじ","左手首","左人指1","左人指2","左人指3","左小指1","左小指2","左小指3","左中指1","左中指2","左中指3","左薬指1","左薬指2","左薬指3","左親指0","左親指1","左親指2","右肩","右腕","右ひじ","右手首","右人指1","右人指2","右人指3","右小指1","右小指2","右小指3","右中指1","右中指2","右中指3","右薬指1","右薬指2","右薬指3","右親指0","右親指1","右親指2","首","頭","両目x","_dummy_左目x","_dummy_右目x","左目x","右目x","_shadow_左目x","_shadow_右目x","胸親","左胸操作","右胸操作","下半身","左足","左ひざ","左足首","左つま先","右足","右ひざ","右足首","右つま先","左足IK","左つま先IK","右足IK","右つま先IK"]
gmeCJKBoneNames = ["X","X","cf_j_spine01","cf_j_spine02","cf_j_bust02_L","X","cf_j_bust02_R","X","cf_d_shoulder02_L","cf_j_arm00_L","cf_j_forearm01_L","cf_j_hand_L","cf_j_index01_L","cf_j_index02_L","cf_j_index03_L","cf_j_little01_L","cf_j_little02_L","cf_j_little03_L","cf_j_middle01_L","cf_j_middle02_L","cf_j_middle03_L","cf_j_ring01_L","cf_j_ring02_L","cf_j_ring03_L","cf_j_thumb01_L","cf_j_thumb02_L","cf_j_thumb03_L","cf_d_shoulder02_R","cf_j_arm00_R","cf_j_forearm01_R","cf_j_hand_R","cf_j_index01_R","cf_j_index02_R","cf_j_index03_R","cf_j_little01_R","cf_j_little02_R","cf_j_little03_R","cf_j_middle01_R","cf_j_middle02_R","cf_j_middle03_R","cf_j_ring01_R","cf_j_ring02_R","cf_j_ring03_R","cf_j_thumb01_R","cf_j_thumb02_R","cf_j_thumb03_R","cf_j_neck","cf_j_head","X","X","X","cf_J_hitomi_tx_L","cf_J_hitomi_tx_R","X","X","X","X","X","cf_j_waist01","cf_j_thigh00_L","cf_j_leg01_L","cf_j_foot_L","X","cf_j_thigh00_R","cf_j_leg01_R","cf_j_foot_R","X","X","X","X","X"]

gmeBoneList = []

# Rename the root bone from p_cf_body_bone to p_cf_body_00
fixModelForKK = True

# First remove all constraints from PMX
for poseBone in pmx.pose.bones:
    for c in poseBone.constraints:
        poseBone.constraints.remove(c)

# Then rename PMX bones
for pmxBone in pmx.data.bones:
    if pmxBone.name in pmxCJKBoneNames:
        for idx, pmxBoneName in enumerate(pmxCJKBoneNames):
            if fnmatch.fnmatchcase(pmxBone.name, pmxBoneName):
                if not gmeCJKBoneNames[idx] == 'X':
                    pmxBone.name = gmeCJKBoneNames[idx]
                    break

# Prepare a list of bones from GME
for bone in gme.data.bones:
    gmeBoneList.append(bone.name)

# Ensure PMX is selected then enable Edit Mode
pmx.select = True
bpy.ops.object.mode_set(mode='EDIT')

# Remove bones that GME doesn't have from PMX
for editBone in pmx.data.edit_bones:
    if not editBone.name in gmeBoneList:
        pmx.data.edit_bones.remove(editBone)

# Reparent feet bones
pmx.data.edit_bones['cf_j_foot_L'].parent = pmx.data.edit_bones['cf_j_leg03_L']
pmx.data.edit_bones['cf_j_foot_R'].parent = pmx.data.edit_bones['cf_j_leg03_R']

# Renames the root bone to be compatible with KK animations
if fixModelForKK:
    pmx.data.bones['p_cf_body_bone'].name = 'p_cf_body_00'
    pmx.data.edit_bones.remove(pmx.data.edit_bones['BodyTop'])

# Disable Edit Mode for PMX
bpy.ops.object.mode_set(mode='OBJECT')
FlailingFog commented 2 years ago

Thanks for this info! I took a slightly different route: https://github.com/FlailingFog/KK-Blender-Shader-Pack/blob/V5-merger/importing/finalizepmx.py If you import the pmx file using the "Import Model" button in CATS (not the hamburger menu) then run this script, it'll...

Then I imported the fbx animation, selected the pmx armature, then shift selected the fbx animation armature and ran this: https://github.com/FlailingFog/KK-Blender-Shader-Pack/blob/V5-merger/extras/importanimation.py This one...

I forgot I make additional armature edits during the bonedrivers.py script, so that's another thing that could break this

What sort of bone connection/correction does it (CATS) do?

It visually connects bones together like fingers and skirt bones. And turns out it's accessible through an ops command: bpy.ops.cats_manual.connect_bones() Unfortunately it breaks something with the animations, so I left it out.

MediaMoots commented 2 years ago

Quite good, there may be one issue with the above workflow though.

How would it deal with many animations?

With the workflow I posted, you could retarget quickly using the rokoko plugin or even in engine (Unity/UE4) since all the names would match, thus removing the need to process KK animations in blender. This is a big time saver, because there are hundreds of animations that can be exported from KK.

Rename the bones a second time to match the output of CATS's fix model button I guess this keeps compatibility?

Set the bone order to be cf_n_height > cf_j_hips (skipped the other bones since they don't seem to contain animation data) Simply curious, why does this need to be done, is it somehow separated, all my models have them connected correctly (PMX/GME) Original PMX bones: image

Delete some of the useless bones. You can't delete all of the bones because some accessories have pmx armature bones that don't appear on the fbx armature (these are the accessories that have the scaling issue). Good catch, which bones are they?

MediaMoots commented 2 years ago

Here's V2 of my script.

Now it should keep all accessory bones that are in use, and instead of directly deleting the bones, it selects them and then you manually use CATS to merge them to parents.

import re
import bpy
import fnmatch

############################################################### CONFIG

# Rename the root bone from p_cf_body_bone to p_cf_body_00 and deletes extra roots
# NOTE: WIP, only enable this if you have merged the bones already.
fixModelForKK = False

############################################################### PRIVATE

pmx = bpy.data.objects['Model_arm']
pmxBody = bpy.data.objects['Model_mesh']
gme = bpy.data.objects['ArmatureGMESchool']

pmxCJKBoneNames = ["全ての親","センター","上半身","上半身2","左AH1","左AH2","右AH1","右AH2","左肩","左腕","左ひじ","左手首","左人指1","左人指2","左人指3","左小指1","左小指2","左小指3","左中指1","左中指2","左中指3","左薬指1","左薬指2","左薬指3","左親指0","左親指1","左親指2","右肩","右腕","右ひじ","右手首","右人指1","右人指2","右人指3","右小指1","右小指2","右小指3","右中指1","右中指2","右中指3","右薬指1","右薬指2","右薬指3","右親指0","右親指1","右親指2","首","頭","両目x","_dummy_左目x","_dummy_右目x","左目x","右目x","_shadow_左目x","_shadow_右目x","胸親","左胸操作","右胸操作","下半身","左足","左ひざ","左足首","左つま先","右足","右ひざ","右足首","右つま先","左足IK","左つま先IK","右足IK","右つま先IK"]
gmeCJKBoneNames = ["X","X","cf_j_spine01","cf_j_spine02","cf_j_bust02_L","X","cf_j_bust02_R","X","cf_d_shoulder02_L","cf_j_arm00_L","cf_j_forearm01_L","cf_j_hand_L","cf_j_index01_L","cf_j_index02_L","cf_j_index03_L","cf_j_little01_L","cf_j_little02_L","cf_j_little03_L","cf_j_middle01_L","cf_j_middle02_L","cf_j_middle03_L","cf_j_ring01_L","cf_j_ring02_L","cf_j_ring03_L","cf_j_thumb01_L","cf_j_thumb02_L","cf_j_thumb03_L","cf_d_shoulder02_R","cf_j_arm00_R","cf_j_forearm01_R","cf_j_hand_R","cf_j_index01_R","cf_j_index02_R","cf_j_index03_R","cf_j_little01_R","cf_j_little02_R","cf_j_little03_R","cf_j_middle01_R","cf_j_middle02_R","cf_j_middle03_R","cf_j_ring01_R","cf_j_ring02_R","cf_j_ring03_R","cf_j_thumb01_R","cf_j_thumb02_R","cf_j_thumb03_R","cf_j_neck","cf_j_head","X","X","X","cf_J_hitomi_tx_L","cf_J_hitomi_tx_R","X","X","X","X","X","cf_j_waist01","cf_j_thigh00_L","cf_j_leg01_L","cf_j_foot_L","X","cf_j_thigh00_R","cf_j_leg01_R","cf_j_foot_R","X","X","X","X","X"]

############################################################### RENAME & CLEAN

# Rename PMX bones
for pmxBone in pmx.data.bones:
    if pmxBone.name in pmxCJKBoneNames:
        for idx, pmxBoneName in enumerate(pmxCJKBoneNames):
            if fnmatch.fnmatchcase(pmxBone.name, pmxBoneName):
                if not gmeCJKBoneNames[idx] == 'X':
                    pmxBone.name = gmeCJKBoneNames[idx]
                    break

# Remove all constraints from PMX
for poseBone in pmx.pose.bones:
    for c in poseBone.constraints:
        poseBone.constraints.remove(c)

############################################################### DATA COLLECTION

### Function to check for empty vertex groups
def survey(obj):
    maxWeight = {}
    for i in obj.vertex_groups:
        maxWeight[i.index] = 0

    for v in obj.data.vertices:
        for g in v.groups:
            gn = g.group
            w = obj.vertex_groups[g.group].weight(v.index)
            if (maxWeight.get(gn) is None or w>maxWeight[gn]):
                maxWeight[gn] = w
    return maxWeight

# Find empty vertex groups
vertexWeightMap = survey(pmxBody)
vertexIndexes = []
vertexIndexes.extend(vertexWeightMap.keys())
vertexIndexes.sort(key=lambda gn: -gn)

# Prepare a list of vertex group names
vertexGroupNames = []
for vg in pmxBody.vertex_groups:
    vertexGroupNames.append(vg.name)

# Prepare a list of bones from GME
gmeBoneList = []
for bone in gme.data.bones:
    gmeBoneList.append(bone.name)

############################################################### SELECT BONES

# Ensure that only the PMX is selected then enable Edit Mode
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
pmx.select = True
bpy.ops.object.mode_set(mode='EDIT')

# First, delete the bones that are not in vertex groups (For some reason CATS does not remove them when merging weights)
for editBone in pmx.data.edit_bones:
    if not editBone.name in vertexGroupNames:
        pmx.data.edit_bones.remove(editBone)

# Then, select the bones that have empty vertex groups and are not in GME
for idx in vertexIndexes:  
    vg = pmxBody.vertex_groups[idx]
    if vertexWeightMap[idx]<=0 and vg.name not in gmeBoneList:
        print(vg.name)
        pmx.data.edit_bones[vg.name].select = True

##### Finally, manually use CATS to merge weights to parents

############################################################### FINAL CLEANUP

# Reparent feet bones
pmx.data.edit_bones['cf_j_foot_L'].parent = pmx.data.edit_bones['cf_j_leg03_L']
pmx.data.edit_bones['cf_j_foot_R'].parent = pmx.data.edit_bones['cf_j_leg03_R']

# Changes the root bone to be compatible with KK animations (Needs to be run after CATS)
if fixModelForKK:
    pmx.data.bones['p_cf_body_bone'].name = 'p_cf_body_00'
    pmx.data.edit_bones.remove(pmx.data.edit_bones['BodyTop'])
    pmx.data.edit_bones.remove(pmx.data.edit_bones['全ての親'])
FlailingFog commented 2 years ago

Here's V2 of my script.

That could work!

I guess this keeps compatibility?

I have no idea. I just assumed CATS renames the bones so they can be automatically detected in Unity. I haven't tried importing the model without the renamed bones to see what it does. I also think bone names like 'Hips' rather than 'cf_j_hips' are easier to identify

Simply curious, why does this need to be done

They're connected correctly on mine too, and it doesn't need to be done. I just think it makes for a slightly cleaner armature, even if it deviates from the KK armature structure (one center bone instead of multiple).

Good catch, which bones are they?

The ca_slot bones

With the workflow I posted, you could retarget quickly using the rokoko plugin or even in engine (Unity/UE4) since all the names would match, thus removing the need to process KK animations in blender.

Interesting! I didn't know that was possible. Though, I want a specific setup for use inside of blender and the animations would still need to be edited with that specific setup. I want a way to add IKs to the arms to use for non-premade animations and the only way I've found to do it is to connect the tail of the arm bone to the head of the hand bone. This reorients the bone, so the animations for those bones have to be reoriented as well. I guess I consider this another reason to not worry about changing the armature structure, since this setup would require code to get the animations to work anyway. I was able to reorient the animations in line 105 of the script from earlier to make the fbx animations compatible with this change. Not sure how the rokoko plugin handles the reoriented bone issue, but if it does it automagically then that might be easier.

Another thought: What if there were two configurations you could choose from?

MediaMoots commented 2 years ago

What if there were two configurations you could choose from?

That would be perfect, haha

FlailingFog commented 2 years ago

Okay, will do then

MediaMoots commented 2 years ago

image

MediaMoots commented 2 years ago

So, made a script to batch retarget all Armature animations (using the Rokoko addon) in the Source collection to the Armature in the Target collection. I'm not sure if this fits in this addon, but just wanted to share.

import bpy

targetCollection = bpy.data.collections['Target']
targetArmature = targetCollection.objects['Armature']

sourceCollection = bpy.data.collections['Source']
sourceArmatures = sourceCollection.objects

for src in sourceArmatures:
    try:
        if src.type == 'ARMATURE':
            bpy.data.scenes["Scene"].rsl_retargeting_armature_target = targetArmature
            bpy.data.scenes["Scene"].rsl_retargeting_armature_source = src
            bpy.ops.rsl.build_bone_list()
            bpy.ops.rsl.retarget_animation()
    except:
        print('Error')
        pass
FlailingFog commented 2 years ago

I don't see why it couldn't be added. I can put it in as a toggle.

FlailingFog commented 2 years ago

Most of this is in the latest commit, so you can try it if you want.

I haven't installed the rokoko plugin yet so I don't know if the toggle works

Haven't put in the "survey" code for removing the useless pmx bones yet, right now it just removes the kf bones and the cf_hit bones that the pmx armature comes with. There's a dictionary with the fbx bone names in finalizepmx.py so I think I'm going to use that instead of importing the fbx armature to generate the bone list.

If you load another animation in it'll overwrite the current one Switching armature types (stock vs modified) after loading an animation currently breaks the animation

You can switch between the two armature types, but going from modified to stock will just mute the IK/joint drivers and stow the extra (modified) bones created during bonedrivers.py under the pv_root_bone. Do those extra bones matter when retargeting animations with other software (rokoko/unity/unreal)? If it doesn't, then I'll probably keep that behaviour because it makes it easier to switch

MediaMoots commented 2 years ago

click the Import ripped fbx button and choose the ripped fbx file (make sure it's the cf_body_00 type or the "center" bone won't move)

GME's fbx?

If you load another animation in it'll overwrite the current one

Hmm, I'm not sure using KKBP to import animations is really that useful (For me anyway, since I need to convert many animations) All KKBP needs to do (imo) is to preserve the stock skeleton perfectly so that it can be retargeted easily.

What do you think?

FlailingFog commented 2 years ago

GME's fbx?

The ripped fbx animations from \Koikatsu\abdata\action\animator\

All KKBP needs to do (imo) is to preserve the stock skeleton perfectly so that it can be retargeted easily.

That's fair, and if you uncheck the modify armature toggle then it'll preserve everything. I just made it such that the Import fbx button will import the fbx animation file (without processing it) and send it through the rokoko code you put above, but maybe I misunderstood the usage.

MediaMoots commented 2 years ago

I think the way it works now is good.

If you had included the "survey" code to remove unused bones, the naming scheme of separate characters (after export) would be different.

As it is now (I think, needs testing) every character that goes through KKBP will have the same bone structure, and that, I feel, is a good thing, because it makes creating multiple characters in Unity/UE4 easier, e.g. no need to code for separate skeletons.

MediaMoots commented 2 years ago

On an unrelated note, would you know how to solve this sort of issue? image The hair not being in the right place. This is the card: Koikatu_F_20210824140538769_Tempest_Rimiru_ROHss

Thanks.

FlailingFog commented 2 years ago

I think the way it works now is good.

Okay I'll leave it as is then. If needed later it can be added as a toggle

MediaMoots commented 2 years ago

These bones are different from the KK base skeleton.

image

image

MediaMoots commented 2 years ago

If you want, I could make the new KKBP_Exporter plugin not add these extra bones and change bone names. So, no more Japanese bone names/extra bones (AH, etc...) in the pmx. Would that be helpful?

MediaMoots commented 2 years ago

All right, I made changes to the plugin, now it exports the rig 1 to 1 (no extra physics/ik/renamed bones) Feel free to test it. If you end up using it then I'll include the plugin (With the bone export edit) in PR #43

KKBP_Exporter_dev.zip

MediaMoots commented 2 years ago

Bug fix KKBP_Exporter_dev.zip

MediaMoots commented 2 years ago

As it is now (I think, needs testing) every character that goes through KKBP will have the same bone structure, and that, I feel, is a good thing, because it makes creating multiple characters in Unity/UE4 easier, e.g. no need to code for separate skeletons.

After more testing, i found that this is incorrect. There's no benefit in keeping the unused bones for retargeting in UE4.

So maybe it would be good to either use the survey code to delete unused bones during finalize pmx or have the survey/unused bones removal script as a button in the extras section.

Edit: it might still cause issues if we remove unused bones during finalize, I think having a button in Extras is better.

FlailingFog commented 2 years ago

Having the original bone structure would help, I'd just have to redo some parts during the finalize step. The unused / intermediate bones are stored on armature layer 11, so if you select the bones on that layer and use the merge weights thing in CATS it should work the same.

MediaMoots commented 2 years ago

@FlailingFog Ok so, after messing around with the skeleton, I found out that these bones are useful for IK image

So would it be possible to keep them? Thanks!

MediaMoots commented 2 years ago

Also found a bug with the hair select image

It seems that subtracting 1 from the len causes the script to not select the last material in the list, thus giving this result: image

Using this: image

Produces the correct result: image

MediaMoots commented 2 years ago

There is also an issue when NOT using Modified armature to Finalize PMX:

finalizepmx.py", line 665, in execute
    bpy.ops.object.select_all(action='DESELECT')
RuntimeError: Operator bpy.ops.object.select_all.poll() failed, context is incorrect

Changing that line to this solves the issue

for obj in bpy.context.selected_objects:
    obj.select_set(False)

But reintroduces the issue to bonedrivers.py Line 852

Also changing that line to this solves the issue

for obj in bpy.context.selected_objects:
    obj.select_set(False)

I'm not sure why this happens though.

FlailingFog commented 2 years ago

Thanks for finding these. The hit/kf bones are on armature layers 12 and 13 now

MediaMoots commented 2 years ago

Great thanks

i found a bug with this shape key image

I think the teeth are supposed to be closed.

FlailingFog commented 2 years ago

It shouldn't do that anymore.

And semi-related to this, sometimes the original pmx exporter creates a model with broken tongue and lower teeth shapekeys (kuti_sita and kuti_ha). This bug carried over into your new version as well. It only happens on certain cards (like that megumin card from a while back) and I haven't noticed a trend for what causes it. Since you have the source, do you happen to know what could cause it to break only those shapekeys like that?

MediaMoots commented 2 years ago

It shouldn't do that anymore.

Thanks!

Since you have the source, do you happen to know what could cause it to break only those shapekeys like that?

Sure! Here's a plugin changed to "hopefully" fix the issue, please try it. I just removed part of the code that the original plugin used to manually modify shape keys, now it should have only the original keys from KK.

KKBP_Exporter.zip

If it works, please let me know and ill add it to the project.

FlailingFog commented 2 years ago

I just removed part of the code that the original plugin used to manually modify shape keys, now it should have only the original keys from KK.

Are the shapekey names supposed to change with this too? I'm still seeing the original ones (and seeing the same behavior too)

MediaMoots commented 2 years ago

Ah, pity, I'll investigate this issue more. The megumin card has this issue right?

FlailingFog commented 2 years ago

Yeah it happens on that one. I've tracked it down to a specific accessory on the card that's causing the tongue shapekeys to become corrupted called "Tiny ahoge no movement".

I also had one more question for armature stuff, do you care if the accessory bone names are renamed in the original armature structure? Some characters have duplicate accessory bone names and that's causing the following issue: When you have accessories that use the same bone and vertex group names, for example two separate hair pieces that use a dynamic bone name of "joint2", the bones will show as "joint2" and "joint2.001" when imported into blender. The vertex group for "joint2 will contain both the joint2 and joint2.001 bone weights and the joint2.001 vertex group will be empty. I'm assuming this happens during the pmx file import, and the importer screws up because it tries to import the same bone / vertex group names twice but instead just merges them. I'm thinking I could modify the finalizepmx.py script to fix this automatically but it would involve renaming the bones and vertex groups.

MediaMoots commented 2 years ago

Yeah it happens on that one. I've tracked it down to a specific accessory on the card that's causing the tongue shapekeys to become corrupted called "Tiny ahoge no movement".

Cool, thank you, I'll see if I can fix it in the dll plugin

I also had one more question for armature stuff, do you care if the accessory bone names are renamed in the original armature structure?

Yeah, I think as long as the base skeleton is unchanged the acc bones can be renamed.

FlailingFog commented 2 years ago

I've been trying to work the duplicate vertex group issue I noted above, and after looking into it a little further I think the KK pmx exporter is the one causing the vertex groups to merge, not Blender's pmx importer. When I take the pmx file into another program (PMXEditor) it's showing that the vertex groups are already merged.

I feel like this would resolve itself if the KKBP exporter didn't merge all the objects into one like it usually does, and instead kept everything in separate objects, similar to how Grey's mesh exporter does it. Is this an easy thing to do? I'm guessing the pmx exporter merges the meshes at some point, so would it be as simple as deleting that chunk of code?

I'll continue trying to get it to work with the code I have now, but so far the trick I'm using isn't completely cutting it for dense groups of accessories (like when people make hair completely out of accessories).

MediaMoots commented 2 years ago

Ok, yeah, I think I found a bug in the plugin, I'll try and fix it.

MediaMoots commented 2 years ago

image : )

MediaMoots commented 2 years ago

image : )

PR #61

MediaMoots commented 2 years ago

V5 is great, thanks!