Adding Dual Quaternion support to UnrealEngine4 (Images inside)

17891113

Comments

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    Thanks. I really appreciate it.

    Ran into a bit of a problem, but I hope it still works. Allocation of vertex buffers is hidden deep in the engine code. So I had to allocate separate buffers for the DQS bone arrays. I haven't tested it yet. But it compiles.

    The way shader buffers work is that on the CPU side, you write to an array then you copy it to an array on the GPU (so CPU array must either be in DMA accessible RAM or copied to that kind of RAM before being copied over to the GPU). The point is I can't change the existing code within a plugin. There's already a shader buffer for the LS bone matrices. I cannot change this (unlike the DQS branch that does change this). What I'm doing now in the plugin is allocating new shader buffers for the DQS bone arrays to be used by the deformer shaders. I then convert from LS to DQS on CPU. I'm hoping since the LS arrays aren't used by any shaders, it'll just be a bit of extra memory used on the CPU side. It's very minimal and shouldn't affect anything. I'm also re-using the buffers (assuming the deformer graph reuses the same node instances) so that should help a little. The irony of all this is that the data actually starts off as quaternions, but because the code is so deep in the engine, it gets converted to matrices then back to quaternions. Oh well.

    I moved the Quat and DualQuat code directly into the plugin that didn't exist in the main code (but did exist on my branch because I added it). If I do a pull request, I may try to get the Quat and DualQuat stuff updated. But I still have no idea where their unit tests are stored (or if they even have any).

    I'm now copying the shader code from my branch to the plugin's custom shader code. The nice thing about having a custom shader file is that I don't need to include *any* of the LS shader code. It's 100% DQS code. This right here is what has me very optimistic about this project. DQS only shader code, not back conversions... everything is just cleaner (well, mostly).

    I looked at the cloth and normal recomputation shaders and I think I'll add those as well for DQS. There doesn't seem to be anything difficult at all there. 

    Sorry if I've been commenting a lot, but this is a lot of fun. I really hope the new shader buffers work otherwise that will kill this project dead in the water. I mean, I could try converting in place, but that's not something I want to do since I can't track the change.

    This is my TODO list:

    1. Convert LS matrices to DQS matrices (DONE)
    2. Convert Skeleton shader to DQS (DONE)
    3. Create custom deformer shaders for DQS (basic, morph, cloth and normal recomputations).

     

    Post edited by AlienRenders on
  • My friend and I implemented DQS with Deformer. There is no rotation Angle limit. But I'm new to using the Unreal Engine, so I'm not sure about its impact on performance.

  • @1044083166: Where did you get the dual quaternion from?

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    Ran into a couple problems. First is that the vertex buffer is set to dynamic. That means it can only be written by CPU and read by GPU. So when I try to read from it, there's only junk. Second thing is I don't think any of the nodes can actually execute anything. All it seems to be doing is compiling a shader and setting the buffers that the shaders use. So the skinning code in the engine always writes to the same buffer (well, there's two buffers, but whatever, they are swapped back and forth). That means my code that converts the LS bone matrices to DQS never gets called. The deformer plugin seems to be a shader plugin only. That's going to be horrific for performance using DQS if you have to convert from LS matrices every single time.

    Sorry to say this project is simply not going to happen. I tried. If I get any other ideas, I'll give it a go, but right now, DQS via deformer is technically possible, but I'm not wasting my time on something that's this bad performance wise.

    edit: One thing I can do is add this plugin to my DQS branch. This may seem odd at first, but it means 100% of the shader code would move to the plugin. And I can update the engine code to check if there's a deformer and some setting on the actor somehow that will tell it to convert the bone matrices to DQS. This would make maintenance easier and allow DQS on specific actors. With so few changes in the main code, I might be able to make a pull request.

    If anyone has a good idea where to put the checkbox for DQS on the actor, please let me know. Maybe a DQS component would be good enough.

    Post edited by AlienRenders on
  • AlienRenders said:

    @1044083166: Where did you get the dual quaternion from?

    There are some code screenshots.

    1.png
    1342 x 1046 - 168K
    2.png
    1718 x 1401 - 317K
  • By the way, this requires adding an Additional Source like a header file to use function: transform().
    If you are free, can you test  its performance? Thank you!

     

    3.png
    1133 x 269 - 28K
    4.png
    1071 x 535 - 76K
  • AlienRenders said:

    @1044083166: Where did you get the dual quaternion from?

    I uploaded the code to a txt file. 

    txt
    txt
    DQS_Main.txt
    2K
    txt
    txt
    DSL_DQS_Custom.txt
    785B
  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    Yeah, you're converting the bone matrices N times for every vertex. This is the method I mentioned above that is highly inefficent. It should work though.

    I'm trying to think of ways to get around this. But I can't think of any. If it was a compute shader, I could probably do the conversion on the GPU, but these are explicitly vertex shaders. Maybe a geometry shader could do it, but I didn't see anything in these deformer graphs that would allow it.

    Post edited by AlienRenders on
  • AlienRenders said:

    Yeah, you're converting the bone matrices N times for every vertex. This is the method I mentioned above that is highly inefficent. It should work though.

    I'm trying to think of ways to get around this. But I can't think of any. If it was a compute shader, I could probably do the conversion on the GPU, but these are explicitly vertex shaders. Maybe a geometry shader could do it, but I didn't see anything in these deformer graphs that would allow it.

    yes  Look forward to your work.

  • I think my best bet is to add an option to write the bone matrices as DQ in the engine itself and try and do a pull request on the main branch. The problem I see here is either have two options (LS or DQS) or have an option to run a blueprint that would allow modifying the array. The deformer plugin added a new member to the skelatal mesh. So maybe I can do the same. Once we have that, I could add a property on the actor (or mesh component) that allows for converting the bone matrices. A bigger issue is to be fully flexible, I'd need a way to change the dimensions and types of the vertex buffer array. I could maybe make it simple and just have a setting for N float4's per vertex.

    Actually, I'm gonna try to find out who maintains the deformer graph and ask if they can add this, or if I can work with them to get this done.

     

  • 1044083166 said:

    AlienRenders said:

    Yeah, you're converting the bone matrices N times for every vertex. This is the method I mentioned above that is highly inefficent. It should work though.

    I'm trying to think of ways to get around this. But I can't think of any. If it was a compute shader, I could probably do the conversion on the GPU, but these are explicitly vertex shaders. Maybe a geometry shader could do it, but I didn't see anything in these deformer graphs that would allow it.

    yes  Look forward to your work.

    Unfortunately, I think this is the end of the line for now.

     

  • AlienRenders said:

    I think my best bet is to add an option to write the bone matrices as DQ in the engine itself and try and do a pull request on the main branch. The problem I see here is either have two options (LS or DQS) or have an option to run a blueprint that would allow modifying the array. The deformer plugin added a new member to the skelatal mesh. So maybe I can do the same. Once we have that, I could add a property on the actor (or mesh component) that allows for converting the bone matrices. A bigger issue is to be fully flexible, I'd need a way to change the dimensions and types of the vertex buffer array. I could maybe make it simple and just have a setting for N float4's per vertex.

    Actually, I'm gonna try to find out who maintains the deformer graph and ask if they can add this, or if I can work with them to get this done.

     

     Thank you for your efforts, it would be great if that could be done.

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    Thanks. I think I'll create a 5.2 DQS branch soon and add my plugin there. At the very least, it'll cut down the amount of changes drastically and I may be able to get a pull request done if I can add a way to run a blueprint or set a delegate. I don't think there'd be any maintenance needed, so it's more likely to get approved.

    edit: I posted a comment on the UE forums. Hopefully, someone can help me out.

    Post edited by AlienRenders on
  • catmastercatmaster Posts: 226

    AlienRenders said:

    Thanks. I think I'll create a 5.2 DQS branch soon and add my plugin there. At the very least, it'll cut down the amount of changes drastically and I may be able to get a pull request done if I can add a way to run a blueprint or set a delegate. I don't think there'd be any maintenance needed, so it's more likely to get approved.

    edit: I posted a comment on the UE forums. Hopefully, someone can help me out.

    Please also put the plugin for UE5.1, UE5.2 could be highly experimental, I don't want to recompile the whole engine while my game is based on the relatively stable UE5.1 and its plugins.  

  • I'm using 5.1 as well, so I'll do that. I noticed that linear skinning doesn't work on my 5.1 mod branch. Trying to fix that now. ALL of the shader code is being reverted on the mod branch. It will be replaced with a deformer plugin. There will be a dropdown in the SkinnedMeshComponent to set LS or DQS. If you use DQS, you must use a deformer that will be supplied in the plugin. So basically, there's very little altered code. Just a few if statements before calling a DQS conversion method before writing to the bones vertex buffer.

    It's not as good as a standalone plugin, but I think it's getting closer. And hopefully, I can clean it up to the point where I can make a pull request on the main branch.

    Now I have to wait for the entire thing to rebuild. lol

     

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    While I couldn't get a standalone plugin going, I do have a bit of good news for the 5.1-mod branch. I haven't checked anything in yet, but I did get the plugin to work on that branch (locally). All the main shader code has been reverted. There's only a little bit of code in GPUSkinVertexFactory.cpp and a new property on the SkinnedMeshComponent (and SkeletalMeshComponent) to specify the type of skinning you want to use on that actor. If you specify DQS, you will have to supply a DQS deformer.

    So this is a feature people have been asking for a while now. To be able to specify which actors use DQS and which ones use LS. That will now be possible to mix them both. And everything will work, mesh, cloth, morphs and normal recomputations.

    I've only created the most basic deformer right now. I will get to the other ones later on. I will add scaling as well. This might be a boolean input to the Skeleton node if you need it. Haven't decided yet. It is Unreal Engine scaling, *not* DAZ scaling. The DQS deformers even work in the preview windows in the editor (but you need to set a default skinning format and default deformer on the mesh). All the DQS deformers will be in their own plugin.

    Once I get this cleaned up a bit, I'm thinking of attempting a pull request on the main UE branch. But that will be on the 5.2 or release branch.

    I will likely update 5.1-mod this weekend or whenever I finish the remaining shaders.

    edit: Forgot to mention that since 5.1-mod will be able to use the deformers, there are no more back conversions. It is way more effiicient than before.

     

    Post edited by AlienRenders on
  • I pushed my changes onto my 5.1-mod branch.

    New features:

    • DQS deformers for vertex, morphs and cloth.
    • Each of the above also has a version with scaling, but it behaves a bit weird on single axis scaling. All three set to the same value seems to work well.
    • Option to use DQS or LS for bone matrices on the skeletal or skinned mesh component.
    • No more back conversions to LS matrices in the shaders and should be much more efficient.

    To use DQS, you need to enable it on the mesh component (dropdown property called "Skinning" in the "Deformer" group) and set one of the DQS deformers. Don't forget to enable both the Deformer and DQS Deformer plugins.

    Note that the DQS build setting has been removed. So DQS is no longer automatic. You need to enable it on the actors you want to use it on.

    This version of the plugin doesn't work on 5.2 since they changed the way weights work with unlimited bone influences. What I intend to do for 5.2 (well, the release branch) is merge my plugin with the main deformer plugin and do a pull request on the main branch. If it get approved, no more custom builds :) But I've figured out where their unit tests are, so I need to write a few tests for the quaternion and dual quaternion methods I added.

    Anyhow, 5.1-mod should be a huge improvement Let me know if something doesn't work.

     

  • FYI, I've started my attempt at making a pull request on ue5-main branch of the main epic games repository. This will take a bit of work and is a long process to get approved (or just looked at).

     

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    I'm done making the changes to ue5-main locally and am now writing unit tests. I think I found a critical bug in the main ue5 code (and ue4 for that matter) as it relates to Dual Quaternions. I find it difficult to believe that they never added any unit tests at all for their dual quaternion class. They do have unit tests for regular quaternions (and those are vector optimized SSE2+ so that's nice).

    Rotations are fine in Dual Quaternions, but translations/offsets are not. I don't know yet to what extent this affected things. I know I had problems with scaling individual axis and I also had problems with rotating bones in my control rig (and this had to do with offsets). Will it fix these issues? I don't know. But the DQ math is wrong in UE4 and UE5's Dual Quaternion class. Not sure how I missed it before now. I will put a fix on my branch (5.1-mod) soon.

    edit: It's wrong in the deformer shader library as well. Luckily, I haven't used that method, but still...

    Post edited by AlienRenders on
  • catmastercatmaster Posts: 226
    edited March 2023

    I find it difficult to believe that they never added any unit tests at all for their dual quaternion class. They do have unit tests for regular quaternions (and those are vector optimized SSE2+ so that's nice).

    Guess that's why Unreal has default motion blur for the templates to hide the defects of skin deform mechanics, Unreal is such a beast that includes huge code library inherited from legacy sources decades ago. It needs lots of practices to learn which blueprint nodes are reliable and which are not, for example I spent weeks to figure out how to use the buggy chaos vehicles and made them work with character body physics, even bought some market place assets trying to learn from them but found those assets didn't fix the problems.

    If the standalone plugin wouldn't be possible, I'd download the whole modded engine to try, but I'm afraid to use that for my current project as the project already used too many experimental features of UE5 and it was very difficult for me to get it into the current state. There is too much to learn as a newbie and I'm trying to find smarter ways to make games.

    Wish the mods could be approved and integrated into the official 5.2 builds and that'd be very good news for Unreal users.

    Post edited by catmaster on
  • I think I'll try to commit my pull request tomorrow. I couldn't find an answer how to add uassets (the deformer graphs) so I'll ask in the pull request. But if it gets approved, you can just download the graphs from my github (and/or I'll make a separate plugin).

    BTW, the changes to the official builds are rather minimal now. There are zero shader changes and there's only two if statements for setting the bone matrices and properties to specify if you want LS or DQS. So the original code is 100% functional and is not affected by anything I've added. So the risk should be minimal compared to before. It should also be a lot simpler to merge to your own branch now.

    Anyhow, hopefully it'll get approved.

    If there are any mathematically inclined people in this forum, could you check the TDualQuat::operator*(const TDualQuat&) method and let me know that I'm not going crazy and the math is wrong? Thanks.

     

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    I have just submitted my pull request to Epic's Unreal Engine git repository. The pull request number is #10230 on the ue5-main branch in case anyone wants to monitor it. This can be a slow process taking months and sometimes they never look at it. But with this pull request, there is ZERO functionailty change on existing behaviour, so with any luck it will get approved.

    For those who don't know, a pull request is a request to have your code included on someone else's project (in this case, Unreal Engine). A pull is from the project owner's side. In git (revision software), a pull command is to grab the changes from the server. A pull request is someone else asking you to "pull" their changes onto your codebase. And yes, from the developer's side, it can look like a push.

    On a sidenote, I've looked into why the non-uniform scaling doesn't work. Non-uniform means not all the same value. So different scaling on X, Y and Z axis is non uniform. And this is expected behaviour when trying to extract scaling from a matrix. It will skew if other transforms have been applied in a bone chain (two or more). It is possible to extract the correct scaling, but it's a non trivial and very lengthy operation. So I'm not including it. Uniform scaling works fine (all three XYZ scaling values are the same).

    edit: Oh, and if it gets approved, it will be on 5.3 at the earliest. This was a crazy amount of work. I'm going to have a beer now :)

    Post edited by AlienRenders on
  • McKenzieMcKenzie Posts: 8
    edited March 2023

    Thank you for all the hardwork you've done...we all are grateful for your efforts,even if the changes don't make it into the engine it makes my day watching people like you do their best for the community,have a good rest and lets hope your work makes into the engine

    BTW is your 5.1 brach working with DQS?...I saw you updated it and said that you tested it with simple deformers,If it works can you post the procees of making it(what nodes to use in the deformer graph and such) work I'll start downloading it then...thx

     

    Post edited by McKenzie on
  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    Thanks for your comments. I appreciate it!

    On 5.1, I already supply the DQS deformer graphs. You need to enable both the deformer and DQSDeformer plugins. There are two plugins. Then you just click the checkbox next to the deformer settings in the Mesh component of your actor. Select Dual Quaternion Skinning and select one of the supplied graphs such as "DQSBlendSkin" (might be DG_ prefix, I can't remember, but the names have DQS in them) and that's it. If you use morphs, use the one with Morph in the name. If you use Cloth, use the one with Cloth in the name..

    If it doesn't work for you, please let me know.

    edit: Oh, if you rotate a bone and it doesn't update, recompile the graph. If it crashes or doesn't display, remove the DQSSkeleton node and replace it with a new one. For some reason, it sometimes thinks it's a different node if you rebuild from source.

    edit2: I updated 5.1-mod to match the pull request code. Same behaviour, just a bit cleaner code.

    Post edited by AlienRenders on
  • Awesome stuff.  Got it working except when I select DQSBlendSkin_Morph my character mesh disappears.  It all works fine with DQSBlendSkin_Morph_Cloth though, so I just switched my character to that deformer graph.  Not sure if that is right but it works.  Appreciate your efforts, thanks.

  • AlienRenders said:

    Thanks for your comments. I appreciate it!

    On 5.1, I already supply the DQS deformer graphs. You need to enable both the deformer and DQSDeformer plugins. There are two plugins. Then you just click the checkbox next to the deformer settings in the Mesh component of your actor. Select Dual Quaternion Skinning and select one of the supplied graphs such as "DQSBlendSkin" (might be DG_ prefix, I can't remember, but the names have DQS in them) and that's it. If you use morphs, use the one with Morph in the name. If you use Cloth, use the one with Cloth in the name..

    If it doesn't work for you, please let me know.

    edit: Oh, if you rotate a bone and it doesn't update, recompile the graph. If it crashes or doesn't display, remove the DQSSkeleton node and replace it with a new one. For some reason, it sometimes thinks it's a different node if you rebuild from source.

    edit2: I updated 5.1-mod to match the pull request code. Same behaviour, just a bit cleaner code.

    Unfortunately, this new approach with deformer graphs breaks compatibility both with the JCM post-process blueprints and the recompute tangents option thus I would advise against upgrading yet, the "old" method is way more robust as of now.

  • AlienRendersAlienRenders Posts: 790
    edited March 2023

    @Krys Kryngle: You can always use the larger graphs. Did you compile the morph graph? Sometimes it will not automatically compile the graphs. You can also try removing the DQS Skeleton node and replacing it with a new one. (edit: Also make sure that DQS skinning is selected. Your character disappearing with LS selected is normal. Your mesh will reappear when you select both DQS and a DQS graph. If it's still not appearing, then try one of the previous suggestions. I've tested them all. They should all work.)

    @fasirozott: I'm not sure what workflow you have. Morphs should work just fine. I haven't looked at the recompute tangents option. That may require recomputing normals and I couldn't implement that graph as it required internal code from the Deformer plugin and wouldn't allow me to add it to the DQS Deformer plugin.

    If anyone wants to send me example projects and an explanation of what breaks, I'll be glad to look at it.

     

    Post edited by AlienRenders on
  • fasirozott said:

    AlienRenders said:

    Thanks for your comments. I appreciate it!

    On 5.1, I already supply the DQS deformer graphs. You need to enable both the deformer and DQSDeformer plugins. There are two plugins. Then you just click the checkbox next to the deformer settings in the Mesh component of your actor. Select Dual Quaternion Skinning and select one of the supplied graphs such as "DQSBlendSkin" (might be DG_ prefix, I can't remember, but the names have DQS in them) and that's it. If you use morphs, use the one with Morph in the name. If you use Cloth, use the one with Cloth in the name..

    If it doesn't work for you, please let me know.

    edit: Oh, if you rotate a bone and it doesn't update, recompile the graph. If it crashes or doesn't display, remove the DQSSkeleton node and replace it with a new one. For some reason, it sometimes thinks it's a different node if you rebuild from source.

    edit2: I updated 5.1-mod to match the pull request code. Same behaviour, just a bit cleaner code.

    Unfortunately, this new approach with deformer graphs breaks compatibility both with the JCM post-process blueprints and the recompute tangents option thus I would advise against upgrading yet, the "old" method is way more robust as of now.

    The 'old' method is having DQS turned on all the time?  Is there a way to do that now with the 5.1 version on github or is there another branch that will allow us to turn DQS on in 5.1? 

  • @AlienRenders: Yes, I'm talking about the normal/tangent recompute feature, the setting found for skeletal meshes in the LOD0 - Sections menu, set Recompute Tangents to "All" there. (with the latest release it has no effect) I also use animation blueprint to apply the JCM morphs (Post Process Anim Blueprint setting for skeletal mesh), and it seemed to behave wierdly, too.

    @Krys: Just use the older commit from November to revert to the old version, where DQS is always turned on: https://github.com/AlienRenders/UnrealEngine/commit/91565c207702b86fec8fb3fc581aed6fb6014e72

  • 10440831661044083166 Posts: 21
    edited March 2023

    When packaging into a project, has anyone encountered skeletal mesh shake? I don;t know how to solve it

    It happens after I change morph target value in Character BP.  But when mesh shake, if I make a small change to any morph target, it will be stable.

    Post edited by 1044083166 on
Sign In or Register to comment.