• <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>

            天行健 君子當自強而不息

            Blending Skeletal Animations(3)

            Check Out the Demo

            Although this chapter only has one demo to tout, it sure is a whopper! Demonstrating the technique of blended animation, the SkeletalAnimBlend demo program (see Figure 6.3) shows off Microsoft's Tiny character in all her blended glory!

            Figure 6.3: Explore your new found blended skeletal animation techniques by choosing which animations to blend in real time.

            I edited the Tiny.x file to split her animation up into multiple sets. There are animation sets for each of her arms and legs, as well as an animation set for her body. Pressing any of the keys displayed on the screen toggles the blending of the appropriate animation set. For instance, hitting 1 toggles the blending of her left arm animation sequence. When enabled, the left arm animation has Tiny swinging her arm in sequence with her step. When disabled, her left arm hangs limp.

            To really illustrate the power of blending, suppose you add a new animation set to the Tiny.x file that has Tiny waving her arm as opposed to swinging it back and forth. You only need to turn off blending of the swinging animation and blend in the waving animation to create a new and totally unique animation!

             

            SkeletalAnimBlend.h:

            #ifndef SKELETAL_ANIM_BLEND_H
            #define SKELETAL_ANIM_BLEND_H

            #include 
            "SkeletalAnim.h"

            class cBlendAnimationCollection : public cAnimationCollection
            {
            public:
                
            void blend(const char* anim_set_name, DWORD time, bool is_loop, float blend);
            };

            #endif

             

            SkeletalAnimBlend.cpp:

            #include "SkeletalAnimBlend.h"

            #pragma warning(disable : 
            4996)

            void cBlendAnimationCollection::blend(const char* anim_set_name, 
                                                  DWORD time, 
            bool is_loop, float blend)
            {
                sAnimationSet
            * anim_set = m_anim_sets;

                
            // look for matching animation set if name used
                if(anim_set_name)
                {
                    
            // find matching animation set name
                    while(anim_set != NULL)
                    {
                        
            // break when match found
                        if(! stricmp(anim_set->name, anim_set_name))
                            
            break;

                        anim_set 
            = anim_set->next;
                    }
                }

                
            if(anim_set == NULL)    // no animation set found
                    return;

                
            // bounds time to animation length
                if(time > anim_set->length)
                    time 
            = is_loop ? (time % (anim_set->length + 1)) : anim_set->length;

                
            for(sAnimation* anim = anim_set->anims; anim != NULL; anim = anim->next)
                {
                    
            if(anim->bone == NULL)    // only process if it is attached to a bone
                        continue;
                
                    
            // reset transformation
                    D3DXMATRIX anim_matrix;
                    D3DXMatrixIdentity(
            &anim_matrix);

                    
            // apply various matrices to transformation

                    
            // scaling
                    if(anim->num_scale_keys && anim->scale_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching scale key
                        for(DWORD i = 0; i < anim->num_scale_keys; i++)
                        {
                            
            if(time >= anim->scale_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_scale_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->scale_keys[key2].time - anim->scale_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->scale_keys[key1].time) / time_diff;

                        
            // calculate interpolated scale values
                        D3DXVECTOR3 scale_vec = anim->scale_keys[key2].vec - anim->scale_keys[key1].vec;
                        scale_vec 
            *= scalar;
                        scale_vec 
            += anim->scale_keys[key1].vec;

                        
            // create scale matrix and combine with transformation
                        D3DXMATRIX scale_matrix;
                        D3DXMatrixScaling(
            &scale_matrix, scale_vec.x, scale_vec.y, scale_vec.z);
                        anim_matrix 
            *= scale_matrix;
                    }

                    
            // rotation
                    if(anim->num_rotation_keys && anim->rotation_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching rotation key
                        for(DWORD i = 0; i < anim->num_rotation_keys; i++)
                        {
                            
            if(time >= anim->rotation_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_rotation_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->rotation_keys[key2].time - anim->rotation_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->rotation_keys[key1].time) / time_diff;

                        
            // slerp rotation values
                        D3DXQUATERNION rot_quat;
                        D3DXQuaternionSlerp(
            &rot_quat, &anim->rotation_keys[key1].quat, &anim->rotation_keys[key2].quat, scalar);

                        
            // create rotation matrix and combine with transformation
                        D3DXMATRIX rot_matrix;
                        D3DXMatrixRotationQuaternion(
            &rot_matrix, &rot_quat);
                        anim_matrix 
            *= rot_matrix;
                    }

                    
            // translation
                    if(anim->num_translation_keys && anim->translation_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching translation key
                        for(DWORD i = 0; i < anim->num_translation_keys; i++)
                        {
                            
            if(time >= anim->translation_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_matrix_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->translation_keys[key2].time - anim->translation_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->translation_keys[key1].time) / time_diff;

                        
            // calculate interpolated vector values
                        D3DXVECTOR3 pos_vec = anim->translation_keys[key2].vec - anim->translation_keys[key1].vec;
                        pos_vec 
            *= scalar;
                        pos_vec 
            += anim->translation_keys[key1].vec;

                        
            // create translation matrix and combine with transformation
                        D3DXMATRIX translation_matrix;
                        D3DXMatrixTranslation(
            &translation_matrix, pos_vec.x, pos_vec.y, pos_vec.z);
                        anim_matrix 
            *= translation_matrix;
                    }

                    
            // matrix
                    if(anim->num_matrix_keys && anim->matrix_keys)
                    {
                        DWORD key1 
            = 0, key2 = 0;

                        
            // loop for matching matrix key
                        for(DWORD i = 0; i < anim->num_matrix_keys; i++)
                        {
                            
            if(time >= anim->matrix_keys[i].time)
                                key1 
            = i;
                        }

                        key2 
            = (key1 >= (anim->num_matrix_keys - 1)) ? key1 : key1+1;

                        DWORD time_diff 
            = anim->matrix_keys[key2].time - anim->matrix_keys[key1].time;

                        
            if(time_diff == 0)
                            time_diff 
            = 1;

                        
            float scalar = (float)(time - anim->matrix_keys[key1].time) / time_diff;

                        
            // calculate interpolated matrix
                        D3DXMATRIX diff_matrix = anim->matrix_keys[key2].matrix - anim->matrix_keys[key1].matrix;
                        diff_matrix 
            *= scalar;
                        diff_matrix 
            += anim->matrix_keys[key1].matrix;

                        
            // combine with transformation
                        anim_matrix *= diff_matrix;
                    }

                    D3DXMATRIX diff_matrix 
            = anim_matrix - anim->bone->mat_original;
                    diff_matrix 
            *= blend;
                    anim
            ->bone->TransformationMatrix += diff_matrix;
                }
            }

             

            WinMain.cpp:

            /***********************************************************************************************
             Demonstrates how multiple skeletal-based animations can be blended together into one animation.
            **********************************************************************************************
            */

            #include 
            <windows.h>
            #include 
            <d3d9.h>
            #include 
            <d3dx9.h>
            #include 
            "Direct3D.h"
            #include 
            "SkeletalAnimBlend.h"

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;
            D3DXMESHCONTAINER_EX
            *    g_mesh_container;
            D3DXFRAME_EX
            *            g_frame;
            IDirect3DTexture9
            *        g_guide_texture;
            ID3DXSprite
            *            g_guide_sprite;

            cBlendAnimationCollection    g_blend_anim_collection;

            char g_blend_flags[5];        // blending toggles (arms, legs, )

            const char CLASS_NAME[] = "BlendSkeletalAnimClass";
            const char CAPTION[]    = "Blended Skeletal Animation Demo";

            ////////////////////////////////////////////////////////////////////////////////////////////////

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

            bool do_init(HWND hwnd);
            void do_shutdown();
            void do_frame();


            //////////////////////////////////////////////////////////////////////////////////////////////

            int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR, int cmd_show)
            {      
                CoInitialize(NULL);    
            // Initialize the COM system

                
            // Create the window class here and register it

                WNDCLASSEX win_class;  

                win_class.cbSize        
            = sizeof(win_class);
                win_class.style         
            = CS_CLASSDC;
                win_class.lpfnWndProc   
            = window_proc;
                win_class.cbClsExtra    
            = 0;
                win_class.cbWndExtra    
            = 0;
                win_class.hInstance     
            = inst;
                win_class.hIcon         
            = LoadIcon(NULL, IDI_APPLICATION);
                win_class.hCursor       
            = LoadCursor(NULL, IDC_ARROW);
                win_class.hbrBackground 
            = NULL;
                win_class.lpszMenuName  
            = NULL;
                win_class.lpszClassName 
            = CLASS_NAME;
                win_class.hIconSm       
            = LoadIcon(NULL, IDI_APPLICATION);

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

                
            // Create the main window
                HWND hwnd = CreateWindow(CLASS_NAME, CAPTION, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                                         
            00640480, NULL, NULL, inst, NULL);

                
            if(hwnd == NULL)
                    
            return -1;

                ShowWindow(hwnd, cmd_show);
                UpdateWindow(hwnd);

                
            // Call init function and enter message pump
                if(do_init(hwnd)) 
                {
                    MSG msg;    
                    ZeroMemory(
            &msg, sizeof(MSG));

                    
            // Start message pump, waiting for user to exit
                    while(msg.message != WM_QUIT) 
                    {
                        
            if(PeekMessage(&msg, NULL, 00, PM_REMOVE)) 
                        {
                            TranslateMessage(
            &msg);
                            DispatchMessage(
            &msg);
                        }
                        
                        do_frame();    
            // Render a single frame
                    }
                }
              
                do_shutdown();
                UnregisterClass(CLASS_NAME, inst);
                CoUninitialize();

                
            return 0;
            }

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                
            // Only handle window destruction messages
                switch(msg) 
                {
                
            case WM_KEYUP:
                    
            // toggle a body part
                    if(wParam >= '1' && wParam <= '5')
                        g_blend_flags[wParam 
            - '1'^= 1;

                    
            // clear toggles
                    if(wParam == VK_SPACE)
                        memset(g_blend_flags, 
            1sizeof(g_blend_flags));

                    
            break;

                
            case WM_KEYDOWN:
                    
            if(wParam == VK_ESCAPE)
                        DestroyWindow(hwnd);
                    
            break;

                
            case WM_DESTROY:
                    PostQuitMessage(
            0);
                    
            break;    
                }

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

            bool do_init(HWND hwnd)
            {
                init_d3d(
            &g_d3d, &g_device, hwnd, falsefalse);

                
            // load skeletal mesh
                if(FAILED(load_mesh(&g_mesh_container, &g_frame, g_device, "..\\Data\\tiny.x""..\\Data\\"
                                    
            0, D3DXMESH_SYSTEMMEM)))
                {
                    
            return false;
                }

                
            // load animation data
                if(! g_blend_anim_collection.load("..\\Data\\tiny.x"))
                    
            return false;

                
            // map the animation to the frame hierarchy
                g_blend_anim_collection.map_frames(g_frame);

                
            // load the guide texture and create the sprite interface

                D3DXCreateTextureFromFileEx(g_device, 
            "..\\Data\\Guide.bmp", D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 
                                            
            0, D3DFMT_A1R5G5B5, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
                                            
            0xFF000000, NULL, NULL, &g_guide_texture);

                D3DXCreateSprite(g_device, 
            &g_guide_sprite);

                
            // clear toggles
                memset(g_blend_flags, 1sizeof(g_blend_flags));

                
            return true;
            }

            void do_shutdown()
            {
                
            // free mesh data
                delete g_mesh_container;    g_mesh_container = NULL;
                delete g_frame;                g_frame 
            = NULL;

                
            // free guide texture and sprite interface
                release_com(g_guide_texture);
                release_com(g_guide_sprite);
                
                
            // release D3D objects
                release_com(g_device);
                release_com(g_d3d);
            }

            void do_frame()
            {
                
            static DWORD start_time = timeGetTime();
                DWORD curr_time 
            = timeGetTime();

                g_frame
            ->reset();

                DWORD time 
            = curr_time - start_time;

                
            // blend the animations

                
            if(g_blend_flags[0])
                    g_blend_anim_collection.blend(
            "left_arm",    time, true1.5f);
                
                
            if(g_blend_flags[1])
                    g_blend_anim_collection.blend(
            "right_arm",    time, true1.5f);

                
            if(g_blend_flags[2])
                    g_blend_anim_collection.blend(
            "left_leg",    time, true1.2f);

                
            if(g_blend_flags[3])
                    g_blend_anim_collection.blend(
            "right_leg",    time, true1.2f);

                
            if(g_blend_flags[4])
                    g_blend_anim_collection.blend(
            "body",        time, true1.0f);

                
            // rebuild the frame hierarchy transformations
                if(g_frame)
                    g_frame
            ->update_hierarchy(NULL);

                
            // rebuild the mesh
                update_skin_mesh(g_mesh_container);

                
            // calculate a view transformation matrix using the mesh's bounding radius to position the viewer
                
                D3DXMATRIX  mat_view;
                D3DXVECTOR3 eye(
            600.0f200.0f-600.0f);
                D3DXVECTOR3 at(
            0.0f0.0f0.0f);
                D3DXVECTOR3 up(
            0.0f1.0f0.0f);

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

                D3DXMATRIX mat_world;
                D3DXMatrixIdentity(
            &mat_world);
                g_device
            ->SetTransform(D3DTS_WORLD, &mat_world);

                
            // clear the device and start drawing the scene

                g_device
            ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0064255), 1.0f0);

                g_device
            ->BeginScene();    

                draw_mesh(g_mesh_container);

                
            // enable per pixel alpha testing
                g_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);

                
            // specifies a reference alpha value against which pixels are tested
                g_device->SetRenderState(D3DRS_ALPHAREF, 0x01);

                
            // accept the new pixel if its value is greater than the value of the current pixel
                g_device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);

                
            // draw the guid teture
                g_guide_sprite->Begin(0);
                g_guide_sprite
            ->Draw(g_guide_texture, NULL, NULL, NULL, D3DCOLOR_RGBA(255 ,2550255));
                g_guide_sprite
            ->End();

                g_device
            ->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

                g_device
            ->EndScene();

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

             

            download source file


            posted on 2008-04-25 21:11 lovedday 閱讀(580) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            日日狠狠久久偷偷色综合免费| 狠狠久久综合| 久久婷婷激情综合色综合俺也去 | 久久精品毛片免费观看| 久久99国产精品一区二区| 精品无码久久久久久久动漫| 亚洲精品午夜国产VA久久成人 | 久久精品国产亚洲av水果派| 一本久久a久久精品综合夜夜 | 亚洲国产视频久久| 2020久久精品国产免费| 精品久久久久久久久免费影院| 国产精品久久永久免费| 久久99久久99精品免视看动漫| 88久久精品无码一区二区毛片| 欧美午夜精品久久久久免费视 | 97久久国产综合精品女不卡| 久久精品国产精品亚洲艾草网美妙| 久久精品亚洲一区二区三区浴池 | 人妻无码久久一区二区三区免费| 久久久久亚洲精品中文字幕| 国产精品美女久久久| 五月丁香综合激情六月久久| 欧美日韩精品久久久免费观看| 国产精品热久久毛片| 亚洲国产精品久久久久| 久久香蕉国产线看观看99| A狠狠久久蜜臀婷色中文网| 久久天天躁狠狠躁夜夜网站 | 久久精品国产99国产精品澳门| 亚洲AV无码成人网站久久精品大| 麻豆av久久av盛宴av| 国产一区二区久久久| 久久精品国产免费观看三人同眠| 久久久久亚洲精品男人的天堂| 精品久久久久久无码国产| 国产精品欧美亚洲韩国日本久久| 国产毛片久久久久久国产毛片 | 综合网日日天干夜夜久久 | 狠狠色丁香婷婷久久综合五月| 中文字幕精品久久|