欧拉角旋转函数


写在前面:正当很高兴地完成了矩阵相关的旋转后,发现如果涉及到旋转;矩阵,欧拉角(EulerAngles) ,四元数(Quaternions)这三个概念哪本书上都会提。这次先讲下欧拉角。

 

 

1.什么是欧拉角

 

欧拉角是由三个角组成,这三个角分别是Yaw,Pitch,Roll。很难翻译这三个单词,Yaw 表示绕y轴旋转的角度,Pitch表示绕x轴旋转的角度,Roll表示绕z轴旋转的角度。也就是说,任意的旋转角度都可以通过这三次按照先后顺序旋转得到。矩阵很难让人具体形象表示,欧拉角就容易多了。注意可能很多地方三个角的先后次序不一样,我们这里选择跟DirectX 中的D3DXMatrixRotationYawPitchRoll函数保持一致,先绕y轴旋转,在绕x轴旋转,最后绕z轴旋转。

感觉Yaw(偏航),Pitch(投掷;倾斜;坠落),Roll(转动) 介绍飞机旋转的比较多,窃了三张图来更象形地表示下:

 

2.欧拉角中的旋转

 

还记得这三个矩阵吗?绕相关轴旋转,乘以相关矩阵就行了,也就是说欧拉角最终还是转换成矩阵相乘,不过是要与三个矩阵相乘

我们知道可以先把这三个矩阵相乘,这样可以节约计算量。就是要先计算这三个矩阵相乘,注意矩阵相乘次序是不可更改的,更改了结果就不一样了。

欧拉角的三个角,可以转变为矩阵与矩阵的相乘。

 

3.开始替换D3DXMatrixRotationYawPitchRoll函数

 

 

Directx 9.0中有个函数叫D3DXMatrixRotationYawPitchRoll(D3DXMATRIX *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll)。根据上面复杂的矩阵,我们用C++替换成下面的函数。可能这个函数还有优化空间,数学太差啊。

?
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
//-----------------------------------------------------------------------------
// Name: setupRotate()
// Desc: 绕3个角度旋转
//-----------------------------------------------------------------------------
  
VOID setupRotate(D3DXMATRIXA16 *returnMatrix, float yaw, float pitch, float roll)
{
  
     float sx = sin (pitch); float sy = sin (yaw); float sz = sin (roll);
     float cx = cos (pitch); float cy = cos (yaw); float cz = cos (roll);
     returnMatrix->_11 = cz * cy - sx * sy * sz;
     returnMatrix->_12 = cy * sz + sx * sy * cz;
     returnMatrix->_13 = -sy * cx;
     returnMatrix->_14 = 0.0f;
     returnMatrix->_21 = -cx * sz;
     returnMatrix->_22 = cx * cz;
     returnMatrix->_23 = sx;
     returnMatrix->_24 = 0.0f;
     returnMatrix->_31 = sy * cz + sx * cy * sz;
     returnMatrix->_32 = sy * sz - sx * cy * cz;
     returnMatrix->_33 = cx * cy;
     returnMatrix->_34 = 0.0f;
     returnMatrix->_41 = 0.0f;
     returnMatrix->_42 = 0.0f;
     returnMatrix->_43 = 0.0f;
     returnMatrix->_44 = 1.0f;
}

 

先看下我们使用这个函数的例子效果:跟随鼠标移动的水壶,而不是自己在那旋转个不停。

 

对上面这张gif图片是如何制作感兴趣?看截取视频,然后制成gif 教程

 

除了上面的函数之外的核心代码(需要对Windows中的消息处理熟悉):

?
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
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;
//鼠标最后位置
static POINT ptLastMousePosit;
//当前鼠标位置
static POINT ptCurrentMousePosit;
static bool bMousing;
switch ( msg )
     {
case WM_LBUTTONDOWN: // 当鼠标左键按下时,记录当前的位置(屏幕坐标),并设置按下标志
             {
                 ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);
                 ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);
                 bMousing = true ;
             }
             break ;
         case WM_LBUTTONUP:
             {
                 bMousing = false ;
             }
             break ;
         case WM_MOUSEMOVE: // 鼠标移动时,保存X/Y轴的移动距离
             {
                 ptCurrentMousePosit.x = LOWORD (lParam);
                 ptCurrentMousePosit.y = HIWORD (lParam);
  
                 if ( bMousing )
                 {
                     g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
                     g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
                 }
  
                 ptLastMousePosit.x = ptCurrentMousePosit.x;
                 ptLastMousePosit.y = ptCurrentMousePosit.y;
             }
          break ;
          }
          //最后两个值传到我们写好的函数中即可
          setupRotate(&matWorld,D3DXToRadian(g_fSpinX),D3DXToRadian(g_fSpinY),0.0f);

