Get Quaternion (FQuat) from Vector

I know that you can easily get an FRotator from a Vector by doing


Vector.Rotation()

but how do I go about getting an FQuat?

Thanks,

  • Alex.

Hi,

Vector.Rotation().Quaternion()

Sadly I still encounter gimbal lock.



	ASpaceGamePlayerController* PlayerController = (ASpaceGamePlayerController*) GetWorld()->GetFirstPlayerController();
	FTransform Transform;
	FQuat Rotation;
	FVector MouseLocation;
	FVector MouseDirection;

	PlayerController->DeprojectMousePositionToWorld(MouseLocation, MouseDirection);
	Transform = this->GetTransform();
	Rotation = MouseDirection.Rotation().Quaternion();

	Transform.SetRotation(FQuat::Slerp(Transform.GetRotation(), Rotation, 0.1F));
	this->SetActorTransform(Transform);


Thanks for the suggestion, though.

Yes, you can’t determine Roll from a vector, it will always be zero.

That makes sense, but I still don’t understand why I get gimbal lock. I just need the pawn to be able to face the mouse, that would be simple except for the fact I need the pawn to only face the mouse when the user holds down the left click (the game is third person), so I can’t exactly just use the Mouse X and Y axes. I’ll try using those to rotate an invisible object and then interpolate the main camera’s rotation to match the invisible object’s rotation, but I have a strong feeling that it won’t work how I intend it to.

It’s probably because you’re still using Rotator’s somewhere in the chain to do the rotation. I’ve managed to avoid Gimbal Lock myself by always rotating around an axis (usually the actors’ Forward, Right & Up Vectors), or using Quat’s from start to end.

The code I posted a few posts ago is the only code I have at the moment in that pawn. :confused:

Just gonna try and work this out on my end, so you just want the actor to face the mouse-cursor position in WS? Also assuming this is 3D?

Not sure what you mean by WS, but yes that’s correct. :smiley:

There’s a video of the effect I’m trying to achieve here:

It should only rotate when I hold left click as well so that the cursor is free to interact with the interface and such.

Ahhh I see, right give me an hour or two and I may come back with something…

Okay. Thank you so much. :smiley:

Okay doing my own version is going to take longer than I thought to set-up but, here’s a trimmed-down version of how i handle steering in my Hovertank game using rotation around Axes, and avoid gimbal lock regardless of orientation. My object simulates physics however, but the basic idea is the same:

Legend:
OmegaSpin = Turn Speed
AlphaSteer = How fast craft responds to steering input.
SteerValue = Current value from the mouse X-axis for steering.
Up = Actor Up Vector
Omega = Current Angular Velocity in World-Space (WS)
LSOmega = Current Angular Velocity in Local-Space



	/* Velocity & Angular Rotation */
	Omega = UpdatedPrimitive->GetPhysicsAngularVelocity();		// Set Omega Initial Value
	FVector LSOmega = UpdatedPrimitive->GetComponentToWorld().InverseTransformVector(Omega); // Omega In Local Space

	FVector SteerVal = FVector::ZeroVector;
	if (OmegaSpin > 0.f)
	{
		/* We Need Local-Space Omega, Since Steering Is Applied In Local Space. */
		SteerVal.Z = AlphaSteer * FMath::Clamp(SteerValue - LSOmega.Z / OmegaSpin, -1.0f, 1.0f);
	}
	else
	{
		SteerVal.Z = 0.f;
	}
	Alpha += Up * SteerVal;

	Omega += Alpha * TimeStep;
	UpdatedPrimitive->SetPhysicsAngularVelocity(Omega);


Edit: Adding to this…

What I would do in your case is Figure out the World-Space position of the Reticle (and make sure it’s somewhere in front of the craft). Then I’d get the normalized direction from the craft to that location, and Dot-Product it against the crafts Right Vector and Up Vectors - and multiply it by some value to determine the strength at which the craft rotates towards it. Something like:



FVector Direction = GetActorLocation() - ReticlePositionWS();

float RightDot = FVector::DotProduct(GetActorRightVector(), Direction) * CraftRotationSpeed;
float UpDot= FVector::DotProduct(GetActorUpVector(), Direction) * CraftRotationSpeed;

FVector Alpha = FVector((GetActorUpVector() * RightDot) + (GetActorRightVector() * UpDot));


Essentially you can use the Dot Products as a way to control how much rotational ‘force’ to apply, since as they start facing 90 degrees to each other, they’ll get closer and closer to zero. What you’ll effectively have is a rotational-spring.

Edit 2: As it’s a spring, you’ll probably also want some kind of damping too:



Alpha += FVector(AlphaDamp * Omega);


If this doesn’t work still let me know, I think you may have to use an extra Cross-Product just before the Dot Product… especially if the craft can ‘Roll’

Hey, thanks for this. It’s been really helpful!

However, the only component my pawn has was a UChildActorComponent which for some reason you can’t do much or any physics stuff with it, so I created a UPrimitiveComponent and set as the root component for the pawn, but applying angular velocity to it does nothing and when it says the angular velocity is 0, 0, 0. Any ideas? I tried setting simulate physics to true, but printing out whether or not physics is enabled returns false. I also called the function to wake the rigid body, but that doesn’t seem to do anything either.

Swapping over to a UCapsuleComponent has fixed that issue. Now I can finish implementing this. :smiley:

Ah yeah, you need a valid collision to make it a physics object :slight_smile:

Thank you so much, TheJamsh. :slight_smile: I’ve managed to get ship movement working. No gimbal lock. It’s not 100% perfect, but it works and it’s very close to what I wanted. I don’t think I would have ever gotten to the point I did without your help. Thanks again. <3

1 Like