新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 使用.x文件模型(2) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 8944 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 使用.x文件模型(2) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 使用.x文件模型(2)

    在三维图形程序中的一个模型对应空间中的一个物体,在现实世界中要完全定位一个物体需要6个参数,物体位置坐标的3个分量(x, y, z)和3个欧拉角(偏航角yaw,俯仰角pitch,侧倾角roll)。

    3个欧拉角的定义为:

    (1)偏航角:物体绕自身y轴(即上向量up)旋转的角度。

    (2)俯仰角:物体绕自身x轴(即右向量right)旋转的角度。

    (3)侧倾角:物体绕自身z轴(即前向量look)旋转的角度。

    通过矩阵实现模型旋转

    在三维图形程序中模型在世界空间中的位置和姿态都是通过通过其世界矩阵来表示的,所以要在程序中确定一个模型的位置和姿态,就是将控制其状态的6个参数应用到其世界矩阵中。

    通过物体的位置和物体的3个自身坐标轴朝向(3个向量)同样也可以完全定位模型,实际上在Direct3D程序中,模型的世界矩阵本身包含了模型的位置向量和3个方向向量,这些向量在世界矩阵中存储的顺序是:第一行是right向量,第二行是up向量,第三行是look向量,第四行是位置向量pos。通过函数D3DXMatrixIdentity()将矩阵设置为单位矩阵,同时也将4个向量都设置为默认值,因此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)。这时模型位于世界坐标系原点,并且朝向和世界坐标系的3个坐标轴方向相同。

    要改变模型的状态,就是移动物体到指定位置,旋转物体改变其朝向。旋转一个物体实质上就是将look、up、right向量中的两个绕另一个作旋转。比如要横滚物体,就需要将up和right向量绕look向量旋转;要使物体产生俯仰,必须将up和look向量绕right向量旋转;要使物体产生偏航,必须将look和right向量绕up向量旋转。

    向量的旋转需要分别借助偏航、俯仰和横滚矩阵来完成,这些矩阵可借助于D3DXMatrixRotationAxis()函数产生,该函数的声明如下:

    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.

    有了偏航、俯仰和横滚矩阵,就可以使用函数D3DXVec3TransformCoord()完成这种向量旋转的计算,该函数的声明如下:

    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.

    以下代码具体说明了实现这种旋转的核心内容:

     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);
    由于计算机对浮点数的处理存在精度问题,所以在向量旋转计算过程中会带来稍许的累加误差。在经过几次旋转之后,这些舍入误差将使3个向量不再相互垂直。以下代码用于归一化所有向量并使其互相垂直。

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

    示例程序演示了使用矩阵旋转一个飞机模型,程序运行时按下"D"和"A"键,可使飞机模型绕look向量旋转;按下"S"和"W"键,可使飞机模型绕right向量旋转;按下"Q"和"E"键,可使飞机模型绕up向量旋转;按下"F"和"V"键,可使飞机模型向前和向后运动。

    按此在新窗口浏览图片


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/6/1 14:07:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    源程序:


    #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.0f, 10.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/4, 1.0f, 1.0f, 500.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(5, 5, 5), 1.0f, 0);

        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, 200, 100, 640, 480,
                                 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, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                    
                render();
            }
        }

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

        return 0;
    }

    [B][URL=http://www.cppblog.com/Files/changingnow/StateControlUseMatrix.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/6/1 14:07:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/25 21:17:56

    本主题贴数2,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    93.750ms