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

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

Timing in Animation and Movement(2)

Animating with Time

In the olden days, games were made to animate graphics based on every frame processed. To ensure that the animations always ran at the same speed, those games sometimes limited the number of frames per second that could be processed. Of course, those old games were made for computers that couldn't easily process more than 20 to 30 frames per second, so it was safe to assume that limiting the number of frames per second would never surpass that 20 or 30 frames per second mark.

But that was then, and this is now. Modern computers can run circles around their ancestors, and limiting the number of frames to control animation is a definite no−no in this day and age. You need to base the speed of animation on the amount of time that has elapsed since the start of the animation sequence. Doing so is no problem because you already know that you can record the time when the animation started. Additionally, for each frame to update, you can read the current time and subtract the starting animation time. The result is a time value to use as an offset to your animation sequence.

Suppose you are using time−based key frames in your animation engine. You can use a simple key−frame structure that stores the time and a transformation matrix to use, such as this:

typedef struct sKeyframe {
  DWORD Time;
  D3DMATRIX matTransformation;
} sKeyframe;

As is typical for key frames, you can store an array of matrices, each with its own unique time. These structures are stored in chronological order, with the lower time values first. Therefore, you can create a small sequence of transformations to orient an object over time (see Figure 2.1).

To replicate the key frames shown in Figure 2.1, I've constructed the following array:

sKeyframe Keyframes[4] = {
{ 0, 1.00000f, 0.00000f, 0.00000f, 0.00000f,
0.00000f, 1.00000f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
0.00000f, 0.00000f, 0.00000f, 1.00000f; },

{ 400, 0.000796f, 1.00000f, 0.00000f, 0.00000f,
−1.00000f, 0.000796f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
50.00000f, 0.00000f, 0.00000f, 1.00000f; },

{ 800, −0.99999f, 0.001593f, 0.00000f, 0.00000f,
−0.001593f, −0.99999f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
25.00000f, 25.00000f, 0.00000f, 1.00000f; },

{ 1200, 1.00000f, 0.00000f, 0.00000f, 0.00000f,
0.00000f, 1.00000f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
0.00000f, 0.00000f, 0.00000f, 1.00000f; }
};

Now comes the fun part. Using the timing methods you read about previously, you can record the time at which the animation started. And, for each frame to update the animation, you can calculate the elapsed time since the animation started (using that as an offset to the key frames). Create a simple frame update function that will determine which transformation to use depending on the elapsed time since the update function was first called.

void FrameUpdate()
{
  static DWORD StartTime = timeGetTime();
  DWORD Elapsed = timeGetTime() − StartTime;

With the elapsed time now in hand, you can scan the key frames to look for the two between which the time value lies. For example, if the current time is 60 milliseconds, the animation is somewhere between key frame #0 (at 0 milliseconds) and key frame #1 (at 400 milliseconds). A quick scan through the key frames determines which to use based on the elapsed time.

DWORD Keyframe = 0; // Start at 1st keyframe

for(DWORD i=0;i<4;i++) {
  // If time is greater or equal to a key−frame's time then update the keyframe to use
  if(Time >= Keyframes[i].Time)
    Keyframe = i;
}

At the end of the loop, the Keyframe variable will hold the first of the two key frames between which the animation time lies. If Keyframe isn't the last key frame in the array (in which there are four key frames), then you can add 1 to Keyframe to obtain the second key frame. If Keyframe is the last key frame in the array, you can use the same key−frame value in your calculations.

Using a second variable to store the next key frame in line is perfect. Remember that if Keyframe is the last key frame in the array, you need to set this new key frame to the same value.

DWORD Keyframe2 = (Keyframe==3) ? Keyframe:Keyframe + 1;

Now you need to grab the time values and calculate a scalar based on the time difference of the keys and the position of the key frame between the keys.

DWORD TimeDiff = Keyframes[Keyframe2].Time − Keyframes[Keyframe].Time;

// Make sure there's a time difference to avoid divide−by−zero errors later on.
if(!TimeDiff)
  TimeDiff=1;

float Scalar = (Time − Keyframes[Keyframe].Time) / TimeDiff;

You now have the scalar value (which ranges from 0 to 1) used to interpolate the transformation matrices of the keys. To make it easy to deal with the transformation matrices, those matrices are cast to a D3DXMATRIX type so that D3DX does the hard work for you.

// Calculate the difference in transformations
D3DXMATRIX matInt = D3DXMATRIX(Keyframes[Keyframe2].matTransformation) −
                                    D3DXMATRIX(Keyframes[Keyframe].matTransformation);

matInt *= Scalar; // Scale the difference

// Add scaled transformation matrix back to 1st keyframe matrix
matInt += D3DXMATRIX(Keyframes[Keyframe].matTransformation);

At this point, you have the proper animated transformation matrix to use stored in matInt. To see your hard work come to life, set matInt as the world transformation and render your animated mesh.

 

Main Routine:

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

IDirect3D9
*                g_d3d;
IDirect3DDevice9
*        g_device;
D3DXMESHCONTAINER_EX
*    g_robot_mesh_container;

struct sKeyFrame
{
    DWORD        time;
    D3DMATRIX    mat_trans;
};

// NOTE: transfromation matrix of key frame 0 is same as key frame 3.
sKeyFrame g_key_frames[4= 
{
  
// key_frame 1, 0ms
  {   01.000000f0.000000f0.000000f0.000000f,
         
0.000000f1.000000f0.000000f0.000000f,
         
0.000000f0.000000f1.000000f0.000000f,
         
0.000000f0.000000f0.000000f1.000000f },

  
// key_frame 2, 40ms
  {  4000.000796f1.000000f0.000000f0.000000f,
         
-1.000000f0.000796f0.000000f0.000000f,
          
0.000000f0.000000f1.000000f0.000000f,
         
50.000000f0.000000f0.000000f1.000000f },

  
// key_frame 3, 80ms
  {  800-0.999999f,  0.001593f0.000000f0.000000f,
          
-0.001593f-0.999999f0.000000f0.000000f,
           
0.000000f,  0.000000f1.000000f0.000000f,
          
25.000000f25.000000f0.000000f1.000000f },

  
// key_frame 4, 120ms
  { 12001.000000f0.000000f0.000000f0.000000f,
          
0.000000f1.000000f0.000000f0.000000f,
          
0.000000f0.000000f1.000000f0.000000f,
          
0.000000f0.000000f0.000000f1.000000f }
};

const char g_class_name[] = "TimeAnimClass";
const char g_caption[] = "Timed Animation";

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

  WNDCLASSEX win_class;

  
// Create the window class here and register it
  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 
= g_class_name;
  win_class.hIconSm       
= LoadIcon(NULL, IDI_APPLICATION);

  
if(!RegisterClassEx(&win_class))
    
return FALSE;

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

  
if(hwnd == NULL)
    
return FALSE;

  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(g_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_DESTROY:
      PostQuitMessage(
0);
      
break;

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

        
break;
  }

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

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

    
if(FAILED(load_mesh(&g_robot_mesh_container, g_device, "..\\Data\\robot.x""..\\Data\\"00)))
        
return FALSE;

    
// setup a directional light

    D3DLIGHT9 light;
    ZeroMemory(
&light, sizeof(D3DLIGHT9));

    light.Type 
= D3DLIGHT_DIRECTIONAL;
    light.Diffuse.r 
= light.Diffuse.g = light.Diffuse.b = light.Diffuse.a = 1.0f;
    light.Direction 
= D3DXVECTOR3(0.0f-0.5f0.5f);

    g_device
->SetLight(0&light);
    g_device
->LightEnable(0, TRUE);

    
return true;
}

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

    
// release D3D objects
    release_com(g_device);
    release_com(g_d3d);
}

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

    DWORD elapsed_time 
= timeGetTime() - start_time;

    
// bounds the time to the animation time, important!!
    elapsed_time %= (g_key_frames[3].time + 1);

    
// dertermin which keyframe to use

    DWORD key_frame 
= 0;

    
for(DWORD i = 0; i < 4; i++)
    {
        
// if time is greater or equal to a key-frame's time then update the keyframe to use
        if(elapsed_time >= g_key_frames[i].time)
            key_frame 
= i;
    }

    
// get second key frame
    DWORD key_frame_2 = (key_frame == 3? key_frame : (key_frame + 1);

    
// Calculate the difference in time between keyframes and calculate a scalar value to use 
    
// for adjusting the transformations.
    DWORD time_diff = g_key_frames[key_frame_2].time - g_key_frames[key_frame].time;

    
if(time_diff == 0)
        time_diff 
= 1;

    
float scalar = (float)(elapsed_time - g_key_frames[key_frame].time) / time_diff;

    
// calculate the difference in transformations
    D3DXMATRIX mat = D3DXMATRIX(g_key_frames[key_frame_2].mat_trans) - D3DXMATRIX(g_key_frames[key_frame].mat_trans);

    mat 
*= scalar;    // scale the difference

    
// add scaled transformation matrix back to 1st key frame matrix
    mat += D3DXMATRIX(g_key_frames[key_frame].mat_trans);

    g_device
->SetTransform(D3DTS_WORLD, &mat);

    
// set a view transformation matrix

    D3DXMATRIX  mat_view;
    D3DXVECTOR3 eye(
25.0f0.0f-80.0f);
    D3DXVECTOR3 at(
25.0f0.0f0.0f);
    D3DXVECTOR3 up(
0.0f1.0f0.0f);

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

    
// clear the device and start drawing the scene

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

    g_device
->BeginScene();

    g_device
->SetRenderState(D3DRS_LIGHTING, TRUE);
    draw_mesh(g_robot_mesh_container);
    g_device
->SetRenderState(D3DRS_LIGHTING, FALSE);

    g_device
->EndScene();

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


Runtime Snap:

As you can see, using time−based animation is pretty simple. Even if you don't use key frames in your animation, you can still rely on these methods of using time in your own code. Now that you've seen how easy it is to use time−based animation, take a look at how easy it is to use time−based movement.

 

download source file

 

posted on 2008-04-15 16:27 lovedday 閱讀(454) 評論(0)  編輯 收藏 引用


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


公告

導(dǎo)航

統(tǒng)計

常用鏈接

隨筆分類(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>
            先锋影音国产一区| 欧美一区久久| 欧美日韩一区成人| 在线视频亚洲一区| 亚洲综合色激情五月| 国产女精品视频网站免费 | 国产午夜久久久久| 久久免费视频在线| 免费短视频成人日韩| aaa亚洲精品一二三区| 这里只有精品电影| 国产一区二区三区高清| 亚洲第一天堂av| 欧美日韩色一区| 久久精品99国产精品酒店日本| 久久精品国产欧美激情| 亚洲欧洲午夜| 亚洲在线观看免费| 亚洲国产一区视频| 亚洲午夜电影网| 亚洲电影在线免费观看| 亚洲视频中文| 亚洲激情一区二区| 亚洲欧美激情视频| 亚洲理论在线| 欧美在线首页| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 欧美新色视频| 欧美风情在线| 国产伦一区二区三区色一情| 欧美韩日亚洲| 国产色综合天天综合网| 亚洲精品一区二区三区99| 国产一区视频在线看| aⅴ色国产欧美| 亚洲国产精品久久久久婷婷老年 | 国产精品爱久久久久久久| 免费不卡中文字幕视频| 国产精品视频网| 亚洲人成毛片在线播放| 影音先锋亚洲精品| 亚洲欧美日韩视频一区| 亚洲一级二级| 欧美激情视频给我| 欧美黄色aa电影| 在线观看欧美日韩国产| 午夜在线a亚洲v天堂网2018| 亚洲调教视频在线观看| 欧美福利在线| 欧美大尺度在线观看| 韩曰欧美视频免费观看| 亚洲欧美日韩在线| 亚洲免费伊人电影在线观看av| 欧美国产第二页| 欧美黄在线观看| 亚洲第一网站| 女人香蕉久久**毛片精品| 免费亚洲网站| 在线观看欧美亚洲| 久久一区精品| 亚洲国产裸拍裸体视频在线观看乱了中文 | 日韩午夜在线观看视频| 亚洲欧洲日产国产综合网| 久久精品在这里| 欧美xx视频| 亚洲精品在线观| 欧美日韩成人在线播放| 亚洲精品偷拍| 亚洲一区二三| 国产精品专区h在线观看| 亚洲一区在线免费| 欧美在线观看视频一区二区三区| 国产精品日本一区二区| 亚洲欧美日韩精品久久奇米色影视| 午夜欧美视频| 激情91久久| 欧美成年人网| 在线综合亚洲| 久久精品2019中文字幕| 在线看欧美视频| 欧美精品大片| 亚洲欧美日本国产有色| 久久精品视频99| 亚洲黑丝一区二区| 国产精品久久久久一区二区三区共 | 美女在线一区二区| 日韩一区二区电影网| 国产精品久久久久婷婷| 久久精品人人做人人爽| 亚洲国产一区在线观看| 亚洲欧美精品中文字幕在线| 国产一区二区三区久久 | 欧美午夜精品久久久久久人妖| 亚洲欧美日韩精品久久亚洲区| 免费视频久久| 亚洲一区激情| 亚洲电影视频在线| 国产精品夫妻自拍| 狂野欧美激情性xxxx| 一本色道久久综合精品竹菊| 久久综合色综合88| 亚洲午夜伦理| 亚洲国产二区| 国产日韩视频| 欧美视频官网| 欧美电影在线| 久久精品麻豆| 亚洲欧美久久| 99精品国产高清一区二区| 久久综合中文字幕| 欧美一级视频| 中文日韩在线视频| 亚洲精品乱码久久久久久黑人| 国产日韩欧美三级| 国产精品久久福利| 欧美国产先锋| 久久伊人精品天天| 欧美在线视频免费播放| 在线亚洲欧美专区二区| 亚洲经典一区| 亚洲电影在线播放| 老鸭窝亚洲一区二区三区| 亚洲欧美激情视频| 一区二区激情| 99精品热视频| 亚洲精品偷拍| 亚洲欧洲日本专区| 亚洲国内精品在线| 亚洲成色最大综合在线| 黄色成人免费网站| 国产一区久久| 国模叶桐国产精品一区| 国产欧美精品一区二区三区介绍| 欧美日韩小视频| 欧美丝袜第一区| 欧美日韩另类综合| 欧美日韩专区| 国产精品久久久久久久久| 欧美日韩在线影院| 国产精品成人v| 国产精品久久国产三级国电话系列| 欧美剧在线免费观看网站| 欧美激情成人在线视频| 欧美区国产区| 国产精品久久网站| 国产伦精品一区二区三区高清| 国产精品日韩欧美一区二区| 国产精品福利网| 国产精品人成在线观看免费| 国产精品视频导航| 国产一区二区三区在线观看网站| 国产综合欧美| 亚洲国产专区| 中文在线不卡| 久久精品国产亚洲5555| 免费久久久一本精品久久区| 欧美国产精品一区| 99re国产精品| 性久久久久久久久久久久| 久久久中精品2020中文| 欧美高清视频一区二区三区在线观看 | 欧美伊人精品成人久久综合97 | 一本综合久久| 欧美在线播放视频| 欧美成人中文字幕| 国产精品久久一卡二卡| 国产一区二区三区成人欧美日韩在线观看 | 久久人人97超碰人人澡爱香蕉| 欧美电影资源| 国产欧美精品一区aⅴ影院| 精品91免费| 亚洲视频在线免费观看| 久久精品国产亚洲一区二区| 欧美激情视频一区二区三区在线播放 | 亚洲国产精品99久久久久久久久| 99re6热在线精品视频播放速度 | 99热免费精品| 久久精品免费电影| 欧美午夜视频一区二区| 国产综合色产| 一区二区三区四区精品| 久久看片网站| 亚洲午夜黄色| 欧美高清你懂得| 国产一区二区三区在线观看精品| 99综合电影在线视频| 久久久噜噜噜久噜久久 | 亚洲国产欧美一区二区三区同亚洲| 亚洲一区中文字幕在线观看| 久久免费国产| 国产精品自拍一区| 一区二区三区 在线观看视频| 久久午夜精品| 亚洲欧美激情在线视频| 欧美伦理a级免费电影| 伊人男人综合视频网| 欧美一级片在线播放| 一本大道久久a久久精品综合| 免费在线国产精品| 激情久久久久久久|