Конференция "Игры" » Класс тени в DirectX [Delphi, Windows]
 
  • ElectriC © (22.04.07 21:56) [0]
    Плиз, помогите перевести нижеприведённый класс тени с C++ на Pascal(Delphi).

    class ShadowVolume
    {
    public:

       void    reset() { m_dwNumVertices = 0L; }
       HRESULT buildShadowVolume( LPD3DXMESH pObject, D3DXVECTOR3 vLight );
       HRESULT render( LPDIRECT3DDEVICE9 pd3dDevice );

    private:

    void addEdge( WORD* pEdges, DWORD& dwNumEdges, WORD v0, WORD v1 );

    D3DXVECTOR3 m_pVertices[32000];
       DWORD       m_dwNumVertices;
    };

    struct ShadowVertex
    {
       D3DXVECTOR4 p;
       D3DCOLOR    color;

    enum FVF
    {
     FVF_Flags = D3DFVF_XYZRHW | D3DFVF_DIFFUSE
    };
    };

    HRESULT ShadowVolume::render( LPDIRECT3DDEVICE9 pd3dDevice )
    {
       pd3dDevice->SetFVF( D3DFVF_XYZ );

       return pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, m_dwNumVertices/3,
                                           m_pVertices, sizeof(D3DXVECTOR3) );
    }

    HRESULT ShadowVolume::buildShadowVolume( LPD3DXMESH pMesh, D3DXVECTOR3 vLight )
    {
    struct MeshVertex { D3DXVECTOR3 p, n; };

       MeshVertex *pVertices;
       WORD       *pIndices;

       pMesh->LockVertexBuffer( 0L, (LPVOID*)&pVertices );
       pMesh->LockIndexBuffer( 0L, (LPVOID*)&pIndices );
       DWORD dwNumFaces    = pMesh->GetNumFaces();

       WORD *pEdges = new WORD[dwNumFaces*6];

       if( pEdges == NULL )
       {
           pMesh->UnlockVertexBuffer();
           pMesh->UnlockIndexBuffer();
           return E_OUTOFMEMORY;
       }

       DWORD dwNumEdges = 0;

       for( DWORD i = 0; i < dwNumFaces; ++i )
       {
           WORD wFace0 = pIndices[3*i+0];
           WORD wFace1 = pIndices[3*i+1];
           WORD wFace2 = pIndices[3*i+2];

           D3DXVECTOR3 v0 = pVertices[wFace0].p;
           D3DXVECTOR3 v1 = pVertices[wFace1].p;
           D3DXVECTOR3 v2 = pVertices[wFace2].p;

           D3DXVECTOR3 vCross1(v2-v1);
           D3DXVECTOR3 vCross2(v1-v0);
           D3DXVECTOR3 vNormal;
           D3DXVec3Cross( &vNormal, &vCross1, &vCross2 );

           if( D3DXVec3Dot( &vNormal, &vLight ) >= 0.0f )
           {
               addEdge( pEdges, dwNumEdges, wFace0, wFace1 );
               addEdge( pEdges, dwNumEdges, wFace1, wFace2 );
               addEdge( pEdges, dwNumEdges, wFace2, wFace0 );
           }
       }

       for( i = 0; i < dwNumEdges; ++i )
       {
           D3DXVECTOR3 v1 = pVertices[pEdges[2*i+0]].p;
           D3DXVECTOR3 v2 = pVertices[pEdges[2*i+1]].p;
           D3DXVECTOR3 v3 = v1 - vLight*10;
           D3DXVECTOR3 v4 = v2 - vLight*10;

           m_pVertices[m_dwNumVertices++] = v1;
           m_pVertices[m_dwNumVertices++] = v2;
           m_pVertices[m_dwNumVertices++] = v3;

           m_pVertices[m_dwNumVertices++] = v2;
           m_pVertices[m_dwNumVertices++] = v4;
           m_pVertices[m_dwNumVertices++] = v3;
       }

       delete[] pEdges;

       pMesh->UnlockVertexBuffer();
       pMesh->UnlockIndexBuffer();

       return S_OK;
    }

    void ShadowVolume::addEdge( WORD* pEdges, DWORD& dwNumEdges, WORD v0, WORD v1 )
    {
       for( DWORD i = 0; i < dwNumEdges; ++i )
       {
           if( ( pEdges[2*i+0] == v0 && pEdges[2*i+1] == v1 ) ||
               ( pEdges[2*i+0] == v1 && pEdges[2*i+1] == v0 ) )
           {
               if( dwNumEdges > 1 )
               {
                   pEdges[2*i+0] = pEdges[2*(dwNumEdges-1)+0];
                   pEdges[2*i+1] = pEdges[2*(dwNumEdges-1)+1];
               }

               --dwNumEdges;
               return;
           }
       }

       pEdges[2*dwNumEdges+0] = v0;
       pEdges[2*dwNumEdges+1] = v1;
       dwNumEdges++;
    }
  • Sapersky (23.04.07 13:05) [1]
    См. пример ShadowVolume из SDK 8 ( http://www.clootie.ru ).
  • ElectriC © (23.04.07 19:43) [2]
    Переделал под DirectX 9, всё равно не выходит.
    Пишет: ошибка доступа 0x040545c: не могу прочитать по адресу 0xd92d48e8.
    Переключаюсь в asm(окно CPU):
    Указатель стоит на строке mov [eax*4+m_pVertices], edx.
    Возможно ошибка в строке: MeshObj.LockVertexBuffer(0, Pointer(pVertices));
    Не подскажите, в чём, может быть, ошибка?

    Код модуля:
    ...

    type
     TVertex = packed record
       p: TD3DXVector3;
       n: TD3DXVector3;
       tu, tv: Single;
     end;
     PVertexArray = ^TVertexArray;
     TVertexArray = array [0..0] of TVertex;

     TShadowVertex = packed record
       p: TD3DXVector4;
       color: TD3DColor;
     end;
     PShadowVertexArray = ^TShadowVertexArray;
     TShadowVertexArray = array [0..MaxInt div SizeOf(TShadowVertex) - 1] of TShadowVertex;

    const
     D3DFVF_VERTEX         = D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_TEX1;
     D3DFVF_SHADOWVERTEX   = D3DFVF_XYZRHW or D3DFVF_DIFFUSE;

    var
     m_pVertices : array [0..32000-1] of TD3DXVector3;
     m_dwNumVertices: DWORD;

    implementation

    procedure Render;
    begin
     with SLEngine.SLD3DDevice do
      begin
        SetFVF(D3DFVF_XYZ);
        DrawPrimitiveUP(D3DPT_TRIANGLELIST, m_dwNumVertices div 3, m_pVertices,
                        SizeOf(TD3DXVector3));
      end;
    end;

    procedure AddEdge(var pEdges : array of Word; var dwNumEdges : DWORD; v0, v1 : Word);
    var i : Integer;
    begin
     for i := 0 to (dwNumEdges - 1) do
      begin
        If ((pEdges[2 * i + 0] = v0) and (pEdges[2 * i + 1] = v1)) or
           ((pEdges[2 * i + 0] = v1) and (pEdges[2 * i + 1] = v0)) then
         begin
           If dwNumEdges > 1 then
            begin
              pEdges[2 * i + 0] := pEdges[2 * (dwNumEdges - 1) + 0];
              pEdges[2 * i + 1] := pEdges[2 * (dwNumEdges - 1) + 1];
            end;
           Dec(dwNumEdges); Exit;
         end;
      end;

     pEdges[2 * dwNumEdges + 0] := v0;
     pEdges[2 * dwNumEdges + 1] := v1;
     Inc(dwNumEdges);
    end;

    function BuildFromMesh(vLight: TD3DXVector3) : HRESULT;
    type
     PMeshVertex = ^TMeshVertex;
     TMeshVertex = packed record
       p, n   : TD3DXVector3;
       tu, tv : Single;
     end;

     PMeshVertexArray = ^TMeshVertexArray;
     TMeshVertexArray = array [0..0] of TMeshVertex;

    var
    //  dwFVF: DWORD;
     pVertices  : PMeshVertexArray;
     pIndices   : PWordArray;

    //  dwNumVertices: DWORD;
     dwNumFaces : DWORD;

     pEdges     : array of Word;
     dwNumEdges : DWord;

     i          : Integer;

     wFace0, wFace1, wFace2 : Word;
     v0, v1, v2, v3, v4     : TD3DXVector3;
     v001, v002             : TD3DXVector3;

     vNormal                : TD3DXVector3;

    begin
     // Note: the MESHVERTEX format depends on the FVF of the mesh
     // dwFVF := pMesh.GetFVF;

     // Lock the geometry buffers
     MeshObj.LockVertexBuffer(0, Pointer(pVertices));
     MeshObj.LockIndexBuffer (0, Pointer(pIndices));
     // dwNumVertices := pMesh.GetNumVertices;
     dwNumFaces    := MeshObj.GetNumFaces;

     // Allocate a temporary edge list
     SetLength(pEdges, dwNumFaces * 6);
     dwNumEdges:= 0;

     // For each face
     for i:= 0 to (dwNumFaces - 1) do
      begin
        wFace0 := pIndices[3 * i + 0];
        wFace1 := pIndices[3 * i + 1];
        wFace2 := pIndices[3 * i + 2];

        v0 := pVertices[wFace0].p;
        v1 := pVertices[wFace1].p;
        v2 := pVertices[wFace2].p;

        // Transform vertices or transform light?
        D3DXVec3Cross(vNormal, D3DXVec3Subtract(v001, v2, v1)^,
                               D3DXVec3Subtract(v002, v1, v0)^);

        If (D3DXVec3Dot(vNormal, vLight) >= 0.0) then
         begin
           AddEdge(pEdges, dwNumEdges, wFace0, wFace1);
           AddEdge(pEdges, dwNumEdges, wFace1, wFace2);
           AddEdge(pEdges, dwNumEdges, wFace2, wFace0);
         end;
      end;

     for i := 0 to (dwNumEdges - 1) do
      begin
        v1 := pVertices[pEdges[2 * i + 0]].p;
        v2 := pVertices[pEdges[2 * i + 1]].p;
        D3DXVec3Scale(v001, vLight, 10);
        // D3DXVECTOR3 v3 = v1 - vLight*10;
        D3DXVec3Subtract(v3, v1, v001);
        // D3DXVECTOR3 v4 = v2 - vLight*10;
        D3DXVec3Subtract(v4, v2, v001);

        // Add a quad (two triangles) to the vertex list
        m_pVertices[m_dwNumVertices] := v1; Inc(m_dwNumVertices);
        m_pVertices[m_dwNumVertices] := v2; Inc(m_dwNumVertices);
        m_pVertices[m_dwNumVertices] := v3; Inc(m_dwNumVertices);

        m_pVertices[m_dwNumVertices] := v2; Inc(m_dwNumVertices);
        m_pVertices[m_dwNumVertices] := v4; Inc(m_dwNumVertices);
        m_pVertices[m_dwNumVertices] := v3; Inc(m_dwNumVertices);
      end;
     // Delete the temporary edge list
     SetLength(pEdges, 0);

     // Unlock the geometry buffers
     MeshObj.UnlockVertexBuffer;
     MeshObj.UnlockIndexBuffer;

     Result := S_OK;
    end;

    P.S. MeshObj : ID3DXMesh - уже загруженная и готовая модель.
  • ElectriC © (24.04.07 13:29) [3]
    Удалено модератором
    Примечание: Создание пустых сообщений
 
Конференция "Игры" » Класс тени в DirectX [Delphi, Windows]
Есть новые Нет новых   [119243   +1][b:0][p:0]