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

天行健 君子當自強而不息

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


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲高清123| 99精品国产99久久久久久福利| 99精品久久免费看蜜臀剧情介绍| 欧美成人有码| 亚洲国产欧美精品| 一区二区三区**美女毛片| 亚洲综合色网站| 久久尤物电影视频在线观看| 欧美激情免费在线| 国产片一区二区| 91久久精品日日躁夜夜躁欧美 | 欧美精品一区二区三区在线播放 | 久久婷婷国产综合国色天香| 欧美日韩高清在线| 激情五月婷婷综合| 亚洲一区二区毛片| 免费在线视频一区| 午夜精彩国产免费不卡不顿大片| 欧美成人一区二区三区| 国产精品综合不卡av| 99国产精品| 亚洲一区二区三区免费视频| 欧美国产日韩精品| 亚洲国产精品国自产拍av秋霞| 亚洲欧美亚洲| 亚洲黄一区二区三区| 久久激情视频免费观看| 国产精品久久久久久久久免费桃花 | 欧美在线观看视频| 欧美日韩一区二区三区在线| 亚洲国产成人tv| 亚洲精品视频免费观看| 久久亚洲欧美| 亚洲天天影视| 一区二区三区久久久| 狠狠久久亚洲欧美| 久久久久国内| 欧美一级大片在线观看| 国产在线播放一区二区三区| 性久久久久久| 午夜久久99| 国内自拍一区| 中文网丁香综合网| 国产精品高潮粉嫩av| 亚洲午夜av在线| 久久蜜臀精品av| 欧美一级成年大片在线观看| 欧美福利视频在线| 男女精品网站| 国产综合精品| 亚洲一区在线视频| 一本综合久久| 一区二区三区精密机械公司| 在线精品国精品国产尤物884a| 另类图片国产| 欧美精品黄色| 亚洲福利视频网| 精品动漫一区| 欧美一级免费视频| 性欧美精品高清| 国产精品国产三级国产aⅴ入口| 亚洲国产精品www| 亚洲区在线播放| 久久亚洲私人国产精品va| 久久福利毛片| 欧美激情成人在线视频| 欧美韩国日本综合| 欧美日韩一区二区三区高清| 亚洲黄色免费| 一区二区成人精品| 午夜欧美大片免费观看| 亚洲欧美日韩精品久久| 久久免费国产| 欧美大片在线看免费观看| 在线精品视频一区二区| 久久久久国产精品人| 国产亚洲va综合人人澡精品| 亚洲福利久久| 一本一本久久a久久精品牛牛影视| 欧美成人精品福利| 亚洲精品免费电影| 伊人久久婷婷| 亚洲影院免费| 久久久久久久综合狠狠综合| 久久黄金**| 欧美激情一级片一区二区| 亚洲黄色免费| 欧美在线免费一级片| 久久亚洲美女| 国产麻豆午夜三级精品| 性色av一区二区三区在线观看| 久久久精品网| 亚洲国产一区二区视频 | 亚洲国产一区二区三区高清| 亚洲精品国产精品国产自| 亚洲综合电影| 美女诱惑一区| 韩国女主播一区| 免费人成网站在线观看欧美高清| 欧美在线观看一二区| 欧美色综合网| 亚洲精品一区二区三区99| 午夜日韩在线观看| 在线欧美一区| 欧美午夜精品久久久久久浪潮 | 亚洲一区二区三区四区中文| 国产精品一区二区三区四区五区| 久久久久久亚洲综合影院红桃| 亚洲国产一区二区三区青草影视| 午夜精品久久久久久久男人的天堂| 精品9999| 国产精品久久久久久亚洲毛片 | 久久久免费精品视频| 亚洲精品少妇网址| 久久久久99| 亚洲自拍16p| 国产精品福利影院| 美女视频黄 久久| 欧美韩国日本一区| 欧美一区二区三区在线观看视频| 亚洲激情视频网站| 国产婷婷精品| 欧美午夜国产| 欧美日韩国产a| 久久综合色影院| 午夜一级在线看亚洲| 9久re热视频在线精品| 欧美va亚洲va香蕉在线| 久久精品在线视频| 欧美一区91| 亚洲女同同性videoxma| 亚洲精品中文字幕在线| 欧美日韩另类在线| 欧美 亚欧 日韩视频在线| 欧美一区三区二区在线观看| 这里是久久伊人| 亚洲免费观看在线视频| 亚洲欧美日韩精品久久亚洲区 | 亚洲日本成人网| 好吊妞**欧美| 国产一区二区三区的电影| 久久亚洲欧美| 久久精品女人天堂| 亚洲精品美女91| 欧美激情国产日韩| 欧美r片在线| 欧美91大片| 欧美国产第二页| 欧美国产日韩a欧美在线观看| 久久久97精品| 久久久久久久久久久久久女国产乱 | 国产精品久久激情| 国产精品夫妻自拍| 国产精品三区www17con| 卡通动漫国产精品| 久久久99国产精品免费| 久久久国产成人精品| 久久精品一本| 久久伊人一区二区| 免费在线看成人av| 欧美日韩精品免费观看视一区二区| 欧美好骚综合网| 欧美色大人视频| 国产色爱av资源综合区| 好男人免费精品视频| 91久久久一线二线三线品牌| 亚洲精品久久久久中文字幕欢迎你| 日韩一级网站| 亚洲欧美国产精品va在线观看 | 亚洲视频播放| 欧美一区二区三区免费视频| 久久五月天婷婷| 亚洲日本电影在线| 亚洲无亚洲人成网站77777| 美国十次成人| 亚洲精品乱码视频| 午夜精彩国产免费不卡不顿大片| 久久激情五月婷婷| 欧美精品二区| 国产欧美日韩精品a在线观看| 又紧又大又爽精品一区二区| 亚洲免费黄色| 久久久久国产精品www| 亚洲国产高清aⅴ视频| 中文亚洲欧美| 麻豆精品91| 国产精品一区免费视频| 亚洲国产天堂久久综合| 亚洲欧美国产精品va在线观看| 久久蜜臀精品av| 夜夜夜精品看看| 久久这里有精品15一区二区三区| 欧美三区不卡| 亚洲激情综合| 久久精品国产亚洲精品| 久久爱www| 亚洲看片一区| 免费成人黄色av| 国产亚洲精品7777| 亚洲午夜精品久久久久久浪潮|