x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

Is there anyway to set control rotation with a quaternion?

I'm trying to have 6DoF with my control rotation. I keep running into gimbal lock. My world is round and the players feet should always point towards the planets center. When I try to add in the mouse input X rotation I believe it is causing it. I keep reading everywhere that keeping rotations as quaternions will eliminate this but I don't see how I can when SetControlRotation only takes a rotator.

Product Version: UE 4.10
Tags:
more ▼

asked Jul 05 '16 at 09:18 PM in C++ Programming

avatar image

Thumper
966 141 150 390

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

Finally!!! The solution was to set the capsule upvector rotation first using MakeFromZX. Then using the capsules AddLocalRotation (which the control rotation doesn't have) I add in the mouse X input rotation. Then finally set the control rotation using the capsule rotations. No Gimbal Lock. I had to set bUseControllerRotation (Pitch, Roll, And Yaw) to False first.

     //Initialize component...
     bUseControllerRotationPitch = false;
     bUseControllerRotationRoll = false;
     bUseControllerRotationYaw = false;
     
     //Tick Function...
  //####### Adjusted UpVector for the capsule
     GetCapsuleComponent()->SetRelativeRotation(FRotationMatrix::MakeFromZX(GetCapsuleComponent()-       >GetComponentLocation(), GetCapsuleComponent()->GetForwardVector()).ToQuat());
 //####### Add in mouse X input rotation
     GetCapsuleComponent()->AddLocalRotation(FRotator(0, mouseX, 0));
 //####### Set the control rotation using the capsules rotation
     Controller->SetControlRotation(GetCapsuleComponent()->GetComponentRotation());





more ▼

answered Jul 07 '16 at 04:19 PM

avatar image

Thumper
966 141 150 390

avatar image jejunus Jan 21 '17 at 02:00 AM

I'm having trouble with gimbal lock and it seems you've grappled with this several times before. Your solution above doesn't work for me, but I'm trying to set rotation of an actor, not component. I assume the capsule component is the root component of your character actor so why are you not just adjusting the actor rotation? Maybe your answer will help me better understand what I'm doing wrong. Thanks in advance.

avatar image Thumper Jan 21 '17 at 02:16 AM

Yeah I've definitely gone the rounds with it. To be honest I've adjusted this so many times I've almost forgot my motivations between the different versions. In my setup I'm trying to point the feet of my character capsule towards the world center. This is done because the world is round. I had already gone through the Character Movement Component and retro fitted it to allow for spherical movement. Looking at my current code I've simplified it even further than the above answer. Perhaps it will help.

 Capsule->SetRelativeRotation(FRotationMatrix::MakeFromZX(Capsule->GetComponentLocation(), inVec).ToQuat());

The trouble is this all ready depends on your characters setup. The above code relies on this vector to point it the direction I want to be looking, so I grab the last movement input vector. I do this because I've not moved the camera to third person, and my character points looks and runs in the direction the left analog stick is pointing. So the code above uses the code below to maintain a relative looking direction, while aiming the orientation of the capsule.

 FVector lastInVec = GetLastMovementInputVector();

Originally I used a different setup which swiveled the capsule based on Mouse X input, which was added in using the "addLocalRotation", then I would set my control rotation using the modified capsule rotation. This avoided many problems I was encountering with gimbal lock. If I remember correctly the addLocalRotation function was key to this.

avatar image jejunus Jan 21 '17 at 05:37 AM

Thanks for your response Thumper. Yeah, I'm trying to do about the same as what you're doing, except I've set up a vehicle pawn with a FloatingPawnMovement component. You said you had already gone through the Character Movement component? Do you remember what you had to change there? All I'm really using the FloatingPawnMovement for is to apply forward acceleration, so I can't see how it would influence rotation.

     FMatrix TargetRotationMatrix = FRotationMatrix::MakeFromZX(VisiOutHit.ImpactNormal, GetActorForwardVector());
     FQuat TargetRotationQuat = TargetRotationMatrix.ToQuat();
     TargetRotationQuat.Normalize();
 
     FTransform NewTransform = GetActorTransform();
     FQuat CurrentRotationQuat = NewTransform.GetRotation();
     FQuat InverseCurrentRotationQuat = CurrentRotationQuat.Inverse();
 
     FQuat LerpedRotationQuat = FQuat::FastLerp(CurrentRotationQuat, TargetRotationQuat, .1f);
     LerpedRotationQuat.Normalize();
 
     NewTransform.SetRotation(CurrentRotationQuat * InverseCurrentRotationQuat * LerpedRotationQuat);
     NewTransform.NormalizeRotation();
     SetActorTransform(NewTransform);

Like you, I have a spherical "world" and I need the pawn to hug the surface as it moves around. The above code starts to gimbal lock near the equator. I'm not even adding any yaw/mouseX input yet, just trying to avoid the gimbal lock first. And as far as I can tell I'm deriving my rotation values strictly with quaternion operations.

avatar image Thumper Jan 21 '17 at 03:16 PM

Attached is a screen grab of the real message I wrote. As you can see I went over my character limit, so I posted it in the image form :) alt textalt text

alt text

6dofcmc.jpg (921.3 kB)
6dofmessage.jpg (497.3 kB)
avatar image Thumper Jan 21 '17 at 03:18 PM

