Конференция "Игры" » Как построить Shadow Volume для произвольного объекта?
 
  • @!!ex_ (05.06.07 12:41) [0]
    Сабж. Че то я никак не фтыкаю как по модельке построить SV.
  • Sapersky (05.06.07 13:45) [1]
    Из DX8 SDK (геометрические расчёты везде одинаковы):

    Each frame, the sihlouette of the plane is computed (using an edge detection algorithm, in which sihlouette edges are found because the normals of adjacent polygons will have opposing normals with respect to the light vector). The resulting edge list (the sihlouette) is pretuded into a 3D object away from the light source. This 3D object is known as the shadow volume, as everypoint inside the volume is inside a shadow.

    //-----------------------------------------------------------------------------
    // Name: AddEdge()
    // Desc: Adds an edge to a list of silohuette edges of a shadow volume.
    //-----------------------------------------------------------------------------
    procedure AddEdge(var pEdges: array of Word; var dwNumEdges: DWord; v0, v1: Word);
    var
     i: Integer;
    begin
     // Remove interior edges (which appear in the list twice)
     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;

    //-----------------------------------------------------------------------------
    // Name: BuildFromMesh()
    // Desc: Takes a mesh as input, and uses it to build a shadowvolume. The
    //       technique used considers each triangle of the mesh, and adds it's
    //       edges to a temporary list. The edge list is maintained, such that
    //       only silohuette edges are kept. Finally, the silohuette edges are
    //       extruded to make the shadow volume vertex list.
    //-----------------------------------------------------------------------------
    function TShadowVolume.BuildFromMesh(pMesh: ID3DXMesh;
     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
     pMesh.LockVertexBuffer(0, PByte(pVertices));
     pMesh.LockIndexBuffer(0, PByte(pIndices));
     // dwNumVertices := pMesh.GetNumVertices;
     dwNumFaces    := pMesh.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
     pMesh.UnlockVertexBuffer;
     pMesh.UnlockIndexBuffer;

     Result := S_OK;
    end;
  • @!!ex_ (05.06.07 13:52) [2]
    А с каких пор примеры из СДК на дельфе? :))
    Спасибо!
  • ElectriC © (06.06.07 16:46) [3]

    > А с каких пор примеры из СДК на дельфе

    С тех пор, как появился дельфи и clootie.ru;)
  • @!!ex_ (06.06.07 17:40) [4]
    > С тех пор, как появился дельфи и clootie.ru;)

    Так это не СДК. Вернее если и СДК, то не оффициальный.

    Кстати, тут продолжение вопроса.
    У меня объект по сцене вращается и перемещается стандартными средствами Дельфи.
    Я правильно понимаю, нужно источник света умножить на матрицу обратную матрицы преобразования, чтобы получить правильный SV?
  • Sapersky (06.06.07 18:53) [5]
    Похоже что да:

     // Transform the light vector to be in object space
     D3DXMatrixInverse(m, nil, m_matObjectMatrix);
     vLight.x := Lx*m._11 + Ly*m._21 + Lz*m._31 + m._41;
     vLight.y := Lx*m._12 + Ly*m._22 + Lz*m._32 + m._42;
     vLight.z := Lx*m._13 + Ly*m._23 + Lz*m._33 + m._43;

     // Build the shadow volume
     m_pShadowVolume.Reset;
     m_pShadowVolume.BuildFromMesh(m_pAirplane.GetSysMemMesh, vLight);
  • @!!ex_ (06.06.07 19:04) [6]
    Отлично, сенька.
  • @!!ex_ (06.06.07 19:14) [7]
    Мля. Две печатки заметил. Не средствами Дельфи, а средствами ОГЛ.
    И не источник умножать, а его позицию...
    :-[
  • имя (24.05.08 15:12) [8]
    Удалено модератором
  • имя (24.05.08 15:12) [9]
    Удалено модератором
 
Конференция "Игры" » Как построить Shadow Volume для произвольного объекта?
Есть новые Нет новых   [134430   +2][b:0][p:0]