📄 shadowvolume.cpp
字号:
CopyMemory( pPatchVBData, pNewVBData, sizeof(SHADOWVERT) * pInputMesh->GetNumFaces() * 3 );
CopyMemory( pdwPatchIBData, pdwNewIBData, sizeof(DWORD) * nNextIndex );
} else
{
// Some serious error is preventing us from locking.
// Abort and return error.
pPatchMesh->Release();
goto cleanup;
}
// Replace pNewMesh with the updated one. Then the code
// can continue working with the pNewMesh pointer.
pNewMesh->UnlockVertexBuffer();
pNewMesh->UnlockIndexBuffer();
pNewVBData = pPatchVBData;
pdwNewIBData = pdwPatchIBData;
pNewMesh->Release();
pNewMesh = pPatchMesh;
// Now, we iterate through the edge mapping table and
// for each shared edge, we generate a quad.
// For each non-shared edge, we patch the opening
// with new faces.
// nNextVertex is the index of the next vertex.
int nNextVertex = pInputMesh->GetNumFaces() * 3;
for( int i = 0; i < nNumMaps; ++i )
{
if( pMapping[i].m_anOldEdge[0] != -1 &&
pMapping[i].m_anOldEdge[1] != -1 )
{
// If the 2nd new edge indexes is -1,
// this edge is a non-shared one.
// We patch the opening by creating new
// faces.
if( pMapping[i].m_aanNewEdge[1][0] == -1 || // must have only one new edge
pMapping[i].m_aanNewEdge[1][1] == -1 )
{
// Find another non-shared edge that
// shares a vertex with the current edge.
for( int i2 = i + 1; i2 < nNumMaps; ++i2 )
{
if( pMapping[i2].m_anOldEdge[0] != -1 && // must have a valid old edge
pMapping[i2].m_anOldEdge[1] != -1 &&
( pMapping[i2].m_aanNewEdge[1][0] == -1 || // must have only one new edge
pMapping[i2].m_aanNewEdge[1][1] == -1 ) )
{
int nVertShared = 0;
if( pMapping[i2].m_anOldEdge[0] == pMapping[i].m_anOldEdge[1] )
++nVertShared;
if( pMapping[i2].m_anOldEdge[1] == pMapping[i].m_anOldEdge[0] )
++nVertShared;
if( 2 == nVertShared )
{
// These are the last two edges of this particular
// opening. Mark this edge as shared so that a degenerate
// quad can be created for it.
pMapping[i2].m_aanNewEdge[1][0] = pMapping[i].m_aanNewEdge[0][0];
pMapping[i2].m_aanNewEdge[1][1] = pMapping[i].m_aanNewEdge[0][1];
break;
}
else
if( 1 == nVertShared )
{
// nBefore and nAfter tell us which edge comes before the other.
int nBefore, nAfter;
if( pMapping[i2].m_anOldEdge[0] == pMapping[i].m_anOldEdge[1] )
{
nBefore = i;
nAfter = i2;
} else
{
nBefore = i2;
nAfter = i;
}
// Found such an edge. Now create a face along with two
// degenerate quads from these two edges.
pNewVBData[nNextVertex] = pNewVBData[pMapping[nAfter].m_aanNewEdge[0][1]];
pNewVBData[nNextVertex+1] = pNewVBData[pMapping[nBefore].m_aanNewEdge[0][1]];
pNewVBData[nNextVertex+2] = pNewVBData[pMapping[nBefore].m_aanNewEdge[0][0]];
// Recompute the normal
D3DXVECTOR3 v1 = pNewVBData[nNextVertex+1].Position - pNewVBData[nNextVertex].Position;
D3DXVECTOR3 v2 = pNewVBData[nNextVertex+2].Position - pNewVBData[nNextVertex+1].Position;
D3DXVec3Normalize( &v1, &v1 );
D3DXVec3Normalize( &v2, &v2 );
D3DXVec3Cross( &pNewVBData[nNextVertex].Normal, &v1, &v2 );
pNewVBData[nNextVertex+1].Normal = pNewVBData[nNextVertex+2].Normal = pNewVBData[nNextVertex].Normal;
pdwNewIBData[nNextIndex] = nNextVertex;
pdwNewIBData[nNextIndex+1] = nNextVertex + 1;
pdwNewIBData[nNextIndex+2] = nNextVertex + 2;
// 1st quad
pdwNewIBData[nNextIndex+3] = pMapping[nBefore].m_aanNewEdge[0][1];
pdwNewIBData[nNextIndex+4] = pMapping[nBefore].m_aanNewEdge[0][0];
pdwNewIBData[nNextIndex+5] = nNextVertex + 1;
pdwNewIBData[nNextIndex+6] = nNextVertex + 2;
pdwNewIBData[nNextIndex+7] = nNextVertex + 1;
pdwNewIBData[nNextIndex+8] = pMapping[nBefore].m_aanNewEdge[0][0];
// 2nd quad
pdwNewIBData[nNextIndex+9] = pMapping[nAfter].m_aanNewEdge[0][1];
pdwNewIBData[nNextIndex+10] = pMapping[nAfter].m_aanNewEdge[0][0];
pdwNewIBData[nNextIndex+11] = nNextVertex;
pdwNewIBData[nNextIndex+12] = nNextVertex + 1;
pdwNewIBData[nNextIndex+13] = nNextVertex;
pdwNewIBData[nNextIndex+14] = pMapping[nAfter].m_aanNewEdge[0][0];
// Modify mapping entry i2 to reflect the third edge
// of the newly added face.
if( pMapping[i2].m_anOldEdge[0] == pMapping[i].m_anOldEdge[1] )
{
pMapping[i2].m_anOldEdge[0] = pMapping[i].m_anOldEdge[0];
} else
{
pMapping[i2].m_anOldEdge[1] = pMapping[i].m_anOldEdge[1];
}
pMapping[i2].m_aanNewEdge[0][0] = nNextVertex + 2;
pMapping[i2].m_aanNewEdge[0][1] = nNextVertex;
// Update next vertex/index positions
nNextVertex += 3;
nNextIndex += 15;
break;
}
}
}
} else
{
// This is a shared edge. Create the degenerate quad.
// First triangle
pdwNewIBData[nNextIndex++] = pMapping[i].m_aanNewEdge[0][1];
pdwNewIBData[nNextIndex++] = pMapping[i].m_aanNewEdge[0][0];
pdwNewIBData[nNextIndex++] = pMapping[i].m_aanNewEdge[1][0];
// Second triangle
pdwNewIBData[nNextIndex++] = pMapping[i].m_aanNewEdge[1][1];
pdwNewIBData[nNextIndex++] = pMapping[i].m_aanNewEdge[1][0];
pdwNewIBData[nNextIndex++] = pMapping[i].m_aanNewEdge[0][0];
}
}
}
}
cleanup:;
if( pNewVBData )
{
pNewMesh->UnlockVertexBuffer();
pNewVBData = NULL;
}
if( pdwNewIBData )
{
pNewMesh->UnlockIndexBuffer();
pdwNewIBData = NULL;
}
if( SUCCEEDED( hr ) )
{
// At this time, the output mesh may have an index buffer
// bigger than what is actually needed, so we create yet
// another mesh with the exact IB size that we need and
// output it. This mesh also uses 16-bit index if
// 32-bit is not necessary.
DXUTTRACE( L"Shadow volume has %u vertices, %u faces.\n", ( pInputMesh->GetNumFaces() + nNumMaps ) * 3, nNextIndex / 3 );
bool bNeed32Bit = ( pInputMesh->GetNumFaces() + nNumMaps ) * 3 > 65535;
ID3DXMesh *pFinalMesh;
hr = D3DXCreateMesh( nNextIndex / 3, // Exact number of faces
( pInputMesh->GetNumFaces() + nNumMaps ) * 3,
D3DXMESH_WRITEONLY | ( bNeed32Bit ? D3DXMESH_32BIT : 0 ),
SHADOWVERT::Decl,
pd3dDevice,
&pFinalMesh );
if( SUCCEEDED( hr ) )
{
pNewMesh->LockVertexBuffer( 0, (LPVOID*)&pNewVBData );
pNewMesh->LockIndexBuffer( 0, (LPVOID*)&pdwNewIBData );
SHADOWVERT *pFinalVBData = NULL;
WORD *pwFinalIBData = NULL;
pFinalMesh->LockVertexBuffer( 0, (LPVOID*)&pFinalVBData );
pFinalMesh->LockIndexBuffer( 0, (LPVOID*)&pwFinalIBData );
if( pNewVBData && pdwNewIBData && pFinalVBData && pwFinalIBData )
{
CopyMemory( pFinalVBData, pNewVBData, sizeof(SHADOWVERT) * ( pInputMesh->GetNumFaces() + nNumMaps ) * 3 );
if( bNeed32Bit )
CopyMemory( pwFinalIBData, pdwNewIBData, sizeof(DWORD) * nNextIndex );
else
{
for( int i = 0; i < nNextIndex; ++i )
pwFinalIBData[i] = (WORD)pdwNewIBData[i];
}
}
if( pNewVBData )
pNewMesh->UnlockVertexBuffer();
if( pdwNewIBData )
pNewMesh->UnlockIndexBuffer();
if( pFinalVBData )
pFinalMesh->UnlockVertexBuffer();
if( pwFinalIBData )
pFinalMesh->UnlockIndexBuffer();
// Release the old
pNewMesh->Release();
pNewMesh = pFinalMesh;
}
*ppOutMesh = pNewMesh;
}
else
pNewMesh->Release();
}
delete[] pMapping;
} else
hr = E_OUTOFMEMORY;
} else
hr = E_FAIL;
if( pVBData )
pInputMesh->UnlockVertexBuffer();
if( pdwIBData )
pInputMesh->UnlockIndexBuffer();
delete[] pdwPtRep;
pInputMesh->Release();
return hr;
}
//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
// Set the callback functions. These functions allow DXUT to notify
// the application about device changes, user input, and windows messages. The
// callbacks are optional so you need only set callbacks for events you're interested
// in. However, if you don't handle the device reset/lost callbacks then the sample
// framework won't be able to reset your device since the application must first
// release all device resources before resetting. Likewise, if you don't handle the
// device created/destroyed callbacks then DXUT won't be able to
// recreate your device resources.
DXUTSetCallbackDeviceCreated( OnCreateDevice );
DXUTSetCallbackDeviceReset( OnResetDevice );
DXUTSetCallbackDeviceLost( OnLostDevice );
DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -