Black Desert Online Modding Tools (1 Viewer)

LingHyun

Composer
Joined
Dec 2, 2022
12.png
13.png

This is the model I got with PACtool 1.4.4 and it doesn't seem to be correct.
 

randomshock

Avid Affiliate
Joined
Jan 11, 2023
Question on the pactool.

Is it possible to extract and modify the non-mesh data? I'm mostly interested in the data that comes after the mesh data, which controls the partcut. There doesn't seem to be enough data to specify every single vertex to cut, so I'd also want to search for where this data is, but having it human-readable would be of great help.

Doing some testing, I've been able to Frankenstein some pacs, replacing the partcut data in the pac with the partcut data from another pac, to force or eliminate a partcut. Ideally, I'd like to be able to get to a place where I can programmatically customize these partcuts instead of relying on ao.dds files to do this (which requires some painting in Blender). So far neither route appears to allow me to have a partcut/ao toggled in-game via cloaks or accessories, but this would be a good first step.

As for the header data, I don't have any idea what it's for, but still interested in it nonetheless.
 

UndercoverPervert

Content Creator
Joined
Aug 9, 2016
This iteration of pactool won't support that, my remake sometime in the future will. I'm currently trying to figure out of the cut data myself.

The structure so far is 1 byte to indicate how many cut "groups" there are and then each group has 1 byte to define how many "positions" there are 4 floats (4 bytes each) long, with current research it seems that the "positions" are actually defining a normalized angle with the last 3 values, the first value is still somewhat of a mystery, in-game the values seem to create "infinite" planes where on one side the mesh stays and on the other it is cut, when "positions" intersect they're no longer "infinite", so with multiple planes you can define different shapes to generate a cut for a very specific area.

I've also confirmed that the bounding box defined right before the cut data (6 floats, lowest X/Y/Z followed by highest X/Y/Z in the mesh, pactool does not update this, which is why cuts don't change with meshes that are supposed to have smaller/bigger boxes, if you do update it, the cut changes).

Also the "groups" cut meshes defined in partcutdesc, a "(Basic)CutType" group has two roles, first it defines a list of files to cut by other meshes, but the group itself can also define whether the listed meshes should cut others, assigned by the "Relation", for example meshes listed in "Underwear" have a relation to cut "Nude" which lists the characters' bodies, I believe that the order of the cuts listed in the relation correlates to the index of the "groups" defined in the pac data.
 

randomshock

Avid Affiliate
Joined
Jan 11, 2023
This iteration of pactool won't support that, my remake sometime in the future will. I'm currently trying to figure out of the cut data myself.

The structure so far is 1 byte to indicate how many cut "groups" there are and then each group has 1 byte to define how many "positions" there are 4 floats (4 bytes each) long, with current research it seems that the "positions" are actually defining a normalized angle with the last 3 values, the first value is still somewhat of a mystery, in-game the values seem to create "infinite" planes where on one side the mesh stays and on the other it is cut, when "positions" intersect they're no longer "infinite", so with multiple planes you can define different shapes to generate a cut for a very specific area.

I've also confirmed that the bounding box defined right before the cut data (6 floats, lowest X/Y/Z followed by highest X/Y/Z in the mesh, pactool does not update this, which is why cuts don't change with meshes that are supposed to have smaller/bigger boxes, if you do update it, the cut changes).

Also the "groups" cut meshes defined in partcutdesc, a "(Basic)CutType" group has two roles, first it defines a list of files to cut by other meshes, but the group itself can also define whether the listed meshes should cut others, assigned by the "Relation", for example meshes listed in "Underwear" have a relation to cut "Nude" which lists the characters' bodies, I believe that the order of the cuts listed in the relation correlates to the index of the "groups" defined in the pac data.

