-
Notifications
You must be signed in to change notification settings - Fork 1
Transferring a costume with new physics bones and adapted animations
In my previous tutorial, we transferred a costume from one character to another, and we removed the extra bones that were not available on that model. Specifically, I removed the bones for ribbons from Agnès' swimsuit, since Shizuna's model did not have the ribbon physics. But what if we wanted to preserve those physics? Moreover, what if we wanted to preserve custom animations for bones that are only partially animated by physics (or not at all)? We can!
Photo Credit: fakecheng
So today we are going to explore an alternate way to port a costume, where we move parts of the skeleton from one character to another. It is expected that you have already done the previous tutorial. For this tutorial, I will actually be using fakecheng's amazing fan recreation of Renne's exclusive Grim Kitty DLC (with permission), since the original is not available to PC gamers.
If we want to port Judith's Grimcat outfit to other characters, such as Renne, we would have to deal with the lack of tail bones on every other character.
On the left, you can see what would happen if I used the prior tutorial's method of transferring weight to the first common ancestor, which in this case is the hips - the tail is a rigid, perfectly straight rod. Not pretty. In the middle, physics bones have been added, similar to my Trails of Cold Steel physics bones tutorial. Notice that the physics system in Trails into Daybreak is vastly improved - the tail is obviously and nicely curved with gravity effect. In fact, in the final mod, we only modified 4 out of 179 animations, and relied on physics for the rest! On the right, we have added Judith's idle tail animation to Renne, for a much more convincing mod.
To my knowledge, most of the bones of a skeleton are used exclusively by the animators, and if those bones are not present on the recipient model, then they will not move without custom animations (which we will address). Luckily, many of the bones are primarily manipulated by the physics system instead. These bones (like the skirt bones, hair bones, chest bones, etc), are capable of moving by themselves, which means that preserving them does preserve some of their natural motion with gravity and the wind. They also tend to either not have children, or their children are also physics bones, which makes porting them very easy.
To demonstrate this, I will give Renne the grimcats outfit from Judith, which requires a tail with physics. I will be using Renne's Kuro 2 outfit (chr5114_c10.mdl) as a recipient, and Judith's Grimcat outfit (chr5007_c03.mdl) as a donor.
To start, unpack the donor and recipient models. Identify the missing bones, but do not merge or delete them. (Go ahead and delete parts you do not need before evaluating bones, to make the process simpler by reducing the number of bones you need to transfer. Note that anything you delete now will need to be replicated later - we will not be using any of these meshes at the end!)
You will notice that I am actually missing quite a few bones, such as Tail_01, Tail_02, Tail_03 and so on. These are all tail bones, and they are all physics bones. (If you open up the .json file for the model they come from {chr5007_c03.mi}, you will see many physics parameters which govern their spontaneous / calculated motion.) Renne's model does not have tail physics, so we will need to add them.
In the above screens, you may have also noticed a missing group called BC01. Interestingly, BC01 (a skirt bone) does not even exist on the skeleton of chr5007_c03! If you look at the vertices that contain BC01, they all have nearly zero influence from BC01. We can safely ignore this group and focus on the tail bones. If BC01 did exist on the skeleton, you would transfer it in the same way as you will transfer the tail bones, described below.
First, prepare your Renne folder (chr5114_c10). Delete every file except for material_info.json (and image_list.json, if you like).
Convert both models to glTF binary format (.glb) using kuro_mdl_to_basic_gltf.py.
python kuro_mdl_to_basic_gltf.py chr5007_c03.mdl
python kuro_mdl_to_basic_gltf.py chr5114_c10.mdl
Import chr5114_c10.glb with Bone Dir set to "Blender (best for re-importing)". Optional: Name the model Renne. Import chr5007_c03.glb with the same settings, naming it Judith.
NOTE: Be sure to import your recipient first, then your donor! Certain duplicate structures are automatically renamed by Blender to avoid conflicts, and we do not want anything in the recipient renamed.
Scale your donor model to match your recipient model. Object -> Transform -> Scale, then pull the mesh until neck lines up with the head. Then apply your changes (Object -> Apply -> Scale). (Since we are transferring the tail bones, it is arguably most important to match the level of the hips, but this can be hard to see.)
Expand out Judith's entry and select the Armature. (Armature.001 in the picture)
Go into Edit Mode. Then expand out the entire skeleton, and select all the tail bones at once. (Click on Tail_01, then SHIFT-click on Tail_Top. Be sure to do this in the Outliner, because Tail_01 is hidden inside her mesh!)
Note that the parent of Tail_01 is Hips. You must start with a bone that is attached to a bone that already exists on your recipient model! We start with Tail_01 because Renne does have Hips. We cannot start with Tail_02 because Renne does not have Tail_01, which is the parent of Tail_02.
Separate the tail bones away from Judith. (Armature menu -> Separate Bones)
You should now see a new base model, Judith.001. This only contains your tail bones.
Go into Object Mode. Select Judith.001, then select Renne. (Renne's skeleton should be outlined in orange, and Judith's in red) Join the tail bones to Renne's model (Object menu -> Join). As always, be careful of the join direction: A->B is not the same as B->A! Judith.001 should be gone, and Renne should remain.
The tail bones are now part of Renne's Armature, but they are not yet properly attached to the skeleton (Tail_01 should be a child of Hips). Select Renne's armature, and once again go into Edit Mode.
In Edit Mode, in the Outliner, click on Tail_01, then CTRL-click on Hips. (You can try to do this in the 3D viewport, but it would be difficult since you cannot see either Tail_01 or Hips with meshes in the way.)
Parent Tail_01 to Hips. (Armature menu -> Parent -> Make.) When presented with the options, select Keep Offset.
The tail bones have now been attached to Renne's skeleton!
For this step, we will transfer Judith's entire body mesh to Renne's body mesh. (I have not found a quick way to transfer individual submeshes, but it does not matter. This method is very fast and foolproof.)
Go into Object mode. Click on Judith's body mesh (chr5007_c03_setup1), then ctrl-click on Renne's body mesh (chr5114_c10_setup02). Judith's body should be outlined in red, Renne's body in orange. Join the meshes. (Object Mode -> Object Menu -> Join, or Ctrl-J). Be sure you joined Judith's body to Renne's body, and not Renne's body to Judith's body! (Order matters!) In the outliner, only the name of Renne's body mesh should remain, not the name of Judith's body.
Note that Renne's body mesh has changed from 10 submeshes to 18 submeshes.
Select Judith (whatever is left of her) and Delete Hierarchy to remove the remainder of the model. When you export, you want to export only a single model, since the game (and my scripts) only accept single models.
After making appropriate backups, export as chr5114_c10.glb, overwriting the original (File menu -> Export -> glTF 2.0). Turn on Tangents export (Geometry -> Mesh -> Tangents).
Remember when we emptied Renne's folder of every file except her materials? It is time to fill that folder with the assets from chr5114_c10.glb. We want to have complete .vgmaps for this next step, so edit kuro_gltf_to_meshes.py and change line 25 complete_vgmaps_default
to True.
From the command line, run kuro_gltf_to_meshes.py on your new .glb file. python kuro_gltf_to_meshes.py chr5114_c10.glb
(Or you can double click kuro_gltf_to_meshes.py and it will attempt to work on every .glb file it finds. Just skip Judith's when it asks.)
From here we will be returning to the original techniques with the prior tutorials. Save your work in Blender, and open a new file / workspace. Import your new meshes, inspect them, and delete the meshes you do not need. I do not need 00-05 (Renne's prior body) or 14-17 (Judith's head), so I deleted the files in a manner identical to the basic tutorial. (I deleted chr5114_c10_setup02_00.vb, chr5114_c10_setup02_01.vb, and so on.)
There is still work to do, changing texture colors, bonding the head to the neck, customizing the model, etc. However, now is a good time to make sure our model works.
The MDL cannot be re-compiled until materials are assigned to all existing meshes. Open chr5114_c10/mesh_info.json
in a JSON editor. Note that meshes chr5114_c10_setup02_06 through chr5114_c10_setup02_09 are originals from Renne, and the materials needed are already in Renne's chr5114_c10/material_info.json
; however chr5114_c10_setup02_10 through chr5114_c10_setup02_13 come from Judith and are new to Renne. Further, Judith's body_skin
has been renamed by Blender to body_skin.001
because models cannot have duplicate materials.
We need to move body_skin
, g_add
, g_metal
, and g_titu
from Judith to Renne's chr5114_c10/material_info.json
. Open Renne's chr5007_c03/material_info.json
and copy the entries to chr5114_c10/material_info.json
Make sure to rename Judith's body_skin
to body_skin.001
.
NOTE: All the changes necessary are in material_info.json. Do not edit mesh_info.json! The import script will skip over entries with missing .fmt/.ib/.vb files automatically. Removing the entries from mesh_info.json will confuse the import script, which counts from the first entry to the last - as implied by the name, id_referenceonly
is ignored and is only for your reference.
After adding the materials to material_info.json, we can now rebuild the mdl with kuro_mdl_import_meshes.py.
If you followed every step correctly, you should now have a working model!
It is now time to finish the model, by connecting the head to the neck, changing textures, etc. However, fakecheng has already made this mod, and even did body sculpting, added the eye mask, changed the shape of the ears, everything. So here is the finished model!
The tail in the above photo is still straight and without any motion. We need to edit the dynamic parameters, which are in the model configuration files (.json in Kuro 1, .mi in Kuro 2). I obtained chr5007_c03.mi and chr5114_c10.mi. Use cle_decrypt_decompress.py to decrypt and decompress them. Despite the .mi extension, they are JSON files and can be edited in a JSON editor.
The section we want from chr5007_c03.mi is in the DynamicBone
section. Grab the final entry, which has all the tail bones, and transfer it to the DynamicBone
section of chr5114_c10.mi. Also, if the bones you are transferring have entries in DynamicBoneCollider
, you can transfer those too (our model does not).
Make sure to compress and encrypt chr5114_c10.mi when you are finished editing it. This is for CLE Kuro 2. If you are editing .json files for Kuro 1, you can skip compression and encryption.
Make a backup, and replace the file in the game. Renne's tail should now have physics!
Adding physics actually is all that is necessary, and the tail moves quite well in most situations. The system is a significant improvement over the prior generation of games. However, the lack of tail droop and curl is still quite noticeable in the idle position, where there is little influence from the physics system. It is here that the lack of animation is very noticeable, so we will take the tail animations from Judith's idle pose, and insert them into Renne's idle pose. We do not want to replace Renne's unique idle pose with Judith's - we only want the tail animation!
Download a special script I wrote just for this, add_ani_bones.py (Right-click, Save As). Note that you must use command line for this tool!
Copy both Judith's idle pose and Renne's idle pose into a folder, they are from the same folder as the models. Each pose has 4 files - two idle poses and two transition poses. They play in the order of pose 1, pose 1->2, pose 2, pose 2->1.
chr5007_m_wait.mdl
chr5007_m_wait2.mdl
chr5007_m_wait2_ed.mdl
chr5007_m_wait2_st.mdl
chr5114_m_wait.mdl
chr5114_m_wait2.mdl
chr5114_m_wait2_ed.mdl
chr5114_m_wait2_st.mdl
Put add_ani_bones.py, kuro_gltf_to_meshes.py, kuro_mdl_export_meshes.py, kuro_mdl_import_animation.py, kuro_mdl_import_meshes.py, kuro_mdl_to_basic_gltf.py and lib_fmtibvb.py into the same folder. (Yes, some of these scripts are not directly applicable. They are simply dependencies.)
Now, for each animation, convert both Judith's and Renne's version from .mdl to .glb, transfer the tail animations, then rebuild a new .mdl for Renne. In total, the full set of commands for the four animations are:
python kuro_mdl_to_basic_gltf.py -o chr5007_m_wait.mdl
python kuro_mdl_to_basic_gltf.py -o chr5114_m_wait.mdl
python add_ani_bones.py -b Tail_01 -l chr5007_m_wait.glb chr5114_m_wait.glb
python kuro_mdl_import_animation.py chr5114_m_wait.mdl
python kuro_mdl_to_basic_gltf.py -o chr5007_m_wait2.mdl
python kuro_mdl_to_basic_gltf.py -o chr5114_m_wait2.mdl
python add_ani_bones.py -b Tail_01 -l chr5007_m_wait2.glb chr5114_m_wait2.glb
python kuro_mdl_import_animation.py chr5114_m_wait2.mdl
python kuro_mdl_to_basic_gltf.py -o chr5007_m_wait2_ed.mdl
python kuro_mdl_to_basic_gltf.py -o chr5114_m_wait2_ed.mdl
python add_ani_bones.py -b Tail_01 -l chr5007_m_wait2_ed.glb chr5114_m_wait2_ed.glb
python kuro_mdl_import_animation.py chr5114_m_wait2_ed.mdl
python kuro_mdl_to_basic_gltf.py -o chr5007_m_wait2_st.mdl
python kuro_mdl_to_basic_gltf.py -o chr5114_m_wait2_st.mdl
python add_ani_bones.py -b Tail_01 -l chr5007_m_wait2_st.glb chr5114_m_wait2_st.glb
python kuro_mdl_import_animation.py chr5114_m_wait2_st.mdl
add_ani_bones.py has a few options that you can use. -b is required, and tells the script the base bone you want to transfer. Since we specified -b Tail_01
, it will take Tail_01 (and all of its descendants, e.g. Tail_02, Tail_03, etc) and transfer them from Judith's Hips to Renne's Hips (Hips is the parent of Tail_01). You can use -b more than once; for example to transfer FS01 and BS01 (skirt bones) you would use python add_ani_bones.py -b FS01 -b BS01 donor.glb recipient.glb
and so on. Using -b more than once is necessary when the two base bones are not part of the same tree. FS01 is a child of Hips, and BS01 is a child of Hips. Neither is a descendant of the other.
Ordinarily the script will adjust the start time and the length of the donor animation to match the recipient animation. -s tells it to leave the start time as is, and -l tells the script to keep the length (playback speed) the same. Notice that I used -l above - Judith's transitions are longer than Renne's, so the default setting will cause the tail whip to speed up since the script will shorten the playtime. Instead, I allow the tail to keep waving even after Renne has stopped transitioning. You may have noticed this warning:
It would have said True instead if I allowed it to adjust the playback speed. You may need to experiment to find the best outcome.
Now Renne has a nice whip to her tail when idling!
We could simply replace chr5114_c10.mdl with this model, but it is nice when we can have a new, selectable costume. Let's make one.
All the following screenshots are in Chinese - I intend to replace them with English language screenshots when this game comes out in English.
For Renne's Grim Kitty costume, we actually do not need to make a new costume item, because an empty item already exists (CLE did not bother to change the tables.) But to make a new one, the steps are exactly the same.
Using KuroTools in the same manner as the basic modding tutorial, decompile t_item.tbl and t_costume.tbl. (They are in different places in Kuro 1 and Kuro 2, but in general look in either {Kuro Game Folder}/f/table/ or {Kuro Game Folder}/{language}/f/table/ for the files.) You should now have t_item.json and t_costume.json.
In t_item.json, find an unused item id, and insert a new item in the ItemTableData
section. For example, here is the Grim Kitty item that we could insert, if it were not already there.
{
"id": 2725,
"character_restriction": 19,
"text1": "",
"text2": "2",
"category": 17,
"subcategory": 16,
"unknown": "00 00 00 00 00 00 00 00 00 00",
"float1": 0.0,
"float2": 0.0,
"effects": [
{
"id": 0,
"value1": 0,
"value2": 0,
"value3": 0
},
{
"id": 0,
"value1": 0,
"value2": 0,
"value3": 0
},
{
"id": 0,
"value1": 0,
"value2": 0,
"value3": 0
},
{
"id": 0,
"value1": 0,
"value2": 0,
"value3": 0
},
{
"id": 0,
"value1": 0,
"value2": 0,
"value3": 0
}
],
"float3": 0.0,
"hp": 0,
"ep": 0,
"patk": 0,
"pdef": 0,
"matk": 0,
"mdef": 0,
"str": 0,
"def": 0,
"ats": 0,
"adf": 0,
"agl": 0,
"dex": 0,
"hit": 0,
"eva": 0,
"meva": 0,
"crit": 0,
"spd": 0,
"mov": 0,
"stack_size": 1,
"price": 100,
"animation": "",
"name": "幻夜小貓",
"description": "服裝【<c698>可在EQUIP的「服裝」頁面裝備</c>】\n可讓蕾恩成為「幻夜小貓」的專用服裝。",
"data": "00 00 00 00 CA 08 00 00 00 00 00 00 00 00 00 00"
},
id
should be unique to the table. character_restriction
should be the character id of Renne (19), you can find the correct id from t_name.tbl which we decompiled in the basic tutorial. text2
should be "2",
category
should be 17, and subcategory
should be 15 (Kuro 1) or 16 (Kuro 2), as far as I can tell (I may be wrong). Set name
and description
to whatever you want. I believe the 5th-8th bytes is the sort order variable as an integer in Little Endian (CA 08 00 00
is 2250 in decimal) although I have not experimented enough to find out. Leave it alone, or try changing it.
In t_costume.tbl, we will tie the item we created to our costume. Edit t_costume.json, and insert a new costume attachment in the CostumeParam
section. Here is the sample entry, again for Grim Kitty:
{
"shrt0": 19,
"shrt1": 0,
"shrt2": 2725,
"shrt3": 0,
"text": "",
"name": "chr5114_c65",
"int3": 0,
"int4": 0,
"attach_name": "",
"text4": "",
"text5": "_c10"
},
Again, it already exists, but if it did not, we would make an entry just like it. Copy an entry from your character, and change shrt2
to your new item id number (2725 in our example). name
should be your new, unique costume name. chr5114_c65.mdl and chr5114_c65.mi will be our new, unique costume, so name
will be chr5114_c65.
The item now exists (and you can use my Cheat Engine table to give it to yourself). However, it would still be nice to be able to obtain it in game. I have not yet figured out the rules to the DLC table, so I will eventually update this. But the simplest method that most modders currently use is to add it to a shop. Edit t_shop.tbl.
Under the ShopInfo
section, you can see that the newsstand in the beginning of the game is shop 20, and the shop inside the restaurant is shop 23. (The restaurant is also listed as shops 21 and 22, which is confusing. I suggest using the newsstand.)
Go to the ShopItem
section, and add a new entry. I put shop_id
as 20 for the newsstand, and item_id
as 2725 for the Grim Kitty costume.
Use json2tbl.py to turn any tables you modified back to .tbl format (usually t_item.tbl, t_costume.tbl and t_shop.tbl - but in this case I only need to process t_shop.tbl because I am using the derelict item 2725 that CLE left in the game for me). If this is for CLE Kuro 2, make sure to compress and encrypt.
If everything worked, you should now have a custom costume that you can buy. Congratulations for making it to the end of this tutorial!