Stumped myself on this one. Here is my yaw rotate function for having my character face the mouse pointer. It’s called in character tick. I utilize typical WASD to move around, when moving toward the cursor he walks forward, away and perpendicular he back peddles or strafes…
Except when moving downward ( negative on the X axis ), he often still faces the +X therefore back peddling. My camera relative to the player is boomed @ 800, rot -60 degrees downward (Y Axis) and is further negative on the X axis. So this happens when he’s facing the camera (or at least should be facing it).
void PlayerController::RotateToMouseCursor() {
// get current mouse rotation
FVector mouseLocation, mouseDirection;
this->DeprojectMousePositionToWorld(mouseLocation, mouseDirection);
// get reference to controllers character
ACharacter *MyPc = this->GetCharacter();
// get current rotation
FRotator curRot = MyPc->GetActorRotation();
// get target rotation
FRotator targetRotation = mouseDirection.Rotation();
//create and set the char to the new rotation, only yaw is needed
FRotator newRot= FRotator(curRot.Pitch, targetRotation.Yaw, curRot.Roll);
MyPc->SetActorRotation(newRot);
}
After doing some reading and testing in the various test types (attached, detached window). I can verify that I only have 180 degrees of rotation. I’m going to look into using a Quaternion.
EDIT: This is actually not a true statement. Playing in the standalone window didn’t allow my cursor to actually reach far enough down the screen to face the character negative of the X axis.
Your post in that thread is what turned my eyes to quaternions.
I actually found that link and played with your previous solution to no avail. The character just floats around seemingly random when I use it directly.
I was able to derive this:
void AShooterPlayerController::RotateToMouseCursor(float DeltaSeconds) {
FVector mouseLocation, mouseDirection;
this->DeprojectMousePositionToWorld(mouseLocation, mouseDirection);
FRotator targetRotation = mouseDirection.Rotation(); // get the mouse pointer rot
FQuat q1 = FQuat(targetRotation); // convert mouse rot to a quaternion
FQuat q2(FVector(1, 0, 0), 0.2*DeltaSeconds); // rotate around axis (1,0,0) on angle 0.2*DeltaSeconds
FQuat qr = q2*q1; // Get result quaternion
ACharacter *MyPc = this->GetCharacter();
qr.Normalize();
MyPc->SetActorRotation(qr.Rotator());
}
But character still does not face the correct direction on the lower half of the screen.
After playing with this some more today I realized this is a direct correlation to the angle of the camera. When working with a boom of 800f and FRotator(-60, 0,0) I experience the issue. When I switch the FRotator(-90, 0, 0). The issue does not exist.
An offset of some type will be needed to “center” the x=0.0 back into the center of the viewport as if it were a 2d top down.
EDIT: After playing with with different camera angles I’ve noticed the characters yaw axis is actually based on the X position of the camera and not the character. The proper solution will be to move the camera’s piviot to (0,0,0).
In your code your get mouse direction, it always points from camera in world space, that’s why your pawn looks forward. Also quaternion q2 has negligible rotation value, so it has no effect.
I slightly modified your code.
ACharacter* pPawn = GetCharacter();
if (!pPawn)
return;
FVector2D mousePos;
GetMousePosition(mousePos.X, mousePos.Y);
int32 width, height;
GetViewportSize(width, height);
mousePos.X /= width;
float ratio = mousePos.X*2-1; // let ratio is [-1;1]; ratio=-1 (left side of the screen); ratio=1 (right side of the screen)
ratio = ratio * PI / 2; // ratio is [-pi/2; pi/2]
FQuat q1 = FQuat(FVector(0, 0, 1), ratio); // relative rotation depended on mouse position
FQuat q2 = pPawn->GetActorRotation().Quaternion(); // current pawn rotation
FQuat qr = q2*q1;
pPawn->SetActorRotation(qr.Rotator());
Note: I assume that you get pawn rotation from WASD (so it can point backward relative camera) and add some turn (rotation) to the left or right depending on your mouse position. Am I right?
Here’s short video with display of the issue. After applying the above suggested changes, middle of screen left and right do properly spin a full 90 (as opposed to 90 being the bottom two corners). Also, this now behaves the same in traditional top down. I’ll play with trying this same setting to the Y axis once I wrap my head around this approach.
… Only been in C++ for about 2 weeks now, and have no real knowledge of 3d application implementation so still plenty to learn.
EDIT: The desired behavior is WASD movement with a facing always at the cursor in Isometric view.