That would explain why, when I incorrectly spliced that section, I ended up with half the body being cut vertically. My initial thinking was that it referenced vertex groups, but the cuts didn't match up with the vertex groups in the body. Using cutting planes and bounding boxes would definitely require a lot less data, so maybe there isn't something external beyond the partcutdesc.xml to the cutting process. That at least makes it simpler, as I kept wondering where both the mapping from the pac to the cut type was, as well as how it defined the cut.

I never really liked partcutdesc.xml because of the way the objects seemed to have multiple meanings, but I may have to play with it a bit more. I was just testing the cut from ruby floretta in different body "placements" and found that, when placed in sho, it just cut the underwear and not the body, like it did when placed in ub, lb, hand, or foot. Cloak and accessories did no cutting at all, but maybe there would be a way to force even those to cut on demand.

For now, I'll probably stick assigning some of the ao files to be used for specified pacs, even though it's far more limited in where it can be used than what the partcut data in the pacs seems like it could do. At least I know I can splice out the partcut section if needed (or just put the mesh in a pac file that does not have partcut data and change the texture name.

Thank you very much for the info!
 

randomshock

Avid Affiliate
Joined
Jan 11, 2023
As an addendum, I realized that making cloaks and accessories create partcuts was actually the more achievable part of this, so I'll just have to investigate the partcut data in the pacs themselves to figure out how to create custom cuts.

For testing, I was using the cloak on Cantabile (Lahn), since it's not a perm_cloak, and the Owl Horn Rimmed Glasses, again for Lahn. Both were set to a Ruby Floretta lb pac with no mesh. The partcut data of that pac defines a cut for some of the torso and part of one arm.

Cloak was easy, as there is already a CutType for Cloak that has a Relation that will affect Nude. Here, I just added the file references to the Cantabile cloak pacs.

Glasses was a tiny bit more involved (only because I had to modify one line of code to handle an empty Relation). Created a new CutType called GlassCutters with the sole file reference being the Owl Horn Rimmed glasses. Created a Relation called GlassCutters and added Nude to its list of Cuts.

And voila, easily togglable part cuts. I don't think it really clicked for me before how to do this because, prior to this conversation, it was all just bouncing around in my head, so thank you. I'm probably going to end up buying one or two of each accessory type for each of my characters to make use of this.
 

randomshock

Avid Affiliate
Joined
Jan 11, 2023
This iteration of pactool won't support that, my remake sometime in the future will. I'm currently trying to figure out of the cut data myself.

The structure so far is 1 byte to indicate how many cut "groups" there are and then each group has 1 byte to define how many "positions" there are 4 floats (4 bytes each) long, with current research it seems that the "positions" are actually defining a normalized angle with the last 3 values, the first value is still somewhat of a mystery, in-game the values seem to create "infinite" planes where on one side the mesh stays and on the other it is cut, when "positions" intersect they're no longer "infinite", so with multiple planes you can define different shapes to generate a cut for a very specific area.

I've also confirmed that the bounding box defined right before the cut data (6 floats, lowest X/Y/Z followed by highest X/Y/Z in the mesh, pactool does not update this, which is why cuts don't change with meshes that are supposed to have smaller/bigger boxes, if you do update it, the cut changes).

Also the "groups" cut meshes defined in partcutdesc, a "(Basic)CutType" group has two roles, first it defines a list of files to cut by other meshes, but the group itself can also define whether the listed meshes should cut others, assigned by the "Relation", for example meshes listed in "Underwear" have a relation to cut "Nude" which lists the characters' bodies, I believe that the order of the cuts listed in the relation correlates to the index of the "groups" defined in the pac data.

Did some research on this last night and got pretty much the same results. Haven't really looked at the bounding box portion of the data (which I had just been calling the header).

All the headers I've checked can be searched for by the last match of the same regex when searching as hex with spaces between each byte:
Regex:
[0-9]{2} ([A-F0-9]{2} ){3}C[A-F0-9]{1} ([A-F0-9]{2} ){3}4[A-F0-9]{1} ([A-F0-9]{2} ){3}C[A-F0-9]{1} ([A-F0-9]{2} ){3}4[A-F0-9]{1} ([A-F0-9]{2} ){3}4[A-F0-9]{1} ([A-F0-9]{2} ){3}4[A-F0-9]{1} ([A-F0-9]{2})

