• 51. 模型动画动画路径


    直线:

    #include<d3d9.h>
    #include<d3dx9.h>
    #include<mmsystem.h>

    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")
    #pragma comment(lib, "winmm.lib")


    #define WINDOW_CLASS "UGPDX"
    #define WINDOW_NAME "Straight Line Animation"
    #define WINDOW_WIDTH 640
    #define WINDOW_HEIGHT 480
    #define FULLSCREEN 0

    // Function Prototypes...
    bool InitializeD3D();
    bool InitializeObjects();
    void RenderScene();
    void Shutdown();


    // Global window handle.
    HWND g_hwnd = 0;


    // Direct3D object and device.
    LPDIRECT3D9 g_D3D = NULL;
    LPDIRECT3DDEVICE9 g_D3DDevice = NULL;


    // Matrices.
    D3DXMATRIX g_projection;
    D3DXMATRIX g_worldMatrix;
    D3DXMATRIX g_ViewMatrix;


    // Display object.
    LPD3DXMESH g_model = NULL;


    //
    struct stVector
    {
    stVector() : x(0), y(0), z(0) {}
    float x, y, z;
    };


    // Path will hold the start and end position of our animation.
    stVector Path[4];
    stVector objPos;

    // CurrentPath will hold which of the two striaght line paths we are on.
    int CurrentPath = 1;

    // Used for time based calculations.
    float StartTime = 0;


    LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch(msg)
    {
    case WM_DESTROY:
    case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
    break;

    case WM_KEYUP:
    if(wParam == VK_ESCAPE) PostQuitMessage(0);
    break;
    }

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


    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmdLine, int show)
    {
    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
    GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
    WINDOW_CLASS, NULL };
    RegisterClassEx(&wc);

    // Create the application's window
    HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW,
    100, 100, WINDOW_WIDTH, WINDOW_HEIGHT,
    GetDesktopWindow(), NULL, wc.hInstance, NULL);

    // Show the window
    ShowWindow(hWnd, SW_SHOWDEFAULT);
    UpdateWindow(hWnd);

    // Record for global.
    g_hwnd = hWnd;

    // Initialize Direct3D
    if(InitializeD3D())
    {
    // Enter the message loop
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while(msg.message != WM_QUIT)
    {
    if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    else
    RenderScene();
    }
    }

    // Release any and all resources.
    Shutdown();

    // Unregister our window.
    UnregisterClass(WINDOW_CLASS, wc.hInstance);
    return 0;
    }


    bool InitializeD3D()
    {
    D3DDISPLAYMODE displayMode;

    // Create the D3D object.
    g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
    if(g_D3D == NULL) return false;

    // Get the desktop display mode.
    if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))
    return false;

    // Set up the structure used to create the D3DDevice
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));

    if(FULLSCREEN)
    {
    d3dpp.Windowed = FALSE;
    d3dpp.BackBufferWidth = WINDOW_WIDTH;
    d3dpp.BackBufferHeight = WINDOW_HEIGHT;
    }
    else
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = displayMode.Format;
    d3dpp.BackBufferCount = 1;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;


    // Create the D3DDevice
    if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hwnd,
    D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
    &d3dpp, &g_D3DDevice))) return false;

    // Initialize any objects we will be displaying.
    if(!InitializeObjects()) return false;

    return true;
    }


    bool InitializeObjects()
    {
    // Set default rendering states.
    g_D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    g_D3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);


    // Here we are setting our striaght line path.
    Path[0].x = -2.5f; Path[0].y = 1.0f; Path[0].z = 0.0f;
    Path[1].x = 2.5f; Path[1].y = 1.0f; Path[1].z = 0.0f;
    Path[2].x = 2.5f; Path[2].y = 1.0f; Path[2].z = 0.0f;
    Path[3].x = -2.5f; Path[3].y = 1.0f; Path[3].z = 0.0f;

    // Initialize the start time for this simulation.
    StartTime = (float)timeGetTime();


    // Create mesh.
    if(FAILED(D3DXCreateBox(g_D3DDevice, 1, 1, 1, &g_model, NULL)))
    return false;


    // Set the projection matrix.
    D3DXMatrixPerspectiveFovLH(&g_projection, D3DX_PI / 4,
    WINDOW_WIDTH/WINDOW_HEIGHT, 0.1f, 1000.0f);

    g_D3DDevice->SetTransform(D3DTS_PROJECTION, &g_projection);


    // Define camera information.
    D3DXVECTOR3 cameraPos(0.0f, 0.0f, -10.0f);
    D3DXVECTOR3 lookAtPos(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 upDir(0.0f, 1.0f, 0.0f);

    // Build view matrix.
    D3DXMatrixLookAtLH(&g_ViewMatrix, &cameraPos,
    &lookAtPos, &upDir);

    return true;
    }


    void RenderScene()
    {
    // Clear the backbuffer.
    g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
    D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

    // Begin the scene. Start rendering.
    g_D3DDevice->BeginScene();

    // Apply the view (camera).
    g_D3DDevice->SetTransform(D3DTS_VIEW, &g_ViewMatrix);

    // Update the time. Since we are using time based movements
    // and calculations we get the time, sub from the start time,
    // then multiply that by the speed of the simulation.
    float Scalar = (float)timeGetTime();
    Scalar = (Scalar - StartTime) * 0.003f;

    // Get the new object position by using a simple interpolation equation. If we are
    // in the first path, then we use the first path data, else the second path data.
    if(CurrentPath == 1)
    {
    // We must divide the scalar by the length of the path so our animation is
    // smooth and correct. Then we use the interpolation calculation to determine
    // the position.
    stVector diff;
    diff.x = Path[1].x - Path[0].x;
    diff.y = Path[1].y - Path[0].y;
    diff.z = Path[1].z - Path[0].z;

    float len = (float)sqrt((diff.x * diff.x +
    diff.y * diff.y +
    diff.z * diff.z));

    Scalar = Scalar / len;
    objPos.x = (Path[1].x - Path[0].x) * Scalar + Path[0].x;
    objPos.y = (Path[1].y - Path[0].y) * Scalar + Path[0].y;
    objPos.z = (Path[1].z - Path[0].z) * Scalar + Path[0].z;
    }
    else
    {
    stVector diff;
    diff.x = Path[3].x - Path[2].x;
    diff.y = Path[3].y - Path[2].y;
    diff.z = Path[3].z - Path[2].z;

    float len = (float)sqrt((diff.x * diff.x +
    diff.y * diff.y +
    diff.z * diff.z));

    Scalar = Scalar / len;
    objPos.x = (Path[3].x - Path[2].x) * Scalar + Path[2].x;
    objPos.y = (Path[3].y - Path[2].y) * Scalar + Path[2].y;
    objPos.z = (Path[3].z - Path[2].z) * Scalar + Path[2].z;
    }

    // If Scalar reaches 1.0f then that means we are at the end of the animation. We
    // simply reset the start time then increase the value that represents which path
    // we are on. Since we have only two paths we then check to make sure we dont go
    // over that value.
    if(Scalar >= 1.0f)
    {
    // Reset the start time.
    StartTime = (float)timeGetTime();

    // Move to the next path.
    CurrentPath++;

    // We only have 2 paths so make sure we don't go over that number.
    if(CurrentPath > 2) CurrentPath = 1;
    }

    D3DXMATRIX mat;
    D3DXMatrixTranslation(&mat, objPos.x, objPos.y, objPos.z);
    g_D3DDevice->SetTransform(D3DTS_WORLD, &mat);

    // Draw the model.
    g_model->DrawSubset(0);

    // End the scene. Stop rendering.
    g_D3DDevice->EndScene();

    // Display the scene.
    g_D3DDevice->Present(NULL, NULL, NULL, NULL);
    }


    void Shutdown()
    {
    if(g_D3DDevice != NULL) g_D3DDevice->Release();
    g_D3DDevice = NULL;

    if(g_D3D != NULL) g_D3D->Release();
    g_D3D = NULL;

    if(g_model != NULL) g_model->Release();
    g_model = NULL;
    }

    2. 曲线路径

     接下来要介绍的一种动画是曲线路径。该路径从点A到点B是取线而不是直线。用大量相互连接的小直线连接在一起就可以创建一条曲线。用的直线越多,曲线看上去就越平滑。这虽不完美,但为了非常接近完美就要用大量的数据。直线路径和曲线路径的差异在于后者使用了点A和点B两个点以及两个控制点,总计4个点。这类曲线即为三次方贝塞尔曲线。控制点用于将直线弯折者曲线。

      直线演示程序用到了两点和一个计算物体最终位置的比值。对于三次方贝塞尔曲线而言,要使用4个点和1个比值。曲线可以根据控制点的位置以任意方式弯曲扭转。像直线路径一样,0%意味着物体在点A,100%意味着物体在点B。计算曲线上点的位置的方程并不像直线的那样简单。

    程序清单13.6中的A代表点A,B代表点B,C1代表控制点1,C2代表控制点2。同样方程中S代表比值,S2代表比值的平方,S3代表比值的三次方。

    三次方贝塞尔曲线公式:Final = A * (1-S)3 + C1 * 3 * S * (1-S)2 + C2 * 3 * S2 * (1-S) + B * S3

     验证该例子的演示程序在本配套光盘上的CHAPTER13文件夹中,名为CurvePath(曲线路径)。为了更方便地创建该演示程序,可以只采用直线演示程序的代码,将其修改为曲线路径即可。CurvePath演示程序的全局部分如程序清单13.7所示。这里用包含了一些重载操作符3D矢量类来代表点,使用该类可以比在每个轴上分别处理要清晰得多。
    #include<d3d9.h>
    #include<d3dx9.h>
    #include<mmsystem.h>
    #include"Vector.h"

    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")
    #pragma comment(lib, "winmm.lib")


    #define WINDOW_CLASS "UGPDX"
    #define WINDOW_NAME "Curve Line Animation"
    #define WINDOW_WIDTH 640
    #define WINDOW_HEIGHT 480
    #define FULLSCREEN 0

    // Function Prototypes...
    bool InitializeD3D();
    bool InitializeObjects();
    void RenderScene();
    void Shutdown();


    // Global window handle.
    HWND g_hwnd = 0;


    // Direct3D object and device.
    LPDIRECT3D9 g_D3D = NULL;
    LPDIRECT3DDEVICE9 g_D3DDevice = NULL;


    // Matrices.
    D3DXMATRIX g_projection;
    D3DXMATRIX g_worldMatrix;
    D3DXMATRIX g_ViewMatrix;


    // Display object.
    LPD3DXMESH g_model = NULL;


    // Path will hold the start and end position of our animation.
    CVector3 Path[4];
    CVector3 objPos;


    // Used for time based calculations.
    float StartTime = 0;


    LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch(msg)
    {
    case WM_DESTROY:
    case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
    break;

    case WM_KEYUP:
    if(wParam == VK_ESCAPE) PostQuitMessage(0);
    break;
    }

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


    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmdLine, int show)
    {
    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
    GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
    WINDOW_CLASS, NULL };
    RegisterClassEx(&wc);

    // Create the application's window
    HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW,
    100, 100, WINDOW_WIDTH, WINDOW_HEIGHT,
    GetDesktopWindow(), NULL, wc.hInstance, NULL);

    // Show the window
    ShowWindow(hWnd, SW_SHOWDEFAULT);
    UpdateWindow(hWnd);

    // Record for global.
    g_hwnd = hWnd;

    // Initialize Direct3D
    if(InitializeD3D())
    {
    // Enter the message loop
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while(msg.message != WM_QUIT)
    {
    if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    else
    RenderScene();
    }
    }

    // Release any and all resources.
    Shutdown();

    // Unregister our window.
    UnregisterClass(WINDOW_CLASS, wc.hInstance);
    return 0;
    }


    bool InitializeD3D()
    {
    D3DDISPLAYMODE displayMode;

    // Create the D3D object.
    g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
    if(g_D3D == NULL) return false;

    // Get the desktop display mode.
    if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))
    return false;

    // Set up the structure used to create the D3DDevice
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));

    if(FULLSCREEN)
    {
    d3dpp.Windowed = FALSE;
    d3dpp.BackBufferWidth = WINDOW_WIDTH;
    d3dpp.BackBufferHeight = WINDOW_HEIGHT;
    }
    else
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = displayMode.Format;
    d3dpp.BackBufferCount = 1;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;


    // Create the D3DDevice
    if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hwnd,
    D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
    &d3dpp, &g_D3DDevice))) return false;

    // Initialize any objects we will be displaying.
    if(!InitializeObjects()) return false;

    return true;
    }


    bool InitializeObjects()
    {
    // Set default rendering states.
    g_D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    g_D3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);


    // Here we are setting our striaght line path.
    Path[0].x = -2.0f; Path[0].y = 1.0f; Path[0].z = 0.0f;
    Path[1].x = -1.0f; Path[1].y = 0.0f; Path[1].z = 0.0f;
    Path[2].x = 1.0f; Path[2].y = 0.0f; Path[2].z = 0.0f;
    Path[3].x = 2.0f; Path[3].y = 1.0f; Path[3].z = 0.0f;

    // Initialize the start time for this simulation.
    StartTime = (float)timeGetTime();

    // Create mesh.
    if(FAILED(D3DXCreateBox(g_D3DDevice, 1, 1, 1, &g_model, NULL)))
    return false;

    D3DXMatrixPerspectiveFovLH(&g_projection, D3DX_PI / 4,
    WINDOW_WIDTH/WINDOW_HEIGHT, 0.1f, 1000.0f);

    g_D3DDevice->SetTransform(D3DTS_PROJECTION, &g_projection);

    D3DXVECTOR3 cameraPos(0.0f, 0.0f, -10.0f);
    D3DXVECTOR3 lookAtPos(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 upDir(0.0f, 1.0f, 0.0f);

    D3DXMatrixLookAtLH(&g_ViewMatrix, &cameraPos, &lookAtPos, &upDir);

    return true;
    }


    CVector3 CalcBezierCurvePos(CVector3 start, CVector3 cnt1,
    CVector3 cnt2, CVector3 end, float Scalar)
    {
    CVector3 out;

    // Here we have a formula that is used to calculate a position on the cubic bezier curve
    // based on the Scalar value.
    out = start * (1.0f - Scalar) * (1.0f - Scalar) * (1.0f - Scalar) +
    cnt1 * 3.0f * Scalar * (1.0f - Scalar) * (1.0f - Scalar) +
    cnt2 * 3.0f * Scalar * Scalar * (1.0f - Scalar) +
    end * Scalar * Scalar * Scalar;

    return out;
    }


    void RenderScene()
    {
    g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
    D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

    g_D3DDevice->BeginScene();

    g_D3DDevice->SetTransform(D3DTS_VIEW, &g_ViewMatrix);

    // First we must calculate the object position along the curve. Since we are using time
    // based movements for everything we first get the time in seconds. The value 0.001 will
    // act as the speed of the animation.
    float Time = (float)timeGetTime();
    Time = (Time - StartTime) * 0.003f;

    // Next we take that value and sin() it, add 1, then divide by half. This will give us
    // a value between 0 and 1. 0 is the start of the curve, 1 is the end, and anything between
    // the two is on the curve. Using a sine wave will allow us to loop the animation back
    // and forward.
    float Scalar = (((float)sin(Time)) + 1.0f) * 0.5f;

    // Now we calculate the position on the curve by taking the curve path data and
    // using the Scalar to dictate where on that curve the position lies.
    objPos = CalcBezierCurvePos(Path[0], Path[1], Path[2], Path[3], Scalar);

    D3DXMATRIX mat;
    D3DXMatrixTranslation(&mat, objPos.x, objPos.y, objPos.z);
    g_D3DDevice->SetTransform(D3DTS_WORLD, &mat);

    g_model->DrawSubset(0);

    g_D3DDevice->EndScene();

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


    void Shutdown()
    {
    if(g_D3DDevice != NULL) g_D3DDevice->Release();
    g_D3DDevice = NULL;

    if(g_D3D != NULL) g_D3D->Release();
    g_D3D = NULL;

    if(g_model != NULL) g_model->Release();
    g_model = NULL;
    }
    3. 圆形路径
    要介绍的最后一种路径是圆形路径。物体将在一个完整的圆上围绕着一个轴移动。为了定义圆形路径,需要知道圆心、半径、起始点、物体移动的平面法线、平面上的u和v两个正交矢量。计算矢量u和平面法线的外积(或叉积)就可得到矢量v。由矢量u的长度可计算出半径。圆形、平面法线和起始点都是定义圆形路径要用到的矢量。
      一旦有了u、v、半径和圆心位置,就可以根据提供的0(0%)和1(100%)之间的数值计算圆上任意点的位置,就像前面在其他函数中所做的一样。本例中,比值作为沿着圆上的一个角度。可以将这个角度值转换成半径,在计算中使用该转换后的值。例子如程序清单13.10所示,它包含了一个名为CalcCirclePos()的函数。像计算三次方贝塞尔曲线上点的位置的CalcBezierCurvePos()函数一样,通过该函数可以计算圆上点的位置。
    #include<d3d9.h>
    #include<d3dx9.h>
    #include<mmsystem.h>
    #include"Vector.h"

    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")
    #pragma comment(lib, "winmm.lib")

    #define WINDOW_CLASS "UGPDX"
    #define WINDOW_NAME "Circle Path Animation"
    #define WINDOW_WIDTH 640
    #define WINDOW_HEIGHT 480
    #define FULLSCREEN 0
    #define M_PI 3.141592654f

    // Function Prototypes...
    bool InitializeD3D();
    bool InitializeObjects();
    void RenderScene();
    void Shutdown();

    // Global window handle.
    HWND g_hwnd = 0;

    // Direct3D object and device.
    LPDIRECT3D9 g_D3D = NULL;
    LPDIRECT3DDEVICE9 g_D3DDevice = NULL;

    // Matrices.
    D3DXMATRIX g_projection;
    D3DXMATRIX g_worldMatrix;
    D3DXMATRIX g_ViewMatrix;

    // Display object.
    LPD3DXMESH g_model = NULL;

    // Center of circle path.
    CVector3 g_center(0.0f, 0.0f, 0.0f);

    // Start position of the animation and the point in the plane (direction).
    CVector3 start(2.0f, 0.0f, 0.0f);
    CVector3 planeDirection(0.0f, 0.0f, 1.0f);

    // u and v are orthonormal vectors in the plane. 正规化的向量u,v
    // u points from the center to the start and v is perpendicular(正交) to u.
    CVector3 g_u, g_v;

    // Circle's radius.
    float g_radius = 0;

    // objPos will hold the objects current position on the curve path.
    CVector3 objPos;

    // Used for time based calculations.
    float StartTime = 0;


    LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch(msg)
    {
    case WM_DESTROY:
    case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
    break;

    case WM_KEYUP:
    if(wParam == VK_ESCAPE) PostQuitMessage(0);
    break;
    }

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


    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmdLine, int show)
    {
    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
    GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
    WINDOW_CLASS, NULL };
    RegisterClassEx(&wc);

    // Create the application's window
    HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW,
    100, 100, WINDOW_WIDTH, WINDOW_HEIGHT,
    GetDesktopWindow(), NULL, wc.hInstance, NULL);

    // Show the window
    ShowWindow(hWnd, SW_SHOWDEFAULT);
    UpdateWindow(hWnd);

    // Record for global.
    g_hwnd = hWnd;

    // Initialize Direct3D
    if(InitializeD3D())
    {
    // Enter the message loop
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while(msg.message != WM_QUIT)
    {
    if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    else
    RenderScene();
    }
    }

    // Release any and all resources.
    Shutdown();

    // Unregister our window.
    UnregisterClass(WINDOW_CLASS, wc.hInstance);
    return 0;
    }


    bool InitializeD3D()
    {
    D3DDISPLAYMODE displayMode;

    // Create the D3D object.
    g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
    if(g_D3D == NULL) return false;

    // Get the desktop display mode.
    if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))
    return false;

    // Set up the structure used to create the D3DDevice
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));

    if(FULLSCREEN)
    {
    d3dpp.Windowed = FALSE;
    d3dpp.BackBufferWidth = WINDOW_WIDTH;
    d3dpp.BackBufferHeight = WINDOW_HEIGHT;
    }
    else
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = displayMode.Format;
    d3dpp.BackBufferCount = 1;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    // Create the D3DDevice
    if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hwnd,
    D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
    &d3dpp, &g_D3DDevice))) return false;

    // Initialize any objects we will be displaying.
    if(!InitializeObjects()) return false;

    return true;
    }


    bool InitializeObjects()
    {
    // Set default rendering states.
    g_D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    g_D3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

    // First we make sure that the center, start pos, and point in the plane are colinear(共线).
    CVector3 planeNormal;
    planeNormal.CrossProduct(start - g_center, planeDirection - g_center);

    // Check if they are colinear.
    if(planeNormal.GetLength() < 0.01f)
    {
    MessageBox(0, "Circle path must be colinear!", "Error...", MB_OK);
    return false;
    }

    // If they are then we normalize and continue the calculation.
    planeNormal.Normal();

    // The radius will be determined by where the center of the circle is and the start
    // position of the animation. The u and v are orthonormal vectors. u goes from
    // the start to center while v is perpendicular to the u.
    g_radius = (start - g_center).GetLength();
    g_u = (start - g_center);
    g_u.Normal();
    g_v.CrossProduct(g_u, planeNormal);

    // Initialize the start time for this simulation.
    StartTime = (float)timeGetTime();


    // Create mesh.
    if(FAILED(D3DXCreateBox(g_D3DDevice, 1, 1, 1, &g_model, NULL)))
    return false;


    // Set the projection matrix.
    D3DXMatrixPerspectiveFovLH(&g_projection, D3DX_PI / 4,
    WINDOW_WIDTH/WINDOW_HEIGHT, 0.1f, 1000.0f);

    g_D3DDevice->SetTransform(D3DTS_PROJECTION, &g_projection);

    // Define camera information.
    D3DXVECTOR3 cameraPos(0.0f, 0.0f, -10.0f);
    D3DXVECTOR3 lookAtPos(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 upDir(0.0f, 1.0f, 0.0f);

    // Build view matrix.
    D3DXMatrixLookAtLH(&g_ViewMatrix, &cameraPos,
    &lookAtPos, &upDir);

    return true;
    }


    CVector3 CalcCirclePos(float angle, CVector3 center, CVector3 u,
    CVector3 v, float radius)
    {
    float newAngle = angle * (float)(M_PI / 180);
    return center + u * radius * float(cos(newAngle)) + v * radius * float(sin(newAngle));
    }


    void RenderScene()
    {
    // Clear the backbuffer.
    g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
    D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

    // Begin the scene. Start rendering.
    g_D3DDevice->BeginScene();

    // Apply the view (camera).
    g_D3DDevice->SetTransform(D3DTS_VIEW, &g_ViewMatrix);

    // First we must calculate the object position along the
    // circle. Since we are using time based movements for
    // everything we first get the time in seconds. The value 0.06 will
    // act as the speed of the animation.
    float Time = (float)timeGetTime();
    Time = (Time - StartTime) * 0.06f;

    // Now we calculate the position on the curve by taking the circle path data and
    // using the scalar Time to dictate where on that circle (the angle) the position lies.
    objPos = CalcCirclePos(Time, g_center, g_u, g_v, g_radius);

    D3DXMATRIX mat;
    D3DXMatrixTranslation(&mat, objPos.x, objPos.y, objPos.z);
    g_D3DDevice->SetTransform(D3DTS_WORLD, &mat);

    // Draw the model.
    g_model->DrawSubset(0);

    // End the scene. Stop rendering.
    g_D3DDevice->EndScene();

    // Display the scene.
    g_D3DDevice->Present(NULL, NULL, NULL, NULL);
    }


    void Shutdown()
    {
    if(g_D3DDevice != NULL) g_D3DDevice->Release();
    g_D3DDevice = NULL;

    if(g_D3D != NULL) g_D3D->Release();
    g_D3D = NULL;

    if(g_model != NULL) g_model->Release();
    g_model = NULL;
    }
  • 相关阅读:
    推荐两款好用的反编译工具(Luyten,Jadx)
    在windows上运行linux
    Spring IOC的理解
    Django 13 admin和auth系统、权限问题
    Django 12 中间件、上下文处理器和admin后台
    Django 11 form表单(状态保持session、form表单及注册实现)
    Django 10 GET和POST(HttpRequest对象,GET和POST请求,文件上传,HttpResponse对象的cookie)
    Django 09 博客小案例
    Django 解答 01 (pycharm创建项目)
    Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)
  • 原文地址:https://www.cnblogs.com/kex1n/p/2203949.html
Copyright © 2020-2023  润新知