• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當(dāng)自強而不息

            使用.x文件模型(2)

            在三維圖形程序中的一個模型對應(yīng)空間中的一個物體,在現(xiàn)實世界中要完全定位一個物體需要6個參數(shù),物體位置坐標(biāo)的3個分量(x, y, z)和3個歐拉角(偏航角yaw,俯仰角pitch,側(cè)傾角roll)。

            3個歐拉角的定義為:

            (1)偏航角:物體繞自身y軸(即上向量up)旋轉(zhuǎn)的角度。

            (2)俯仰角:物體繞自身x軸(即右向量right)旋轉(zhuǎn)的角度。

            (3)側(cè)傾角:物體繞自身z軸(即前向量look)旋轉(zhuǎn)的角度。

             

            通過矩陣實現(xiàn)模型旋轉(zhuǎn)

            在三維圖形程序中模型在世界空間中的位置和姿態(tài)都是通過通過其世界矩陣來表示的,所以要在程序中確定一個模型的位置和姿態(tài),就是將控制其狀態(tài)的6個參數(shù)應(yīng)用到其世界矩陣中。

            通過物體的位置和物體的3個自身坐標(biāo)軸朝向(3個向量)同樣也可以完全定位模型,實際上在Direct3D程序中,模型的世界矩陣本身包含了模型的位置向量和3個方向向量,這些向量在世界矩陣中存儲的順序是:第一行是right向量,第二行是up向量,第三行是look向量,第四行是位置向量pos。通過函數(shù)D3DXMatrixIdentity()將矩陣設(shè)置為單位矩陣,同時也將4個向量都設(shè)置為默認值,因此right向量為(1.0f, 0.0f, 0.0f),up向量為(0.0, 1.0f, 0.0f),look向量為(0.0f, 0.0f, 1.0f),pos向量為(0.0f, 0.0f, 0.0f)。這時模型位于世界坐標(biāo)系原點,并且朝向和世界坐標(biāo)系的3個坐標(biāo)軸方向相同。

            要改變模型的狀態(tài),就是移動物體到指定位置,旋轉(zhuǎn)物體改變其朝向。旋轉(zhuǎn)一個物體實質(zhì)上就是將look、up、right向量中的兩個繞另一個作旋轉(zhuǎn)。比如要橫滾物體,就需要將up和right向量繞look向量旋轉(zhuǎn);要使物體產(chǎn)生俯仰,必須將up和look向量繞right向量旋轉(zhuǎn);要使物體產(chǎn)生偏航,必須將look和right向量繞up向量旋轉(zhuǎn)。

            向量的旋轉(zhuǎn)需要分別借助偏航、俯仰和橫滾矩陣來完成,這些矩陣可借助于D3DXMatrixRotationAxis()函數(shù)產(chǎn)生,該函數(shù)的聲明如下:

            Builds a matrix that rotates around an arbitrary axis.

            D3DXMATRIX * D3DXMatrixRotationAxis(
            D3DXMATRIX * pOut,
            CONST D3DXVECTOR3 * pV,
            FLOAT Angle
            );

            Parameters

            pOut
            [in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
            pV
            [in] Pointer to the arbitrary axis. See D3DXVECTOR3.
            Angle
            [in] Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.

            Return Values

            Pointer to a D3DXMATRIX structure rotated around the specified axis.

            Remarks

            The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixRotationAxis function can be used as a parameter for another function.

            有了偏航、俯仰和橫滾矩陣,就可以使用函數(shù)D3DXVec3TransformCoord()完成這種向量旋轉(zhuǎn)的計算,該函數(shù)的聲明如下:

            Transforms a 3D vector by a given matrix, projecting the result back into w = 1.

            D3DXVECTOR3 * D3DXVec3TransformCoord(
            D3DXVECTOR3 * pOut,
            CONST D3DXVECTOR3 * pV,
            CONST D3DXMATRIX * pM
            );

            Parameters

            pOut
            [in, out] Pointer to the D3DXVECTOR3 structure that is the result of the operation.
            pV
            [in] Pointer to the source D3DXVECTOR3 structure.
            pM
            [in] Pointer to the source D3DXMATRIX structure.

            Return Values

            Pointer to a D3DXVECTOR3 structure that is the transformed vector.

            Remarks

            This function transforms the vector, pV (x, y, z, 1), by the matrix, pM, projecting the result back into w=1.

            The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXVec3TransformCoord function can be used as a parameter for another function.

            以下代碼具體說明了實現(xiàn)這種旋轉(zhuǎn)的核心內(nèi)容:

            	static D3DXMATRIX mat_around_right, mat_around_up, mat_around_look;
            	D3DXMatrixRotationAxis(&mat_around_up, &up, angle_around_up);
            D3DXVec3TransformCoord(&look, &look, &mat_around_up);
            D3DXVec3TransformCoord(&right, &right, &mat_around_up);
            	D3DXMatrixRotationAxis(&mat_around_look, &look, angle_around_look);	
            D3DXVec3TransformCoord(&right, &right, &mat_around_look);
            D3DXVec3TransformCoord(&up, &up, &mat_around_look);
            	D3DXMatrixRotationAxis(&mat_around_right, &right, angle_around_right);	
            D3DXVec3TransformCoord(&look, &look, &mat_around_right);
            D3DXVec3TransformCoord(&up, &up, &mat_around_right);

            由于計算機對浮點數(shù)的處理存在精度問題,所以在向量旋轉(zhuǎn)計算過程中會帶來稍許的累加誤差。在經(jīng)過幾次旋轉(zhuǎn)之后,這些舍入誤差將使3個向量不再相互垂直。以下代碼用于歸一化所有向量并使其互相垂直。

            	D3DXVec3Normalize(&look, &look);
            D3DXVec3Cross(&right, &up, &look);
            D3DXVec3Normalize(&right, &right);
            D3DXVec3Cross(&up, &look, &right);
            D3DXVec3Normalize(&up, &up);

             

            示例程序演示了使用矩陣旋轉(zhuǎn)一個飛機模型,程序運行時按下"D"和"A"鍵,可使飛機模型繞look向量旋轉(zhuǎn);按下"S"和"W"鍵,可使飛機模型繞right向量旋轉(zhuǎn);按下"Q"和"E"鍵,可使飛機模型繞up向量旋轉(zhuǎn);按下"F"和"V"鍵,可使飛機模型向前和向后運動。

            源程序:

            #include <d3dx9.h>

            #pragma warning(disable : 
            4127)

            #define CLASS_NAME    "GameApp"

            #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;

            ID3DXMesh
            *                g_mesh;
            D3DMATERIAL9
            *            g_mesh_materials;
            IDirect3DTexture9
            **        g_mesh_textures;
            DWORD                    g_num_materials;

            BYTE                    g_keys[
            256];
            D3DXMATRIX                g_mat_world;

            void setup_world_matrix()
            {
                
            static long  previous_time = 0;
                
            static float elapsed_time  = 0.0f;

                elapsed_time  
            = (timeGetTime() - previous_time) / 1000.0f;
                previous_time 
            = timeGetTime();

                
            float angle_around_right = 0.0f, angle_around_up = 0.0f, angle_around_look = 0.0f;

                
            if(g_keys['D'])    angle_around_look  -= 3 * elapsed_time;
                
            if(g_keys['A'])    angle_around_look  += 3 * elapsed_time;
                
            if(g_keys['S'])    angle_around_right -= 3 * elapsed_time;
                
            if(g_keys['W'])    angle_around_right += 3 * elapsed_time;
                
            if(g_keys['Q'])    angle_around_up       -= 3 * elapsed_time;
                
            if(g_keys['E'])    angle_around_up       += 3 * elapsed_time;

                
            static D3DXVECTOR3 right, up, look, pos;

                
            // save old model pos

                right.x 
            = g_mat_world._11;
                right.y 
            = g_mat_world._12;
                right.z 
            = g_mat_world._13;

                up.x    
            = g_mat_world._21;
                up.y    
            = g_mat_world._22;
                up.z    
            = g_mat_world._23;

                look.x    
            = g_mat_world._31;
                look.y    
            = g_mat_world._32;
                look.z    
            = g_mat_world._33;

                pos.x    
            = g_mat_world._41;
                pos.y    
            = g_mat_world._42;
                pos.z    
            = g_mat_world._43;    

                
            // now, calculate ratation matrix.

                
            static D3DXMATRIX mat_around_right, mat_around_up, mat_around_look;

                D3DXMatrixRotationAxis(
            &mat_around_up, &up, angle_around_up);
                D3DXVec3TransformCoord(
            &look,  &look,  &mat_around_up);
                D3DXVec3TransformCoord(
            &right, &right, &mat_around_up);

                D3DXMatrixRotationAxis(
            &mat_around_look, &look, angle_around_look);    
                D3DXVec3TransformCoord(
            &right, &right, &mat_around_look);
                D3DXVec3TransformCoord(
            &up,    &up,    &mat_around_look);

                D3DXMatrixRotationAxis(
            &mat_around_right, &right, angle_around_right);    
                D3DXVec3TransformCoord(
            &look,  &look,  &mat_around_right);
                D3DXVec3TransformCoord(
            &up,    &up,    &mat_around_right);

                
            // normalize look, right, up to avoid float calculation error

                D3DXVec3Normalize(
            &look, &look);
                D3DXVec3Cross(
            &right, &up, &look);
                D3DXVec3Normalize(
            &right, &right);
                D3DXVec3Cross(
            &up, &look, &right);
                D3DXVec3Normalize(
            &up, &up);

                
            // update model pos

                g_mat_world._11 
            = right.x;
                g_mat_world._12 
            = right.y;
                g_mat_world._13 
            = right.z;

                g_mat_world._21    
            = up.x;
                g_mat_world._22    
            = up.y;
                g_mat_world._23    
            = up.z;

                g_mat_world._31 
            = look.x;
                g_mat_world._32 
            = look.y;
                g_mat_world._33 
            = look.z;

                
            // move model forward or backward

                
            if(g_keys['F'])
                {
                    g_mat_world._41 
            += 30 * elapsed_time * look.x;
                    g_mat_world._42 
            += 30 * elapsed_time * look.y;
                    g_mat_world._43 
            += 30 * elapsed_time * look.z;
                }

                
            if(g_keys['V'])
                {
                    g_mat_world._41 
            -= 30 * elapsed_time * look.x;
                    g_mat_world._42 
            -= 30 * elapsed_time * look.y;
                    g_mat_world._43 
            -= 30 * elapsed_time * look.z;
                }

                g_device
            ->SetTransform(D3DTS_WORLD, &g_mat_world);
            }

            void setup_view_proj_matrix()
            {
                
            // setup view matrix

                D3DXVECTOR3 eye(
            0.0f10.0f-20.0f);
                D3DXVECTOR3 at(
            0.0f,  0.0f,   0.0f);
                D3DXVECTOR3 up(
            0.0f,  1.0f,   0.0f);

                D3DXMATRIX mat_view;
                D3DXMatrixLookAtLH(
            &mat_view, &eye, &at, &up);
                g_device
            ->SetTransform(D3DTS_VIEW, &mat_view);

                
            // setup projection matrix

                D3DXMATRIX mat_proj;
                D3DXMatrixPerspectiveFovLH(
            &mat_proj, D3DX_PI/41.0f1.0f500.0f);
                g_device
            ->SetTransform(D3DTS_PROJECTION, &mat_proj);
            }

            bool init_geometry()
            {
                ID3DXBuffer
            * material_buffer;

                
            /*
                 D3DXLoadMeshFromXA(
                    LPCSTR pFilename, 
                    DWORD Options, 
                    LPDIRECT3DDEVICE9 pD3DDevice, 
                    LPD3DXBUFFER *ppAdjacency,
                    LPD3DXBUFFER *ppMaterials, 
                    LPD3DXBUFFER *ppEffectInstances, 
                    DWORD *pNumMaterials,
                    LPD3DXMESH *ppMesh);
                
            */

                
            if(FAILED(D3DXLoadMeshFromX("airplane.x", D3DXMESH_MANAGED, g_device, NULL, &material_buffer, NULL,
                                            
            &g_num_materials, &g_mesh)))
                {
                    MessageBox(NULL, 
            "Could not find airplane.x""ERROR", MB_OK);
                    
            return false;
                }

                D3DXMATERIAL
            * xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();

                g_mesh_materials 
            = new D3DMATERIAL9[g_num_materials];
                g_mesh_textures     
            = new IDirect3DTexture9*[g_num_materials];

                
            for(DWORD i = 0; i < g_num_materials; i++)
                {
                    g_mesh_materials[i] 
            = xmaterials[i].MatD3D;

                    
            // set ambient reflected coefficient, because .x file do not set it.
                    g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse;

                    g_mesh_textures[i] 
            = NULL;

                    
            if(xmaterials[i].pTextureFilename != NULL && strlen(xmaterials[i].pTextureFilename) > 0)    
                        D3DXCreateTextureFromFile(g_device, xmaterials[i].pTextureFilename, 
            &g_mesh_textures[i]);    
                }

                material_buffer
            ->Release();

                
            return true;
            }

            bool init_d3d(HWND hwnd)
            {
                g_d3d 
            = Direct3DCreate9(D3D_SDK_VERSION);

                
            if(g_d3d == NULL)
                    
            return false;

                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;

                
            if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                              
            &d3dpp, &g_device)))
                {
                    
            return false;
                }
                
                
            if(! init_geometry())
                    
            return false;

                D3DXMatrixIdentity(
            &g_mat_world);
                setup_view_proj_matrix();    

                g_device
            ->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
                g_device
            ->SetTextureStageState(0, D3DTSS_COLOROP,    D3DTOP_SELECTARG1);
                
                
            return true;
            }

            void cleanup()
            {
                delete[] g_mesh_materials;

                
            if(g_mesh_textures)
                {
                    
            for(DWORD i = 0; i < g_num_materials; i++)
                        release_com(g_mesh_textures[i]);

                    delete[] g_mesh_textures;
                }
                
                release_com(g_mesh);
                release_com(g_device);
                release_com(g_d3d);
            }

            void render()
            {
                g_device
            ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(555), 1.0f0);

                g_device
            ->BeginScene();

                setup_world_matrix();

                
            for(DWORD i = 0; i < g_num_materials; i++)
                {
                    g_device
            ->SetMaterial(&g_mesh_materials[i]);
                    g_device
            ->SetTexture(0, g_mesh_textures[i]);

                    g_mesh
            ->DrawSubset(i);
                }
                
                g_device
            ->EndScene();

                g_device
            ->Present(NULL, NULL, NULL, NULL);
            }

            LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                
            switch(msg)
                {
                
            case WM_KEYDOWN:
                    g_keys[wParam] 
            = 1

                    
            if(wParam == VK_ESCAPE)
                        DestroyWindow(hwnd);

                    
            break;

                
            case WM_KEYUP:
                    g_keys[wParam] 
            = 0;
                    
            break;

                
            case WM_DESTROY:        
                    PostQuitMessage(
            0);
                    
            return 0;
                }

                
            return DefWindowProc(hwnd, msg, wParam, lParam);
            }

            int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
            {
                WNDCLASSEX wc;

                wc.cbSize            
            = sizeof(WNDCLASSEX);
                wc.style            
            = CS_CLASSDC;
                wc.lpfnWndProc        
            = WinProc;
                wc.cbClsExtra        
            = 0;
                wc.cbWndExtra        
            = 0;
                wc.hInstance        
            = inst;
                wc.hIcon            
            = NULL;
                wc.hCursor            
            = NULL;
                wc.hbrBackground    
            = NULL;
                wc.lpszMenuName        
            = NULL;
                wc.lpszClassName    
            = CLASS_NAME;
                wc.hIconSm            
            = NULL;

                
            if(! RegisterClassEx(&wc))
                    
            return -1;

                HWND hwnd 
            = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200100640480,
                                         NULL, NULL, wc.hInstance, NULL);    

                
            if(hwnd == NULL)
                    
            return -1;

                
            if(init_d3d(hwnd))
                {
                    ShowWindow(hwnd, SW_SHOWDEFAULT);
                    UpdateWindow(hwnd);

                    MSG msg;
                    ZeroMemory(
            &msg, sizeof(msg));

                    
            while(msg.message != WM_QUIT)
                    {
                        
            if(PeekMessage(&msg, NULL, 00, PM_REMOVE))
                        {
                            TranslateMessage(
            &msg);
                            DispatchMessage(
            &msg);
                        }
                            
                        render();
                    }
                }

                cleanup();
                UnregisterClass(CLASS_NAME, wc.hInstance);    

                
            return 0;
            }

             

            下載示例工程


            posted on 2008-05-09 14:30 lovedday 閱讀(1085) 評論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評論

            亚洲国产香蕉人人爽成AV片久久| 欧美麻豆久久久久久中文| 人人狠狠综合久久88成人| 精品国产乱码久久久久久郑州公司| 1000部精品久久久久久久久| 四虎国产精品免费久久久| 亚洲精品无码久久久久AV麻豆| 久久久久99精品成人片直播| 伊人久久综合热线大杳蕉下载| 国产高清美女一级a毛片久久w| 中文精品99久久国产| 久久精品人人槡人妻人人玩AV| 精品欧美一区二区三区久久久| 久久亚洲私人国产精品vA| 久久久久亚洲AV成人网人人网站| 少妇精品久久久一区二区三区| 国内精品久久久久久不卡影院| 伊人久久大香线蕉亚洲| 久久久WWW成人免费毛片| 69国产成人综合久久精品| 久久综合久久综合亚洲| 精品久久久久久无码中文野结衣 | 久久综合九色综合网站| 精品综合久久久久久88小说| 91久久精品91久久性色| 色综合久久无码五十路人妻| 亚洲国产精品成人AV无码久久综合影院 | 嫩草伊人久久精品少妇AV| 久久99精品国产麻豆蜜芽| 国产99久久精品一区二区| 亚洲欧洲久久久精品| 一本久久免费视频| 欧美精品福利视频一区二区三区久久久精品 | 久久天天躁狠狠躁夜夜avapp| 精品国产91久久久久久久a| 国产一久久香蕉国产线看观看 | 久久久久亚洲精品无码网址| 伊人久久免费视频| 久久精品一区二区影院| 久久国产三级无码一区二区| 久久精品国产第一区二区|