青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

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

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 閱讀(583) 評論(0)  編輯 收藏 引用


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


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

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

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧美三级伦理| 午夜久久美女| 国产精品一级二级三级| 欧美日韩亚洲精品内裤| 欧美激情一区在线| 欧美日韩一区二区免费在线观看| 欧美激情一区二区三区高清视频| 欧美国产日韩二区| 欧美日韩伦理在线| 欧美日韩国产一中文字不卡 | 久久精品国产综合| 久久国产精品久久久久久| 欧美一级片一区| 久热这里只精品99re8久| 欧美高清视频在线观看| 欧美三区视频| 黄色日韩在线| 日韩视频在线一区二区三区| 亚洲少妇诱惑| 久久亚洲捆绑美女| 91久久国产综合久久| 日韩一区二区免费高清| 亚洲欧美一区二区激情| 老司机精品视频一区二区三区| 欧美精品激情在线| 国产视频在线观看一区二区| 亚洲精品韩国| 欧美一区二区播放| 亚洲电影在线观看| 香蕉成人久久| 欧美久久在线| 在线精品观看| 性色av一区二区三区在线观看| 欧美成人午夜激情视频| 亚洲免费中文| 香蕉亚洲视频| 国产精品久久精品日日| 狠狠色狠狠色综合人人| 国产精品99久久99久久久二8 | 久久亚洲一区二区| 国产精品v欧美精品∨日韩| 狠狠色综合一区二区| 亚洲永久视频| 欧美成人一区二区三区片免费| 中文精品视频| 欧美美女日韩| 亚洲激情啪啪| 久久综合狠狠| 午夜在线视频一区二区区别| 欧美日韩三级| av成人动漫| 亚洲国产精品第一区二区| 久久精品99国产精品日本| 国产精品网站视频| 中文精品99久久国产香蕉| 亚洲国产精品成人| 玖玖国产精品视频| 在线色欧美三级视频| 久久久人成影片一区二区三区| 亚洲网站视频| 国产精品白丝黑袜喷水久久久| 一区二区三区 在线观看视频 | 亚洲欧美日韩精品久久久久| 国产精品卡一卡二卡三| 亚洲一区二区三区国产| 一区二区福利| 国产精品久久网站| 欧美一区二区三区免费在线看| av成人福利| 国产精品久久久久久久久久妞妞 | 欧美三日本三级三级在线播放| 日韩一级片网址| 亚洲免费观看高清在线观看 | 久久午夜av| 久久一区精品| 亚洲啪啪91| 亚洲欧洲一区二区天堂久久 | 午夜精品在线| 夜夜嗨av色综合久久久综合网| 欧美国产精品v| 91久久国产综合久久91精品网站| 免费看精品久久片| 麻豆国产精品一区二区三区| 亚洲欧洲在线一区| 日韩视频不卡中文| 国产精品久久久久久久一区探花| 欧美一级片久久久久久久| 欧美一区二区大片| 影音先锋欧美精品| 亚洲美女黄色片| 国产精品天美传媒入口| 久久久水蜜桃| 欧美激情精品久久久久久变态 | 久久九九热免费视频| 久久九九精品99国产精品| 亚洲欧洲精品一区| 亚洲香蕉网站| 亚洲国产精品一区| 一区二区三区视频在线播放| 韩日精品视频| 日韩亚洲欧美中文三级| 国产亚洲精品自拍| 亚洲精品一区二区三区四区高清| 国产精品午夜av在线| 欧美黑人在线观看| 国产伦精品一区二区三区在线观看| 玖玖视频精品| 欧美日韩一区二区在线视频| 久久婷婷影院| 国产精品久久久亚洲一区| 美女国产精品| 国产精品免费在线| 亚洲欧洲一级| 亚洲国产高潮在线观看| 亚洲欧美视频在线| 亚洲一区二区视频| 欧美高清在线播放| 久久久一区二区三区| 国产精品v片在线观看不卡 | 国产欧美在线| 亚洲美女在线看| 亚洲黄色天堂| 久久久精品五月天| 久久国产黑丝| 欧美日韩亚洲一区在线观看| 欧美激情2020午夜免费观看| 国产主播一区二区| 亚洲女人天堂av| 亚洲午夜精品久久| 欧美精品在线视频观看| 欧美激情第二页| 在线成人小视频| 午夜在线播放视频欧美| 欧美一二区视频| 国产精品一区二区在线观看不卡| 亚洲免费精品| 中文在线一区| 欧美四级伦理在线| 一区二区成人精品| 欧美黄色免费| 一区二区三区久久久| 免费在线观看一区二区| 欧美sm重口味系列视频在线观看| 国内自拍一区| 久久精品国产一区二区三区| 免费看亚洲片| 亚洲综合首页| 亚洲国产成人久久| 亚洲主播在线| 亚洲视频欧美在线| 欧美人与性动交a欧美精品| 亚洲激情一区| 9l视频自拍蝌蚪9l视频成人| 欧美日韩免费网站| 一区二区欧美国产| 午夜精品在线观看| 国产日韩一区在线| 久久成人18免费网站| 久久久亚洲精品一区二区三区 | 久久免费国产| 国产在线精品自拍| 久久久久久久欧美精品| 欧美国产综合视频| 欧美精品久久一区二区| 久久青草福利网站| 蜜桃av久久久亚洲精品| 久久婷婷蜜乳一本欲蜜臀| 国产精品免费网站| 亚洲一区免费| 久久手机免费观看| 亚洲欧洲一区二区在线观看 | 免费久久99精品国产自在现线| 亚洲福利在线观看| 亚洲一二三区在线| 韩国在线一区| 欧美人成在线| 新狼窝色av性久久久久久| 欧美激情成人在线| 亚洲欧美日韩另类| 亚洲国产日本| 国产精品一区二区你懂得| 久久亚洲影院| 国产精品99久久久久久宅男| 欧美日韩日日骚| 亚洲综合视频一区| 亚洲第一区在线观看| 久久久99国产精品免费| 麻豆久久精品| 国产精品一区一区三区| 性亚洲最疯狂xxxx高清| 国产一区二区久久久| 欧美另类一区二区三区| 欧美一区二区视频免费观看| 亚洲黄色三级| 久久裸体视频| 欧美一级午夜免费电影| 亚洲美女精品久久| 伊人精品久久久久7777| 久久成人av少妇免费| 国产精品久久久久久久电影|