ssbucarlos / smash-ultimate-blender

Blender Plugin containing utilities for Smash Ultimate Models and Animations.
45 stars 9 forks source link

Fix Anim Export sometimes glitching out ingame despite working on re-import or in ssbh_editor #157

Closed ssbucarlos closed 1 year ago

ssbucarlos commented 2 years ago

The tested anim is fighter/sonic/motion/body/c00/j01appealhir.nuanmb The issue does not appear on re-import into blender or in ssbh_editor.

Reference: bad.zip

image

I cannot reproduce with simply loading and resaving via ssbh_data_py so i think the issue must be something with how im gathering the data. re-exporting using ssbh_data_py didnt seem to work, nor did changing the version number from 2.0 to 2.1, likewise taking the vanilla and downgrading did not cause the issue so its safe to say the version number wasn't the problem.

The following are the differences i can pick up on between a blender exported anim and the vanilla re-export using ssbh_data_py. I will be fixing these since its probably a good idea to address these discrepancies anyways.

ssbucarlos commented 2 years ago

image image image @ScanMountGoat The issue seems to appear in both the old .nuanmb importer and in studioSB, as well as in-game, but not in ssbh_editor or reimport with smush_blender, so i believe it may be ssbh_data_py related after all.

I have attached the file below. In the meantime ill step through the debugger and potentially try to see what the issue is with the .nuanmb is test6-resaved.zip

ScanMountGoat commented 2 years ago

Are you able to reproduce this just by resaving the animation?

import ssbh_data_py
anim = ssbh_data_py.anim_data.read_anim(...)
anim.save(...)
ssbucarlos commented 2 years ago

No, and its strange because the issue doesn't appear if i simply resave the vanilla animation, and it persists if i re-save the broken one. Only the ones exported with smush_blender have this issue in-game and other programs.

ScanMountGoat commented 2 years ago

If that code snippet or something like it works, it's not an ssbh_data_py issue. Have you tried diffing the JSON output from ssbh_data_json before and after exporting? You can also try using ssbh_lib_json but ignore changes in the buffer at the end of the file to check for changes in flags. If I had to guess, the rotations aren't being preserved on export for some bones. The only things I can think of that we do differently in Blender is changing bones to point along the y-axis (Blender) instead of the x-axis (Ultimate) and the code to detect sign flips in the rotation. Commenting out those operations should help track things down.

ssbucarlos commented 2 years ago

i tried diffing with ssbh_lib_json but the only thing i gathered was that each transform nodes data buffer was much bigger. I did not try ssbh_data_json. The reason i thought its an ssbh_data_py issue is because only ssbh_data_py is able to parse this .nuanmb 'correctly', while the old importer and studiosb and in-game had issues with it.

ScanMountGoat commented 2 years ago

StudioSB, Cross Mod, and SSBH Editor all calculate animation transformation matrices slightly differently. This is why I encourage people to only test in SSBH Editor and in game. Cross Mod and StudioSB use the world transforms from the skel, StudioSB doesn't render flags, etc. There are subtle differences between programs that aren't intuitive to figure out just from looking at the animations playing in the viewport. The animation code is kind of a mess in CrossMod/StudioSB, so I don't have a good understanding of when it does or doesn't work correctly. ssbh_data_json will give you the actual transform values, which are more objective but a little hard to interpret.

ssbucarlos commented 2 years ago

Makes sense. Im still confused because in this case SSBH-Editor and smush_blender have no apparent issue, i can re-import and re-export this animation without any obvious problem. After looking at this problem for the last two days, did i think to try out the old programs and was surprised to see the animation 'glitch' out in those programs just like it is doing in-game.

ssbucarlos commented 2 years ago

comparing using ssbh_data_json shows that the difference in the actual transform values compared to vanilla seem to be only rounding errors

ssbucarlos commented 2 years ago

