ousnius / BodySlide-and-Outfit-Studio

BodySlide and Outfit Studio, a tool to convert, create, and customize outfits and bodies for Bethesda games.
GNU General Public License v3.0
286 stars 63 forks source link

Import from .obj - deformed model #429

Closed Indarello closed 2 years ago

Indarello commented 2 years ago

game: fallout 4 Import from .obj (model looks ok) Save project Reopen project and model deformed now, best seen in the eye area I tested several older versions 5.x and 4.9.1, same problem for all of them untitled3.zip

sts1skj commented 2 years ago

@ousnius I think it's highly likely this got broken in commit 94ccd2d (Dec. 23, 2020) "Import OBJs as static shapes". In commit bc97fa5 (Aug. 12, 2020) "Added checks for skin coordinates for FBX and OBJ", I added code for setting the global-to-skin transform on import of FBX and OBJ. But with no skinning for new OBJ and FBX shapes, the global-to-skin transform is discarded, leaving the shape with the default (identity) global-to-skin transform, which is no good for FO4 heads.

If the user goes to the trouble of loading a reference shape so that the imported OBJ/FBX shape can copy its global-to-skin transform, I think the imported shape ought to be skinned.

sts1skj commented 2 years ago

@Indarello Until we get this bug fixed, here's a workaround. I'm sorry it's so complex.

  1. Load a reference (such as CBBE Body).
  2. Import your Head OBJ.
  3. Go to the "Bones" tab, select a bone, and paint some weight all over the head.
  4. Go to the "Meshes" tab and double-click your Head shape to open the Shape Properties window.
  5. Go to the "Coordinates" tab, click on the "Z" field below "Origin", and replace "0.00000" with "-121". Hit OK.
  6. Save your NIF.

I've tried this with your "untitled3.obj", and it works for me.

sts1skj commented 2 years ago

@ousnius Here's an alternate idea: when loading an FBX/OBJ shape, maybe letting it be unskinned (static) initially is okay, if the reference's global-to-skin transform is used to initialize the static shape's node-to-global transform. Then, when the user does something to skin the shape, maybe the node-to-global transform could be used to initialize the new global-to-skin transform.

ousnius commented 2 years ago

@sts1skj If I'm not mistaken, copying bone weights to a shape should bring over the global-to-skin transform from the reference already?

sts1skj commented 2 years ago

@ousnius Yes, doing Copy Bone Weights to an unskinned shape will cause it to copy the reference's global-to-skin transform. This is (or was) a good thing. But there are good reasons why this should not be the only place the transform is copied:

That's why, in August 2020, we decided to add code to ImportOBJ and ImportFBX:

This added code is pointless and misleading, now, as the user's choices have no effect on what these functions actually do.

Here's the fundamental problem that needs to be solved, as I see it: saving a shape to a FO4 NIF causes damage to the vertex data, because that NIF version uses half-precision floating point. Half the bits of the 32-bit float's mantissa are lost. There's only one way to minimize the damage: by selecting a shape coordinate system whose origin is close to the vertices whose coordinates need to be most precise (typically the character's face).

That's why most skinned FO4 NIF shapes have a global-to-skin translation of roughly (0, 1, -121). This puts the origin of shape coordinates inside the head. The damage to head-vertex coordinates is minimized, at the expense of feet vertices.

This isn't just a problem for skinned meshes. Unskinned meshes are damaged by the saving process, too. For unskinned meshes, the critical transform is the node-to-global transform, I think. For an unskinned head mesh, the node-to-global transform would need a translation of roughly (0, -1, 121) to minimize damage, opposite to the needed global-to-skin translation because the transform is in the opposite direction (shape to global instead of global to shape).

Back when we added the code to Copy Bone Weights to copy the global-to-skin transform (in PR #275 ), we had two purposes:

So I see two good places where we could set the shape's coordinate system to minimize damage: loading and saving.

If we did it on loading (and didn't revert commit 94ccd2d, which made the shapes unskinned on loading), then the shape would be unskinned, so the transform that would need to be set would be the node-to-global transform. Then we'd have the problem: what happens when the user does something to cause the shape to be skinned? Probably, then, the new global-to-skin transform should be set to be the inverse of the unskinned shape's node-to-global transform. Likewise, if the user did "Remove Skinning", the new node-to-global transform should be set to be the inverse of the skinned shape's global-to-skin transform.

I don't see a good reason to ever copy the transform from the reference, anymore. It's not needed for the automorpher or the brushes anymore, assuming PR #425 works correctly. The main reason for doing it, I think, would be compatibility with old or existing code.

So here's my new favorite idea for solving this problem:

The user can always set the transform in the Shape Properties dialog to whatever they wish, and their choice will never be overridden. (I also think the Shape Properties dialog should be updated so that the transformation shown is the same for skinned and unskinned shapes.)

Sorry for the long post. I hope I wasn't arrogant, condescending, or insulting. What do you think?

sts1skj commented 2 years ago

Pull request #439 does not fully implement the plan I suggested above. In particular, it only does the two "preserve" parts and not the "set" or "remove" parts.

Ousnius argued that setting the shape's origin to its center, while it would help preserve the quality of the vertex coordinates, would result in every shape having a different origin. He said that every vanilla Fallout 4 skinned shape uses the same shape origin (specifically x=0, y=-.88, z=120.84), even though the quality of the vertex coordinates would be improved by letting every shape have a distinct origin. This suggests that something in Fallout 4 or one of the Bethesda tools has a flaw that makes it unable to handle shapes with different origins. For compatibility, Outfit Studio should always use the same origin for skinned shapes.

That seems like a good enough reason to me, so I scaled back my plan. (I actually fully implemented setting the origin to the center, and then reverted it.)

sts1skj commented 2 years ago

@Indarello Once my pull request is integrated and released, which will probably be in Outfit Studio 5.6.0, the workaround for your issue will become:

  1. Load a reference.
  2. Import your Head OBJ.
  3. Do either one of these (or both): A. Open Shape Properties and set the Z coordinate of the Origin to 121. B. Do Copy Bone Weights.
  4. Save your NIF.

I've tested this with your untitled3.obj, and both options work.

ousnius commented 2 years ago

As sts1skj mentioned, the fix for this (in the next version) is copying bone weights, which will copy transforms.