频道栏目
首页 > 程序开发 > 软件开发 > C++ > 正文
矩阵中的数学旋转公式 转换到 C++中函数 替换DirectX 9.0中D3DXMatrixRotationAxis函数
2013-01-20 15:19:00           
收藏   我要投稿
首先看下数学公式:

 

 

由上面的数学公式,我们转换的C++函数:

[cpp]  

//-----------------------------------------------------------------------------  

// Name: setupRotate()  

// Desc: 绕x,y,z轴旋转,axis:1表示绕x轴,2表示y轴,3表示z轴  

//-----------------------------------------------------------------------------  

VOID setupRotate(D3DXMATRIXA16 *returnMatrix,int axis, float theta)  

{   www.2cto.com

    float s, c;  

    s = sin(theta),c=cos(theta);  

      

    switch (axis) {  

    case 1: // Rotate about the x-axis  

        returnMatrix->_11 = 1.0f; returnMatrix->_12 = 0.0f; returnMatrix->_13 = 0.0f; returnMatrix->_14 = 0.0f;  

        returnMatrix->_21 = 0.0f; returnMatrix->_22 = c; returnMatrix->_23 = s; returnMatrix->_24 = 0.0f;  

        returnMatrix->_31 = 0.0f; returnMatrix->_32 = -s; returnMatrix->_33 = c; returnMatrix->_34 = 0.0f;  

        returnMatrix->_41 = 0.0f; returnMatrix->_42 = 0.0f; returnMatrix->_43 = 0.0f; returnMatrix->_44 = 1.0f;  

        break;  

    case 2: // Rotate about the y-axis  

        returnMatrix->_11 = c; returnMatrix->_12 = 0.0f; returnMatrix->_13 = -s; returnMatrix->_14 = 0.0f;  

        returnMatrix->_21 = 0.0f; returnMatrix->_22 = 1.0f; returnMatrix->_23 = 0.0f; returnMatrix->_24 = 0.0f;  

        returnMatrix->_31 = s; returnMatrix->_32 = 0.0f; returnMatrix->_33 = c; returnMatrix->_34 = 0.0f;  

        returnMatrix->_41 = 0.0f; returnMatrix->_42 = 0.0f; returnMatrix->_43 = 0.0f; returnMatrix->_44 = 1.0f;  

        break;  

    case 3: // Rotate about the z-axis  

        returnMatrix->_11 = c; returnMatrix->_12 = s; returnMatrix->_13 = 0.0f; returnMatrix->_14 = 0.0f;  

        returnMatrix->_21 = -s; returnMatrix->_22 = c; returnMatrix->_23 = 0.0f; returnMatrix->_24 = 0.0f;  

        returnMatrix->_31 = 0.0f; returnMatrix->_32 = 0.0f; returnMatrix->_33 = 1.0f; returnMatrix->_34 = 0.0f;  

        returnMatrix->_41 = 0.0f; returnMatrix->_42 = 0.0f; returnMatrix->_43 = 0.0f; returnMatrix->_44 = 1.0f;  

        break;  

    default:  

        // bogus axis index  

        assert(false);  

    }  

}  

//-----------------------------------------------------------------------------  

// Name: setupRotate()  

// Desc: 绕自定义轴旋转  

//-----------------------------------------------------------------------------  

VOID setupRotate(const D3DXVECTOR3 &axis, D3DXMATRIXA16 *returnMatrix, float theta)  