image To better show the issue, i made this image. Note that the smush_blender re-import incorrectly displays the test7-internal-name-changed-2.1-internal-name.nuanmb animation as having no issue when in reality once its loaded in-game, it appears like it does when loaded by the old model.nuanmb importer script. image

I believe it may be a compression/decompression issue, as when i step through the studiosb debugger for test7-internal-name-changed-2.1-internal-name.nuanmb , the values that get de-compressed are not consistent with the values i get from ssbh_data_json. image

However when i step through with the good file, the values are consistent. image

good-resaved-internal-name.zip test7-internal-name-changed-2.1-internal-name.nuanmb.zip

ScanMountGoat commented 2 years ago

Do you still get a difference like that if you limit the animation to only one frame? The process would be to import the vanilla animation in Blender to start with good values, export a single frame anim file to force the uncompressed path in ssbh_data, and then export from Blender.

ssbucarlos commented 2 years ago

if the animation is one frame it now imports ok into all programs, but it did crash the emulator, but i imagine something else may have been related to the emulator crashing test7rexportedfromblender_oneframe.zip edit: i think it is actually this anim

ScanMountGoat commented 2 years ago

I'll try and test the decompression differences between ssbh_data and in game for those values using Vector4 animations since these are the only floating point values I can reliably test. It may also be compression flag related. Matrices add too many opportunities for other floating point errors to creep in, so I can't really test transforms directly. This still doesn't explain the issue in game, however, since the values from the two animations you listed have different values before being saved.

ssbucarlos commented 2 years ago

My most recent commit helps the compression by addressing some of the slight floating point innacuracies that occur frame-by-frame or from blender's matrices, this results in less bits-per-entry for the compression entries. Its a nice change anyways since filesizes should now be smaller, and as a side-effect the issue no longer seems to appear, so-far exported anims work fine in all programs and in-game now. image

test8.zip

ScanMountGoat commented 2 years ago

Some of those values that are different in StudioSB are actually using a compressed value of 0, which is just using whatever the min value of the range is. I've tested these values on a Vector4 animation in Ryujinx, and the results are identical to ssbh_data at least for the case of using the min value. The animation system in game is pretty complex, so it's going to be really hard to narrow down differences like that between SSBH Editor and in game.

One other approach is to round the values from Blender before saving to handle cases like 0.9999... instead of 1.0. ssbh_data can detect if the values are constant and use more efficient compression. The compression is very conservative, so ssbh_data uses either 24 bits or 0 bits (constant) for float compression. The old implementation in StudioSB has some bugs with handling flags, so you may see weird results in certain circumstances.

ssbucarlos commented 2 years ago

in the most recent commit, rounding .999999 to 1.0 for scale values is something that was implemented. ssbh_data_py did detect they are constant and correctly used the more efficient compression so file sizes were way smaller. If the issue does come back up, it should now be easier to compare the files now / debug and find the issue.

ScanMountGoat commented 2 years ago

I was able to improve the accuracy of the decompression using in ssbh_data slightly based on testing Vector4 material animations in an emulator. The changes are small like 0.4878173 to 0.48781726 and don't seem to cause the issues seen in the screenshots. https://github.com/ultimate-research/ssbh_lib/commit/c7826ef009a0540a8a583ab1f352ad78b3383b2a

ssbucarlos commented 2 years ago

oh nice, its good u made it more accurate at least, even if changes are small. The errors earlier were pretty big for the decompressed rotations. Im still not too sure what the cause was, the biggest change i saw was in the size of the tracks, and the flags used since scale was not constant and was instead like [.9999996,.999998,...]. After the newest updates, the scale tracks are rounded to 1.0 and duplicate keys track values have been removed, and nodes are sorted alphabetically like in vanilla. Since then, i can't reproduce the issue, and as such i have stopped looking into it. We can close this for now, if it happens to come up again we can re-open the issue. Thanks for looking into it with me, believe me i was struggling to find the cause and/or a solution.

ssbucarlos commented 2 years ago

Reopening as the issue is other users have ran into the issue again. This is palutenas vanilla ftilt exported from blender image The rotation appears bugged in game, and crossmod/studioSB correctly show it as bugged. Does not appear bugged in ssbh_editor in blender vanilla-exported-ftilt.zip c01attacks3s.zip (vanilla)

ScanMountGoat commented 2 years ago

What does the JSON diff show in ssbh_data_json? CrossMod/StudioSB are so old at this point that they aren't useful for debugging anymore.

ssbucarlos commented 2 years ago

I think the issue is a compression bug caused by inherit_scale being true when non-constant scale values are present. Thats probably why its not noticeable in many anims. I replicated this by going to the vanilla anim, running ssbh_data_json, and changing inherit_scale to true on S_SkirtBL2 and after testing only that bone was bugged. In addition i was able to fix the glitched anim by setting inherit_scale to false on all bones.

ScanMountGoat commented 2 years ago

Is the inherit_scale value being preserved on export? I can run through all the anim files later and check if inherit_scale is true for constant scale animations. Scale compensation is an actual field. Scale inheritance is based on the scale type flag in the compression flags and may or may not have anything to do with scale inheritance at this point lol. Thanks for helping look into this. This makes narrowing the problem down a lot easier.

ScanMountGoat commented 2 years ago

The compression code seems to be fine. The expected in game and calculated bit counts from ssbh_data get tested against every animation in game. I'll double check it once I get the flags sorted out.

There are four scale types used in game. Setting inherit_scale to true will use a scale type used for what seems to be constant scaling in game. Setting inherit_scale to false will use a scale type used for variable scale values in game. I'll do some more testing to try and figure out the other types. As long as we don't need the other two scale types, there shouldn't be any need to update ssbh_data and ssbh_data_py any time soon. The uniform scale type isn't currently used on export, but it works like the variable scale from my testing a while ago.

We can probably just use ScaleOptions(inherit_scale=False, compensate_scale=False) on export for all animations.

ssbucarlos commented 2 years ago

Is the inherit_scale value being preserved on export? I can run through all the anim files later and check if inherit_scale is true for constant scale animations. Scale compensation is an actual field. Scale inheritance is based on the scale type flag in the compression flags and may or may not have anything to do with scale inheritance at this point lol. Thanks for helping look into this. This makes narrowing the problem down a lot easier.

The value is not being preserved. As a quick fix i think im just going to set ""inherit_scale"" to false and see what happens. Another reason i was thinking that it maybe could be a compression issue for this specific case is that the way the de-compressed anim glitches out in-game matches the behavior of old programs with old parsers (old blender script, studioSB/Crossmod)

ScanMountGoat commented 2 years ago

I'm getting different results from the screenshots you showed in game for the exported anim. I removed the inherit_scale field from ssbh_data and reworked how the scale flags are used. I'm able to recreate the flickering for Palutena's ftilt in ssbh_wgpu after disabling some checks in ssbh_data, but the rotation values are slightly different. This is probably related to the issues with sonic you're experiencing. I got similar results setting inherit_scale to true from my testing.

Any custom anim made with the current tooling should have inherit_scale set to false for all tracks. This avoids a bug where ssbh_data sets a uniform scale flag but writes three distinct scale values. This doesn't impact reading any in game anim files, which don't run into this edge case. Setting "inherit_scale" to false uses the scale flags in game for non-uniform scale that doesn't have to be constant. Rounding or checking if the values are close to one another shouldn't be necessary to prevent glitches, but it might still be a good idea for file sizes.

The updated ssbh_data/ssbh_data_py will return an error on some exported anims since the specified bit counts don't match what it expects. The parser in game is clearly less picky, but I'm not comfortable removing a safety check for incorrectly formatted data. It's worth waiting to update ssbh_data_py, so we have time to fix #156 and give users time to fix their existing anim files. Setting inherit_scale to false using find and replace on the current ssbh_data_json should fix the issue.

I'd also like to do some more testing to see if the "const" variants of the scale types actually affect anything in game. If you still run into issues with inherit_scale set to false, I can push another version of ssbh_data_py.

ssbucarlos commented 2 years ago

thank you for looking into this. Ill go ahead and update smush_blender to use false then for inherit_scale . Ill let you know if the issue returns despite setting inherit_scale to false.
I forgot to mention, but for the ftilt specifically i needed to adjust the swingblend.prc to disable blending with the dynamic physics calculations in order to get it to closer match older programs. I figured the inaccuracies was due to me not properly disabling blending in swingblend.prc. But yeah the previous screenshots with the sonic anim was alot closer. This is what the ftilt looked like for me ingame after adjusting the swingblend.prc. https://user-images.githubusercontent.com/77519735/201237766-e9bb8aff-cb9e-418e-bbd8-52ce5e542bff.mp4

ssbucarlos commented 1 year ago

re-opening because its happening again rip https://github.com/ssbucarlos/smash-ultimate-blender/commit/f9ad7922ff958f6caa14837c7f13fa0eb8eeada0 This is the commit where the issue happens again

ScanMountGoat commented 1 year ago

Is this the exact same issue as before or should we open a new issue? SSBH Editor and ssbh_data_py should both be using the same code now, so it might be a slightly different problem this time.

ssbucarlos commented 1 year ago

it appears as intended in ssbh_editor and blender, but the animations are glitched in-game, so i don't know if the cause is the same this time, but it does look like to be the same issue (glitches in-game despite working in ssbh_editor and re-import back into blender)

ssbucarlos commented 1 year ago

I tested with mario's d04final.nuanmb

ScanMountGoat commented 1 year ago

I tested with mario's d04final.nuanmb

I'm able to reproduce this with SSBH Editor and the latest smush blender. Does this happen on other anims too?

ScanMountGoat commented 1 year ago

The only differences I can find other than rounding errors is a compression flag value change. The parsing is already fixed in the latest ssbh_data_py, so Palu's ftilt no longer has the rotation issue. It still flickers in game possibly due to the flag value. I'll need to do some more testing in game to figure out what's causing this. See the description in https://github.com/ultimate-research/ssbh_lib/issues/149.

ssbucarlos commented 1 year ago

I tested with mario's d04final.nuanmb

I'm able to reproduce this with SSBH Editor and the latest smush blender. Does this happen on other anims too?

A user said it happened to other anims, but i didn't go looking for more or ask which ones specifically, but it looks like u found another anim. i can go ask or go test myself to try to find some more if needed.

ScanMountGoat commented 1 year ago

This doesn't seem to impact all anim files. My best guess at the moment is incorrect handling of whatever the "const scale" flag actually does. Mario's wait anims don't use this flag and work fine in game after testing with ssbh_data. I've attached a list of all anims with the flag set and potentially affected by this bug. It also doesn't seem to impact every anim in this list. Not all of Kirby's wait anims seem to break, for example. const_scale.txt

I'm not going to roll back the ssbh_data_py update since it fixes some critical bugs with anim compression related to uniform scale. Users can try the earlier commit for now if they run into any issues. It should be pretty easy to tell if the anim is broken lol. It may end up working for them in spite of the other bugs with that version.

ScanMountGoat commented 1 year ago

I seem to have tracked down the issue and should hopefully have a fix and updates out in the next couple of days for ssbh_data, SSBH Editor, and ssbh_data_py. See my comments on the ssbh_lib issue for more information. @ssbucarlos

ssbucarlos commented 1 year ago

Ohhh good job tracking that down, tyvm once again SMG! 🙏

ScanMountGoat commented 1 year ago

ssbh_data is already fixed, so I just need to make some new releases. We keep running into a lot of cases that don't come up in game. This is definitely the last bug...until we find another one a month from now lol.

ssbucarlos commented 1 year ago

until we find another one a month from now lol.

lol ok that would be pretty unfortunate, hopefully this was the last one (real)