Hi staticvoidlol,
I have not heard any updates on this issue. I’ll see if I can get any new information tomorrow.
Hi staticvoidlol,
I have not heard any updates on this issue. I’ll see if I can get any new information tomorrow.
Thanks very much .
I just received a response from one of our developers that works with skeletal mesh support in the Engine. Unfortunately there isn’t much in the way of new information at this time. They believe they know what the problem is, but finding a fix that does not create a choke point in game performance is proving to be rather difficult.
The recommendation that was passed on to me was the same as it was last time: it is best not to use negative scale to mirror a SkeletalMeshComponent at this time.
I did have a thought while I was looking at this again, though. Are you using a scale of -1 to create the mirrored left arm, and then applying a scale of -1 to the socket where the sword is attached? If so, that may be contributing to the results that you are seeing. The first -1 scale mirrors the arm, and the second -1 scale for the socket mirrors the weapon twice, essentially putting it back to its original orientation.
Hi ,
Thanks very much for getting back to me.
Phew, that’s quite unfortunate news as I’m also at my wit’s end with this one.
I’ve even considered creating a hidden instance (which would be the non-mirrored version) and reading the transforms at each tick - then on the mirrored version I won’t attach the weapon model to the arm model at all, but manually set the transform from the hidden instance’s weapon model). This would be a hack of note and also terrible performance-wise - in any case, I can only find a socket reference via SkeletalMeshComponent->GetSocketByName(), which returns a const, so unfortunately I can’t modify the values even if I tried this. (Also, there are no methods to do it either).
As for my setup, I’m only mirroring the Actor - not the arm mesh component, socket or weapon mesh component. I’ve also tried all the combinations of mirroring the Actor and/or Arm Mesh Component and/or Weapon Mesh Component, but no luck.
I’ve attached two screenshots that show that it goes a bit more wonky than just being “unmirrored”.
As I’m really stuck here, do you or the engine team maybe have any ideas for possible fixes that I can explore on my side in the meantime?
Maybe just a more technical description of what is actually causing this, and/or a high level overview of how it might be solved?
Not sure if it is allowed, but maybe you could tell me how this was done in UE3?
I’m building the engine from source, so I do have access to the lower level stuff, and maybe there’s a non-zero probability that I can figure something out.
In any case, thanks very much - I do hope you guys manage to figure this one out eventually.
Thanks again and cheers!
staticvoidlol
Hi,
This is because we don’t use matrix as a base transform but FTranform which contains vector(loc), quaternion(rot) and vector(scale). FTransform doesn’t do well with concatenated mirroring because quaternion will have to flip based on previously concated axis, and it is a bit of problem.
Since this is only problem with socket, what you can do is to add special option in socket that mirrors(saying mirror socket being right arm), and get the transform (of the right arm) and just mirror using matrix? I think that might fix this particular issue.
Socket code path here - FTransform USkinnedMeshComponent::GetSocketTransform(FName InSocketName, ERelativeTransformSpace TransformSpace) const
But this will have one side effect. You’ll get a frame delay since the transform you’re querying is a frame delay. There is no good way to get reliable bone transform of current frame in particular when physics is combined. So the safest thing to do right now is to just modify that function to use one transform to mirror it manually with a frame of delay.
The real issue we should fix is to have concatenation to work with mirroring.
Thanks,
–Lina,
Hi Lina,
Thanks very much for the detailed response - makes sense.
I’ll have a look at fixing it in the suggested way and check if the frame delay poses an issue.
Thanks!
staticvoidlol
so you need manual set RelativeScale3d, after AttachTo
Hi,
I have been struggling with this problem in the past week, and I have found a workaround. You need a bit of C++ to do it.
Let me explain the problem first. As I’ve understood it, UE4 does not use 4x4 matrixes in homogenous coordinates for transforms, but a system of 3 vectors (scale, rotation and translation, in that order). The math they’re using gives wrong results under limited circumstances, one of that being a component high in the hierarchy having negative scale.
This does not affect meshes (they get rendered correctly, by being mirrored), but it affects the scene component attachment system.
What you need to do to fix it is to forego attaching the component to a mesh, and instead manually calculate the socket world coordinates, converting first into FMatrixes, multiplying them, and converting back to FTransform.
For example, you could make a derived SceneComponent with a SkeletalMeshComponent and SocketName public field and insert code similar to this in its TickComponent method:
Please beware that in matrix product the order of operands matters.
if (!SkeletalMeshComponent) return;
FTransform socketTransform = SkeletalMeshComponent->GetSocketTransform(SocketName, RTS_Component);
FMatrix localSocketMtx = socketTransform.ToMatrixWithScale();
FMatrix componentWorldMtx = SocketMasterComponent->GetComponentTransform().ToMatrixWithScale();
FMatrix finalMtx = localSocketMtx * componentWorldMtx;
this->SetWorldTransform(FTransform(finalMtx));
I have tested this and it works in my project. If you want more details contact me privately.
I would strongly suggest Epic Games look into this. Skeletal Mesh mirroring is an important feature, for example for platformers where you need to always have the character facing the screen.
While converting to FMatrix might not be an ideal choice performance-wise, the engine should include an option to use more correct transformation math for a set of components as an option. At least, that’s my view on it.
Hi Claudio,
Thanks a million for the clear and articulate answer - it is much appreciated!
I will have a look next week and get back on this.
Cheers!
It’s something like a year and a half late :). I’m glad you found it useful nonetheless.
Hi everyone,
I just wanted to provide a quick update on this issue. This is an area that we have been putting some focus on recently, and we believe we have some initial fixes in place for the behavior that you have been experiencing. The fixes are currently a little fragile, but they have been added into version 4.12. Since the first preview for 4.12 was released today, please feel free to download the preview and let us know if you see any improvements in this behavior.
I confirm that in the latest 4.12 Preview 1, the bug is fixed.
By the way, I wonder if my latest reply brought the issue to light again, or was it already being fixed?
Hi
From what I can tell it was just a coincidence. When I went back to the Developers that are responsible for this part of the Engine, they let me know that they had actually started focusing on mirroring issues a few days before I contacted them.
It is good to hear that the issue has been resolved for you in 4.12 Preview 1. We are going to continue working on this to try to firm up the fixes.
Hi .
I’m using 4.12 and have a related issue - with negative scaling on sockets, physics simulating child meshes attached to such a socket report warnings because of a mass mismatch. From what I can see, the volume calculation returns a negative volume, which ends up being clamped resulting in a zero mass.
Should negative scales with physics bodies be supported? Note I’m using convex collision volumes.
Another minor related issue is that in the static mesh editor, negative scales do not visibly flip the widget axes of the socket, as I would expect to happen.
Hi ,
I apologize, I completely missed this comment. I spoke with a few people who are more familiar with physics in UE4 and they weren’t sure why you would be seeing these results. If you are still seeing this behavior, would you be able to provide some more detailed information about how you are setting this up, or perhaps provide a sample project that would demonstrate the behavior?