完整代码:如果觉得看起来太累,拉到最底部,下载整个项目来看。

?
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
//-----------------------------------------------------------------------------
// File: Lights.cpp
// Copyright (c) Microsoft Corporation & Waitingfy.com. All rights reserved.
//-----------------------------------------------------------------------------
#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#include <strsafe.h>
#include <math.h>
#include <assert.h>
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // Buffer to hold vertices
ID3DXMesh* Objects = 0; //茶壶
  
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;
  
// A structure for our custom vertex type. We added a normal, and omitted the
// color (which is provided by the material)
struct CUSTOMVERTEX
{
     D3DXVECTOR3 position; // The 3D position for the vertex
     D3DXVECTOR3 normal;   // The surface normal for the vertex
};
  
// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
  
//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
     // Create the D3D object.
     if ( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
         return E_FAIL;
  
     // Set up the structure used to create the D3DDevice. Since we are now
     // using more complex geometry, we will create a device with a zbuffer.
     D3DPRESENT_PARAMETERS d3dpp;
     ZeroMemory( &d3dpp, sizeof (d3dpp) );
     d3dpp.Windowed = TRUE;
     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
     d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
     d3dpp.EnableAutoDepthStencil = TRUE;
     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  
     // Create the D3DDevice
     if ( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                       D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                       &d3dpp, &g_pd3dDevice ) ) )
     {
         return E_FAIL;
     }
  
     // Turn off culling
     g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  
     // Turn on the zbuffer
     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  
     return S_OK;
}
  
//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
     if ( g_pVB != NULL )
         g_pVB->Release();
  
     if ( g_pd3dDevice != NULL )
         g_pd3dDevice->Release();
  
     if ( g_pD3D != NULL )
         g_pD3D->Release();
     if (Objects != NULL){
        Objects->Release();
     }
  
}
  
//-----------------------------------------------------------------------------
// Name: setupRotate()
// Desc: 绕3个角度旋转
//-----------------------------------------------------------------------------
  
VOID setupRotate(D3DXMATRIXA16 *returnMatrix, float yaw, float pitch, float roll)
{
  
     float sx = sin (pitch); float sy = sin (yaw); float sz = sin (roll);
     float cx = cos (pitch); float cy = cos (yaw); float cz = cos (roll);
     returnMatrix->_11 = cz * cy - sx * sy * sz;
     returnMatrix->_12 = cy * sz + sx * sy * cz;
     returnMatrix->_13 = -sy * cx;
     returnMatrix->_14 = 0.0f;
     returnMatrix->_21 = -cx * sz;
     returnMatrix->_22 = cx * cz;
     returnMatrix->_23 = sx;
     returnMatrix->_24 = 0.0f;
     returnMatrix->_31 = sy * cz + sx * cy * sz;
     returnMatrix->_32 = sy * sz - sx * cy * cz;
     returnMatrix->_33 = cx * cy;
     returnMatrix->_34 = 0.0f;
     returnMatrix->_41 = 0.0f;
     returnMatrix->_42 = 0.0f;
     returnMatrix->_43 = 0.0f;
     returnMatrix->_44 = 1.0f;
}
  
//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
     // 旋转
     D3DXMATRIXA16 matWorld;
     D3DXMatrixIdentity( &matWorld );
     //根据x轴和y轴移动距离旋转
     setupRotate(&matWorld,D3DXToRadian(g_fSpinX),D3DXToRadian(g_fSpinY),0.0f);
     g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  
     // 摄像机的位置
     D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
     D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
     D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
     D3DXMATRIXA16 matView;
     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
     g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  
     // 设置视锥体大小
     D3DXMATRIXA16 matProj;
     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
     g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
  
