• <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>

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

            Timing in Animation and Movement(6)

            Creating In−Game Cinematic Sequences

            Using time−based animation is crucial to achieving smooth playback, but what good could using time−based movement possibly do? Sure, moving a few objects around a set path is neat, but is that all you can do? The answer is a resounding no! There's much more you can do with time−based movement, including creating in−game cinematic sequences, like those from games such as Silicon Knights' Eternal Darkness: Sanity's Requiem In Eternal Darkness, the player is treated to animation sequences that play out using the game's 3D engine.

            To use a cinematic camera, you can rely on the techniques you read about earlier in this chapter, and you can use the pre−calculated animation sequences, it's only a matter of plotting out the path that your camera will follow over time. Mix that with a complete
            pre−calculated animation, and you've got yourself a complete in−game cinematic engine!

            Rather than reiterate what you already saw in this chapter, I'll leave it up to you to check out the Cinematic demo, which shows a small cinematic sequence. In a nutshell, the demo merely loads a series of keys (using the .X path parser class) that represent the paths the camera follows. In every frame, the position of the camera is calculated using the keys, and the viewport is oriented. Then the pre−calculated animation is updated and the entire scene is rendered.

            As shown in Figure 2.12, you get to see how complex routes can be applied to cameras in order to traverse a 3D scene in real time. This technique of moving a camera is perfect to use for an in−game cinematic system.

            Figure 2.12: The cinematic camera demo adds a moving camera to the Route demo.

             

            Route.x:

            xof 0303txt 0032
            template Path {
            <F8569BED-53B6-4923-AF0B-59A09271D556>
            DWORD Type; // 0=straight, 1=curved
            Vector Start;
            Vector Point1;
            Vector Point2;
            Vector End;
            }
            template Route {
            <18AA1C92-16AB-47a3-B002-6178F9D2D12F>
            DWORD NumPaths;
            array Path Paths[NumPaths];
            }
            Route Robot {
            5; // 5 paths
              0; // Straight path type
            0.0, 10.0, 0.0; // Start
            0.0, 0.0, 0.0; // Unused
            0.0, 0.0, 0.0; // Unused
            0.0, 10.0, 150.0;, // End
              1; // Curved path type
            0.0, 10.0, 150.0; // Start
            75.0, 10.0, 150.0; // Point1
            150.0, 10.0, 75.0; // Point2
            150.0, 10.0, 0.0;, // End
              1; // Curved path type
            150.0, 10.0, 0.0; // Start
            150.0, 10.0, -75.0; // Point1
            75.0, 10.0, -150.0; // Point2
            0.0, 10.0, -150.0;, // End
              0; // Straight path type
            0.0, 10.0, -150.0; // Start
            0.0, 0.0, 0.0; // Unused
            0.0, 0.0, 0.0; // Unused
            -150.0, 10.0, 75.0;, // End
              0; // Straight path type
            -150.0, 10.0, 75.0; // Start
            0.0, 10.0, 0.0; // Unused
            0.0, 10.0, 0.0; // Unused
            0.0, 10.0, 0.0;; // End
            }
            Route Camera {
            4; // 4 paths
              1;  // Curved path type
            0.0, 80.0, 300.0; // Start
            150.0, 80.0, 300.0; // Point1
            300.0, 80.0, 150.0; // Point2
            300.0, 80.0, 0.0;, // End
              1;  // Curved path type
            300.0, 80.0, 0.0; // Start
            300.0, 80.0, -150.0; // Point1
            151.0, 80.0, -300.0; // Point2
            0.0, 80.0, -300.0;, // End
              1;  // Curved path type
            0.0, 80.0, -300.0; // Start
            -150.0, 80.0, -300.0; // Point1
            -300.0, 80.0, -150.0; // Point2
            -300.0, 80.0, 0.0;, // End
              1;  // Curved path type
            -300.0, 80.0, 0.0; // Start
            -300.0, 80.0, 150.0; // Point1
            -150.0, 80.0, 300.0; // Point2
            0.0, 80.0, 300.0;; // End
            }
            Route Target {
            5; // 5 paths
              0; // Straight path type
            0.0, 10.0, 0.0; // Start
            0.0, 0.0, 0.0; // Unused
            0.0, 0.0, 0.0; // Unused
            0.0, 10.0, 150.0;, // End
              1; // Curved path type
            0.0, 10.0, 150.0; // Start
            75.0, 10.0, 150.0; // Point1
            150.0, 10.0, 75.0; // Point2
            150.0, 10.0, 0.0;, // End
              1; // Curved path type
            150.0, 10.0, 0.0; // Start
            150.0, 10.0, -75.0; // Point1
            75.0, 10.0, -150.0; // Point2
            0.0, 10.0, -150.0;, // End
              0; // Straight path type
            0.0, 10.0, -150.0; // Start
            0.0, 0.0, 0.0; // Unused
            0.0, 0.0, 0.0; // Unused
            -150.0, 10.0, 75.0;, // End
              0; // Straight path type
            -150.0, 10.0, 75.0; // Start
            0.0, 10.0, 0.0; // Unused
            0.0, 10.0, 0.0; // Unused
            0.0, 10.0, 0.0;; // End
            }

            WinMain.cpp:

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

            struct sBackdropVertex
            {
                
            float x, y, z, rhw;
                
            float u, v;        
            };

            #define BACKDROP_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)

            ////////////////////////////////////////////////////////////////////////////////////////////////

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;
            IDirect3DVertexBuffer9
            *    g_backdrop_vb;
            IDirect3DTexture9
            *        g_backdrop_texture;
            D3DXMESHCONTAINER_EX
            *    g_robot_mesh_container;
            D3DXMESHCONTAINER_EX
            *    g_ground_mesh_container;

            cXRouteParser            g_route_parser;

            D3DXVECTOR3 g_robot_pos, g_robot_last_pos;    

            const char CLASS_NAME[] = "CinematicClass";
            const char CAPTION[]    = "Cinematic 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_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;

                
            if(FAILED(load_mesh(&g_ground_mesh_container, g_device, "..\\Data\\ground.x""..\\Data\\"00)))
                    
            return false;

                
            // create the backdrop

                sBackdropVertex backdrop_verts[
            4= 
                {
                    {   
            0.0f,   0.01.01.0f0.0f0.0f },
                    { 
            640.0f,   0.01.01.0f1.0f0.0f },
                    {   
            0.0f480.01.01.0f0.0f1.0f },
                    { 
            640.0f480.01.01.0f1.0f1.0f }            
                };

                g_device
            ->CreateVertexBuffer(sizeof(backdrop_verts), D3DUSAGE_WRITEONLY, BACKDROP_FVF, D3DPOOL_DEFAULT,
                                             
            &g_backdrop_vb, NULL);

                
            char* ptr;

                g_backdrop_vb
            ->Lock(00, (void**)&ptr, 0);
                memcpy(ptr, backdrop_verts, 
            sizeof(backdrop_verts));
                g_backdrop_vb
            ->Unlock();

                D3DXCreateTextureFromFile(g_device, 
            "..\\Data\\Backdrop.bmp"&g_backdrop_texture);

                
            // 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);

                
            if(! g_route_parser.load("..\\Data\\Route.x"))
                    
            return false;

                
            return true;
            }

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

                release_com(g_backdrop_vb);
                release_com(g_backdrop_texture);

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

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

                
            // calculate the position in which to place the robot along the path based on time and robot_route_length of route.
                float robot_route_length = g_route_parser.get_length("Robot");
                DWORD robot_dist 
            = (curr_time - start_time) / 10;
                robot_dist 
            %= ((DWORD)robot_route_length + 1);

                
            // get the camera's position
                float camera_route_length = g_route_parser.get_length("Camera");
                DWORD camera_dist 
            = (curr_time - start_time) / 20;
                camera_dist 
            %= ((DWORD) camera_route_length + 1);

                
            // get the target's position
                float target_route_length = g_route_parser.get_length("Target");
                DWORD target_dist 
            = (curr_time - start_time) / 10;
                target_dist 
            %= ((DWORD) target_route_length + 1);

                
            // update the positions of the robot
                g_robot_last_pos = g_robot_pos;
                g_route_parser.locate(
            "Robot", (float)robot_dist, &g_robot_pos);

                
            // get camera and target position
                D3DXVECTOR3 camera_pos, target_pos;
                g_route_parser.locate(
            "Camera", (float)camera_dist, &camera_pos);
                g_route_parser.locate(
            "Target", (float)target_dist, &target_pos);

                
            // set a view transformation matrix
                D3DXMATRIX  mat_view;    
                D3DXVECTOR3 up(
            0.0f1.0f0.0f);
                D3DXMatrixLookAtLH(
            &mat_view, &camera_pos, &target_pos, &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();

                
            // draw the backdrop
                g_device->SetFVF(BACKDROP_FVF);
                g_device
            ->SetStreamSource(0, g_backdrop_vb, 0sizeof(sBackdropVertex));
                g_device
            ->SetTexture(0, g_backdrop_texture);
                g_device
            ->DrawPrimitive(D3DPT_TRIANGLESTRIP, 02);

                g_device
            ->SetRenderState(D3DRS_LIGHTING, TRUE);

                
            // draw the ground mesh
                D3DXMATRIX mat_world;
                D3DXMatrixIdentity(
            &mat_world);
                g_device
            ->SetTransform(D3DTS_WORLD, &mat_world);
                draw_mesh(g_ground_mesh_container);

                
            // calculate the rotation of the robots based on last known position, and update last position once done.
                D3DXVECTOR3 diff = g_robot_pos - g_robot_last_pos;
                
            float rot_x =  atan2(diff.y, diff.z);
                
            float rot_y = -atan2(diff.z, diff.x);

                
            // rotate the robot to point in direction of movement
                D3DXMatrixRotationYawPitchRoll(&mat_world, rot_y, rot_x, 0.0f);

                
            // position the robot by setting the coordinates directly in the world transformation matrix
                mat_world._41 = g_robot_pos.x;
                mat_world._42 
            = g_robot_pos.y;
                mat_world._43 
            = g_robot_pos.z;
                g_device
            ->SetTransform(D3DTS_WORLD, &mat_world);

                draw_mesh(g_robot_mesh_container);

                g_device
            ->SetRenderState(D3DRS_LIGHTING, FALSE);

                g_device
            ->EndScene();

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

            download source file


            posted on 2008-04-21 18:23 lovedday 閱讀(360) 評(píng)論(0)  編輯 收藏 引用


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


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評(píng)論

            久久天堂AV综合合色蜜桃网| 久久精品国产一区二区三区不卡| 一本一本久久a久久综合精品蜜桃| 久久影院综合精品| 99久久精品国产一区二区蜜芽 | 潮喷大喷水系列无码久久精品| 久久精品国产久精国产| 手机看片久久高清国产日韩 | 久久人人爽人人爽人人AV东京热| 久久96国产精品久久久| 久久这里都是精品| 伊人色综合久久| 欧美丰满熟妇BBB久久久| 欧美久久亚洲精品| 亚洲一区中文字幕久久| 久久精品日日躁夜夜躁欧美| 国产L精品国产亚洲区久久| 99久久精品免费看国产一区二区三区| 91久久精品国产成人久久| 亚洲天堂久久久| 久久精品国产99久久香蕉| 久久99精品国产| 久久久久国产精品熟女影院| 99久久国产亚洲综合精品| 久久国产成人精品国产成人亚洲| 久久99国产精一区二区三区| 久久国产欧美日韩精品| 亚洲国产成人久久一区WWW| 99久久99久久精品国产| 国产一级持黄大片99久久| 97久久久精品综合88久久| 久久香蕉国产线看观看精品yw| 久久久久99这里有精品10| 青青草国产97免久久费观看| 国产精品嫩草影院久久| 丁香五月综合久久激情| 一本伊大人香蕉久久网手机| 色综合久久中文色婷婷| 国产精品欧美久久久久无广告 | 一97日本道伊人久久综合影院| 欧美精品福利视频一区二区三区久久久精品 |