Last byte in the header being the number of cut groups.

As an example:
Coco-Nutty Pirates LB (Lahn):
header
00 B8 40 8F C1 30 2A 5A 41 2D B2 5D C1 B8 40 8F 41 CB 21 EF 42 12 A5 2A 41 06

groin cut
04 5A 5E 02 C1 00 00 80 BF 0C 3F 4B BA EE 2E BC 38 8E C0 E0 C2 3D 82 E6 34 3C 32 76 3F 86 55 8C BE 98 74 02 C1 00 00 80 3F 4D 3A 42 BA 2A 89 5D 39 9C 0A C1 42 00 00 00 00 6E 4D 7E BF DE 74 EB 3D

left leg
05 BC 4F 6F C1 97 1D 56 BF 92 76 33 3E 0A F5 04 BF DB 75 C6 C0 D1 96 7F BF F1 FA 67 3D 82 D1 EE B1 92 E0 E0 C2 FB C3 75 34 3C 32 76 3F 86 55 8C BE AB C2 F3 C1 24 F0 7F 3F FC 06 DC BB 75 7F AB BC C8 E5 8C 41 00 00 00 00 00 00 80 BF D7 C5 03 34

right leg
05 AD 75 C6 C0 D1 96 7F 3F F1 FA 67 3D 82 D1 EE B1 D7 4F 6F C1 97 1D 56 3F 92 76 33 3E 0A F5 04 BF 90 E0 E0 C2 AC 0C 92 33 3C 32 76 3F 86 55 8C BE A2 9D F7 C1 00 00 80 BF E7 27 F3 39 D8 52 7A AE C8 E5 8C 41 00 00 00 00 00 00 80 BF D7 C5 03 34

second groin cut
04 FE 7C C5 C2 00 00 00 00 05 8C 76 3F 2B D9 89 BE F3 3C 96 42 00 00 00 00 58 FF 7F BF 6E 6C 93 3B B7 8C 3C 41 DA 20 7B BF 3F 1F 45 BE 66 47 CF 3C B7 8C 3C 41 DA 20 7B 3F 3F 1F 45 BE 66 47 CF 3C

right breast
05 34 98 BD C1 CC 28 36 3F 44 C2 D7 3D AE D6 31 BF D4 FE 09 C3 DD 5D C7 BE 4F CB 6B 3F 85 7D 16 3B C0 91 6B 42 AA F2 11 BF 35 40 E1 BE 06 A0 31 3F 26 8B F9 42 DD 5D C7 3E 4F CB 6B BF 84 7C 16 BB 4D C8 CB C1 C2 A2 26 3F EB FC 8B 3E 98 4C 35 3F

left breast
05 31 91 B2 C1 96 40 36 BF 88 4C C9 3D 21 02 32 BF EB 3B 0A C3 28 EF C3 3E 66 83 6C 3F 34 08 E9 B4 56 70 3E 42 AB E8 1B 3F 89 EC BB BE AC FF 33 3F A5 99 F0 42 C0 77 E3 BE B0 AC 64 BF 7D 87 8C BD F2 0E 06 C2 F7 E5 20 BF 39 60 A7 3E 36 AD 34 3F

So, 6 cut groups as defined by the header. For each cut group, you have the number of positions as the header byte, from which you can determine how long that cut is going to be, as each group is 16 bytes. So 02 would be 32 bytes, 03 would be 48 bytes, etc (plus the header byte). In randomly picking pacs to examine, the highest I've seen was 06.

Your hypothesis on there potentially being a correlation from the cut type index of the relation to the cut group index is interesting. With the above example, we have two groin cuts (first and fourth), which would seem pretty needless unless they are meant to cut different things (nude vs underwear, for example). However, the Lowerbody relation only lists three cuts:

