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

天行健 君子當(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 閱讀(463) 評論(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>
            国产酒店精品激情| 欧美激情久久久久久| 99热精品在线| 99精品99久久久久久宅男| 蜜桃久久精品乱码一区二区| 蜜臀va亚洲va欧美va天堂| 欧美一级欧美一级在线播放| 久久国产天堂福利天堂| 欧美精品激情| 国产嫩草一区二区三区在线观看| 国产精品久久久久久久久久三级 | 久久久成人精品| 久久久久91| 久久精品国产96久久久香蕉| 亚洲国产99精品国自产| 一本色道久久| 久热精品视频在线| 一区二区三区免费网站| 欧美一二区视频| 一区二区在线视频播放| 亚洲午夜视频| 欧美激情亚洲自拍| 欧美午夜美女看片| 91久久精品久久国产性色也91| 亚洲色诱最新| 亚洲人成人一区二区三区| 亚洲天堂免费观看| 午夜精品美女久久久久av福利| 欧美成人在线网站| 国产一区二区成人| 亚洲欧美中文日韩在线| 欧美电影在线免费观看网站| 先锋亚洲精品| 欧美先锋影音| 久久久久99| 久久资源av| 国产视频一区在线观看| 欧美日韩国产精品自在自线| 国产欧美精品日韩精品| 女人色偷偷aa久久天堂| 欧美插天视频在线播放| 美女黄色成人网| 日韩视频在线免费观看| 欧美成熟视频| 一区二区高清视频| 亚洲免费影院| 欧美日本高清视频| 免费在线播放第一区高清av| 亚洲国产欧美一区二区三区同亚洲| 一本色道久久综合亚洲精品高清| 亚洲一区二区免费视频| 国产精品日日做人人爱 | 亚洲精品免费在线观看| 欧美一区二区高清| 蜜臀久久99精品久久久画质超高清 | 欧美成人午夜免费视在线看片| 尤物99国产成人精品视频| 午夜精品网站| 精品动漫av| 欧美精品一区二区高清在线观看| aa级大片欧美| 亚洲美女在线一区| 免费观看成人| 亚洲视频欧美在线| 99精品免费网| 国产亚洲精品一区二555| 免费日韩视频| 亚洲欧美日韩国产一区| 男同欧美伦乱| 欧美一区二区三区久久精品茉莉花| 欧美福利在线观看| 欧美波霸影院| 亚洲图片你懂的| 亚洲第一精品夜夜躁人人躁| 久久爱另类一区二区小说| 亚洲黄色高清| 亚洲大胆人体视频| 国产精品一区二区三区四区| 久久综合99re88久久爱| 亚洲欧美国产精品桃花| 亚洲欧美日韩中文视频| 国产专区欧美专区| 中文精品视频一区二区在线观看| 欧美一区二区在线观看| 亚洲高清在线观看| 国产精品极品美女粉嫩高清在线| 亚洲午夜电影在线观看| 亚洲精品一级| 麻豆国产va免费精品高清在线| 亚洲一区二区三区免费在线观看| 在线中文字幕不卡| 国产精品yjizz| 欧美搞黄网站| 欧美+亚洲+精品+三区| 欧美在线观看一区| 亚洲高清电影| 亚洲视频在线观看| 亚洲人体大胆视频| 亚洲大片在线观看| 国产亚洲精品一区二区| 国产欧美日韩不卡| 国产精品久久久久毛片软件 | 亚洲欧美怡红院| 亚洲免费观看在线观看| 欧美亚洲网站| 亚洲国产福利在线| 尤物九九久久国产精品的特点 | 欧美伊久线香蕉线新在线| 国产精品99久久久久久人| 亚洲精品网址在线观看| 亚洲精品一二三区| 日韩网站免费观看| 亚洲免费精彩视频| 一区二区三区高清| 亚洲一区欧美二区| 国产综合色产在线精品| 国产亚洲欧美日韩精品| 国产手机视频精品| 国产一区亚洲一区| 黄色在线一区| 亚洲国内精品| 一区二区三区欧美日韩| 亚洲视频在线观看免费| 亚洲免费伊人电影在线观看av| 亚洲一二三区在线| 欧美伊人精品成人久久综合97| 欧美伊久线香蕉线新在线| 久久精品二区| 亚洲私人影院| 欧美一区2区三区4区公司二百| 欧美一区二区三区久久精品茉莉花| 久久精品国产综合| 欧美成人精品影院| 亚洲精品乱码久久久久久| 一区二区三区国产精品| 先锋影音网一区二区| 久久综合导航| 欧美日韩一区二区三区在线观看免| 亚洲一区三区电影在线观看| 先锋影音国产一区| 久久久久久香蕉网| 久久久五月天| 一本色道久久综合狠狠躁篇的优点 | av成人免费在线观看| 日韩午夜中文字幕| 亚洲丝袜av一区| 久久国产精品色婷婷| 亚洲国产高清高潮精品美女| 一区二区三区免费在线观看| 久久激情视频| 欧美日韩免费网站| 亚洲电影第1页| 亚洲自拍偷拍麻豆| 欧美高清视频在线观看| 亚洲一区二区av电影| 欧美岛国激情| 国产一区二区三区高清 | 亚洲在线视频网站| 久久综合国产精品| 久久夜色精品国产亚洲aⅴ | 亚洲精品一区在线观看| 欧美福利网址| 亚洲一区二区三区精品在线 | 久久精品视频一| 欧美一区二区高清在线观看| 欧美国产精品人人做人人爱| 国产欧美视频一区二区三区| 亚洲精品一区在线观看香蕉| 久久精品视频99| 在线中文字幕一区| 免费观看日韩| 伊人一区二区三区久久精品| 亚洲一区二区3| 91久久精品一区二区三区| 亚洲精品国精品久久99热| 久久精品欧美日韩精品| 国产精品人成在线观看免费| 亚洲老司机av| 欧美国产丝袜视频| 久久福利电影| 国产视频综合在线| 小黄鸭视频精品导航| 99re这里只有精品6| 免费亚洲一区二区| 一区二区三区中文在线观看| 久久久久久高潮国产精品视| 亚洲一区二区精品在线观看| 欧美老女人xx| 亚洲乱码国产乱码精品精| 欧美顶级艳妇交换群宴| 久久天天狠狠| 欧美成人精品在线观看| 亚洲国产精品传媒在线观看| 老牛国产精品一区的观看方式| 亚洲免费网址| 国产偷久久久精品专区| 欧美怡红院视频| 欧美在线看片a免费观看| 国产在线欧美| 免费看亚洲片|