{  

   //要旋转的向量轴必须是单位向量,不然物体会变形  

   //assert(fabs(axis*axis - 1.0f) < .01f);  

   float s, c;  

    s = sin(theta),c=cos(theta);  

    // 计算出一些重复利用的子表达式。  

    float a = 1.0f - c;  

    float ax = a * axis.x;  

    float ay = a * axis.y;  

    float az = a * axis.z;  

    returnMatrix->_11 = ax*axis.x + c;  

    returnMatrix->_12 = ax*axis.y + axis.z*s;  

    returnMatrix->_13 = ax*axis.z - axis.y*s;  

    returnMatrix->_14 = 0.0f;  

    returnMatrix->_21 = ay*axis.x - axis.z*s;  

    returnMatrix->_22 = ay*axis.y + c;  

    returnMatrix->_23 = ay*axis.z + axis.x*s;  

    returnMatrix->_24 = 0.0f;  

    returnMatrix->_31 = az*axis.x + axis.y*s;  

    returnMatrix->_32 = az*axis.y - axis.x*s;  

    returnMatrix->_33 = az*axis.z + c;  

    returnMatrix->_34 = 0.0f;  

    returnMatrix->_41 = 0.0f;  

    returnMatrix->_42 = 0.0f;  

    returnMatrix->_43 = 0.0f;  

    returnMatrix->_44 = 1.0f;  

}  

可能会有人对上面函数中的D3DXMATRIXA16和D3DXVECTOR3不理解,他们其实是Direct3D中表示4维矩阵和3维向量的结构体,可是我们数学公式里涉及到的是3维矩阵,可以看下下面的转换,因为要设计到矩阵相乘,故只能4维矩阵跟4维矩阵相乘,故把3维的转换成4维的了。

具体使用上面两个函数的例子:

[cpp]  

   // 旋转  

   D3DXMATRIXA16 matWorld;  

//自定义旋转的轴  

D3DXVECTOR3 axis(1.0f/sqrt(3), 1.0f/sqrt(3), 1.0f/sqrt(3));  

  

   D3DXMatrixIdentity( &matWorld );  

  

/*DirectX 官方API*/  

   //D3DXMatrixRotationY( &matWorld, timeGetTime()/500.0f );  

  

/*使用自定义旋转函数1*/  

//setupRotate(&matWorld,2,timeGetTime()/500.0f);  

  

   /*使用自定义旋转函数2*/  

setupRotate(axis,&matWorld,timeGetTime()/500.0f);  

   g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );  

 

旋转效果:

我稍微修改了下自定义旋转的轴,改成一个非单位向量,(1.0f, 1.0f, 0.0f),旋转效果(变形的飞起,哈哈):

完整代码(看的麻烦的同学,可以拉到底下载整个项目来看):

[cpp] 

//-----------------------------------------------------------------------------  

// 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;//茶壶  

  

// 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: 绕x,y,z轴旋转,axis:1表示绕x轴,2表示y轴,3表示z轴  

//-----------------------------------------------------------------------------  

VOID setupRotate(D3DXMATRIXA16 *returnMatrix,int axis, float theta)  

{  

    float s, c;  

    s = sin(theta),c=cos(theta);  

      

    switch (axis) {  

    case 1: // Rotate about the x-axis  

        returnMatrix->_11 = 1.0f; returnMatrix->_12 = 0.0f; returnMatrix->_13 = 0.0f; returnMatrix->_14 = 0.0f;  

        returnMatrix->_21 = 0.0f; returnMatrix->_22 = c; returnMatrix->_23 = s; returnMatrix->_24 = 0.0f;  

        returnMatrix->_31 = 0.0f; returnMatrix->_32 = -s; returnMatrix->_33 = c; returnMatrix->_34 = 0.0f;  

        returnMatrix->_41 = 0.0f; returnMatrix->_42 = 0.0f; returnMatrix->_43 = 0.0f; returnMatrix->_44 = 1.0f;  

        break;  

    case 2: // Rotate about the y-axis  

        returnMatrix->_11 = c; returnMatrix->_12 = 0.0f; returnMatrix->_13 = -s; returnMatrix->_14 = 0.0f;  

        returnMatrix->_21 = 0.0f; returnMatrix->_22 = 1.0f; returnMatrix->_23 = 0.0f; returnMatrix->_24 = 0.0f;  

        returnMatrix->_31 = s; returnMatrix->_32 = 0.0f; returnMatrix->_33 = c; returnMatrix->_34 = 0.0f;  

        returnMatrix->_41 = 0.0f; returnMatrix->_42 = 0.0f; returnMatrix->_43 = 0.0f; returnMatrix->_44 = 1.0f;  

        break;  

    case 3: // Rotate about the z-axis  

        returnMatrix->_11 = c; returnMatrix->_12 = s; returnMatrix->_13 = 0.0f; returnMatrix->_14 = 0.0f;  

        returnMatrix->_21 = -s; returnMatrix->_22 = c; returnMatrix->_23 = 0.0f; returnMatrix->_24 = 0.0f;  

        returnMatrix->_31 = 0.0f; returnMatrix->_32 = 0.0f; returnMatrix->_33 = 1.0f; returnMatrix->_34 = 0.0f;  

        returnMatrix->_41 = 0.0f; returnMatrix->_42 = 0.0f; returnMatrix->_43 = 0.0f; returnMatrix->_44 = 1.0f;  

        break;  

    default:  

        // bogus axis index  

        assert(false);  

    }  

}  

//-----------------------------------------------------------------------------  

// Name: setupRotate()  

// Desc: 绕自定义轴旋转,类似DirectX中的函数D3DXMatrixRotationAxis  

//-----------------------------------------------------------------------------  

VOID setupRotate(const D3DXVECTOR3 &axis, D3DXMATRIXA16 *returnMatrix, float theta)  

{  

   //要旋转的向量轴必须是单位向量,不然物体会变形  

   //assert(fabs(axis*axis - 1.0f) < .01f);  

   float s, c;  

    s = sin(theta),c=cos(theta);  

    // 计算出一些重复利用的子表达式。  

    float a = 1.0f - c;  

    float ax = a * axis.x;  

    float ay = a * axis.y;  

    float az = a * axis.z;  

    returnMatrix->_11 = ax*axis.x + c;  

    returnMatrix->_12 = ax*axis.y + axis.z*s;  

    returnMatrix->_13 = ax*axis.z - axis.y*s;  

    returnMatrix->_14 = 0.0f;  

    returnMatrix->_21 = ay*axis.x - axis.z*s;  

    returnMatrix->_22 = ay*axis.y + c;  

    returnMatrix->_23 = ay*axis.z + axis.x*s;  

    returnMatrix->_24 = 0.0f;  

    returnMatrix->_31 = az*axis.x + axis.y*s;  

    returnMatrix->_32 = az*axis.y - axis.x*s;  

    returnMatrix->_33 = az*axis.z + c;  

    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;  

    //自定义旋转的轴  

    //D3DXVECTOR3 axis(1.0f/sqrt(3), 1.0f/sqrt(3), 1.0f/sqrt(3));  

    D3DXVECTOR3 axis(1.0f, 1.0f, 0.0f);  

    D3DXMatrixIdentity( &matWorld );  

  

    /*DirectX 官方API*/  

    //D3DXMatrixRotationY( &matWorld, timeGetTime()/500.0f );  

  

    /*使用自定义旋转函数1*/  

    //setupRotate(&matWorld,2,timeGetTime()/500.0f);  

  

    /*使用自定义旋转函数2*/  

    setupRotate(axis,&matWorld,timeGetTime()/500.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 );  

}  

  

  

  

  

//-----------------------------------------------------------------------------  

// Name: MsgProc()  

// Desc: The window's message handler  

//-----------------------------------------------------------------------------  

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )  

{  

    switch( msg )  

    {  

        case WM_DESTROY:  

            Cleanup();  

            PostQuitMessage( 0 );  

            return 0;  

    }  

  

    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;  

}  

 

点击复制链接 与好友分享!回本站首页
上一篇:AMPS:单向链表源码解读
下一篇:C++学习笔记汇总
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站