//-----------------------------------------------------------------------------
// Name: SetupLights()
// Desc: Sets up the Lights and materials for the scene.
//-----------------------------------------------------------------------------
VOID SetupLights()
{
     // 初始化一个材料
  
     D3DMATERIAL9 mtrl;
     ZeroMemory( &mtrl, sizeof (D3DMATERIAL9) );
     mtrl.Diffuse = mtrl.Ambient = D3DXCOLOR(1.0f,1.0f,0.0f,1.0f); //材质有漫射和环境光的设置,都为黄色
     g_pd3dDevice->SetMaterial( &mtrl );
  
     // 初始化一个白色的方向光
     ///*
     D3DXVECTOR3 vecDir;
     D3DLIGHT9 light;
     ZeroMemory( &light, sizeof (D3DLIGHT9) );
     light.Type       = D3DLIGHT_DIRECTIONAL; //方向光
     light.Diffuse = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f); //设置光源的漫射光颜色为白色
     light.Direction = D3DXVECTOR3(0.0f,0.0f,1.0f); //光的传播方向平行z轴
     light.Range       = 1000.0f;
     g_pd3dDevice->SetLight( 0, &light );
     g_pd3dDevice->LightEnable( 0, TRUE );
     g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  
     //*/
     // Finally, turn on some ambient light.
     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );
}
  
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
     // 背景为蓝色
     g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                          D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
     // Begin the scene
     if ( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
     {
         // 茶壶的材料颜色也定义在这个函数中
         SetupLights();
  
         // Setup the world, view, and projection matrices
         SetupMatrices();
  
         // Render the vertex buffer contents
         g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof (CUSTOMVERTEX) );
         g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  
         //创建一个茶壶
  
         //Objects = 0;
         D3DXMATRIX  Worlds;
         D3DXCreateTeapot(g_pd3dDevice, &Objects, 0);
         Objects->DrawSubset(0);
         Objects->Release();
         Objects = 0;
         // End the scene
         g_pd3dDevice->EndScene();
     }
  
     // Present the backbuffer contents to the display
     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
     //Objects->Release();
}
  
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
     static POINT ptLastMousePosit;
     static POINT ptCurrentMousePosit;
     static bool bMousing;
     switch ( msg )
     {
         case WM_DESTROY:
             Cleanup();
             PostQuitMessage( 0 );
             return 0;
         case WM_LBUTTONDOWN: // 当鼠标左键按下时,记录当前的位置(屏幕坐标),并设置按下标志
             {
                 ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);
                 ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);
                 bMousing = true ;
             }
             break ;
         case WM_LBUTTONUP:
             {
                 bMousing = false ;
             }
             break ;
         case WM_MOUSEMOVE: // 鼠标移动时,保存X/Y轴的移动距离
             {
                 ptCurrentMousePosit.x = LOWORD (lParam);
                 ptCurrentMousePosit.y = HIWORD (lParam);
                 if ( bMousing )
                 {
                     g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
                     g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
                 }
                 ptLastMousePosit.x = ptCurrentMousePosit.x;
                 ptLastMousePosit.y = ptCurrentMousePosit.y;
             }
          break ;
     }
     return DefWindowProc( hWnd, msg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE , LPSTR , INT )
{
     // Register the window class
     WNDCLASSEX wc = { sizeof (WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                       GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                       "D3D Tutorial" , NULL };
     RegisterClassEx( &wc );
     // Create the application's window
     HWND hWnd = CreateWindow( "D3D Tutorial" , "D3D Tutorial 04: Lights" ,
                               WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                               GetDesktopWindow(), NULL, wc.hInstance, NULL );
     // Initialize Direct3D
     if ( SUCCEEDED( InitD3D( hWnd ) ) )
     {
             // Show the window
             ShowWindow( hWnd, SW_SHOWDEFAULT );
             UpdateWindow( hWnd );
  
             // Enter the message loop
             MSG msg;
             ZeroMemory( &msg, sizeof (msg) );
             while ( msg.message!=WM_QUIT )
             {
                 if ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                 {
                     TranslateMessage( &msg );
                     DispatchMessage( &msg );
                 }
                 else
                     Render();             
             }
     }
     UnregisterClass( "D3D Tutorial" , wc.hInstance );
     return 0;
}

文章源地址:http://www.waitingfy.com/?p=375

YawPitchRoll (本站下载)

http://download.csdn.net/detail/fox64194167/4856842(CSDN下载,免积分)
参考资源:http://hi.baidu.com/_鈊_烦_薏乱/blog/item/bac886c46164c1d438db49e7.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值