体积阴影GPU实现--数据预处理

HRESULT CShadow::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXMESH pMesh )
{
  BASEMESHVERTEX*   pVertices;
  WORD*             pIndices;
  EdgeMap           edgeMap; //sharing edges
  EdgeMap::iterator edgeMapIter;
  DWORD             dwNumSavedEdges = 0L; // No of coplanar edges optimized
  DWORD             dwI;


  ShadowVertices    shadowVerticesVector;  //存放网格预处理之后,添加了退化四边形后的顶点数组
  ShadowIndices     shadowIndicesVector; //同上,索引数组


  // Copy pointer to d3d device
  if ( pd3dDevice )
m_pd3dDevice = pd3dDevice;
  else
return E_FAIL;


  // Lock the geometry buffers
  pMesh->LockVertexBuffer( D3DLOCK_READONLY, (VOID**)&pVertices );
  pMesh->LockIndexBuffer( D3DLOCK_READONLY, (VOID**)&pIndices );
  DWORD dwNumSourceVertices     = pMesh->GetNumVertices();
  DWORD dwNumFaces              = pMesh->GetNumFaces();
  
  // Step thru all faces
  for ( DWORD faceIndex=0; faceIndex   {
    WORD wIndex0 = pIndices[3*faceIndex+0];
    WORD wIndex1 = pIndices[3*faceIndex+1];
    WORD wIndex2 = pIndices[3*faceIndex+2];


    D3DXVECTOR3 v0 = pVertices[wIndex0].p;
    D3DXVECTOR3 v1 = pVertices[wIndex1].p;
    D3DXVECTOR3 v2 = pVertices[wIndex2].p;


    // Compute face normal
    D3DXVECTOR3 faceNormal;
    D3DXVec3Cross( &faceNormal, &( v2 - v0 ), &( v1 - v0 ) );
    D3DXVec3Normalize( &faceNormal, &faceNormal );


    // Create shadow mesh vertices for current face
    SHADOWMESHVERTEX shadowVertices[3];
    for ( DWORD vertIndex = 0; vertIndex < 3; vertIndex++ )
    {
shadowVertices[vertIndex].p = pVertices[pIndices[3*faceIndex+vertIndex]].p;
      // There was a time when a typo (.p instead of .n) caused me 6 hours...
shadowVertices[vertIndex].n = faceNormal;
    }


    // Search edgeMap for a possible partner edge to the current edge 
    // e.g. Equivalent positions
    EdgePositions edgePositions[3];
    EdgeData sharedEdgesData[3];
    EdgePositions edgeToFind;
    BOOL edgeFound[3];
    BOOL quadRequired[3];
//检查当前面的每一边,是否为共享边,如果是,检查法线是否平行,不平行的才需要插入退化四边形
    for ( DWORD edgeIndex = 0; edgeIndex < 3; edgeIndex++ )
    {
      edgePositions[edgeIndex].p0 = shadowVertices[edgeIndex].p;
      edgePositions[edgeIndex].p1 = shadowVertices[( edgeIndex + 1 ) % 3].p;


      // Find shared edge with reverse vertices
      edgeToFind.p0 = edgePositions[edgeIndex].p1;
      edgeToFind.p1 = edgePositions[edgeIndex].p0;
      edgeMapIter = edgeMap.find( edgeToFind );


      // Did we find it?
      if ( edgeMapIter != edgeMap.end() ) // Found!
      {
edgeFound[edgeIndex] = TRUE;
sharedEdgesData[edgeIndex] = edgeMapIter->second;
edgeMap.erase( edgeMapIter );


// We can optimize away coplanar shared edges. e.g. their normals are 
// almost parallel
if ( ( D3DXVec3Dot( &faceNormal, &sharedEdgesData[edgeIndex].n0 ) ) < 
              MERGE_COS_ANGLE_PROXIMITY )
{
quadRequired[edgeIndex] = TRUE;
}
else
{
quadRequired[edgeIndex] = FALSE;
dwNumSavedEdges++;
}
      }
      else  // New
 {
edgeFound[edgeIndex] = FALSE;
 }
    }


// Selected index of vertices
//如果当前边是共享边,已经被优化(不需要加入退化四边形),直接将它的顶点和索引数据放入shadowVerticesVector shadowIndicesVector
//如果当前边不是共享边(新发现的),或者需要加入退化四边形,添加新的顶点和索引数据
    WORD index[3]; 
    for ( DWORD vertIndex=0; vertIndex<3; vertIndex++ )
    {
// Vertex creation
DWORD edgeIndex0  = vertIndex;              // 0, 1, 2
DWORD edgeIndex1  = ( vertIndex + 2 ) % 3;  // 2, 0, 1
// We check whether the current edge had been optimized away
// If it is, we just need to copy the index from the shared edge since 
// the current vertex is gone
if ( ( edgeFound[edgeIndex0] ) && ( !quadRequired[edgeIndex0] ) )
{
index[vertIndex] = sharedEdgesData[edgeIndex0].i1;
}
else if ( ( edgeFound[edgeIndex1] ) && ( !quadRequired[edgeIndex1] ) )
{
index[vertIndex] = sharedEdgesData[edgeIndex1].i0;
}
else  // No optimization, new vertex OR degenerate quad required
{
// Current size = index
index[vertIndex] = (WORD)shadowVerticesVector.size();
// Store current vertex
shadowVerticesVector.push_back( shadowVertices[vertIndex] );
}


// Index creation
shadowIndicesVector.push_back( index[vertIndex] );
}


    // Time to create the degenerate quads
    for ( DWORD edgeIndex = 0; edgeIndex < 3; edgeIndex++ )
    {
EdgeData edgeData;
edgeData.i0   = index[edgeIndex];             // 0, 1, 2
edgeData.i1   = index[( edgeIndex + 1 ) % 3]; // 1, 2, 0
edgeData.n0   = faceNormal;
if ( edgeFound[edgeIndex] ) // Shared edge found
{
// Handle 3 cases: Insert full quad, insert left side tri or insert 
// right side tri
// If current edge had NOT been optimized away
if ( ( sharedEdgesData[edgeIndex].i0 != edgeData.i1 ) && 
( sharedEdgesData[edgeIndex].i1 != edgeData.i0 ) )
{
shadowIndicesVector.push_back( edgeData.i1 );
shadowIndicesVector.push_back( edgeData.i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i1 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i0 );
shadowIndicesVector.push_back( edgeData.i0 );
}
else if ( sharedEdgesData[edgeIndex].i1 != edgeData.i0 )
{
shadowIndicesVector.push_back( edgeData.i1 );
shadowIndicesVector.push_back( edgeData.i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i1 );
}
else if( sharedEdgesData[edgeIndex].i0 != edgeData.i1 )
{
shadowIndicesVector.push_back( edgeData.i1 );
shadowIndicesVector.push_back( edgeData.i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i0 );
}
// All other cases meant that the current edge had been optimized away 
// and only the shared edge is left. The shared edge is left alone with 
// additional degenerate triangles added
}
else  // New edge
{
edgeMap[edgePositions[edgeIndex]] = edgeData;
}
}
  }


  // Gather some stats
  m_dwVertexBufferSize  = (DWORD)shadowVerticesVector.size();
  m_dwIndexBufferSize   = (DWORD)shadowIndicesVector.size();
  
  // ********** Create vertex and index buffers **********
  // Create index buffer
  if ( FAILED( m_pd3dDevice->CreateIndexBuffer( m_dwIndexBufferSize * 
        sizeof( WORD ), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, 
            &m_pIndexBuffer, NULL ) ) )
  {
    OutputDebugString( "Index buffer creation failed!\n" );
    return E_FAIL;
  }


  // Lock index buffer
  WORD* pLockedIndexBuffer;
  m_pIndexBuffer->Lock( 0, m_dwIndexBufferSize * sizeof( WORD ), 
        (VOID**)&pLockedIndexBuffer, 0 );


  // Fill locked index buffer with data
  IndexIter indexIter;
  for ( indexIter = shadowIndicesVector.begin(), dwI = 0; 
        indexIter != shadowIndicesVector.end(); ++indexIter, dwI++ )
  {
    pLockedIndexBuffer[dwI] = (WORD)*indexIter;
  }
  m_pIndexBuffer->Unlock();


  // Create vertex buffer
  if ( FAILED( m_pd3dDevice->CreateVertexBuffer( m_dwVertexBufferSize * 
        sizeof( SHADOWMESHVERTEX ), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, 
            &m_pVertexBuffer, NULL ) ) )
  {
    OutputDebugString( "Vertex buffer creation failed!\n" );
    return E_FAIL;
  }


  // Lock vertex buffer
  SHADOWMESHVERTEX* pLockedVertexBuffer;
  VertexIter vertexIter;
  m_pVertexBuffer->Lock( 0, m_dwVertexBufferSize * sizeof( SHADOWMESHVERTEX ), 
        (VOID**)&pLockedVertexBuffer, 0 );
  // Fill locked vertex buffer with data
  for ( vertexIter=shadowVerticesVector.begin(), dwI=0; 
        vertexIter != shadowVerticesVector.end(); ++vertexIter, dwI++ )
  {
    pLockedVertexBuffer[dwI] = *vertexIter;
  }

  m_pVertexBuffer->Unlock();

}

你可能感兴趣的:(Engine)