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

天行健 君子當(dāng)自強(qiá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) 評(píng)論(0)  編輯 收藏 引用


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


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

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

搜索

最新評(píng)論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美影院一区| 亚洲电影免费观看高清完整版在线观看 | 欧美精品免费观看二区| 亚洲国产成人一区| 亚洲国产精品一区二区www在线| 久久久久久夜精品精品免费| 亚洲福利视频免费观看| 91久久精品国产| 欧美亚州一区二区三区 | 99re这里只有精品6| 亚洲精品资源美女情侣酒店| 国产精品区一区二区三区| 久久国产精彩视频| 美腿丝袜亚洲色图| 亚洲免费伊人电影在线观看av| 亚洲欧美日韩人成在线播放| 国内偷自视频区视频综合| 欧美激情成人在线| 欧美日韩中文字幕综合视频| 久久国产精品久久久久久| 猛男gaygay欧美视频| 亚洲午夜视频在线| 欧美一级在线视频| 亚洲卡通欧美制服中文| 亚洲欧美国内爽妇网| 亚洲国产精品一区| 亚洲一区亚洲| 亚洲免费成人| 久久国产直播| 亚洲欧美日韩专区| 久久精品视频播放| 午夜精品国产更新| 欧美成人中文字幕| 久久免费国产精品1| 欧美日韩在线不卡一区| 美女免费视频一区| 国产精品一区二区在线观看不卡| 欧美承认网站| 国产综合精品一区| 亚洲无亚洲人成网站77777| 亚洲精品欧美| 久久琪琪电影院| 久久都是精品| 国产精品美女久久久久久免费| 欧美激情在线观看| 136国产福利精品导航| 欧美在线日韩在线| 性欧美大战久久久久久久免费观看| 欧美国产一区二区三区激情无套| 久久久久久香蕉网| 国产亚洲精品自拍| 午夜电影亚洲| 欧美亚洲视频| 国产欧美91| 亚洲永久精品大片| 午夜精品久久久久久久久久久 | 亚洲综合视频1区| 亚洲一区亚洲二区| 国产精品久久久久aaaa樱花| 99国产精品久久久久久久| 艳妇臀荡乳欲伦亚洲一区| 欧美国产日韩视频| 亚洲精品乱码| 国产精品99久久久久久久vr| 欧美日韩第一页| 日韩亚洲欧美一区二区三区| 亚洲视频精选在线| 国产精品分类| 亚洲欧美精品伊人久久| 久久精品国产久精国产爱| 国模套图日韩精品一区二区| 久久久91精品国产一区二区精品| 久久一区中文字幕| 亚洲欧洲一区二区在线观看| 欧美激情免费在线| 一区二区欧美激情| 欧美一区二区三区喷汁尤物| 国精品一区二区三区| 玖玖精品视频| 日韩视频在线一区二区| 午夜免费日韩视频| 黄色成人av在线| 欧美激情一二三区| 亚洲视频第一页| 久久伊人免费视频| 亚洲精品久久久蜜桃| 欧美午夜一区| 久久九九99视频| 亚洲品质自拍| 欧美在线不卡| 91久久精品国产91性色| 国产精品久久久久久久久久久久久| 欧美一区二区三区在线观看| 欧美不卡在线视频| 亚洲欧美日韩网| 樱桃视频在线观看一区| 亚洲香蕉伊综合在人在线视看| 亚洲黄色免费| 国产精品扒开腿做爽爽爽软件| 久久精品99无色码中文字幕| 亚洲黄色一区二区三区| 午夜天堂精品久久久久| 亚洲国产三级网| 国产区日韩欧美| 欧美激情一区二区三区不卡| 欧美一级午夜免费电影| 亚洲理论在线观看| 欧美jjzz| 久久精品道一区二区三区| 99精品视频免费| 狠狠色丁香婷综合久久| 国产精品成人一区二区艾草| 麻豆成人小视频| 欧美伊人久久久久久午夜久久久久 | 亚洲午夜久久久久久久久电影院 | 久久久久久精| 亚洲一区二区在线免费观看视频| 亚洲成色www久久网站| 久久动漫亚洲| 亚洲欧美一区二区三区久久 | 亚洲成人在线| 国产日韩欧美在线| 国产精品久久久久久久久久久久久久 | 欧美成人情趣视频| 欧美综合国产精品久久丁香| 亚洲色图在线视频| 亚洲另类自拍| 亚洲人成7777| 亚洲国产日韩在线| 亚洲国产精品va在线观看黑人| 国产日韩欧美在线一区| 国产精品久久一区二区三区| 欧美精品一区二区三区视频| 美女诱惑黄网站一区| 久久青青草综合| 麻豆精品精品国产自在97香蕉| 欧美一区国产一区| 新狼窝色av性久久久久久| 亚洲图片你懂的| 亚洲午夜高清视频| 亚洲一区二区三区精品动漫| 亚洲视频网站在线观看| 亚洲视频一区在线观看| 亚洲影视中文字幕| 午夜精品剧场| 久久精品女人天堂| 久久一日本道色综合久久| 久久久精品五月天| 老司机67194精品线观看| 免费h精品视频在线播放| 欧美大片91| 欧美色视频一区| 国产精品视频在线观看| 国产婷婷色一区二区三区| 国内精品免费在线观看| 亚洲高清在线视频| 99热免费精品| 欧美一区二区三区免费在线看 | 一区视频在线看| 91久久精品国产91久久| 中国av一区| 性视频1819p久久| 久久免费精品日本久久中文字幕| 欧美aa在线视频| 亚洲美女视频网| 午夜精品福利在线| 久久综合色8888| 欧美日韩国产丝袜另类| 国产日韩欧美成人| 91久久精品网| 亚洲欧美日本精品| 美女精品在线| 9久re热视频在线精品| 欧美在线网址| 欧美精品久久久久久| 国产啪精品视频| 亚洲精品日产精品乱码不卡| 亚洲欧美日韩第一区| 蜜臀av一级做a爰片久久| 亚洲精品视频在线看| 亚洲欧美在线免费观看| 免费成人av在线| 国产欧美 在线欧美| 亚洲精品美女91| 久久国产精品久久精品国产| 亚洲激情在线激情| 欧美影院视频| 欧美网站在线观看| 国产一区在线免费观看| 在线电影一区| 亚洲欧美不卡| 欧美激情精品久久久久久大尺度| 亚洲无毛电影| 欧美激情中文不卡| 伊人色综合久久天天五月婷| 亚洲欧美在线一区| 亚洲另类在线视频| 欧美波霸影院| 亚洲高清影视| 久久综合福利|