Edit: Re-checked and both groin cuts are necessary for this one. First one is higher than the second cut, which, when combined with the two leg cuts, makes it so that the little big of leg that is exposed in the pants shows.

Lowerbody:
<Relation CutType="Lowerbody">
    <Cut>Underwear</Cut>
    <Cut>Nude</Cut>
    <Cut>UnderUp</Cut>
</Relation>

Interestingly, this relation lists Underwear before Nude, unlike most of the other relations, but I haven't seen a meaning to their order. When creating new cuts (or excluding cuts), I've generally been appending new cuts to relation cut list with no unexpected results that might occur due to them being ordered.

Next step will be for me to start playing with the individual cuts themselves to see if I can get to the point of creating custom cuts. It's currently pretty easy to manipulate the groups, but I still have to load up BDO to verify what is getting cut.
 
Last edited:

randomshock

Avid Affiliate
Joined
Jan 11, 2023
More partcut research and testing.

TLDR:
- First 4 bytes in each cut group is a magnitude and the last 12 bytes make up a vector with x, y, and z components.
- Normally, magnitude would be multiplied by the vector. Here, it just does a translation.
- Bounding box seems kind of useless. In my testing using Orchid Falls LB, the bounding box only comes up to the chest and doesn't include arms.
- Y axis is fucking weird.
- Translating to Blender is still very much a work in progress


Longer version:

I created quite a number of tests using standard unit vectors for each of the axes in both directions (6 vectors in total), along with a variety of magnitudes, giving me an initial 12 test suites. There are a couple more test suites in the zip file, along with trying to recreate a partcut in Blender from the 3rd partcut of Ruby Floretta (the arm cut). All the pacs used in testing and the result images are in the zip.

- lowest point of nude body is about (0, 1, 0) (x, y, z)
- center of cutting plane starts at (0, 0, 0)
- camera is in front of body, facing body

Y starting position: ground level; complete body visibility affected by which way plane is facing
Code:
yneg mag neg        body always invisible
yneg mag pos        plane moves up body, "below" plane is visible       
ypos mag neg        plane moves up body, "above" plane is visible      
ypos mag pos        body always visible


Y is being weird. Doesn't seem to be consistent with other axes. Note: I re-checked the files and retested this multiple times with the same results.


What I'm seeing:
Code:
n/n    -> p/n            direction -1 * y -> p        position n * n * -1 -> n
n/p    -> p/p            direction -1 * y -> p        position n * p * -1 -> p
p/n    -> n/p            direction -1 * y -> n        position p * n * -1 -> p
p/p    -> n/n            direction -1 * y -> n        position p * p * -1 -> n


X with magnitude of 0: body is vertically bisected into left and right sections
- when using the words "right" and "left" in these results, these are camera right and camera left
Code:
xneg mag neg        plane moves camera left; vertices camera left of plane are visible
xneg mag pos        plane moves camera right; vertices camera left of plane are visible
xpos mag neg        plane moves camera right; vertices camera right of plane are visible
xpos mag pos        plane moves camera left; vertices camera right of plane are visible


x-positive is camera right
x-negative is camera left

Z with magnitude of 0: body is vertically bisected into front and back sections
- when using the words "front" and behind", "front" means towards the front of the body and "behind" towards the back of the body
Code:
zneg mag neg        plane moves towards front of body; vertices in front of plane are visible
zneg mag pos        plane moves towards back of body; vertices in front of plane are visible
zpos mag neg        plane moves towards back of body; vertices behind plane are visible
zpos mag pos        plane moves towards front of body; vertices behind plane are visible


z-positive is towards camera
z-negative is away from camera

conclusion: magnitude does not change the direction of the vector, only its position, with initial position being the vector components.
conclusion: vertices on the facing side of the plane are cut

