2014-04-26 4 views
3

나는 SharpDX로 카메라를 작성하고 쿼터니온을 사용하여 회전시킨다.Tait-Bryan 각의 쿼터니언

카메라 회전하므로 "Tiat-브라이언"각도 (호출 피치 (X 회전), 요 (Y 회전)과 롤 (Z 회전)로 설정되고
  • 이러한을 가질 것이다 하지 오일러 각은 XYX 회전이 아닌 XYZ 회전).
  • 왼손잡이 좌표계를 사용하고 있습니다. X +가 오른쪽, Y +가 위쪽, Z +가 화면 아래쪽입니다.
  • X ("피칭")를 중심으로 회전하면 양수 값을 지정하면 카메라가 아래쪽으로 보입니다. Y 주위를 회전하면 (yawing) 양수 값을 지정하면 카메라가 왼쪽으로 보입니다. Z를 중심으로 회전하면 ("롤링") 카메라가 시계 방향으로 굴립니다.

나는 쿼터니언에서 피치, 요요 및 롤을 이미 얻을 수있었습니다. 다음 C# 코드 :

public static class QuaternionExtensions 
{   
    public static Vector3 GetPitchYawRoll(this Quaternion q) 
    { 
     return new Vector3(q.GetPitch(), q.GetYaw(), q.GetRoll()); 
    } 

    public static float GetPitch(this Quaternion q) 
    { 
     return q.GetK().GetPitch(); 
    } 

    public static float GetYaw(this Quaternion q) 
    { 
     return q.GetK().GetYaw(); 
    } 

    public static float GetRoll(this Quaternion q) 
    { 
     // This is M12 * M22 of rotation matrix 
     float xx = q.X * q.X; 
     float xy = q.X * q.Y; 
     float zz = q.Z * q.Z; 
     float wz = q.W * q.Z; 
     return (float)Math.Atan2(2f * (xy - wz), 1f - 2f * (xx + zz)); 
    } 

    public static Vector3 GetK(this Quaternion q) 
    { 
     float xz = q.X * q.Z; 
     float wy = q.W * q.Y; 
     float yz = q.Y * q.Z; 
     float wx = q.W * q.X; 
     float xx = q.X * q.X; 
     float yy = q.Y * q.Y; 
     return new Vector3(
      2f * (xz - wy), 
      2f * (yz + wx), 
      1f - 2f * (xx + yy)); 
    } 

} 

public static class Vector3Extensions 
{ 
    public static float GetPitch(this Vector3 v) 
    { 
     return (float)-Math.Atan2(v.Y, Math.Sqrt(v.X * v.X + v.Z * v.Z)); 
    } 

    public static float GetYaw(this Vector3 v) 
    { 
     return (float)-Math.Atan2(v.X, v.Z); 
    } 
} 

나는 다른 방법으로는 모른다. 피치, 요 및 롤 (예 : GetPitchYawRoll에서 Vector3에 반환되는 값)을 지정하여 쿼터니언을 얻는 방법은 무엇입니까?

변환의 모든 변종

http://en.wikipedia.org/wiki/Euler_angleshttp://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/ 에있는 Ken Shoemake에서 찾을 수 있습니다

답변

2

Kryzon 여기에 나를 도와 (그의 게시물은 http://blitzbasic.com/Community/post.php?topic=102458&post=1224801에 있습니다 :

internal static class QuaternionExtensions 
{ 
    internal static Vector3 GetYawPitchRollVector(this Quaternion q) 
    { 
     return new Vector3(q.GetYaw(), q.GetPitch(), q.GetRoll()); 
    } 

    private static float GetYaw(this Quaternion q) 
    { 
     float x2 = q.X * q.X; 
     float y2 = q.Y * q.Y; 
     return (float)Math.Atan2(2f * q.Y * q.W - 2f * q.Z * q.X, 1f - 2f * y2 - 2f * x2); 
    } 

    private static float GetPitch(this Quaternion q) 
    { 
     return (float)-Math.Asin(2f * q.Z * q.Y + 2f * q.X * q.W); 
    } 

    private static float GetRoll(this Quaternion q) 
    { 
     float x2 = q.X * q.X; 
     float z2 = q.Z * q.Z; 
     return (float)-Math.Atan2(2f * q.Z * q.W - 2f * q.Y * q.X, 1f - 2f * z2 - 2f * x2); 
    } 
} 

internal static class Vector3Extensions 
{ 
    internal static Quaternion GetYawPitchRollQuaternion(this Vector3 v) 
    { 
     float c1 = (float)Math.Cos(-v.Z/2.0); 
     float c2 = (float)Math.Cos(-v.Y/2.0); 
     float c3 = (float)Math.Cos(v.X/2.0); 
     float c1c2 = c1 * c2; 
     float s1 = (float)Math.Sin(-v.Z/2.0); 
     float s2 = (float)Math.Sin(-v.Y/2.0); 
     float s3 = (float)Math.Sin(v.X/2.0); 
     float s1s2 = s1 * s2; 

     return new Quaternion(
      c1 * s2 * c3 - s1 * c2 * s3, 
      c1c2 * s3 + s1s2 * c3, 
      s1 * c2 * c3 + c1 * s2 * s3, 
      c1c2 * c3 - s1s2 * s3); 
    } 
} 
0

이 모든 자주라는 오일러 각도는 BlitzBasic.com 포럼에서 1993

+4

전화하기 Tait-Bryan 각 "오일러 각 "값이 해석되는 다른 방식으로 인해 오해의 소지가 있습니다. 위키 피 디아가 "고전적"또는 "적절한"오일러 각으로 분류하는 것이 소스가 아니라고 확신합니까? 그 코드에서 기대하는 값을 확인하기 위해 살펴 보았습니다. 변수 이름과 설명 할 수없는 EulGetOrd 함수로 인해 이해하는 것이 끔찍한 일입니다. ( –

+0

Ken Shoemake는 Axes 회전의 가능한 모든 변형을 다룹니다. 코드에 대한 모든 설명 그의 기사에서 찾을 수 있습니다 http://thehuwaldtfamily.org/jtrl/math/Shoemake,%20Euler%20Angle%20Conversion,%20Graphic's%20Gems%20IV.pdf – minorlogic

+1

@Ray Koopa에 동의해야하는 코드를 살펴보면 "오일러 각 표현"의 가능한 변종에는 두 가지가 있습니다.이 코드에는 적절한, 카단 (cardan), 'XYZ', 'ZYX'등의 표현을 구별하는 매개 변수가 없습니다. – ntg