저번에 했던 플레이어 회전을 오일러에서 쿼터니온으로 변경하였다. 

이유는.


DirectX에서 구면 선형 보간 함수인 D3DXQuaternionSLerp 함수를 제공해주기 때문이다


D3DXQUATERNION *D3DXQuaternionSlerp(      

    D3DXQUATERNION *pOut,     CONST D3DXQUATERNION *pQ1,     CONST D3DXQUATERNION *pQ2,     FLOAT t );

참고 : Microsoft DirectX 9.0



일단 영상을 보자




구면선형보간과 그냥 선형보간의 다른 점을 찾아봤는데 

만약 정원에 있는 


두 점을 


선형보간을하게 되면 원의 표면을 따라가는 곡선이 아니라 원이 관통되어 직선이 그어진다


구면 선형 보간을 하게되면 원의 표면을 따라가는 곡선이 그어져 더 부드럽게 보간된다고 한다.


나는 카메라가 그냥 직선으로 보간되어 회전되는것 보단 구면 선형 보간을 사용해 원을 그리듯이 회전하면 더욱 부드러울꺼 같아서 사용했다.


일단 PlayerAIrPlane 클래스에 부모클래스인 AirPlane 클래스에다가 쿼터니온을 사용하여 비행기를 회전하는 함수를 만들었다 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//AirPlane.cpp
//Quaternion == D3DXQUATERNION
void AirPlane::YawRotation(float fAngle)
{
    Quaternion qRot;
    D3DXQuaternionRotationAxis(&qRot, &vAxis[E_AXIS_UP], fAngle);
    transform->qRot = transform->qRot * qRot;
    
    Matrix matRot;
    D3DXMatrixRotationQuaternion(&matRot, &qRot);
    D3DXVec3TransformNormal(&vAxis[E_AXIS_RIGHT], &vAxis[E_AXIS_RIGHT], &matRot);
    D3DXVec3TransformNormal(&vAxis[E_AXIS_FORWARD], &vAxis[E_AXIS_FORWARD], &matRot);
}
void AirPlane::RollRotation(float fAngle)
{
    Quaternion qRot;
    D3DXQuaternionRotationAxis(&qRot, &vAxis[E_AXIS_FORWARD], fAngle);
    transform->qRot = transform->qRot * qRot;
    Matrix matRot;
    D3DXMatrixRotationQuaternion(&matRot, &qRot);
    D3DXVec3TransformNormal(&vAxis[E_AXIS_RIGHT], &vAxis[E_AXIS_RIGHT], &matRot);
    D3DXVec3TransformNormal(&vAxis[E_AXIS_UP], &vAxis[E_AXIS_UP], &matRot);
}
void AirPlane::PitchRotation(float fAngle)
{
    Quaternion qRot;
    D3DXQuaternionRotationAxis(&qRot, &vAxis[E_AXIS_RIGHT], fAngle);
    transform->qRot = transform->qRot * qRot;
    Matrix matRot;
    D3DXMatrixRotationQuaternion(&matRot, &qRot);
    D3DXVec3TransformNormal(&vAxis[E_AXIS_FORWARD], &vAxis[E_AXIS_FORWARD], &matRot);
    D3DXVec3TransformNormal(&vAxis[E_AXIS_UP], &vAxis[E_AXIS_UP], &matRot);
}
void AirPlane::SetAirPlaneMatrix()
{
    if (fRollAngle)
        AirPlane::RollRotation(fRollAngle);
    if (fYawAngle)
        AirPlane::YawRotation(fYawAngle);
    if (fPitchAngle)
        AirPlane::PitchRotation(fPitchAngle);
 
    if (fRollAngle || fYawAngle || fPitchAngle)
        fRollAngle = fYawAngle = fPitchAngle = 0.f;
 
    D3DXMatrixTranslation(&transform->matPos, transform->pos.x, transform->pos.y, transform->pos.z);
    D3DXMatrixScaling(&transform->matScale, transform->scale.x, transform->scale.y, transform->scale.z);
}
 
cs

각각 비행기의 YawRotation RollRotation PitchRotation 함수를 구현해놨다. 


AirPlane 클래스에 멤버변수에는


1
2
3
    float fYawAngle;
    float fPitchAngle;
    float fRollAngle;
cs


이 값을 변경해주면 