For Blender: (Global Coordinates) Flip X, Swap Y and Z
 

Attachments

partcut_testing.7z
17.1 MB · Views: 110

Last edited:

UndercoverPervert

Content Creator
Joined
Aug 9, 2016
Your hypothesis on there potentially being a correlation from the cut type index of the relation to the cut group index is interesting. With the above example, we have two groin cuts (first and fourth), which would seem pretty needless unless they are meant to cut different things (nude vs underwear, for example). However, the Lowerbody relation only lists three cuts:
I forgot to reply to this sooner, yes I've seen pacs with higher group count than relation count, my theory is that it loops back, so if there are 3 items and 4 groups, by index it would go 0 1 2 and then back to 0, your example above seems to match up to that, where the "groin cut" is the first cut and the "second groin cut" is the fourth, in theory both of these would correlate to relation index 0. I could still be wrong but it seemed to correlate with most cuts, I need to do a bunch more testing myself but I've been both busy and a little sick so I haven't gotten around to it.
 

randomshock

Avid Affiliate
Joined
Jan 11, 2023
I forgot to reply to this sooner, yes I've seen pacs with higher group count than relation count, my theory is that it loops back, so if there are 3 items and 4 groups, by index it would go 0 1 2 and then back to 0, your example above seems to match up to that, where the "groin cut" is the first cut and the "second groin cut" is the fourth, in theory both of these would correlate to relation index 0. I could still be wrong but it seemed to correlate with most cuts, I need to do a bunch more testing myself but I've been both busy and a little sick so I haven't gotten around to it.

If you have some samples that seem to exhibit this, I could put them through some testing. When I was just starting to play around with partcuts, I did run across some odd behavior that I have yet to loop back around to in order to see if I could now pin down an explanation to what I saw back then. Of course, the most likely reason for me thinking they were 'odd' is that I was at ground-level understanding back then.

I've started getting the hang of Geometry Nodes in Blender, but I still need to do a bit more testing with vectors other than standard unit vectors. When dealing with a single axis, everything looks perfect, but I'm getting some "drift" when working with non-zero values along multiple axes. Once I've got that down, I'll write a custom geometry node to translate the floats back into binary to make it faster to get the data back into the pacs and post the whole thing here.
 

randomshock

Avid Affiliate
Joined
Jan 11, 2023
Don't want to make another really long post, so I've shoved all the instruction text into the partcut_blender zip. This post will just be a summary.

Partcuts in Blender:
- The 16 bytes of each cut represent a magnitude and a unit vector (must be a unit vector to work properly in game).
- Preceding bounding box still seems to do nothing. Set it to (0,0,0) (0,0,0) at one point with no visual change.
- Included Blender file contains scripts for both "importing" and "exporting" partcuts.
- There still exists a very small difference between what you see in Blender and what you see in game, generally within a single unit of measurement. Easily corrected with some really small adjustments to the magnitude.
- I may improve the partcut creation side of things to simply calculate the magnitude and unit vector of a freely transformable plane in Blender to make it easier to work with.

Custom Partcut Sample:
- Two pacs, based on the Lahn body, intended to cut just the top or just the bottom off of underwear. Works nicely on accessories to toggle on and off (requires new entries in partcutdesc.xml).
- Would be cool if I could "erase" a partcut with another partcut. Not sure if this is possible or not, so hiding part of some underwear may reveal the underwear's own cuts into the body.

Other thoughts:
- Working with the partcut data can be a bit tricky. A fairly conceptually simple cut can result in having to make multiple cut groups to achieve the desired result. The topless partcut was a single group of three cuts, but the bottomless partcut ended up being three different cut groups, just to basically achieve a "reverse" cut.
- Started researching some files that previously confounded me, but so far have found nothing strange about them, now that I understand partcuts and partcutdesc.xml more. Mostly, it's just a matter of their weird, inconsistent use of partcuts.

Cheers.
 

Attachments

partcut_blender.7z
54 MB · Views: 146

custom_partcuts.7z
693 bytes · Views: 124

UndercoverPervert

Content Creator
Joined
Aug 9, 2016
Thanks for sharing, I took a quick look and will take a deeper look when I've got some more time.
I read your instructions, and I'll probably try to simplify the process by updating Better Collada to export "meshes" that pactool will recognize as cut updates. As for importing, Better Collada doesn't support that and I'm not really sure it's needed, I might instead make similar "meshes" when exporting with pactool and provide a modified version of your script to load the data from those "meshes" as cuts instead of needing to use raw hex.

- Would be cool if I could "erase" a partcut with another partcut. Not sure if this is possible or not, so hiding part of some underwear may reveal the underwear's own cuts into the body.
I don't believe this is possible, so your cuts need to be conservative, only cut what's absolutely necessary (as in, what would actually end up clipping) that way if a part of the mesh needs to cut to prevent other clipping, it won't leave areas with "gaps", though this would be exceedingly rare either way, take mystic as an example, her arms are cut on many outfits, and then the sleeves/gloves of many of those outfits are cut by her gauntlets, at no point is the arm under actually going to appear again because it's always covered by something, this is only going to be relevant if you're trying to "un-cut" for a translucent texture mesh, and technically there is a way to do this, but it's currently blocked due to armor swapping, I am looking into ways to only allow this with limited capacity that would be useful for actual mods but not for people who want every outfit for free.
 

Dihlofosss

3D Artist
Joined
Feb 7, 2023
Hi, is it possible atm somehow to add extra objects/models with additional material to the PAC scene?
Currently, if I understant it correct, if we have only one source obj in PAC file, we only able to replace it with a new one
 

UndercoverPervert

Content Creator
Joined
Aug 9, 2016
Hi, is it possible atm somehow to add extra objects/models with additional material to the PAC scene?
Currently, if I understant it correct, if we have only one source obj in PAC file, we only able to replace it with a new one
Not with this version of pactool. For now you can find a pac file with as many meshes as you'd like to have (trial and error with i3dconverter preview, or with OpenBD right click -> properties) and import into it.
 

Dihlofosss

3D Artist
Joined
Feb 7, 2023
Unfortunately Dae to Pac converter is not overwriting material data in target PAC file =(
Gometry data replaced but material is original
 

brilliantfizz

Potential Patron
Joined
Apr 1, 2023
The feet of the suzu‘s nude model are smaller than normal and too short for the shoes. i tried to scale them in blender.
i used pactool1.4.4 converting the .pac to .dae(3 dae:lod0,lod1,lod2). it seems the lod0 is suzu's model and lod1 and lod2 are PA's original models. i scaled the lod0 model's feet, then ran dae_to_pac(both tried "-replaceAllLOD" mode and no "-replaceAllLOD" mode), but this problem occured. Did I make a mistake?
屏幕截图 2023-04-23 195915.jpg
 
Last edited:

nopopup

Potential Patron
Joined
Sep 12, 2016
Hello, I have the old resorpress mod and also using meta injector to install mods.
But the resorpress nude body is kind of old now. I can see polygons on the body...not sure if it's because I turned on the Remaster graphic setting. Is there any update to the mod?
Also, is there any way to use the meta injector to install the resorpress nude body mod?
 
Last edited:

Shiea2

2D Artist
3D Artist
Modder
Joined
May 21, 2022
I know these tools are aging and people tend to just use other people's finished work for the modding community, but has anyone actually been keeping up and updating the real_names.txt file? Would definitely help me out if someone has.
 

Manoj209

Illustrator
Streamer
Joined
Jan 15, 2024
Where do we find items and artifacts in PAZ file. For Example I need to see the model of Black Stone, Where do I search?
 

Users who are viewing this thread

Top


Are you 18 or older?

This website requires you to be 18 years of age or older. Please verify your age to view the content, or click Exit to leave.