[UE4] 두개의 벡터 사이에 로테이션

#언리얼4 공부중 / UE4 버젼: 4.22.3

좌표 시스템이 아래와 같고,더미 캐릭터를 XY plane 위에서 Z축을 중심으로 로테이션을 시켜보려고 한다.

 모델의 forward vector로 부터 A 벡터까지 로테이션을 해보면, 

Dot product를 구하여 두 벡터 사이의 각도를 구해보았다.  Dot Product는 wiki에서 잘 설명되어 있는데, 대략 공식은 다음과 같다.  

    \[  a \cdot b =  \|  a \|     \|  b  \|  \cos \theta \]

위의 공식을 이용하여, 각도를 구하려면, (두개의 벡터는 Unit Vector(단위벡터)로 길이는 1로 가정하자. \|  a \| = \|  b  \| = 1 )  

    \[   \cos \theta  =  \frac{ a \cdot b }{  \|  a \|     \|  b  \| } \]

    \[   \theta =  \arccos( a \cdot b )  \]

코드를 통해 각도를 구해보자.

auto forwardVect = GetActorForwardVector();    // forward 벡터
FVector A(-0.8f, 0.7f, 0);                   // A 벡터
A.Normalize();        

float dot = FVector::DotProduct(forwardVect, A);  
float angle = FMath::RadiansToDegrees(FMath::Acos(dot));

FMath::Acos를 통해 얻은 값은 Radian값이기 때문에 Degree로 변환이 필요하고, FMath::RadiansToDegrees를 통해 얻을 수 있다.

이제 Degree 값을 얻었기 때문에, 로테이션만 시키면 되는데, 회전 방향의 설정이 필요하다.  왼쪽이냐 오른쪽이냐. Cross Product벡터곱)을 통하여 어느 방향인지 찾아보았다.  Cross Product에 대한 것은 wiki에 잘 나와있다. 오른손 법칙을 사용하면, Cross Product의 방향을 쉽게 알 수 있는데, 언리얼은 왼손 좌표계를 사용하므로, 집게 손가락을 첫번째 벡터 (forward)로, 중지를 두번째 벡터 (A)로 가리키면, 엄지 손가락이 가리키는 방향이 Cross Product의 방향이 된다. 

위에 코드에 연결해보면, 

FVector crossPrdt = FVector::CrossProduct(forwardVect, A);

float delta = GetWorld()->DeltaTimeSeconds;
float yawDelta = 0;
if (crossPrdt.Z < 0)
{    
     yawDelta = angle * delta * -1;
}
else
{    
     yawDelta = angle * delta;
}
FRotator deltaRotation = FRotator(0, yawDelta, 0);   //Yaw
AddActorWorldRotation(deltaRotation);

매 프레임마다 delta만큼을 돌려주면 원하는 방향으로 회전이 가능하다. 다른 방식이 있는지는 더 공부해 봐야 알 것 같다..



Leave a Reply

Your email address will not be published. Required fields are marked *