Advertisement
Guest User

Fixed time step

a guest
Aug 5th, 2013
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.64 KB | None | 0 0
  1. #define D3D_DEBUG_INFO          1
  2. #define WIN32_LEAN_AND_MEAN
  3.  
  4. #include <Windows.h>
  5. #include <d3d9.h>
  6. #include <d3dx9.h>
  7. #include <vector>
  8. #include <memory>
  9. #include <array>
  10. #include <ctime>
  11.  
  12. typedef unsigned long long uint64;
  13.  
  14. const SIZE WIN_DIM   = { 600, 600 };
  15. HWND hwnd                           = NULL;;
  16. LPDIRECT3D9       d3d9              = NULL;
  17. LPDIRECT3DDEVICE9 d3d9device        = NULL;
  18.  
  19. class Timer
  20. {
  21. private:
  22.     uint64 lastTime;
  23.     uint64 currTime;
  24.  
  25.     uint64 getRealTime()
  26.     {
  27.         uint64 time;
  28.         QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&time));
  29.         return time;
  30.     }
  31.  
  32.     void updateBy(uint64 t)
  33.     {
  34.         currTime += t;
  35.     }
  36.  
  37. public:
  38.     Timer()
  39.         : lastTime(0ULL), currTime(0ULL)
  40.     {
  41.     }
  42.  
  43.     void update()
  44.     {
  45.         auto timeNow = getRealTime();
  46.         auto diff    = timeNow - lastTime;
  47.         lastTime     = timeNow;
  48.         updateBy(diff);
  49.     }
  50.  
  51.     uint64 get() const { return currTime; }
  52. };
  53.  
  54. Timer gTimer;
  55.  
  56. float randfr(float l, float h)
  57. {
  58.     return l + (float)rand()/((float)RAND_MAX/(h-l));
  59. }
  60.  
  61. struct Vertex
  62. {
  63.     D3DXVECTOR3 pos;
  64. };
  65.  
  66. class Drawer
  67. {
  68. private:
  69.     LPDIRECT3DVERTEXBUFFER9      vBuffer;
  70.     LPDIRECT3DINDEXBUFFER9       iBuffer;
  71.     LPDIRECT3DVERTEXDECLARATION9 vDeclaration;
  72.     std::size_t                  maxVertices;
  73.     std::vector<Vertex>          vVertices;
  74. public:
  75.     Drawer()
  76.     {
  77.         maxVertices = 1000u;
  78.         HRESULT hr;
  79.         hr = d3d9device->CreateVertexBuffer(sizeof(Vertex) * maxVertices, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &vBuffer, nullptr);
  80.         if(FAILED(hr))
  81.         {
  82.             MessageBox(0, TEXT("CreateVertexBuffer() failed!"), 0, MB_OK);
  83.         }
  84.  
  85.         hr = d3d9device->CreateIndexBuffer(sizeof(USHORT) * ((maxVertices / 4) * 6), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &iBuffer, nullptr);
  86.         if(FAILED(hr))
  87.         {
  88.             MessageBox(0, TEXT("CreateIndexBuffer() failed!"), 0, MB_OK);
  89.         }
  90.  
  91.         D3DVERTEXELEMENT9 vertexElements[] =
  92.         {
  93.             {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
  94.             D3DDECL_END()
  95.         };
  96.         hr = d3d9device->CreateVertexDeclaration(vertexElements, &vDeclaration);
  97.         if(FAILED(hr))
  98.         {
  99.             MessageBox(0, TEXT("CreateVertexDeclaration() failed!"), 0, MB_OK);
  100.         }
  101.  
  102.         int index       = 0;
  103.         USHORT* indices = nullptr;
  104.         iBuffer->Lock(0, 0, reinterpret_cast<LPVOID*>(&indices), D3DLOCK_DISCARD);
  105.         for(USHORT vertex = 0; vertex < static_cast<USHORT>(maxVertices); vertex += 4)
  106.         {
  107.             indices[index]     = vertex;
  108.             indices[index + 1] = vertex + 1;
  109.             indices[index + 2] = vertex + 3;
  110.             indices[index + 3] = vertex + 1;
  111.             indices[index + 4] = vertex + 2;
  112.             indices[index + 5] = vertex + 3;
  113.             index += 6;
  114.         }
  115.         iBuffer->Unlock();
  116.     }
  117.  
  118.     ~Drawer()
  119.     {
  120.         release();
  121.     }
  122.     void release()
  123.     {
  124.         vBuffer->Release();
  125.         iBuffer->Release();
  126.         vDeclaration->Release();
  127.     }
  128.     void addVertex(const Vertex& v) { vVertices.push_back(v); }
  129.  
  130.     void drawAll()
  131.     {
  132.         if(!vVertices.empty())
  133.         {
  134.             d3d9device->SetVertexDeclaration(vDeclaration);
  135.             d3d9device->SetIndices(iBuffer);
  136.             d3d9device->SetStreamSource(0, vBuffer, 0, sizeof(Vertex));
  137.  
  138.             DWORD numTris                = 0;
  139.  
  140.             Vertex* pVertices;
  141.             vBuffer->Lock(0, 0, reinterpret_cast<LPVOID*>(&pVertices), D3DLOCK_DISCARD);
  142.  
  143.             for(std::size_t i = 0; i < (vVertices.size() / 4u); ++i)
  144.             {
  145.                 *pVertices++ = vVertices[i * 4 + 0];
  146.                 *pVertices++ = vVertices[i * 4 + 1];
  147.                 *pVertices++ = vVertices[i * 4 + 2];
  148.                 *pVertices++ = vVertices[i * 4 + 3];
  149.  
  150.                 numTris += 2;
  151.  
  152.                 if(numTris == ((maxVertices / 4) * 2))
  153.                 {
  154.                     vBuffer->Unlock();
  155.                     d3d9device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numTris * 2, 0, numTris);
  156.                     vBuffer->Lock(0, 0, reinterpret_cast<LPVOID*>(&pVertices), D3DLOCK_DISCARD);
  157.                     numTris = 0;
  158.                 }
  159.             }
  160.             vBuffer->Unlock();
  161.  
  162.             if(numTris > 0)
  163.             {
  164.                 d3d9device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numTris * 2, 0, numTris);
  165.             }
  166.             vVertices.clear();
  167.         }
  168.     }
  169. };
  170.  
  171. Drawer* gDrawer;
  172.  
  173. class Sprite
  174. {
  175. private:
  176.     D3DXVECTOR2 pos;
  177.     D3DXVECTOR2 lastPos;
  178.     D3DXVECTOR2 targetPos;
  179.     D3DXVECTOR2 dim;
  180.     std::array<Vertex, 4u> verts;
  181. public:
  182.     Sprite(const D3DXVECTOR2& startPos, float size)
  183.         : pos(startPos), lastPos(startPos), targetPos(0.0f, 0.0f), dim(size, size)
  184.     {
  185.         float maxX = (float)WIN_DIM.cx - size;
  186.         float maxY = (float)WIN_DIM.cy - size;
  187.         targetPos = D3DXVECTOR2(randfr(0.0f, maxX), randfr(0.0f, maxY));
  188.     }
  189.     const D3DXVECTOR2& getPosition() const { return pos; }
  190.     void setPos(const D3DXVECTOR2& _pos) { pos = _pos; }
  191.     const D3DXVECTOR2& getDim() { return dim; }
  192.  
  193.     void moveRandom()
  194.     {
  195.         float moveSpeed = 0.1f;
  196.  
  197.         static const float collDist   = 2.0f;
  198.         static const float collDistSq = collDist * collDist;
  199.  
  200.         auto oldPos      = getPosition();
  201.         D3DXVECTOR2 dir  = targetPos - oldPos;
  202.         float currDistSq = D3DXVec2LengthSq(&dir);
  203.         D3DXVec2Normalize(&dir, &dir);
  204.  
  205.         D3DXVECTOR2 newPos = oldPos + dir * moveSpeed;
  206.         setPos(newPos);
  207.  
  208.         if(collDistSq > currDistSq)
  209.         {
  210.             float maxX = (float)WIN_DIM.cx - dim.x;
  211.             float maxY = (float)WIN_DIM.cy - dim.y;
  212.             targetPos = D3DXVECTOR2(randfr(0.0f, maxX), randfr(0.0f, maxY));
  213.         }
  214.     }
  215.  
  216.     void commitVertices()
  217.     {
  218.         lastPos    = pos;
  219.  
  220.         verts[0].pos = D3DXVECTOR3(pos.x,         pos.y        , 1.0f);
  221.         verts[1].pos = D3DXVECTOR3(pos.x + dim.x, pos.y        , 1.0f);
  222.         verts[2].pos = D3DXVECTOR3(pos.x + dim.x, pos.y + dim.y, 1.0f);
  223.         verts[3].pos = D3DXVECTOR3(pos.x,         pos.y + dim.y, 1.0f);
  224.  
  225.         gDrawer->addVertex(verts[0]);
  226.         gDrawer->addVertex(verts[1]);
  227.         gDrawer->addVertex(verts[2]);
  228.         gDrawer->addVertex(verts[3]);
  229.     }
  230.  
  231.     void update(uint64 dt)
  232.     {
  233.         float t = dt * (1.0f / 1000000.0f);
  234.         D3DXVECTOR2 result_pos;
  235.         D3DXVec2Lerp(&result_pos, &pos, &lastPos, t);
  236.         pos = result_pos;
  237.     }
  238. };
  239.  
  240. typedef std::shared_ptr<Sprite> sp_Sprite;
  241. typedef std::vector<sp_Sprite>  v_Sprite;
  242. v_Sprite vSprites;
  243.  
  244. D3DMATRIX* D3DXMatrixOrtho2D(D3DMATRIX* m, const float w, const float h, const float znear, const float zfar)
  245. {
  246.     m->_11 = 2.0f / w;
  247.     m->_12 = 0.0f;
  248.     m->_13 = 0.0f;
  249.     m->_14 = 0.0f;
  250.     m->_21 = 0.0f;
  251.     m->_22 = 2.0f / -h;
  252.     m->_23 = 0.0f;
  253.     m->_24 = 0.0f;
  254.     m->_31 = 0.0f;
  255.     m->_32 = 0.0f;
  256.     m->_33 = 1.0f / (zfar - znear);
  257.     m->_34 = 0.0f;
  258.     m->_41 = (w + 1.0f) / -w;
  259.     m->_42 = (h + 1.0f) / h;
  260.     m->_43 = znear / (znear - zfar);
  261.     m->_44 = 1.0;
  262.     return m;
  263. }
  264.  
  265. D3DXMATRIX proj;
  266.  
  267. bool run            = true;
  268.  
  269. bool init();
  270. void sceneMove();
  271. void sceneUpdate(uint64 dt);
  272. void draw();
  273. void close();
  274.  
  275. LRESULT CALLBACK StaticWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  276. {
  277.     switch(msg)
  278.     {
  279.     case WM_KEYUP:
  280.         {
  281.             if(wParam == VK_ESCAPE)
  282.             {
  283.                 run = false;
  284.             }
  285.             return 0;
  286.         }break;
  287.     case WM_CLOSE:
  288.         {
  289.             run = false;
  290.             return 0;
  291.         }break;
  292.     case WM_DESTROY:
  293.         {
  294.             PostQuitMessage(0);
  295.             return 0;
  296.         }break;
  297.     };
  298.     return DefWindowProc(hWnd, msg, wParam, lParam);
  299. }
  300.  
  301. int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  302. {
  303.     WNDCLASS wndClass;
  304.     memset(&wndClass, 0, sizeof(WNDCLASS));
  305.     wndClass.hInstance     = GetModuleHandle(0);
  306.     wndClass.style         = CS_HREDRAW | CS_VREDRAW;
  307.     wndClass.lpfnWndProc   = reinterpret_cast<WNDPROC>( StaticWindowProc );
  308.     wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  309.     wndClass.lpszClassName = TEXT("FixTimeStepClass");
  310.     wndClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  311.  
  312.     DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS | WS_MINIMIZEBOX | WS_THICKFRAME;
  313.     style |= WS_VISIBLE;
  314.  
  315.     if(0 == RegisterClass(&wndClass))
  316.     {
  317.         MessageBox(0, TEXT("RegisterClass() failed!"), 0, 0);
  318.         return EXIT_FAILURE;
  319.     }
  320.  
  321.     RECT clientSize;
  322.     clientSize.top    = 0;
  323.     clientSize.left   = 0;
  324.     clientSize.right  = WIN_DIM.cx;
  325.     clientSize.bottom = WIN_DIM.cy;
  326.     AdjustWindowRect(&clientSize, style, FALSE);
  327.     int realWidth  = clientSize.right - clientSize.left;
  328.     int realHeight = clientSize.bottom - clientSize.top;
  329.     int windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2;
  330.     int windowTop  = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2;
  331.  
  332.     hwnd = CreateWindowEx(0,
  333.         TEXT("FixTimeStepClass"), TEXT("FixTimeStep"), style,              
  334.         windowLeft, windowTop, realWidth, realHeight,
  335.         NULL, NULL, GetModuleHandle(0), NULL);
  336.     if(NULL == hwnd)
  337.     {
  338.         MessageBox(0, TEXT("CreateWindowEx() failed!"), 0, 0);
  339.         return EXIT_FAILURE;
  340.     }
  341.  
  342.     ShowWindow(hwnd, SW_SHOW);
  343.     UpdateWindow(hwnd);
  344.  
  345.     if(!init())
  346.     {
  347.         close();
  348.         return EXIT_FAILURE;
  349.     }
  350.  
  351.     while(run)
  352.     {
  353.         MSG  msg   = {0};
  354.         while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  355.         {
  356.             TranslateMessage(&msg);
  357.             DispatchMessage(&msg);
  358.         }
  359.  
  360.         // step one
  361.         sceneMove();
  362.  
  363.         // step two
  364.         static const uint64 freq = 33333ull;
  365.         static auto updatedTime  = gTimer.get();
  366.         auto currTime            = gTimer.get();
  367.         while((currTime - updatedTime) > freq )
  368.         {
  369.             sceneUpdate(freq);
  370.             updatedTime += freq;
  371.         }
  372.  
  373.         // step three
  374.         draw();
  375.     }
  376.  
  377.     close();
  378.     return EXIT_SUCCESS;
  379. }
  380.  
  381. bool init()
  382. {
  383.     HRESULT hr = D3D_OK;
  384.     D3DPRESENT_PARAMETERS  presentParams;
  385.     D3DCAPS9               caps;
  386.     D3DDISPLAYMODE         displayMode;
  387.     D3DADAPTER_IDENTIFIER9 adapterIdentifier;
  388.     UINT                   adapter;
  389.     D3DDEVTYPE             deviceType;
  390.     memset(reinterpret_cast<void*>(&presentParams),     0, sizeof(D3DPRESENT_PARAMETERS));
  391.     memset(reinterpret_cast<void*>(&caps),              0, sizeof(D3DCAPS9));
  392.     memset(reinterpret_cast<void*>(&displayMode),       0, sizeof(D3DDISPLAYMODE));
  393.     memset(reinterpret_cast<void*>(&adapterIdentifier), 0, sizeof(D3DADAPTER_IDENTIFIER9));
  394.  
  395.     if(NULL == (d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
  396.     {
  397.         MessageBox(0, TEXT("Direct3DCreate9() failed!"), 0, 0);
  398.         return false;
  399.     }
  400.  
  401.     hr = d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode);
  402.     if(FAILED(hr))
  403.     {
  404.         MessageBox(0, TEXT("GetAdapterDisplayMode() failed!"), 0, 0);
  405.         return false;
  406.     }
  407.  
  408.     hr = d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  409.     if(FAILED(hr))
  410.     {
  411.         MessageBox(0, TEXT("GetDeviceCaps() failed!"), 0, 0);
  412.         return false;
  413.     }
  414.  
  415.     hr = d3d9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapterIdentifier);
  416.     if(FAILED(hr))
  417.     {
  418.         MessageBox(0, TEXT("GetAdapterIdentifier() failed!"), 0, 0);
  419.         return false;
  420.     }
  421.  
  422.     //
  423.     presentParams.hDeviceWindow              = hwnd;
  424.     presentParams.Windowed                   = TRUE;
  425.     presentParams.BackBufferWidth            = 0;
  426.     presentParams.BackBufferHeight           = 0;
  427.     presentParams.BackBufferCount            = 1;
  428.     presentParams.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
  429.     presentParams.BackBufferFormat           = displayMode.Format;
  430.     presentParams.MultiSampleType            = D3DMULTISAMPLE_NONE;
  431.     presentParams.MultiSampleQuality         = 0;
  432.     presentParams.FullScreen_RefreshRateInHz = 0;
  433. #if 1
  434.     presentParams.PresentationInterval       = D3DPRESENT_INTERVAL_ONE;
  435. #else
  436.     presentParams.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  437. #endif
  438.     presentParams.EnableAutoDepthStencil     = TRUE;
  439.     presentParams.AutoDepthStencilFormat     = D3DFMT_D16;
  440.     presentParams.Flags                      = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
  441.  
  442.     DWORD Flags  = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  443.     adapter      = D3DADAPTER_DEFAULT;
  444.     deviceType   = D3DDEVTYPE_HAL;
  445.  
  446.     hr = d3d9->CreateDevice(adapter, deviceType, presentParams.hDeviceWindow, Flags, &presentParams, &d3d9device);
  447.     if(FAILED(hr))
  448.     {
  449.         MessageBox(0, TEXT("CreateDevice() failed!"), 0, 0);
  450.         return false;
  451.     }
  452.  
  453.     d3d9device->SetRenderState(D3DRS_LIGHTING, FALSE);
  454.  
  455.     gDrawer = new Drawer;
  456.  
  457.     const std::size_t numSprites = 100u;
  458.     for(std::size_t i = 0u; i < numSprites; ++i)
  459.     {
  460.         float size = 15.0f;
  461.         float maxX = (float)WIN_DIM.cx - size;
  462.         float maxY = (float)WIN_DIM.cy - size;
  463.         D3DXVECTOR2 startPos = D3DXVECTOR2(randfr(0.0f, maxX), randfr(0.0f, maxY));
  464.         vSprites.push_back( sp_Sprite( new Sprite(startPos, size) ) );
  465.     }
  466.  
  467.     D3DXMatrixOrtho2D(&proj, (float)WIN_DIM.cx, (float)WIN_DIM.cy, 0.0f, 1.0f);
  468.  
  469.     return true;
  470. }
  471.  
  472. void sceneMove()
  473. {
  474.     for(std::size_t i = 0u; i < vSprites.size(); ++i)
  475.     {
  476.         vSprites[i]->moveRandom();
  477.         vSprites[i]->commitVertices();
  478.     }
  479. }
  480.  
  481. void sceneUpdate(uint64 dt)
  482. {
  483.     for(std::size_t i = 0u; i < vSprites.size(); ++i)
  484.     {
  485.         vSprites[i]->update(dt);
  486.     }
  487. }
  488.  
  489. void draw()
  490. {
  491.     d3d9device->BeginScene();
  492.     d3d9device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 255, 0, 255), 1.0f, 0);
  493.    
  494.     D3DXMATRIX idnt;
  495.     D3DXMatrixIdentity(&idnt);
  496.     d3d9device->SetTransform(D3DTS_PROJECTION, &proj);
  497.     d3d9device->SetTransform(D3DTS_VIEW, &idnt);
  498.     d3d9device->SetTransform(D3DTS_WORLD, &idnt);
  499.  
  500.     gDrawer->drawAll();
  501.  
  502.     d3d9device->EndScene();
  503.     d3d9device->Present(NULL, NULL, NULL, NULL);
  504. }
  505.  
  506. void close()
  507. {
  508.     delete gDrawer;
  509.     d3d9device->Release();
  510.     d3d9->Release();
  511. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement