Конференция "Игры" » Пример из туториала по Direct3D [Delphi, Windows]
 
  • Piroxyline © (15.04.07 13:47) [0]
    Читаю туториал по Direct3D от мелкомягкого. Чтобы не дай Бог чего-нибудь наперекосяк не пошло (с этим зверем никогда не работал), делаю все так, как там сказано. Ну, иногда переписываю часть кода из примеров, чтобы все работало, где-то экспериментирую, сравниваю с OpenGL, но это мелочи. Пользуюсь джедаевскими заголовками. В-общем, кто-нибудь может мне объяснить, почему эти прямоугольники не могут вращаться как им положено?

    program Project1;

    uses
     Windows,
     Messages,
     Direct3D9,
     D3DX9;

    const
     D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_DIFFUSE;

    type
     HINST = Cardinal;
     Float = Single;

     CUSTOMVERTEX = record
       x, y, z: Float;
       color: DWord;
     end;

    var
     g_hInst: HINST = 0;
     g_hWnd: HWND = 0;
     g_pD3D: IDirect3D9;
     g_pd3dDevice: IDirect3DDevice9;

     g_pVB: IDirect3DVertexBuffer9;

     vertices: Array[0..11] of CUSTOMVERTEX =
                                       ((x: 0.0; y: 0.0; z: 0.0; color: $ffff0000),
                                        (x: 1.0; y: 0.0; z: 0.0; color: $ff0000ff),
                                        (x: 1.0; y: 1.0; z: 0.0; color: $ffffffff),

                                        (x: 1.0; y: 1.0; z: 0.0; color: $ffff0000),
                                        (x: 0.0; y: 1.0; z: 0.0; color: $ff0000ff),
                                        (x: 0.0; y: 0.0; z: 0.0; color: $ffffffff),

                                        (x: 0.0; y: 0.0; z: 1.0; color: $ffff0000),
                                        (x: 1.0; y: 0.0; z: 1.0; color: $ff0000ff),
                                        (x: 1.0; y: 1.0; z: 1.0; color: $ffffffff),

                                        (x: 1.0; y: 1.0; z: 1.0; color: $ffff0000),
                                        (x: 0.0; y: 1.0; z: 1.0; color: $ff0000ff),
                                        (x: 0.0; y: 0.0; z: 1.0; color: $ffffffff));

    procedure Render;
    var
     matWorld: TD3DXMATRIXA16;
     matView: TD3DXMATRIXA16;
     matProj: TD3DXMATRIXA16;
     iTime: Integer;
     fAngle: Float;
     vEyePt, vLookatPt, vUpVec: TD3DXVECTOR3;
    begin
     g_pd3dDevice.Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);
     g_pd3dDevice.BeginScene;

     iTime  := GetTickCount();
     fAngle := iTime * (1.0 * D3DX_PI) / 1000.0;
     D3DXMatrixRotationY( matWorld, fAngle );
     g_pd3dDevice.SetTransform( D3DTS_WORLD, matWorld );

     vEyePt := D3DXVECTOR3( 0.0, 3.0,-5.0 );
     vLookatPt := D3DXVECTOR3( 0.0, 0.0, 0.0 );
     vUpVec := D3DXVECTOR3( 0.0, 1.0, 0.0 );
     D3DXMatrixLookAtLH( matView, vEyePt, vLookatPt, vUpVec );
     g_pd3dDevice.SetTransform( D3DTS_VIEW, matView );

     D3DXMatrixPerspectiveFovLH( matProj, D3DX_PI/4, 1.0, 1.0, 100.0 );
     g_pd3dDevice.SetTransform( D3DTS_PROJECTION, matProj );

     g_pd3dDevice.SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
     g_pd3dDevice.SetFVF( D3DFVF_CUSTOMVERTEX );
     g_pd3dDevice.DrawPrimitive( D3DPT_TRIANGLELIST, 0, Length(vertices) div 3 );

     g_pd3dDevice.EndScene;
     g_pd3dDevice.Present(nil, nil, 0, nil);
    end;

    procedure Cleanup;
    begin
     if g_pVB <> nil then begin
       g_pVB._Release;
       g_pVB := nil;
     end;
     if g_pd3dDevice <> nil then begin
       g_pd3dDevice._Release;
       g_pd3dDevice := nil;
     end;
     if g_pD3D <> nil then begin
       g_pD3D._Release;
       g_pD3D := nil;
     end;
    end;

    function WndProc(hWnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    begin
     case Message of
       WM_PAINT: begin
         Render;
       end;
       WM_DESTROY: begin
         PostQuitMessage(0);
         Cleanup;
       end;
       else begin
         Result := DefWindowProc(hWnd, message, wParam, lParam);
         Exit;
       end;
     end;

     Result := 0;
    end;

    function InitWindow(hInstance: HINST; nCmdShow: Integer): HRESULT;
    var
     wcex: WNDCLASSEX;
     rc: TRect;
    begin
     Result := E_FAIL;

     wcex.cbSize := sizeof(WNDCLASSEX);
     wcex.style          := CS_HREDRAW or CS_VREDRAW;
     wcex.lpfnWndProc    := @WndProc;
     wcex.cbClsExtra     := 0;
     wcex.cbWndExtra     := 0;
     wcex.hInstance      := hInstance;
     wcex.hIcon          := LoadIcon(0, IDI_APPLICATION);
     wcex.hCursor        := LoadCursor(0, IDC_ARROW);
     wcex.hbrBackground  := COLOR_WINDOW+1;
     wcex.lpszMenuName   := 0;
     wcex.lpszClassName  := 'TutorialWindowClass';
     wcex.hIconSm        := LoadIcon(0, IDI_APPLICATION);
     if RegisterClassEx(wcex) = 0 then Exit;

     g_hInst := hInstance;
     rc.Left := 0;
     rc.Top := 0;
     rc.Right := 640;
     rc.Bottom := 480;

     AdjustWindowRect( rc, WS_OVERLAPPEDWINDOW, FALSE );
     g_hWnd := CreateWindow( 'TutorialWindowClass', 'Direct3D 10 Tutorial 0: Setting Up Window', WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, 0, 0, hInstance, 0);
     if g_hWnd = 0 then Exit;

     ShowWindow( g_hWnd, nCmdShow );

     Result := S_OK;
    end;

    function InitD3D: HRESULT;
    var
     d3dpp: D3DPRESENT_PARAMETERS;
     pVertices: Pointer;
    begin
     Result := E_FAIL;

     g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);

     if g_pD3D = nil then Exit;

     ZeroMemory(@d3dpp, SizeOf(d3dpp));

     d3dpp.Windowed := TRUE;
     d3dpp.SwapEffect := D3DSWAPEFFECT_DISCARD;
     d3dpp.BackBufferFormat := D3DFMT_UNKNOWN;

     if( FAILED( g_pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
                                     D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                     @d3dpp, g_pd3dDevice ) ) ) then Exit;

     g_pd3dDevice.SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
     g_pd3dDevice.SetRenderState( D3DRS_LIGHTING, iFalse );

     if FAILED( g_pd3dDevice.CreateVertexBuffer( sizeof(vertices),
            0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, g_pVB, 0 ) ) then Exit;

     if FAILED( g_pVB.Lock( 0, sizeof(vertices), pVertices, 0 ) ) then Exit;

     CopyMemory(pVertices, @vertices, sizeof(vertices));

     g_pVB.Unlock;

     Result := S_OK;
    end;

    function wWinMain(hInstance, hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow: Integer): Integer; stdcall;
    var
     msg: tagMSG;
    begin
     Result := 0;
     if FAILED( InitWindow( hInstance, nCmdShow ) ) then Exit;
     if FAILED( InitD3D ) then Exit;
     while( GetMessage( msg, 0, 0, 0 ) ) do begin
       TranslateMessage( msg );
       DispatchMessage( msg );
     end;
     Result := msg.wParam;
    end;

    begin
     wWinMain(hInstance, hPrevInst, CmdLine, CmdShow);
    end.

  • Sapersky (16.04.07 13:00) [1]
    Если нужно, чтобы они вращались симметрично - вычесть 0.5 из всех координат, т.к. матрица трансформации поворачивает относительно центра (0,0,0). Можно включить перемещение в саму матрицу.
  • Мистер Т (19.04.07 07:56) [2]
    Если Сишный код не проблема - много хороших туториалов тут:
    http://www.codesampler.com/dx9src.htm

    Но
    > почему эти прямоугольники не могут вращаться как им положено?
    А как положено ? =)
    То есть - как они должны вращаться ?

    З.Ы.
    g_pd3dDevice._Release; и вообще _Release вызывать не надо.
  • Мистер Т (19.04.07 07:59) [3]
    Пара примеров:
    //-----------------------------------------------------------------------------
    //           Name: dx9_vertex_data.dpr
    //         Author: Kevin Harris (kevin@codesampler.com)
    //     Translator: Egor Konovalov
    //  Last Modified: 28.08.2005
    //    Description: This sample demonstrates how to create 3D geometry with
    //                 Direct3D by loading vertex data into a Vertex Buffer.
    //-----------------------------------------------------------------------------

    program dx9_vertex_data;

    {$R *.res}

    {$IFDEF FPC}
     {$MODE DELPHI}
     {$APPTYPE GUI}
    {$ENDIF}

    // {$DEFINE RELEASED}

    uses
     Windows,
     Messages,
     MMSystem,
     Direct3D9,
     D3DX9;

    //-----------------------------------------------------------------------------
    // GLOBALS
    //-----------------------------------------------------------------------------
    type
     TVertex = record
       x,  y,  z : Single;
       tu, tv    : Single
     end;

    const
     FVF_Flags = D3DFVF_XYZ or D3DFVF_TEX1;

    var
     g_hWnd                : THandle                 = 0;
     g_pD3D                : IDirect3D9              = nil;
     g_pd3dDevice          : IDirect3DDevice9        = nil;
     g_pVertexBuffer       : IDirect3DVertexBuffer9  = nil;
     g_pTexture            : IDirect3DTexture9       = nil;

     g_fElapsedTime        : Single                  = 0;
     g_dCurrentTime        : Double                  = 0;
     g_dLastTime           : Double                  = 0;

     g_fXrot               : Single                  = 0.0;
     g_fYrot               : Single                  = 0.0;
     g_fZrot               : Single                  = 0.0;

     winClass              : WNDCLASSEX;
     uMsg                  : MSG;

     g_cubeVertices        : array[0..23] of TVertex =
     ((x:-1.0; y: 1.0; z:-1.0; tu: 0.0; tv: 0.0),
      (x: 1.0; y: 1.0; z:-1.0; tu: 1.0; tv: 0.0),
      (x:-1.0; y:-1.0; z:-1.0; tu: 0.0; tv: 1.0),
      (x: 1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 1.0),

      (x:-1.0; y: 1.0; z: 1.0; tu: 1.0; tv: 0.0),
      (x:-1.0; y:-1.0; z: 1.0; tu: 1.0; tv: 1.0),
      (x: 1.0; y: 1.0; z: 1.0; tu: 0.0; tv: 0.0),
      (x: 1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 1.0),

      (x:-1.0; y: 1.0; z: 1.0; tu: 0.0; tv: 0.0),
      (x: 1.0; y: 1.0; z: 1.0; tu: 1.0; tv: 0.0),
      (x:-1.0; y: 1.0; z:-1.0; tu: 0.0; tv: 1.0),
      (x: 1.0; y: 1.0; z:-1.0; tu: 1.0; tv: 1.0),

      (x:-1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 0.0),
      (x:-1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 0.0),
      (x: 1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 1.0),
      (x: 1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 1.0),

      (x: 1.0; y: 1.0; z:-1.0; tu: 0.0; tv: 0.0),
      (x: 1.0; y: 1.0; z: 1.0; tu: 1.0; tv: 0.0),
      (x: 1.0; y:-1.0; z:-1.0; tu: 0.0; tv: 1.0),
      (x: 1.0; y:-1.0; z: 1.0; tu: 1.0; tv: 1.0),

      (x:-1.0; y: 1.0; z:-1.0; tu: 1.0; tv: 0.0),
      (x:-1.0; y:-1.0; z:-1.0; tu: 1.0; tv: 1.0),
      (x:-1.0; y: 1.0; z: 1.0; tu: 0.0; tv: 0.0),
      (x:-1.0; y:-1.0; z: 1.0; tu: 0.0; tv: 1.0));

    //-----------------------------------------------------------------------------
    // Name: WindowProc()
    // Desc: The window's message handler
    //-----------------------------------------------------------------------------  
    function WindowProc(ihwnd: THandle; uMsg: Longword; wParam: Longint; lParam: Longint): Longint; stdcall;
    begin
     WindowProc := 0;
     case uMsg of
       WM_KEYDOWN:     begin
                         if wParam = VK_ESCAPE then PostQuitMessage(0);
                       end;
       WM_CLOSE:       PostQuitMessage(0);
       WM_DESTROY:     PostQuitMessage(0);
       else WindowProc := DefWindowProc(ihwnd, uMsg, wParam, lParam);
       end;
    end;

    //-----------------------------------------------------------------------------
    // Name: LoadTexture()
    // Desc:
    //-----------------------------------------------------------------------------
    procedure LoadTexture;
    begin
     g_pTexture := nil;

     D3DXCreateTextureFromFile(g_pd3dDevice, '
    test.bmp', g_pTexture);

     g_pd3dDevice.SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     g_pd3dDevice.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    end;

    //-----------------------------------------------------------------------------
    // Name: Init()
    // Desc:
    //-----------------------------------------------------------------------------
    procedure Init;
    var
     d3ddm     : TD3DDisplayMode;
     d3dpp     : TD3DPresentParameters;
     matProj   : TD3DMatrix;
     pVertices : Pointer;
    begin
     g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);

     g_pD3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
                                  d3ddm);

     ZeroMemory(@d3dpp, SizeOf(TD3DPresentParameters));

     with d3dpp do
       begin
         Windowed                := True;
         SwapEffect              := D3DSWAPEFFECT_DISCARD;
         BackBufferFormat        := d3ddm.Format;
         EnableAutoDepthStencil  := True;
         AutoDepthStencilFormat  := D3DFMT_D16;
         PresentationInterval    := D3DPRESENT_INTERVAL_IMMEDIATE;
       end;

     g_pD3D.CreateDevice(D3DADAPTER_DEFAULT,
                         D3DDEVTYPE_HAL,
                         g_hWnd,
                         D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                         @d3dpp,
                         g_pd3dDevice);

     LoadTexture;

     g_pd3dDevice.CreateVertexBuffer(24 * SizeOf(TVertex),
                                     0,
                                     FVF_Flags,
                                     D3DPOOL_DEFAULT,
                                     g_pVertexBuffer,
                                     nil);

     pVertices := nil;

     g_pVertexBuffer.Lock(0, SizeOf(g_cubeVertices), pVertices, 0);
       Move(g_cubeVertices, pVertices^, SizeOf(g_cubeVertices));
     g_pVertexBuffer.Unlock;

     g_pd3dDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
     g_pd3dDevice.SetRenderState(D3DRS_ZENABLE, iTrue);

     D3DXMatrixPerspectiveFovLH(matProj,
                                D3DXToRadian(45.0),
                                (640 / 480),
                                0.1,
                                100.0);

     g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);
    end;

    //-----------------------------------------------------------------------------
    // Name: ShutDown()
    // Desc:
    //-----------------------------------------------------------------------------
    procedure ShutDown;
    begin
     if Assigned(g_pTexture) then
       begin
         {$IFDEF RELEASED}
         g_pTexture._Release;
         {$ENDIF}
         g_pTexture := nil;
       end;

     if Assigned(g_pVertexBuffer) then
       begin
         {$IFDEF RELEASED}
         g_pVertexBuffer._Release;
         {$ENDIF}
         g_pVertexBuffer := nil;
       end;

     if Assigned(g_pd3dDevice) then
       begin
         {$IFDEF RELEASED}
         g_pd3dDevice._Release;
         {$ENDIF}
         g_pd3dDevice := nil;
       end;

     if Assigned(g_pD3D) then
       begin
         {$IFDEF RELEASED}
         g_pD3D._Release;
         {$ENDIF}
         g_pD3D := nil;
       end;
       
    end;

  • Мистер Т (19.04.07 08:00) [4]
    продолжение кода...


    //-----------------------------------------------------------------------------
    // Name: Render()
    // Desc:
    //-----------------------------------------------------------------------------
    procedure Render;
    var
     matWorld  : TD3DMatrix;
     matTrans  : TD3DMatrix;
     matRot    : TD3DMatrix;
    begin
     if g_pd3dDevice = nil then Exit;

     g_pd3dDevice.Clear(0,
                        nil,
                        D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
                        D3DCOLOR_COLORVALUE(0.0, 0.0, 0.0, 1.0),
                        1.0,
                        0);

     g_fXrot := g_fXrot + (10.1 * g_fElapsedTime);
     g_fYrot := g_fYrot + (10.2 * g_fElapsedTime);
     g_fZrot := g_fZrot + (10.3 * g_fElapsedTime);

     D3DXMatrixTranslation(matTrans, 0.0, 0.0, 5.0);
     D3DXMatrixRotationYawPitchRoll(matRot,
                                    D3DXToRadian(g_fXrot),
                                    D3DXToRadian(g_fYrot),
                                    D3DXToRadian(g_fZrot));
     D3DXMatrixMultiply(matWorld, matRot, matTrans);

     g_pd3dDevice.SetTransform(D3DTS_WORLD, matWorld);

     g_pd3dDevice.BeginScene;

       g_pd3dDevice.SetTexture(0, g_pTexture);
       g_pd3dDevice.SetStreamSource(0, g_pVertexBuffer, 0, SizeOf(TVertex));
       g_pd3dDevice.SetFVF(FVF_Flags);

      g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,  0, 2 );
      g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,  4, 2 );
      g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,  8, 2 );
      g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2 );
      g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2 );
      g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2 );

     g_pd3dDevice.EndScene;

     g_pd3dDevice.Present(nil, nil, 0, nil);
    end;

    //-----------------------------------------------------------------------------
    // Name:
    // Desc: The application's entry point
    //-----------------------------------------------------------------------------
    begin
     ZeroMemory(@uMsg, SizeOf(MSG));
     ZeroMemory(@winClass, SizeOf(WNDCLASSEX));

     with winClass do
       begin
         lpszClassName := '
    MY_WINDOWS_CLASS';
         cbSize        := SizeOf(WNDCLASSEX);
         style         := CS_HREDRAW or CS_VREDRAW;
         lpfnWndProc   := @WindowProc;
         hInstance     := hInstance;
         hIcon         := LoadIcon(hInstance, IDI_APPLICATION);
         hIconSm       := LoadIcon(hInstance, IDI_APPLICATION);
         hCursor       := LoadCursor(0, IDC_ARROW);
         hbrBackground := $000000;
         lpszMenuName  := nil;
         cbClsExtra    := 0;
         cbWndExtra    := 0;
       end;

     if (RegisterClassEx(winClass) = 0) then
       Halt(0);

     g_hWnd := CreateWindowEx(0,
                                winClass.lpszClassName,
                                '
    Direct3D (DX9) - Vertex Data',
                                WS_OVERLAPPEDWINDOW or WS_VISIBLE,
                                0,
                                0,
                                640,
                                480,
                                0,
                                0,
                                winClass.hInstance,
                                nil);

     if g_hWnd = 0 then
       Halt(0);

     ShowWindow(g_hWnd, SW_SHOW);
     UpdateWindow(g_hWnd);

     Init;

     while (uMsg.message <> WM_QUIT) do
       begin
         if PeekMessage(uMsg, 0, 0, 0, PM_REMOVE) then
           begin
             TranslateMessage(uMsg);
             DispatchMessage(uMsg);
           end
         else
           begin
             g_dCurrentTime := timeGetTime;
             g_fElapsedTime := ((g_dCurrentTime - g_dLastTime) * 0.001);
             g_dLastTime := g_dCurrentTime;

             Render;
           end;
       end;

     ShutDown;

     UnregisterClass(winClass.lpszClassName, winClass.hInstance);
    end.

  • Мистер Т (19.04.07 08:04) [5]
    Второй пример:
    //---
    //           Name: dx9_transforms.dpr
    //         Author: Kevin Harris (kevin@codesampler.com)
    //     Translator: Egor Konovalov (tujh@ru66.ru)
    //  Last Modified: 30.08.2005
    //    Description: Demonstrates how to use translation, rotation, and scaling
    //                 matrices to create a simulated solar system.
    //
    //   Control Keys: F1    - Speed up rotations
    //                 F2    - Slow down rotations
    //                 Space - Toggle orbiting on/off
    //---

    program dx9_transforms;

    {$R *.res}

    {$IFDEF FPC}
     {$MODE DELPHI}
     {$APPTYPE GUI}
    {$ENDIF}

    // {$DEFINE RELEASED}

    uses
     Windows,
     Messages,
     MMSystem,
     Direct3D9,
     D3DX9;

    //---
    // GLOBALS
    //---
    type
     TVertex = record
       x, y, z : Single;
       diffuse : Longword;
     end;

    const
     D3DFVF_MY_VERTEX = D3DFVF_XYZ or D3DFVF_DIFFUSE;

    var
     g_hWnd                  : THandle                 = 0;
     g_pD3D                  : IDirect3D9              = nil;
     g_pd3dDevice            : IDirect3DDevice9        = nil;
     g_pSunMesh              : ID3DXMesh               = nil;
     g_pEarthMesh            : ID3DXMesh               = nil;
     g_pMoonMesh             : ID3DXMesh               = nil;
     g_matrixStack           : ID3DXMatrixStack        = nil;

     g_fElpasedTime          : Single;
     g_dCurrentTime          : Longword;
     g_dLastTime             : Longword;

     g_fSpeedmodifier        : Single                  = 1.0;
     g_bOrbitOn              : Boolean                 = True;

     g_fSunSpin              : Single                  = 0.0;
     g_fEarthSpin            : Single                  = 0.0;
     g_fEarthOrbit           : Single                  = 0.0;
     g_fMoonSpin             : Single                  = 0.0;
     g_fMoonOrbit            : Single                  = 0.0;

     winClass              : WNDCLASSEX;
     uMsg                  : MSG;

    //---
    // Name: WindowProc()
    // Desc: The window's message handler
    //---
    function WindowProc(ihwnd: THandle; uMsg: Longword; wParam: Longint; lParam: Longint): Longint; stdcall;
    begin
     WindowProc := 0;
     case uMsg of
       WM_KEYDOWN:     begin
                         case wParam of
                           VK_ESCAPE   : PostQuitMessage(0);
                           VK_F1       : g_fSpeedmodifier := g_fSpeedmodifier + 1.0;
                           VK_F2       : g_fSpeedmodifier := g_fSpeedmodifier - 1.0;
                           VK_SPACE    : g_bOrbitOn := not(g_bOrbitOn);
                         end;
                       end;
       WM_CLOSE:       PostQuitMessage(0);
       WM_DESTROY:     PostQuitMessage(0);
       else WindowProc := DefWindowProc(ihwnd, uMsg, wParam, lParam);
       end;
    end;

    //---
    // Name: Init()
    // Desc:
    //---
    procedure Init;
    var
     d3ddm             : TD3DDisplayMode;
     d3dpp             : TD3DPresentParameters;
     matProj           : TD3DMatrix;
     pTempEarthMesh    : ID3DXMesh;
     pTempSunMesh      : ID3DXMesh;
     pTempVertexBuffer : IDirect3DVertexBuffer9;
     nNumVerts         : Longword;
     i                 : Longword;
     pVertex           : Pointer;
     Vertex            : array of TVertex;
    begin
     g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);

     g_pD3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
                                  d3ddm);

     ZeroMemory(@d3dpp, SizeOf(TD3DPresentParameters));

     with d3dpp do
       begin
         Windowed                := True;
         SwapEffect              := D3DSWAPEFFECT_DISCARD;
         BackBufferFormat        := d3ddm.Format;
         EnableAutoDepthStencil  := True;
         AutoDepthStencilFormat  := D3DFMT_D16;
         PresentationInterval    := D3DPRESENT_INTERVAL_IMMEDIATE;
       end;

     g_pD3D.CreateDevice(D3DADAPTER_DEFAULT,
                         D3DDEVTYPE_HAL,
                         g_hWnd,
                         D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                         @d3dpp,
                         g_pd3dDevice);

     g_pd3dDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
     g_pd3dDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
     g_pd3dDevice.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

     D3DXMatrixPerspectiveFovLH(matProj,
                                D3DXToRadian(45.0),
                                (640 / 480),
                                0.1,
                                100.0);

     g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);

     // We'
    ll use the D3DXCreateSphere utility function to create three simple
     // sphere meshes to experiment with.

     D3DXCreateSphere(g_pd3dDevice, 1.0, 20, 20, pTempSunMesh,   nil);
     D3DXCreateSphere(g_pd3dDevice, 1.0, 10, 10, pTempEarthMesh, nil);
     D3DXCreateSphere(g_pd3dDevice, 0.5, 8,   8, g_pMoonMesh,    nil);

     // Unfortunately, the D3DXCreateSphere utility function creates a mesh
     // with no color, so we'll need to make a clone of the original meshes
     // using a FVF code that does include color so we can set up the Earth
     // and Sun with color.
     //
     // Once that'
    s been done, we'll need to set the color values to something
     // appropriate for our solar system model.

     // Clone the original Earth mesh and make it blue...

     pTempVertexBuffer := nil;

     pTempEarthMesh.CloneMeshFVF(0, D3DFVF_MY_VERTEX, g_pd3dDevice, g_pEarthMesh);

     if Succeeded(g_pEarthMesh.GetVertexBuffer(pTempVertexBuffer)) then
       begin
         nNumVerts := g_pEarthMesh.GetNumVertices;
         pVertex := nil;
         SetLength(Vertex, nNumVerts);
         pTempVertexBuffer.Lock(0, 0, pVertex, 0);
           Move(pVertex^, Vertex[0], nNumVerts * SizeOf(TVertex));

           for i := 0 to (nNumVerts - 1) do
             Vertex[i].diffuse := D3DCOLOR_COLORVALUE(0.0, 0.0, 1.0, 1.0);

           Move(Vertex[0], pVertex^, nNumVerts * SizeOf(TVertex));
         pTempVertexBuffer.Unlock;

         {$IFDEF RELEASED}
         pTempVertexBuffer._Release
         {$ENDIF}
         pTempVertexBuffer := nil;

         SetLength(Vertex, 0);
       end;

     // Clone the original Sun mesh and make it yellow...

     pTempSunMesh.CloneMeshFVF(0, D3DFVF_MY_VERTEX, g_pd3dDevice, g_pSunMesh);
     if Succeeded(g_pSunMesh.GetVertexBuffer(pTempVertexBuffer)) then
       begin
         nNumVerts := g_pSunMesh.GetNumVertices;
         pVertex := nil;
         SetLength(Vertex, nNumVerts);
         pTempVertexBuffer.Lock(0, 0, pVertex, 0);
           Move(pVertex^, Vertex[0], nNumVerts * SizeOf(TVertex));

           for i := 0 to (nNumVerts - 1) do
             Vertex[i].diffuse := D3DCOLOR_COLORVALUE(1.0, 1.0, 0.0, 1.0);

           Move(Vertex[0], pVertex^, nNumVerts * SizeOf(TVertex));
         pTempVertexBuffer.Unlock;

         {$IFDEF RELEASED}
         pTempVertexBuffer._Release
         {$ENDIF}
         pTempVertexBuffer := nil;

       end;

     {$IFDEF RELEASED}
     pTempEarthMesh._Release;
     {$ENDIF}
     pTempEarthMesh := nil;
     {$IFDEF RELEASED}
     pTempSunMesh._Release;
     {$ENDIF}
     pTempSunMesh := nil;

     D3DXCreateMatrixStack(0, g_matrixStack);

    end;

  • Мистер Т (19.04.07 08:05) [6]
    Продолжение кода:
    //-----------------------------------------------------------------------------
    // Name: ShutDown()
    // Desc:
    //-----------------------------------------------------------------------------
    procedure ShutDown;
    begin
     if Assigned(g_matrixStack) then
       begin
         {$IFDEF RELEASED}
         g_matrixStack._Release;
         {$ENDIF}
         g_matrixStack := nil;
       end;

     if Assigned(g_pSunMesh) then
       begin
         {$IFDEF RELEASED}
         g_pSunMesh._Release;
         {$ENDIF}
         g_pSunMesh := nil;
       end;

     if Assigned(g_pEarthMesh) then
       begin
         {$IFDEF RELEASED}
         g_pEarthMesh._Release;
         {$ENDIF}
         g_pEarthMesh := nil;
       end;

     if Assigned(g_pMoonMesh) then
       begin
         {$IFDEF RELEASED}
         g_pMoonMesh._Release;
         {$ENDIF}
         g_pMoonMesh := nil;
       end;

     if Assigned(g_pd3dDevice) then
       begin
         {$IFDEF RELEASED}
         g_pd3dDevice._Release;
         {$ENDIF}
         g_pd3dDevice := nil;
       end;

     if Assigned(g_pD3D) then
       begin
         {$IFDEF RELEASED}
         g_pD3D._Release;
         {$ENDIF}
         g_pD3D := nil;
       end;
       
    end;

    //-----------------------------------------------------------------------------
    // Name: Render()
    // Desc:
    //-----------------------------------------------------------------------------
    procedure Render;
    var
     matView                   : TD3DMatrix;

     mSunScale                 : TD3DMatrix;
     mSunSpinRotation          : TD3DMatrix;
     mSunMatrix                : TD3DMatrix;

     mEarthTranslationToOrbit  : TD3DMatrix;
     mEarthSpinRotation        : TD3DMatrix;
     mEarthOrbitRotation       : TD3DMatrix;
     mEarthMatrix              : TD3DMatrix;

     mMoonTranslationToOrbit   : TD3DMatrix;
     mMoonSpinRotation         : TD3DMatrix;
     mMoonOrbitRotation        : TD3DMatrix;
     mMoonMatrix               : TD3DMatrix;
    begin
     if g_pd3dDevice = nil then Exit;

     g_pd3dDevice.Clear(0,
                        nil,
                        D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
                        D3DCOLOR_COLORVALUE(0.0, 0.0, 0.0, 1.0),
                        1.0,
                        0);

     g_pd3dDevice.BeginScene;

       //
       // Have the view matrix move the view move us to a good vantage point so
       // we can see the Sun sitting at the origin while the Earth orbits it.
       //

       D3DXMatrixLookAtLH(matView,
                          D3DXVector3(0.0, 2.0, -25.0),  // Camera position
                          D3DXVector3(0.0, 0.0,   0.0),  // Look-at point
                          D3DXVector3(0.0, 1.0,   0.0)); // Up vector

       g_pd3dDevice.SetTransform(D3DTS_VIEW, matView);

       //
       // Cache rotational positions between frames...
       //

       if g_bOrbitOn then
         begin
           g_fSunSpin    := g_fSunSpin     + (g_fSpeedmodifier * (g_fElpasedTime * 10.0));

           g_fEarthSpin  := g_fEarthSpin   + (g_fSpeedmodifier * (g_fElpasedTime * 100.0));
           g_fEarthOrbit := g_fEarthOrbit  + (g_fSpeedmodifier * (g_fElpasedTime * 20.0));

           g_fMoonSpin   := g_fMoonSpin    + (g_fSpeedmodifier * (g_fElpasedTime * 50.0));
           g_fMoonOrbit  := g_fMoonOrbit   + (g_fSpeedmodifier * (g_fElpasedTime * 200.0));
         end;

       //
       // The Sun is easy because the mesh for it is initially created centered
       // at origin. All we have to do is spin it by rotating it about the Y axis
       // and scale it by 5.0f.
       //

       D3DXMatrixRotationY(mSunSpinRotation, D3DXToRadian(g_fSunSpin));
       D3DXMatrixScaling(mSunScale, 5.0, 5.0, 5.0);

       //
       // Now, concatenate them together...
       // 1. Uniformly scale the Sun up in size
       // 2. and then spin it on its axis.
       //

       D3DXMatrixMultiply(mSunMatrix, mSunScale, mSunSpinRotation);

       g_pd3dDevice.SetTransform(D3DTS_WORLD, mSunMatrix);
       g_pSunMesh.DrawSubset(0);

       //
       // The Earth is a little more complicated since it needs to spin as well
       // as orbit the Sun. This can be done by combining three transformations
       // together.
       //

       D3DXMatrixRotationY(mEarthSpinRotation, D3DXToRadian(g_fEarthSpin));
       D3DXMatrixTranslation(mEarthTranslationToOrbit, 0.0, 0.0, 12.0);
       D3DXMatrixRotationY(mEarthOrbitRotation, D3DXToRadian(g_fEarthOrbit));

       //
       // Now, concatenate them together...
       // 1. Spin the Earth on its own axis.
       // 2. Then translate it away from the origin (where the Sun's at)
       // 3. and rotate it again to make it orbit the origin (or the Sun).
       //

       D3DXMatrixMultiply(mEarthMatrix, mEarthSpinRotation, mEarthTranslationToOrbit);
       D3DXMatrixMultiply(mEarthMatrix, mEarthMatrix,       mEarthOrbitRotation);

       g_pd3dDevice.SetTransform(D3DTS_WORLD, mEarthMatrix);
       g_pEarthMesh.DrawSubset(0);

       //
       // The Moon is the hardest to understand since it needs to not only spin on
       // its own axis and orbit the Earth, but needs to follow the Earth,
       // which is orbiting the Sun.
       //
       // This can be done by combining five transformations together with the last
       // two being borrowed from the Earth'
    s transformation.
       //

       D3DXMatrixRotationY(mMoonSpinRotation, D3DXToRadian(g_fMoonSpin));
       D3DXMatrixRotationY(mMoonOrbitRotation, D3DXToRadian(g_fMoonOrbit));
       D3DXMatrixTranslation(mMoonTranslationToOrbit, 0.0, 0.0, 2.0);

       //
       // The key to understanding the first three transforms is to pretend that
       // the Earth is located at the origin. We know it's not, but if we pretend
       // that it is, we can set up the Moon just like the we did the Earth since
       // the Moon orbits the Earth just like the Earth orbits the Sun.
       //
       // Once the Moon'
    s transforms are set up we simply reuse the Earth's
       // translation and rotation matrix, which placed it in orbit, to offset
       // the Moon out to where it should be... following the Earth.
       //

       //
       // Now, concatenate them together...
       // 1. Spin the Moon on its own axis.
       // 2. Then translate it away from the origin (pretending that the Earth is there)
       // 3. and rotate it again to make it orbit the origin (or the pretend Earth).
       // 4. Now, translate out to where the Earth is really at
       // 5. and move with it by matching its orbit of the Earth.
       //

       D3DXMatrixMultiply(mMoonMatrix, mMoonSpinRotation, mMoonTranslationToOrbit);
       D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mMoonOrbitRotation);
       D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthTranslationToOrbit);
       D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthOrbitRotation);

       g_pd3dDevice.SetTransform(D3DTS_WORLD, mMoonMatrix);
       g_pMoonMesh.DrawSubset(0);

     g_pd3dDevice.EndScene;

     g_pd3dDevice.Present(nil, nil, 0, nil);
    end;

  • Мистер Т (19.04.07 08:06) [7]
    Продолжение, второй вариант процедуры рендера:
    (*
    //-----------------------------------------------------------------------------
    // Name: Render()
    // Desc: Render a solar system using the D3DXMATRIX utility class and a matrix
    //       stack similar to OpenGL's. See the note below for details.
    //      
    // Note:
    //
    // Direct3D uses the world and view matrices that we set to configure several
    // internal data structures. Each time we set a new world or view matrix, the
    // system is forced to recalculate these internal structures. Therefore,
    // setting these matrices frequently, which is the case for applications that
    // require a high frame-rate, is computationally expensive. We can minimize
    // the number of required calculations by concatenating our world and view
    // matrices into a combined world-view matrix that we set as the world matrix.
    //
    // With the view matrix combined in with each world matrix that we set, we no
    // longer have to set the view matrix separately and incur its overhead.
    // Instead, we simply set the view matrix to the identity once and leave it
    // untouched during all calculations.
    //
    // For clarity, Direct3D samples rarely employ this optimization since it
    // confuses beginners.
    //
    //-----------------------------------------------------------------------------
    procedure Render;
    var
     matView                   : TD3DMatrix;

     mSunScale                 : TD3DMatrix;
     mSunSpinRotation          : TD3DMatrix;
     mSunMatrix                : TD3DMatrix;

     mEarthTranslationToOrbit  : TD3DMatrix;
     mEarthSpinRotation        : TD3DMatrix;
     mEarthOrbitRotation       : TD3DMatrix;
     mEarthMatrix              : TD3DMatrix;

     mMoonTranslationToOrbit   : TD3DMatrix;
     mMoonSpinRotation         : TD3DMatrix;
     mMoonOrbitRotation        : TD3DMatrix;
     mMoonMatrix               : TD3DMatrix;
    begin
     if g_pd3dDevice = nil then Exit;

     g_pd3dDevice.Clear(0,
                        nil,
                        D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
                        D3DCOLOR_COLORVALUE(0.0, 0.0, 0.0, 1.0),
                        1.0,
                        0);

     g_pd3dDevice.BeginScene;

       //
       // Have the view matrix move the view move us to a good vantage point so
       // we can see the Sun sitting at the origin while the Earth orbits it.
       //

       D3DXMatrixLookAtLH(matView,
                          D3DXVector3(0.0, 2.0, -25.0),  // Camera position
                          D3DXVector3(0.0, 0.0,   0.0),  // Look-at point
                          D3DXVector3(0.0, 1.0,   0.0)); // Up vector

       g_matrixStack.LoadIdentity;
       g_matrixStack.LoadMatrix(matView);

       //
       // Cache rotational positions between frames...
       //

       if g_bOrbitOn then
         begin
           g_fSunSpin    := g_fSunSpin     + (g_fSpeedmodifier * (g_fElpasedTime * 10.0));

           g_fEarthSpin  := g_fEarthSpin   + (g_fSpeedmodifier * (g_fElpasedTime * 100.0));
           g_fEarthOrbit := g_fEarthOrbit  + (g_fSpeedmodifier * (g_fElpasedTime * 20.0));

           g_fMoonSpin   := g_fMoonSpin    + (g_fSpeedmodifier * (g_fElpasedTime * 50.0));
           g_fMoonOrbit  := g_fMoonOrbit   + (g_fSpeedmodifier * (g_fElpasedTime * 200.0));
         end;

       //
       // The Sun is easy because the mesh for it is initially created centered
       // at origin. All we have to do is spin it by rotating it about the Y axis
       // and scale it by 5.0f.
       //

       D3DXMatrixRotationY(mSunSpinRotation, D3DXToRadian(g_fSunSpin));
       D3DXMatrixScaling(mSunScale, 5.0, 5.0, 5.0);

       //
       // Now, concatenate them together...
       // 1. Uniformly scale the Sun up in size
       // 2. and then spin it on its axis.
       //

       D3DXMatrixMultiply(mSunMatrix, mSunScale, mSunSpinRotation);

       g_matrixStack.Push;
         g_matrixStack.MultMatrixLocal(mSunMatrix);
         g_pd3dDevice.SetTransform(D3DTS_WORLD, g_matrixStack.GetTop^);
         g_pSunMesh.DrawSubset(0);
       g_matrixStack.Pop;

       //
       // The Earth is a little more complicated since it needs to spin as well
       // as orbit the Sun. This can be done by combining three transformations
       // together.
       //

       D3DXMatrixRotationY(mEarthSpinRotation, D3DXToRadian(g_fEarthSpin));
       D3DXMatrixTranslation(mEarthTranslationToOrbit, 0.0, 0.0, 12.0);
       D3DXMatrixRotationY(mEarthOrbitRotation, D3DXToRadian(g_fEarthOrbit));

       //
       // Now, concatenate them together...
       // 1. Spin the Earth on its own axis.
       // 2. Then translate it away from the origin (where the Sun'
    s at)
       // 3. and rotate it again to make it orbit the origin (or the Sun).
       //

       D3DXMatrixMultiply(mEarthMatrix, mEarthSpinRotation, mEarthTranslationToOrbit);
       D3DXMatrixMultiply(mEarthMatrix, mEarthMatrix,       mEarthOrbitRotation);

       g_matrixStack.Push;
         g_matrixStack.MultMatrixLocal(mEarthMatrix);
         g_pd3dDevice.SetTransform(D3DTS_WORLD, g_matrixStack.GetTop^);
         g_pEarthMesh.DrawSubset(0);
       g_matrixStack.Pop;

       //
       // The Moon is the hardest to understand since it needs to not only spin on
       // its own axis and orbit the Earth, but needs to follow the Earth,
       // which is orbiting the Sun.
       //
       // This can be done by combining five transformations together with the last
       // two being borrowed from the Earth's transformation.
       //

       D3DXMatrixRotationY(mMoonSpinRotation, D3DXToRadian(g_fMoonSpin));
       D3DXMatrixRotationY(mMoonOrbitRotation, D3DXToRadian(g_fMoonOrbit));
       D3DXMatrixTranslation(mMoonTranslationToOrbit, 0.0, 0.0, 2.0);

       //
       // The key to understanding the first three transforms is to pretend that
       // the Earth is located at the origin. We know it'
    s not, but if we pretend
       // that it is, we can set up the Moon just like the we did the Earth since
       // the Moon orbits the Earth just like the Earth orbits the Sun.
       //
       // Once the Moon's transforms are set up we simply reuse the Earth's
       // translation and rotation matrix, which placed it in orbit, to offset
       // the Moon out to where it should be... following the Earth.
       //

       //
       // Now, concatenate them together...
       // 1. Spin the Moon on its own axis.
       // 2. Then translate it away from the origin (pretending that the Earth is there)
       // 3. and rotate it again to make it orbit the origin (or the pretend Earth).
       // 4. Now, translate out to where the Earth is really at
       // 5. and move with it by matching its orbit of the Earth.
       //

       D3DXMatrixMultiply(mMoonMatrix, mMoonSpinRotation, mMoonTranslationToOrbit);
       D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mMoonOrbitRotation);
       D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthTranslationToOrbit);
       D3DXMatrixMultiply(mMoonMatrix, mMoonMatrix, mEarthOrbitRotation);

       g_matrixStack.Push;
         g_matrixStack.MultMatrixLocal(mMoonMatrix);
         g_pd3dDevice.SetTransform(D3DTS_WORLD, g_matrixStack.GetTop^);
         g_pMoonMesh.DrawSubset(0);
       g_matrixStack.Pop;

     g_pd3dDevice.EndScene;

     g_pd3dDevice.Present(nil, nil, 0, nil);

    end;
    *)

  • Мистер Т (19.04.07 08:07) [8]
    Завершение второго примера:
    //-----------------------------------------------------------------------------
    // Name:
    // Desc: The application's entry point
    //-----------------------------------------------------------------------------
    begin
     ZeroMemory(@uMsg, SizeOf(MSG));
     ZeroMemory(@winClass, SizeOf(WNDCLASSEX));

     with winClass do
       begin
         lpszClassName := '
    MY_WINDOWS_CLASS';
         cbSize        := SizeOf(WNDCLASSEX);
         style         := CS_HREDRAW or CS_VREDRAW;
         lpfnWndProc   := @WindowProc;
         hInstance     := hInstance;
         hIcon         := LoadIcon(hInstance, IDI_APPLICATION);
         hIconSm       := LoadIcon(hInstance, IDI_APPLICATION);
         hCursor       := LoadCursor(0, IDC_ARROW);
         hbrBackground := $000000;
         lpszMenuName  := nil;
         cbClsExtra    := 0;
         cbWndExtra    := 0;
       end;

     if (RegisterClassEx(winClass) = 0) then
       Halt(0);

     g_hWnd := CreateWindowEx(0,
                                winClass.lpszClassName,
                                '
    Direct3D (DX9) - Transforms',
                                WS_OVERLAPPEDWINDOW or WS_VISIBLE,
                                0,
                                0,
                                640,
                                480,
                                0,
                                0,
                                winClass.hInstance,
                                nil);

     if g_hWnd = 0 then
       Halt(0);

     ShowWindow(g_hWnd, SW_SHOW);
     UpdateWindow(g_hWnd);

     Init;

     g_dLastTime := timeGetTime;

     while (uMsg.message <> WM_QUIT) do
       begin
         if PeekMessage(uMsg, 0, 0, 0, PM_REMOVE) then
           begin
             TranslateMessage(uMsg);
             DispatchMessage(uMsg);
           end
         else
           begin
             g_dCurrentTime := timeGetTime;
             g_fElpasedTime := ((g_dCurrentTime - g_dLastTime) * 0.001);
             g_dLastTime    := g_dCurrentTime;

             Render;
           end;
       end;

     ShutDown;

     UnregisterClass(winClass.lpszClassName, winClass.hInstance);
    end.

  • Piroxyline © (21.04.07 17:53) [9]
    Должны были вращаться так, чтобы первый (который вначале ближе к нам) перекрывался потом вторым. Решение оказалось простым, когда я посмотрел другие примеры и сравнил с этим кодом: надо было Z-буффер поставить :) Так привый к OpenGL'ю, в котором это делается не задумываясь, что забыл совсем
 
Конференция "Игры" » Пример из туториала по Direct3D [Delphi, Windows]
Есть новые Нет новых   [134430   +2][b:0][p:0.028]