1
2
3
4
5
6
7
8
9
10
11
12
void AirPlane::SetAirPlaneMatrix()
{
    if (fRollAngle)
        AirPlane::RollRotation(fRollAngle);
    if (fYawAngle)
        AirPlane::YawRotation(fYawAngle);
    if (fPitchAngle)
        AirPlane::PitchRotation(fPitchAngle);
 
    if (fRollAngle || fYawAngle || fPitchAngle)
        fRollAngle = fYawAngle = fPitchAngle = 0.f;
 
cs

이 함수에서 위 변수의 값으로 각각의 회전함수를 써서 비행기를 회전한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//PlayerAirPlane.cpp
void PlayerAirplane::Update()
{
    InputMouse();
    InputKeyboard();
 
    if (fSpeed > fMaxSpeed)
        fSpeed -= PlayerUnAccel;
 
    transform->pos += vAxis[E_AXIS_FORWARD] * (fSpeed * Et);
 
    AirPlane::SetAirPlaneMatrix();
 
    if (KEYDOWN(VK_SPACE))
    {
        Vector3 LeftFirePos = Vector3(-20.f, 0.f, 30.f);
        Vector3 RightFirePos = Vector3(20.f, 0.f, 30.f);
 
        D3DXMATRIX matRot;
        D3DXMatrixRotationQuaternion(&matRot, &transform->qRot);
        memcpy(&matRot._41, transform->pos, sizeof(Vector3));
 
        D3DXVec3TransformCoord(&LeftFirePos, &LeftFirePos, &matRot);
        D3DXVec3TransformCoord(&RightFirePos, &RightFirePos, &matRot);
 
        OBJECT.AddObject<PlayerBullet>()
            ->SetBullet(LeftFirePos, transform->qRot, 2000.f, 1.f);
        OBJECT.AddObject<PlayerBullet>()
            ->SetBullet(RightFirePos, transform->qRot, 2000.f, 1.f);
    }
 
    CamreaSetting();
}
 
void PlayerAirplane::InputMouse()
{
    Vector2 vGap(INPUT.GetMouseGap());
 
    float XGap = D3DXToRadian(vGap.x) * 0.05f;
    float YGap = D3DXToRadian(vGap.y) * 0.05f;
 
    if (XGap)
        fRollAngle = (XGap * -1);
    if (YGap)
        fPitchAngle = (YGap * -1);
}
 
void PlayerAirplane::InputKeyboard()
{
    if (KEYPRESS(VK_UP))
        fPitchAngle = PlayerPitchAngle;
    if (KEYPRESS(VK_DOWN))
        fPitchAngle = -PlayerPitchAngle;
    
    if (KEYPRESS(VK_LEFT))
        fRollAngle = PlayerRollAngle;
    if (KEYPRESS(VK_RIGHT))
        fRollAngle = -PlayerRollAngle;
 
    if (KEYPRESS('A'))
        fYawAngle = -PlayerYawAngle;
    if (KEYPRESS('D'))
        fYawAngle = PlayerYawAngle;
 
    if (KEYPRESS('C'))
        bCameraBack = true;
    else if (KEYPRESS(VK_MBUTTON))
        bCameraBack = true;
    else
        bCameraBack = false;
 
    if (KEYPRESS('W'))
    {
        if(fSpeed < fMaxSpeed)
            fSpeed += PlayerAccel;
    }
    
    if (KEYPRESS('S'))
    {
        if(fSpeed > 0.f)
            fSpeed -= PlayerUnAccel;
    }
 
    if (KEYPRESS(VK_LSHIFT))
        fMaxSpeed = 800.f;
    else
        fMaxSpeed = 500.f;    
}
 
void PlayerAirplane::CamreaSetting()
{
    Vector3 vCameraDir = Vector3(0.f, 0.f, bCameraBack ? 1.f : -1.f);
 
    D3DXQuaternionSlerp(&qCameraRot, &qCameraRot, &transform->qRot, 0.1f);
 
    D3DXMATRIX matCamreaRot;
    D3DXMatrixRotationQuaternion(&matCamreaRot, &qCameraRot);
    
    
    //vCameraPos;
    D3DXMATRIX matInitCameraRot;
    D3DXMatrixRotationX(&matInitCameraRot, bCameraBack ? -fCameraAngle : fCameraAngle);
 
    D3DXVec3TransformNormal(&vCameraDir, &vCameraDir, &matInitCameraRot);
    D3DXVec3TransformNormal(&vCameraDir, &vCameraDir, &matCamreaRot);
    vCameraPos = transform->pos + vCameraDir * fCameraDistance;
 
    //Up
    vCameraUp = Vector3(0.f, 1.f, 0.f);
    D3DXVec3TransformNormal(&vCameraUp, &vCameraUp, &matCamreaRot);
 
    //LookAt
    vCameraLookAt = Vector3(0.f, 50.f, 0.f);
    memcpy(&matCamreaRot._41, &transform->pos, sizeof(Vector3));
    
    D3DXVec3TransformCoord(&vCameraLookAt, &vCameraLookAt, &matCamreaRot);
    
 
    CAMERA.SetCameraPos(vCameraPos, false0.f);
    CAMERA.SetCameraLookAt(vCameraLookAt, false0.f);
    CAMERA.SetCameraUp(vCameraUp, false0.f);
}
cs


PlayerAirPlane 클래스를 보면 입력에 따라 fYawAngle, fPitchAngle, fRollAngle 변수를 변경해서


80 번째줄 AirPlane::SetAirPlaneMatrix(); 으로 회전을 반영시켰다.


그리고


162번째 줄 

1
void PlayerAirplane::CamreaSetting()
cs


함수에서 구면보간 함수인 D3DXQuaternionSlerp 함수를 써서 카메라의 회전을 구면 보간하는것을 알 수있다.






 

+ Recent posts