📄 object.cpp
字号:
#endif
pwIndices[pVCRCur->wIndexOffset[i]] = pVCRCur->wKeptVert;
}
#if EXTRA_DEBUGGING
// Make sure the indices are all in range.
for ( int j = 0; j < iCurNumTris * 3; j++ )
{
ASSERT ( pwIndices[j] < (WORD)iCurNumVerts );
}
#endif
}
hres = pIndexBuffer->Unlock();
ASSERT ( SUCCEEDED ( hres ) );
return TRUE;
}
}
BOOL OMIVanilla::UndoCollapse ( int iNum )
{
if ( pVCRCur->bNumChanges == (BYTE)-1 )
{
// No more to undo.
ASSERT ( iCurNumCollapses == 0 );
return FALSE;
}
else
{
ASSERT ( pIndexBuffer != NULL );
WORD *pwIndices;
HRESULT hres = pIndexBuffer->Lock ( 0,
iCurNumTris * 3 * sizeof ( WORD ),
(BYTE**)&pwIndices,
0 );
ASSERT ( SUCCEEDED ( hres ) );
while ( --iNum >= 0 )
{
if ( pVCRCur->bNumChanges == (BYTE)-1 )
{
// No more to undo.
ASSERT ( iCurNumCollapses == 0 );
break;
}
iCurNumCollapses--;
for ( int i = 0; i < pVCRCur->bNumChanges; i++ )
{
// Change the relevant instances of the kept vertex to the one that's just been unbinned .
ASSERT ( pVCRCur->wIndexOffset[i] < ( iCurNumTris * 3 ) );
#if EXTRA_DEBUGGING
ASSERT ( pwIndices[pVCRCur->wIndexOffset[i]] == pVCRCur->wKeptVert );
#endif
pwIndices[pVCRCur->wIndexOffset[i]] = (WORD)iCurNumVerts;
}
iCurNumTris += pVCRCur->bNumOfTris;
ASSERT ( iCurNumTris <= pOptMesh->wIndices.Size() );
iCurNumVerts++;
ASSERT ( iCurNumVerts <= pOptMesh->iNumVerts );
#if EXTRA_DEBUGGING
// Make sure the indices are all in range.
for ( int j = 0; j < iCurNumTris * 3; j++ )
{
ASSERT ( pwIndices[j] < (WORD)iCurNumVerts );
}
#endif
pVCRCur = pVCRCur->Next();
}
hres = pIndexBuffer->Unlock();
ASSERT ( SUCCEEDED ( hres ) );
return TRUE;
}
}
void OMIVanilla::Check ( void )
{
// Check my global data is the same type as me!
ASSERT ( pOptMesh != NULL );
ASSERT ( pOptMesh->GetType() == GetType() );
pOptMesh->Check();
}
///////// SLIDING WINDOW VIPM ////////////
// A table of these exists, one per collapse.
struct SlidingWindowRecord
{
DWORD dwFirstIndexOffset; // Offset of the first index in the index buffer to start at (note! no retrictions. Can easily be >64k)
WORD wNumTris; // Number of tris to render (most cards can't do more than 65536)
WORD wNumVerts; // Number of vertices to render with (using WORD indices)
};
class OMSlidingWindow : public OptimisedMesh
{
friend class OMISlidingWindow;
Object *pObj;
int iNumVerts; // Number of verts at full rez.
int iNumCollapses; // Total number of collapses.
int iNumLevels; // Total number of levels.
int iSizeOfIB; // In indices. Just for info.
//ArbitraryList<WORD> wIndices; // The index list, all levels clumped together. Always using TRILISTs.
ArbitraryList<SlidingWindowRecord> swrRecords; // The records of the collapses.
BOOL bOptimised; // Have the tris been reordered optimally?
LPDIRECT3DVERTEXBUFFER8 pVB; // The VB with the vertices in.
LPDIRECT3DINDEXBUFFER8 pIB; // The index list, all levels clumped together. Always using TRILISTs.
public:
OMSlidingWindow ( Object *pObject );
virtual ~OMSlidingWindow ( void );
virtual VIPMTypeEnum GetType ( void );
virtual char *GetTypeName ( void );
virtual OptimisedMeshInstance *CreateInstance ( ObjectInstance *pObjectInstance );
virtual void Check ( void );
virtual void Update ( void );
virtual void AboutToChangeDevice ( void );
};
class OMISlidingWindow : public OptimisedMeshInstance
{
friend class OMSlidingWindow;
ObjectInstance *pObjInst;
OMSlidingWindow *pOptMesh;
SlidingWindowRecord *pswrLast; // For the Info* functions.
// No per-instance VIPM data. Hooray!
public:
OMISlidingWindow ( ObjectInstance *pObjectInstance, OMSlidingWindow *pOptimisedMesh );
virtual ~OMISlidingWindow ( void );
virtual VIPMTypeEnum GetType ( void );
virtual char *GetTypeName ( void );
virtual void RenderCurrentObject ( LPDIRECT3DDEVICE8 pd3ddev, int iMaterialNumber, int iLoD );
virtual BOOL bNeedsUpdate ( void );
virtual void Update ( void );
virtual void Check ( void );
virtual void AboutToChangeDevice ( void );
virtual const void InfoGetGlobal ( DWORD *pdwMemoryUsed, DWORD *pdwOfWhichAGP );
virtual const void InfoGetInstance ( DWORD *pdwMemoryUsed, DWORD *pdwOfWhichAGP, DWORD *pdwVerticesLoaded, DWORD *pdwRealTrisDrawn, DWORD *pdwTotalVertices );
};
OMSlidingWindow::OMSlidingWindow ( Object *pObject )
{
pObj = pObject;
pVB = NULL;
pIB = NULL;
bOptimised = FALSE;
}
OMSlidingWindow::~OMSlidingWindow ( void )
{
pObj = NULL;
ASSERT ( pVB == NULL );
ASSERT ( pIB == NULL );
}
VIPMTypeEnum OMSlidingWindow::GetType ( void )
{
return VIPMType_SlidingWindow;
}
char *OMSlidingWindow::GetTypeName ( void )
{
return "Sliding Window";
}
void OMSlidingWindow::AboutToChangeDevice ( void )
{
HRESULT hres = g_pd3dDevice->SetStreamSource ( 0, NULL, 0 );
ASSERT ( SUCCEEDED ( hres ) );
hres = g_pd3dDevice->SetIndices ( NULL, 0 );
ASSERT ( SUCCEEDED ( hres ) );
SAFE_RELEASE ( pVB );
SAFE_RELEASE ( pIB );
MarkAsDirty ( g_bShowVIPMInfo );
bOptimised = FALSE;
}
// Create an instance of this optimised mesh, and returns the pointer to it.
// Pass in the object instance you wish to associate it with.
OptimisedMeshInstance *OMSlidingWindow::CreateInstance ( ObjectInstance *pObjectInstance )
{
return new OMISlidingWindow ( pObjectInstance, this );
}
void OMSlidingWindow::Check ( void )
{
}
void OMSlidingWindow::Update ( void )
{
if ( !bDirty && ( bOptimised == g_bOptimiseVertexOrder ) )
{
// Nothing to do!
return;
}
bDirty = FALSE;
iVersion++; // Just for luck.
bOptimised = g_bOptimiseVertexOrder;
SAFE_RELEASE ( pVB );
SAFE_RELEASE ( pIB );
swrRecords.SizeTo ( 0 );
MeshPt *pt;
MeshTri *tri;
// Undo all the collapses, so we start from the maximum mesh.
while ( pObj->UndoCollapse() ) {}
// How many vertices are we looking at?
iNumVerts = 0;
for ( pt = pObj->CurPtRoot.ListNext(); pt != NULL; pt = pt->ListNext() )
{
pt->mypt.dwIndex = -1;
iNumVerts++;
}
// Er... word indices, guys... nothing supports 32-bit indices yet.
ASSERT ( iNumVerts < 65535 );
// How many tris are we looking at?
int iNumTris = 0;
for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
{
tri->mytri.dwIndex = -1;
iNumTris++;
}
// A lot of cards have this annoying limit - see D3DCAPS8.MaxPrimitiveCount, which is
// exactly 65535 for DX7 and previous devices. So might as well stick with that number.
ASSERT ( iNumTris < 65535 );
// Create a place to put indices while we build up the list. Because we don't know
// how many we need yet, we can't create the IB until the end. Then we'll copy this into it.
ArbitraryList<WORD> wIndices;
wIndices.SizeTo ( 0 );
// Create the vertex buffer.
HRESULT hres = g_pd3dDevice->CreateVertexBuffer ( iNumVerts * sizeof ( STDVERTEX ),
D3DUSAGE_WRITEONLY,
STDVERTEX_FVF,
D3DPOOL_DEFAULT,
&pVB );
ASSERT ( SUCCEEDED ( hres ) );
STDVERTEX *pVertices, *pCurVertex;
hres = pVB->Lock ( 0, 0, (BYTE **)(&pVertices), 0 );
ASSERT ( SUCCEEDED ( hres ) );
pCurVertex = pVertices;
// Now do all the collapses, so we start from the minimum mesh.
// Along the way, mark the vertices in reverse order.
int iCurVerts = iNumVerts;
int iCurCollapse = 0;
int iCurSlidingWindowLevel = 0;
while ( TRUE )
{
GeneralCollapseInfo *pCollapse = pObj->pNextCollapse;
if ( pObj->pNextCollapse == &(pObj->CollapseRoot) )
{
break;
}
iCurSlidingWindowLevel = pCollapse->iSlidingWindowLevel;
iCurCollapse++;
iCurVerts--;
pCollapse->pptBin->mypt.dwIndex = iCurVerts;
pObj->DoCollapse();
}
iNumCollapses = iCurCollapse;
// Add the remaining existing pts in any old order.
WORD wCurIndex = 0;
for ( pt = pObj->CurPtRoot.ListNext(); pt != NULL; pt = pt->ListNext() )
{
if ( pt->mypt.dwIndex == (DWORD)-1 )
{
// Not binned in a collapse.
pt->mypt.dwIndex = wCurIndex;
pCurVertex->v = pt->mypt.vPos;
pCurVertex->norm = pt->mypt.vNorm;
pCurVertex->tu = pt->mypt.fU;
pCurVertex->tv = pt->mypt.fV;
pCurVertex++;
wCurIndex++;
}
}
// Should meet in the middle!
ASSERT ( wCurIndex == iCurVerts );
// And count the tris that are left.
int iCurNumTris = 0;
for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
{
iCurNumTris++;
}
// Reserve space for the collapse table - this is stored so that
// "number of collapses" is the index. So we'll be adding from the
// back.
iCurCollapse++; // Implicit "last collapse" is state after last collapse.
swrRecords.SizeTo ( iCurCollapse );
// And add the last one.
iCurCollapse--;
SlidingWindowRecord *swr = swrRecords.Item ( iCurCollapse );
swr->dwFirstIndexOffset = 0;
swr->wNumTris = (WORD)iCurNumTris;
swr->wNumVerts = wCurIndex;
// Now go through each level in turn.
int iCurTriBinned = 0;
// Useful thing.
ArbitraryList<WORD> wTempIndices;
int iMaxSlidingWindowLevel = iCurSlidingWindowLevel;
#if ALLOW_PROGRESS_BARS
CreateProgressBars();
if ( g_hProgress1 != NULL )
{
// Set min to 0, max to whatever
SendMessage ( g_hProgress1, PBM_SETRANGE, 0, MAKELPARAM ( 0, iMaxSlidingWindowLevel + 1 ) );
// Set step increment to 1.
SendMessage ( g_hProgress1, PBM_SETSTEP, (WPARAM) 1, 0 );
// Start it at 0.
SendMessage ( g_hProgress1, PBM_SETPOS, 0, 0 );
}
#else
ASSERT ( g_hProgress1 == NULL );
#endif //#if ALLOW_PROGRESS_BARS
while ( TRUE )
{
// Now we go through the collapses for this level, undoing them.
// As we go, we add the binned tris to the start of the index list,
//
// This coming list will be three sections:
// 1. the tris that get binned by the splits.
// 2. the tris that aren't affected.
// 3. the tris that are added by the splits.
//
// We know that at the moment, we are just rendering
// 1+2, which must equal the number of tris.
// So 3 starts iCurNumTris on from the start of 1.
int iCurTriAdded = iCurTriBinned + iCurNumTris;
wIndices.SizeTo ( iCurTriAdded * 3 );
int iJustCheckingNumTris = 0;
for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
{
tri->mytri.dwIndex = -1; // Mark them as not being in a collapse.
iJustCheckingNumTris++;
}
ASSERT ( iJustCheckingNumTris == iCurNumTris );
BOOL bJustStartedANewLevel = TRUE;
// Now undo all the collapses for this level in turn, adding vertices,
// binned tris, and SlidingWindowRecords as we go.
while ( ( pObj->pNextCollapse->ListNext() != NULL ) &&
( pObj->pNextCollapse->ListNext()->iSlidingWindowLevel == iCurSlidingWindowLevel ) )
{
GeneralCollapseInfo *pCollapse = pObj->pNextCollapse->ListNext();
// If we've just started a new level, EXCEPT on the last level,
// we don't need to store the post-collapse version of the tris,
// since we'll just switch down to the next level instead.
if ( !bJustStartedANewLevel || ( iCurSlidingWindowLevel == iMaxSlidingWindowLevel ) )
{
// These tris will be binned by the split.
if ( pCollapse->TriCollapsed.Size() > 0 )
{
wTempIndices.SizeTo(pCollapse->TriCollapsed.Size() * 3);
for ( int i = 0; i < pCollapse->TriCollapsed.Size(); i++ )
{
GeneralTriInfo *pTriInfo = pCollapse->TriCollapsed.Item(i);
MeshTri *tri = pTriInfo->ppt[0]->FindTri ( pTriInfo->ppt[1], pTriInfo->ppt[2] );
ASSERT ( tri != NULL );
ASSERT ( tri->mytri.dwIndex == -1 ); // Should not have been in a collapse this level.
ASSERT ( pTriInfo->ppt[0]->mypt.dwIndex < wCurIndex );
ASSERT ( pTriInfo->ppt[1]->mypt.dwIndex < wCurIndex );
ASSERT ( pTriInfo->ppt[2]->mypt.dwIndex < wCurIndex );
*wTempIndices.Item(i*3+0) = (WORD)pTriInfo->ppt[0]->mypt.dwIndex;
*wTempIndices.Item(i*3+1) = (WORD)pTriInfo->ppt[1]->mypt.dwIndex;
*wTempIndices.Item(i*3+2) = (WORD)pTriInfo->ppt[2]->mypt.dwIndex;
iCurNumTris--;
}
// Now try to order them as best you can.
if ( g_bOptimiseVertexOrder )
{
OptimiseVertexCoherencyTriList ( wTempIndices.Ptr(), pCollapse->TriCollapsed.Size() );
}
// And write them to the index list.
wIndices.CopyFrom ( iCurTriBinned * 3, wTempIndices, 0, 3 * pCollapse->TriCollapsed.Size() );
//memcpy ( wIndices.Item ( iCurTriBinned * 3 ), wTempIndices.Ptr(), sizeof(WORD)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -