DarkStarSword / 3d-fixes

Stereoscopic 3D fixes using Helix mod & 3DMigoto
108 stars 128 forks source link

Certain extracted models can't be imported to blender due to missing or undefined SemanticNames #25

Closed 2u843yt385592yjh closed 9 months ago

2u843yt385592yjh commented 10 months ago

This is a continuation of the blender addon issue https://github.com/DarkStarSword/3d-fixes/issues/10

The change you made fixes that issue and the script still works as intended.

However, I still can't import these problematic models successfully.

I send here a zip file with a FrameAnalysis which supposedly contains a character's hair (from the game Tekken 7) FrameAnalysis-2023-12-13-154509.zip

Inside a problematic vb0 file imagen Each element's SemanticName are not defined correctly or missing and appear as ATTRIBUTE. Perhaps this issue has to do with how 3DMigoto (or my mod manager) extracts the vb0 files.

I have sometimes had success importing problematic models by manually renaming the vb0. For example, if I open a vb0 file from a correct working extracted model, I noticed that the elements which have "Format: R32G32B32_FLOAT" tend to have "SemanticName: TEXCOORD" instead of ATTRIBUTE

So I would manually rename elements with R32G32B32_FLOAT to TEXCOORD R8G8B8A8_UNORM to UNORM and so on, but this is very inconsistent.

In the example zip file I gave you, I later got the model to work by manually renaming element[6] to POSITION

element[6]:
  SemanticName: POSITION
  SemanticIndex: 0
  Format: R32G32B32_FLOAT

and also did a search and replace... on notepad to find ATTRIBUTE: and replace for POSITION:

imagen

My blender version is 2.93.0 Also, here is my d3dx.ini and I'm using 3DMigoto 1.3.16 d3dx.zip

2u843yt385592yjh commented 10 months ago

OK, I read on another posted issue that I might need blender 3.6.7 LTS to get the feature Semantic Remap on import

imagen

However, all this feature does is add the ATTRIBUTES to the list without changing the outcome. The model still doesnt show up. imagen

This is another frame analysis FrameAnalysis-2023-12-13-163924.zip

DarkStarSword commented 10 months ago

The semantic remap feature is not automatic - you need to tell the script which names the game uses map to which standard semantics, which is game and material specific. Unreal Engine in particular is problematic for this, as it uses the generic term "ATTRIBUTE" for everything, and in some cases may even pass additional vertex data in a structured buffer bound to a texture slot. The feature is effectively the same as renaming the semantics in the .txt files, but can be more convenient if importing a large number of files that have identical semantics (not a given since these can be material specific), or to use the operator presets to save semantic remappings you need frequently while working on the same game/engine.

I may add a feature for the script to try to guess which inputs are what in the future, but that is unlikely to ever be able to correctly guess 100% of the time, and for now you have to do this yourself, e.g.

image

Taking a look at your frame analysis dump:

The rest are not immediately obvious: ATTRIBUTE1 and ATTRIBUTE2 are likely to be the NORMAL and TANGENT (e.g. if you import them as TEXCOORDs to examine them in the UV editor you will notice their points all cover a unit circle), but it's not clear which is which, and neither of them look quite right in Blender. I think the normals in UE might not quite match up with Blender normals, and I might need to take a closer look and add some conversion here. For now I would recommend caution importing these semantics in case they get damaged - especially TANGENT, which gets completely recalculated by Blender on export (custom normals are at least preserved until something edits them, though I still recommend caution as it's easy to inadvertently change a custom normal and not realise right away). You might be better off leaving them as unknown attributes (which will be preserved in a vertex layer) unless you actually need to edit them.

ATTRIBUTE13 is a bit of a mystery - importing it as a TEXCOORD is plausible - the mouth in particular has a bit of possible UV island here: image

But overall the diagonal line in the xy channels and diagonal/horizontal/vertical lines in the zw channels are not typical for UVs: image image

2u843yt385592yjh commented 10 months ago

Thank you so much.

ChatGPT proved useful. Here is the result it gave me. It basically matches yours

POSITION: ATTRIBUTE + (R32G32B32_FLOAT - XYZ coordinates) NORMAL: ATTRIBUTE13 + (B8G8R8A8_UNORM - Normal vector) TANGENT: ATTRIBUTE8 + (R16G16_FLOAT - Tangent vector) BLENDINDICES: ATTRIBUTE3 + (R8G8B8A8_UINT - Blend indices) BLENDWEIGHT: ATTRIBUTE4 + (R8G8B8A8_UNORM - Blend weights) TEXCOORD: Multiple instances, ATTRIBUTE5, ATTRIBUTE6, ATTRIBUTE7 + (R16G16_FLOAT - Texture coordinates) COLOR: Multiple instances, ATTRIBUTE1, ATTRIBUTE2, ATTRIBUTE4 + (R8G8B8A8_UNORM - Color information)

The prompt I used 3DMigoto_ChatGPT_Prompt.txt

Interestingly, by putting normals on ATTRIBUTE13, I get a message from your script saying "Normals are 4D". I will try to figure out why this happens.

EDIT: It seems that disabling Auto Smooth displays the model and its normals correctly! I think I might get the mod working! imagen

DarkStarSword commented 10 months ago

I wouldn't really trust ChatGPT to be an expert in this area. To be frank I wouldn't really trust ChatGPT to be an expert in any area - ask it questions in a domain you personally know very well and you will soon see that although it sounds knowledgeable it actually makes tonnes of mistakes - now you have to realise that it's going to make similar mistakes in other areas where you lack the expertise to spot them. It can be useful, just don't trust it to always be correct.

TANGENT: ATTRIBUTE8 + (R16G16_FLOAT - Tangent vector)

No, this ATTRIBUTE8 is definitely a TEXCOORD, not a TANGENT. The data type here R16G16_FLOAT is 2D (R...G... = 2 channels if this was a colour, or 2 dimensions if this is a position/vector), but a tangent on a 3D model has to be a 3D vector. Importing this as a TEXCOORD very clearly confirms that it is a UV coordinate used on specific parts of the mesh that presumably have a material assigned that uses a second set of UVs:

image image

NORMAL: ATTRIBUTE13 + (B8G8R8A8_UNORM - Normal vector)

No, although I'm not positive what ATTRIBUTE13 is, it is definitely not a normal. Normals will be 3D unit vectors (i.e. length=1), and on a typical 3D model you would expect to see normals pointing in virtually every direction. If you were to import these as a TEXCOORD their .xy channels would look something like this (as would TANGENT and BINORMAL, as those are also 3D unit vectors at right angles to the normal):

image

That only shows the first 2 dimensions of the normal. You could also visualise their full 3 dimensions by importing them as the POSITION, in which case you would see they all lie on the surface of a unit sphere (because normals are unit vectors):

image

Interestingly, by putting normals on ATTRIBUTE13, I get a message from your script saying "Normals are 4D". I will try to figure out why this happens.

That's simply because ATTRIBUTE13 has a 4D data type (R...G...B...A... = 4 channels/dimensions), which is one more dimension than a valid normal, so the script is warning you that there is extra data that it doesn't know what to do with. In the past this was fatal and the script refused to continue if there was any non-zero data in the 4th channel, but since there are some games that use 4D data types to store normals (with the 4th dimension either being garbage, or having some other custom meaning) the script now continues and stores the data in this extra dimension in a custom vertex attribute on the mesh so that it can restore it on export in case it was important to the game.

EDIT: It seems that disabling Auto Smooth displays the model and its normals correctly! I think I might get the mod working!

That's because turning that option off disables custom normals.

This is custom normals with auto smooth on (importing ATTRIBUTE1 as NORMAL): image

This is Blender's vertex normals (auto smooth doesn't matter): image

This is custom normals with auto smooth off - notice that these match Blenders normals, not the custom normals: image

If the normals aren't being handled correctly I think you might be better off not importing them, so that the script will preserve the original values the game was using in a custom vertex attribute/layer rather than importing them and risking them being damaged. If that isn't an option because you do need to edit them, proceed with caution.

DarkStarSword commented 10 months ago

Looking at those custom normals I think I might know what's wrong with them - might be an artefact of the game packing them into a UNORM (range 0:1) rather than an SNORM (range -1:+1) or FLOAT (no practical range limit)... I'll play around with this and see if I can make them work...

Edit: Yes, was a combination of this and being flipped reversed winding order. Polishing up a fix for this and will submit shortly...

DarkStarSword commented 10 months ago

Grab latest and give it a go. I've added a range conversion for normals/tangents stored in UNORM data types (there's no option for this - I assume all normals stored in UNORMs would have been broken before), as well as options to flip the winding order and/or normals on import - in your case I would recommend flipping the winding order, not the normal.

ATTRIBUTE1 is TANGENT ATTRIBUTE2 is NORMAL Flip Winding Order should be enabled

image

If imported correctly the custom normals should look like this - sticking out of the mesh at angles that make sense: image

Enabling the face orientation overlay should show the mesh in blue (this is what flip winding order corrects - before it was red): image

2u843yt385592yjh commented 10 months ago

I remember people used to have some issues with normals a few years back when they modded Nioh 2. Maybe this just fixed that. Thank you so much! I am learning a lot of stuff

By the way, how did you get the full model? Are you using the frame analysis I gave you? This is all I got in my blender when importing it. Am I missing something? imagen

DarkStarSword commented 10 months ago

By the way, how did you get the full model? Are you using the frame analysis I gave you?

Yes, I am using your frame analysis - I turned on the "load .buf files instead" option in the import dialog. The .txt files only include the vertices/indices actually used in the draw call (i.e. limited by first vertex/index and their count), while the .buf files are the entire buffer that the game passed to DirectX which will often include additional pieces of the mesh that were not drawn in that particular draw call, which can be useful in some situations.

However, in most cases (particularly if you intend to inject the modified mesh back into the game) you don't actually want the entire buffer loaded into a single mesh with that option, because you want it split up in the same way the game split it between draw calls (which generally will correspond with the different materials / material instances the mesh uses), so the usual workflow is to either use the "auto-load related meshes" (automatically selects any other files in the frame analysis directory with the same vertex buffer hash) or just selecting all files when importing and modify each piece individually.

Going forward I might be changing this - the stream output pre-skinning support for Unity games needs vertices in the skinning pass (where the entire mesh is skinned in a single draw call) to match up with those used in the actual draw passes (that are split up by material), and this will be a lot easier if they are all imported to a single mesh that is split up again on export, and if I can get that working it might also be a generally useful workflow even in games that don't use the pre-skinning pass.

2u843yt385592yjh commented 10 months ago

noticed something about the issue modders had with Nioh 2 normals. In your previous comments, you mentioned normals should look like this imagen

Have a look at this nioh 2 frame analysis. FrameAnalysis-2023-12-20-131641.zip When reimporting this mesh into the game, without modifying it whatsoever, the normals break. I tried your latest Flip Winding Order and Flip Normal options, with the same result.

What I noticed: When importing the NORMAL as TEXCOORD through semantic remap, this is how it looks on its xy. imagen

Not sure what is going on here

DarkStarSword commented 9 months ago

You closed this - do you still need help with it?

The reason you are only seeing a partial circle is just because the mesh you imported is only a small partial mesh with surfaces pointing in more or less the same direction as each other. You should see the whole circle if you imported the entire mesh of that character.

The normals look fine to me imported into Blender, but I haven't tried exporting yet to check for issues there.

When reimporting this mesh into the game, without modifying it whatsoever, the normals break.

Can you give me some more info about this? Maybe a screenshot from in game showing the broken result?