Here are those functions in copy pastable form.

 //To Orthagonal space
 FVector UKoreCharMoveComp::toOrthoSpace(FVector VectorToConvert) const
 {
     FTransform compToWorldTrans = CharacterOwner->GetCapsuleComponent()->GetComponentTransform();
     FVector rotatedVector = compToWorldTrans.InverseTransformVectorNoScale(VectorToConvert);
     return rotatedVector;
 }
 //From Orthagonal space
 FVector UKoreCharMoveComp::fromOrthoSpace(FVector VectorToConvert) const
 {
     FTransform compToWorldTrans = CharacterOwner->GetCapsuleComponent()->GetComponentTransform();
     FVector rotatedVector = compToWorldTrans.TransformVectorNoScale(VectorToConvert);
     return rotatedVector;
 }
avatar image jejunus Jan 22 '17 at 06:22 PM

Thanks again, this is very useful. Yeah, I want the pawn's rotation to conform to the topo surface, and feeding in the impact normal as Z for the makeFromZX method seems to work as it should. Now I suspect the problem is in the forward movement, which I was assuming to be calculated relatively by the FloatingPawnMovement component. Thanks for pointing out that this is a bad assumption, I think I see where the forward vector for movement is being converted to world space, which is obviously not what I want. Fortunately the FloatingPawnMovement component is far less complicated than the Character Movement component. I actually think I'll just write my own forward movement function rather than modifying the UE codebase.

avatar image jejunus Jan 23 '17 at 03:06 AM

So turns out the problem was not with the rotation, my above code does what it's supposed to. But I was also adjusting the pawn's location every tick to keep it at a fixed distance from the topo surface, and of course I was only adjusting the pawn's Z value to do this. Unfortunately for me it kind of simulated gimbal lock since updating the pawn's world Z made its movement progressively more erratic as it neared the world "equator". So, a total red herring. What a waste of time. Thanks a lot for jumping in on this closed thread anyway Thumper, I think your world space conversion functions will come in handy at some point.

avatar image LaOwLLol Apr 05 '17 at 01:12 AM

Hey there,

I've been looking over this post (and other), slowing trying to understand the code and quaternion math. And Thumper you have a lot of comments on this subject!

I think I have a similar problem with rotation, but I'm working with a different camera position, and controller inputs.

I was just hoping one of you could maybe help out on my question:

https://answers.unrealengine.com/questions/583586/concatenate-fquat-rotation-resulting-in-gimbal-loc.html

thanks in advance!

avatar image Insomnawolf Aug 02 '17 at 08:40 AM

Hello! I am having issues with gimbal lock as well, and as I read the comments y'all posted, I see that you have experience with the matter. My issue will probably seem trivial as it does not involve a sphere or 6dof but rather less (or make it harder in some convoluted way...I hope not hehe).

Here is my post. I would love help on this as I am continuing my months of research to smoothly rotate around only one axis! :D

https://answers.unrealengine.com/questions/666020/gimbal-lock-causing-smooth-rotational-issues.html

Thank you for your time!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

FRotators are not Euler internally. They let you modify the rotation of a character with Euler because it's intuitive as opposed to entering Quaternion values directly. You can calculate your quaternion and assign it to your rotator.

 FRotator NewRot(YourCalculatedQuaternion);
 SetControlRotation(NewRot);

This next part I'm writing off the top of my head so there might be mistakes, but to calculate that quaternion assuming the player is standing on a sphere I would try something like the following:

If VecUp is the 'up' vector at the point on the sphere the player is standing, then:

 VecUp = PlayerActor.GetActorLocation() - SphereActor.GetActorLocation;
 VecUp.Normalize();
 FQuat YourCalculatedQuaternion = FQuat::FindBetween(FVector::UpVector, VecUp);

That would put him in the correct orientation (feet on ground, head towards the sky), then to spin him in place to the desired facing:

 FQuat LocalSpin(FVector::UpVector, MyYaw);
 YourCalculatedQuaternion *= LocalSpin;

You would keep track of what 'Yaw' or spin round his center he has at the time.

more ▼

answered Jul 06 '16 at 09:34 PM

avatar image

rantrod
1.5k 49 47 216

avatar image Thumper Jul 06 '16 at 11:24 PM

I haven't used fquat::findbetween yet so I'm hopeful. I was using makefromzx which could have been the problem. I had setup the yaw part though, and did the fquat * fquat part. It still produced gimbal lock, but maybe this new way of getting the correct vertical orientation will add in better. I'll check it out. Thank you!

avatar image rantrod Jul 06 '16 at 11:33 PM

Yes, I replied to one of your threads where you ask about your method. I recommended trying to change your line:

 orgRot.ConcatenateRotation(addInRot);

to

 orgRot.SetRotation(addInRot * orgRot.GetRotation());

The method I describe here might also work. Just thought a slight modification to what you already had would be a quick test.

avatar image Thumper Jul 06 '16 at 11:45 PM

Haha, yeah it would have been a quick test but I spent today going through this response I received. It required me to use a pawn, and movement component instead of character and CMP. So far it has been worth it because I have it working using this method. Its rough but it appears to avoid gimbal lock.

The link

avatar image Thumper Jul 07 '16 at 03:49 PM

Okay I I put the Character and CharacterMovementComponent back in play (they have so much nice functionality built into them already). I tried to apply what you wrote above

 FQuat upRot(FQuat::FindBetween(FVector::UpVector, GetCapsuleComponent()->GetComponentLocation().GetSafeNormal()));
     FQuat yawRot(FVector::UpVector, mouseX);
     Controller->SetControlRotation((upRot * yawRot).Rotator());

This appears to point me in the right vertical direction but adding in the mouse X rotation results in twitching (like it's trying to Yaw but not being allowed to). And I just noticed that when I walk my character over to the axis poles of the world - the character still flips over on his head.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question