This is the script i use:
FRotator UMy_AnimInstance::Get_Look_At_Rotation(FVector start_location, const float clamp_angle, const float rotation_factor, FVector offset, bool& b_touching_limit)
{
if (!riftHMD)
riftHMD = GEngine->HMDDevice.Get();
if (!player_controller)
player_controller = GetWorld()->GetFirstPlayerController();
if (!player_camera_manager)
player_camera_manager = player_controller->PlayerCameraManager;
if (!riftHMD || !player_camera_manager)
return FRotator::ZeroRotator;
FVector local_head_mount_location;
FQuat head_mount_orientation; //Not using it, just there to use the below function.
riftHMD->GetCurrentOrientationAndPosition(head_mount_orientation, local_head_mount_location);
FVector camera_location = player_camera_manager->GetCameraLocation();
FRotator player_rotation = player_controller->GetControlRotation();
FVector world_head_mount_location = player_rotation.RotateVector(local_head_mount_location)
+ camera_location + offset;
FVector direction = world_head_mount_location - start_location;
direction.Normalize();
FRotator rotation = direction.Rotation();
FVector right_vector = FRotationMatrix(rotation).GetScaledAxis(EAxis::Y);
right_vector *= -1.0f;
FRotator final_rotation = FRotator::ZeroRotator;
final_rotation.Yaw = FMath::Clamp(right_vector.Rotation().Yaw
* rotation_factor, -clamp_angle, clamp_angle);
final_rotation.Roll = FMath::Clamp(rotation.Pitch*-1 * rotation_factor, -clamp_angle, clamp_angle);
b_touching_limit = FMath::Abs(final_rotation.Yaw) == clamp_angle
|| FMath::Abs(final_rotation.Roll) == clamp_angle;
//Checks if there is too drastic movement since last rotation.
if (!last_rotation.Equals(final_rotation, 0.1f))
{
final_rotation = RLerp(last_rotation, final_rotation, 1.0f - lerp_alpha, true);
lerp_alpha -= GetWorld()->DeltaTimeSeconds/20;
}
else
{
lerp_alpha = 1;
}
last_rotation = final_rotation;
return final_rotation;
}
FRotator UMy_AnimInstance::RLerp(FRotator A, FRotator B, float Alpha, bool bShortestPath)
{
FRotator DeltaAngle = B - A;
// if shortest path, we use Quaternion to interpolate instead of using FRotator
if (bShortestPath)
{
FQuat AQuat(A);
FQuat BQuat(B);
FQuat Result = FQuat::Slerp(AQuat, BQuat, Alpha);
Result.Normalize();
return Result.Rotator();
}
return A + Alpha*DeltaAngle;
}
*start_location is the head’s location.
It work’s great when this character is at rotation 0 0 0 inside the world.
But when i rotates it, it get messed up, i even tried to rotate the root in my 3d package program so i can leave it at 0 0 0 in unreal, but still the same issue.
I’m using blender so the forward axis is not X, therefor i need to rotate the head to it’s right side before it looks at the player.
This character is looking at the OculusRift head mounted device on the player ( riftMHD ).
I’m using animation blueprint to rotate the head.
There is a Tick event in the left side:
This is like i need to give him the current local rotation of the head_socket for the calculation, but as i see i can get only the world location:
https://docs.unrealengine.com/latest/INT/BlueprintAPI/Utilities/Transformation/GetSocketRotation/index.html
How can i access this Socket component to read that relative rotator variable?
*Edit: Ok i can get the relative transforms via the GetSocketTreansform node, but still, can’t find how to use it correctly to solve this issue.
Any idea anyone?..
And why is it have to be so complex? in Unity3D they have this LookAt() function that just works