diff options
Diffstat (limited to 'mdllib/mdllib_stripmodel.cpp')
| -rw-r--r-- | mdllib/mdllib_stripmodel.cpp | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/mdllib/mdllib_stripmodel.cpp b/mdllib/mdllib_stripmodel.cpp new file mode 100644 index 0000000..e05d8cd --- /dev/null +++ b/mdllib/mdllib_stripmodel.cpp @@ -0,0 +1,504 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "mdllib_common.h" +#include "mdllib_stripinfo.h" +#include "mdllib_utils.h" + +#include "studio.h" +#include "optimize.h" + +#include "smartptr.h" + + +bool CMdlLib::CreateNewStripInfo( IMdlStripInfo **ppStripInfo ) +{ + if ( !ppStripInfo ) + return false; + + if ( *ppStripInfo ) + { + CMdlStripInfo *pMdlStripInfo = ( CMdlStripInfo * ) ( *ppStripInfo ); + pMdlStripInfo->Reset(); + return true; + } + + *ppStripInfo = new CMdlStripInfo; + return ( NULL != *ppStripInfo ); +} + +// +// StripModelBuffers +// The main function that strips the model buffers +// mdlBuffer - mdl buffer, updated, no size change +// vvdBuffer - vvd buffer, updated, size reduced +// vtxBuffer - vtx buffer, updated, size reduced +// ppStripInfo - if nonzero on return will be filled with the stripping info +// +bool CMdlLib::StripModelBuffers( CUtlBuffer &mdlBuffer, CUtlBuffer &vvdBuffer, CUtlBuffer &vtxBuffer, IMdlStripInfo **ppStripInfo ) +{ + DECLARE_PTR( byte, mdl, BYTE_OFF_PTR( mdlBuffer.Base(), mdlBuffer.TellGet() ) ); + DECLARE_PTR( byte, vvd, BYTE_OFF_PTR( vvdBuffer.Base(), vvdBuffer.TellGet() ) ); + DECLARE_PTR( byte, vtx, BYTE_OFF_PTR( vtxBuffer.Base(), vtxBuffer.TellGet() ) ); + + int vvdLength = vvdBuffer.TellPut() - vvdBuffer.TellGet(); + int vtxLength = vtxBuffer.TellPut() - vtxBuffer.TellGet(); + + // + // =================== + // =================== Modify the checksum and check if further processing is needed + // =================== + // + + DECLARE_PTR( studiohdr_t, mdlHdr, mdl ); + DECLARE_PTR( vertexFileHeader_t, vvdHdr, vvd ); + DECLARE_PTR( OptimizedModel::FileHeader_t, vtxHdr, vtx ); + + long checksumOld = mdlHdr->checksum; + + // Don't do anything if the checksums don't match + if ( ( mdlHdr->checksum != vvdHdr->checksum ) || + ( mdlHdr->checksum != vtxHdr->checkSum ) ) + { + DLog( "mdllib", 1, "ERROR: [StripModelBuffers] checksum mismatch!\n" ); + return false; + } + + // Modify the checksums + mdlHdr->checksum ^= ( mdlHdr->checksum * 123457 ); + vvdHdr->checksum ^= ( vvdHdr->checksum * 123457 ); + vtxHdr->checkSum ^= ( vtxHdr->checkSum * 123457 ); + + long checksumNew = mdlHdr->checksum; + + // Allocate the model stripping info + CMdlStripInfo msi; + CMdlStripInfo *pMsi; + + if ( ppStripInfo ) + { + if ( *ppStripInfo ) + { + pMsi = ( CMdlStripInfo * ) ( *ppStripInfo ); + pMsi->Reset(); + } + else + { + *ppStripInfo = pMsi = new CMdlStripInfo; + } + } + else + { + pMsi = &msi; + } + + // Set the basic stripping info settings + pMsi->m_lChecksumOld = checksumOld; + pMsi->m_lChecksumNew = checksumNew; + + // + // Early outs + // + + if ( !( mdlHdr->flags & STUDIOHDR_FLAGS_STATIC_PROP ) ) + { + DLog( "mdllib", 2, "No special stripping - the model is not a static prop.\n" ); + pMsi->m_eMode = CMdlStripInfo::MODE_NO_CHANGE; + return true; + } + + if ( vvdHdr->numLODs <= 1 ) + { + DLog( "mdllib", 2, "No special stripping - the model has only %d lod(s).\n", vvdHdr->numLODs ); + pMsi->m_eMode = CMdlStripInfo::MODE_NO_CHANGE; + return true; + } + + if ( mdlHdr->numbones != 1 ) + { + DLog( "mdllib", 2, "No special stripping - the model has %d bone(s).\n", mdlHdr->numbones ); + pMsi->m_eMode = CMdlStripInfo::MODE_NO_CHANGE; + return true; + } + + // Otherwise do stripping + pMsi->m_eMode = CMdlStripInfo::MODE_STRIP_LOD_1N; + + + // + // =================== + // =================== Build out table of LOD0 vertexes + // =================== + // + + CGrowableBitVec &mapVtxIndex = pMsi->m_vtxVerts; + ITERATE_CHILDREN2( OptimizedModel::BodyPartHeader_t, mstudiobodyparts_t, vtxBodyPart, mdlBodyPart, vtxHdr, mdlHdr, pBodyPart, pBodypart, numBodyParts ) + ITERATE_CHILDREN2( OptimizedModel::ModelHeader_t, mstudiomodel_t, vtxModel, mdlModel, vtxBodyPart, mdlBodyPart, pModel, pModel, numModels ) + + OptimizedModel::ModelLODHeader_t *vtxLod = CHILD_AT( vtxModel, pLOD, 0 ); + ITERATE_CHILDREN2( OptimizedModel::MeshHeader_t, mstudiomesh_t, vtxMesh, mdlMesh, vtxLod, mdlModel, pMesh, pMesh, numMeshes ) + ITERATE_CHILDREN( OptimizedModel::StripGroupHeader_t, vtxStripGroup, vtxMesh, pStripGroup, numStripGroups ) + ITERATE_CHILDREN( OptimizedModel::StripHeader_t, vtxStrip, vtxStripGroup, pStrip, numStrips ) + + if ( !( vtxStrip->flags & OptimizedModel::STRIP_IS_TRILIST ) ) + continue; + for ( int i = 0; i < vtxStrip->numIndices; ++ i ) + { + unsigned short *vtxIdx = CHILD_AT( vtxStripGroup, pIndex, vtxStrip->indexOffset + i ); + OptimizedModel::Vertex_t *vtxVertex = CHILD_AT( vtxStripGroup, pVertex, *vtxIdx ); + + unsigned short usIdx = vtxVertex->origMeshVertID + mdlMesh->vertexoffset; + mapVtxIndex.GrowSetBit( usIdx ); + } + + ITERATE_END + ITERATE_END + ITERATE_END + + ITERATE_END + ITERATE_END + + // + // Now having the table of which vertexes to keep we will construct a remapping table + // + CUtlSortVector< unsigned short, CLessSimple< unsigned short > > &srcIndices = pMsi->m_vtxIndices; + srcIndices.EnsureCapacity( mapVtxIndex.GetNumBits() ); + for ( int iBit = -1; ( iBit = mapVtxIndex.FindNextSetBit( iBit + 1 ) ) >= 0; ) + srcIndices.InsertNoSort( ( unsigned short ) ( unsigned int ) iBit ); + srcIndices.RedoSort(); // - doesn't do anything, just validates the vector + + // Now we have the following questions answered: + // - for every index we know if it belongs to lod0 "mapVtxIndex.IsBitSet( oldVertIdx )" + // - for every new vertex we know its old index "srcIndices[ newVertIdx ]" + // - for every old vertex if it's in lod0 we know its new index "srcIndices.Find( oldVertIdx )" + + + // + // =================== + // =================== Process MDL file + // =================== + // + + // + // Update vertex counts + // + int mdlNumVerticesOld = 0; + CUtlSortVector< CMdlStripInfo::MdlRangeItem, CLessSimple< CMdlStripInfo::MdlRangeItem > > &arrMdlOffsets = pMsi->m_vtxMdlOffsets; + ITERATE_CHILDREN( mstudiobodyparts_t, mdlBodyPart, mdlHdr, pBodypart, numbodyparts ) + ITERATE_CHILDREN( mstudiomodel_t, mdlModel, mdlBodyPart, pModel, nummodels ) + + DLog( "mdllib", 3, " Stripped %d lod(s).\n", vvdHdr->numLODs - 1 ), + DLog( "mdllib", 3, " Stripped %d vertexes (was: %d, now: %d).\n", mdlModel->numvertices - srcIndices.Count(), mdlModel->numvertices, srcIndices.Count() ); + + mdlNumVerticesOld = mdlModel->numvertices; + mdlModel->numvertices = srcIndices.Count(); + + mdlModel->vertexdata.pVertexData = BYTE_OFF_PTR( vvdHdr, vvdHdr->vertexDataStart ); + mdlModel->vertexdata.pTangentData = BYTE_OFF_PTR( vvdHdr, vvdHdr->tangentDataStart ); + + ITERATE_CHILDREN( mstudiomesh_t, mdlMesh, mdlModel, pMesh, nummeshes ) + + CMdlStripInfo::MdlRangeItem mdlRangeItem( mdlMesh->vertexoffset, mdlMesh->numvertices ); + + mdlMesh->vertexdata.modelvertexdata = &mdlModel->vertexdata; + mdlMesh->numvertices = srcIndices.FindLess( mdlMesh->vertexoffset + mdlMesh->numvertices ); + mdlMesh->vertexoffset = srcIndices.FindLess( mdlMesh->vertexoffset ) + 1; + mdlMesh->numvertices -= mdlMesh->vertexoffset - 1; + + mdlRangeItem.m_offNew = mdlMesh->vertexoffset; + mdlRangeItem.m_numNew = mdlMesh->numvertices; + arrMdlOffsets.Insert( mdlRangeItem ); + + // Truncate the number of vertexes + for ( int k = 0; k < ARRAYSIZE( mdlMesh->vertexdata.numLODVertexes ); ++ k ) + mdlMesh->vertexdata.numLODVertexes[ k ] = mdlMesh->numvertices; + + ITERATE_END + ITERATE_END + ITERATE_END + + // + // Update bones not to mention anything below LOD0 + // + ITERATE_CHILDREN( mstudiobone_t, mdlBone, mdlHdr, pBone, numbones ) + mdlBone->flags &= ( BONE_USED_BY_VERTEX_LOD0 | ~BONE_USED_BY_VERTEX_MASK ); + ITERATE_END + + DLog( "mdllib", 3, " Updated %d bone(s).\n", mdlHdr->numbones ); + + + // + // =================== + // =================== Process VVD file + // =================== + // + + vvdHdr->numLODs = 1; + for ( int k = 0; k < ARRAYSIZE( vvdHdr->numLODVertexes ); ++ k ) + vvdHdr->numLODVertexes[ k ] = srcIndices.Count(); + + DECLARE_PTR( mstudiovertex_t, vvdVertexSrc, BYTE_OFF_PTR( vvdHdr, vvdHdr->vertexDataStart ) ); + DECLARE_PTR( Vector4D, vvdTangentSrc, vvdHdr->tangentDataStart ? BYTE_OFF_PTR( vvdHdr, vvdHdr->tangentDataStart ) : NULL ); + + // Apply the fixups first of all + if ( vvdHdr->numFixups ) + { + CArrayAutoPtr< byte > memTempVVD( new byte[ vvdLength ] ); + DECLARE_PTR( mstudiovertex_t, vvdVertexNew, BYTE_OFF_PTR( memTempVVD.Get(), vvdHdr->vertexDataStart ) ); + DECLARE_PTR( Vector4D, vvdTangentNew, BYTE_OFF_PTR( memTempVVD.Get(), vvdHdr->tangentDataStart ) ); + DECLARE_PTR( vertexFileFixup_t, vvdFixup, BYTE_OFF_PTR( vvdHdr, vvdHdr->fixupTableStart ) ); + for ( int k = 0; k < vvdHdr->numFixups; ++ k ) + { + memcpy( vvdVertexNew, vvdVertexSrc + vvdFixup[ k ].sourceVertexID, vvdFixup[ k ].numVertexes * sizeof( *vvdVertexNew ) ); + vvdVertexNew += vvdFixup[ k ].numVertexes; + if ( vvdTangentSrc ) + { + memcpy( vvdTangentNew, vvdTangentSrc + vvdFixup[ k ].sourceVertexID, vvdFixup[ k ].numVertexes * sizeof( *vvdTangentNew ) ); + vvdTangentNew += vvdFixup[ k ].numVertexes; + } + } + + // Move back the memory after fixups were applied + vvdVertexSrc ? memcpy( vvdVertexSrc, BYTE_OFF_PTR( memTempVVD.Get(), vvdHdr->vertexDataStart ), mdlNumVerticesOld * sizeof( *vvdVertexSrc ) ) : 0; + vvdTangentSrc ? memcpy( vvdTangentSrc, BYTE_OFF_PTR( memTempVVD.Get(), vvdHdr->tangentDataStart ), mdlNumVerticesOld * sizeof( *vvdTangentSrc ) ) : 0; + } + + vvdHdr->vertexDataStart -= ALIGN_VALUE( sizeof( vertexFileFixup_t ) * vvdHdr->numFixups, 16 ); + vvdHdr->numFixups = 0; + DECLARE_PTR( mstudiovertex_t, vvdVertexNew, BYTE_OFF_PTR( vvdHdr, vvdHdr->vertexDataStart ) ); + for ( int k = 0; k < srcIndices.Count(); ++ k ) + vvdVertexNew[ k ] = vvdVertexSrc[ srcIndices[ k ] ]; + + size_t newVertexDataSize = srcIndices.Count() * sizeof( mstudiovertex_t ); + int vvdLengthOld = vvdLength; + vvdLength = vvdHdr->vertexDataStart + newVertexDataSize; + + if ( vvdTangentSrc ) + { + // Move the tangents + vvdHdr->tangentDataStart = vvdLength; + DECLARE_PTR( Vector4D, vvdTangentNew, BYTE_OFF_PTR( vvdHdr, vvdHdr->tangentDataStart ) ); + + for ( int k = 0; k < srcIndices.Count(); ++ k ) + vvdTangentNew[ k ] = vvdTangentSrc[ srcIndices[ k ] ]; + + vvdLength += srcIndices.Count() * sizeof( Vector4D ); + } + DLog( "mdllib", 3, " Stripped %d vvd bytes.\n", vvdLengthOld - vvdLength ); + + + // + // =================== + // =================== Process VTX file + // =================== + // + + size_t vtxOffIndexBuffer = ~size_t(0), vtxOffIndexBufferEnd = 0; + size_t vtxOffVertexBuffer = ~size_t(0), vtxOffVertexBufferEnd = 0; + CRemoveTracker vtxRemove; + CUtlVector< size_t > vtxOffIndex; + CUtlVector< size_t > vtxOffVertex; + + vtxRemove.RemoveElements( CHILD_AT( vtxHdr, pMaterialReplacementList, 1 ), vtxHdr->numLODs - 1 ); + ITERATE_CHILDREN( OptimizedModel::MaterialReplacementListHeader_t, vtxMatList, vtxHdr, pMaterialReplacementList, numLODs ) + if ( !vtxMatList_idx ) continue; + vtxRemove.RemoveElements( CHILD_AT( vtxMatList, pMaterialReplacement, 0 ), vtxMatList->numReplacements ); + ITERATE_CHILDREN( OptimizedModel::MaterialReplacementHeader_t, vtxMat, vtxMatList, pMaterialReplacement, numReplacements ) + char const *szName = vtxMat->pMaterialReplacementName(); + vtxRemove.RemoveElements( szName, szName ? strlen( szName ) + 1 : 0 ); + ITERATE_END + ITERATE_END + + ITERATE_CHILDREN( OptimizedModel::BodyPartHeader_t, vtxBodyPart, vtxHdr, pBodyPart, numBodyParts ) + ITERATE_CHILDREN( OptimizedModel::ModelHeader_t, vtxModel, vtxBodyPart, pModel, numModels ) + + vtxRemove.RemoveElements( CHILD_AT( vtxModel, pLOD, 1 ), vtxModel->numLODs - 1 ); + ITERATE_CHILDREN( OptimizedModel::ModelLODHeader_t, vtxLod, vtxModel, pLOD, numLODs ) + if ( !vtxLod_idx ) // Process only lod1-N + continue; + + vtxRemove.RemoveElements( CHILD_AT( vtxLod, pMesh, 0 ), vtxLod->numMeshes ); + ITERATE_CHILDREN( OptimizedModel::MeshHeader_t, vtxMesh, vtxLod, pMesh, numMeshes ) + vtxRemove.RemoveElements( CHILD_AT( vtxMesh, pStripGroup, 0 ), vtxMesh->numStripGroups ); + ITERATE_CHILDREN( OptimizedModel::StripGroupHeader_t, vtxStripGroup, vtxMesh, pStripGroup, numStripGroups ) + vtxRemove.RemoveElements( CHILD_AT( vtxStripGroup, pStrip, 0 ), vtxStripGroup->numStrips ); + ITERATE_CHILDREN( OptimizedModel::StripHeader_t, vtxStrip, vtxStripGroup, pStrip, numStrips ) + vtxRemove.RemoveElements( CHILD_AT( vtxStrip, pBoneStateChange, 0 ), vtxStrip->numBoneStateChanges ); + ITERATE_END + ITERATE_END + ITERATE_END + + ITERATE_END + + // Use all lods to determine the ranges of vertex and index buffers. + // We rely on the fact that vertex and index buffers are laid out as one solid memory block for all lods. + ITERATE_CHILDREN( OptimizedModel::ModelLODHeader_t, vtxLod, vtxModel, pLOD, numLODs ) + ITERATE_CHILDREN( OptimizedModel::MeshHeader_t, vtxMesh, vtxLod, pMesh, numMeshes ) + ITERATE_CHILDREN( OptimizedModel::StripGroupHeader_t, vtxStripGroup, vtxMesh, pStripGroup, numStripGroups ) + + size_t offIndex = BYTE_DIFF_PTR( vtxHdr, CHILD_AT( vtxStripGroup, pIndex, 0 ) ); + size_t offIndexEnd = BYTE_DIFF_PTR( vtxHdr, CHILD_AT( vtxStripGroup, pIndex, vtxStripGroup->numIndices ) ); + size_t offVertex = BYTE_DIFF_PTR( vtxHdr, CHILD_AT( vtxStripGroup, pVertex, 0 ) ); + size_t offVertexEnd = BYTE_DIFF_PTR( vtxHdr, CHILD_AT( vtxStripGroup, pVertex, vtxStripGroup->numVerts ) ); + + if ( offIndex < vtxOffIndexBuffer ) + vtxOffIndexBuffer = offIndex; + if ( offIndexEnd > vtxOffIndexBufferEnd ) + vtxOffIndexBufferEnd = offIndexEnd; + if ( offVertex < vtxOffVertexBuffer ) + vtxOffVertexBuffer = offVertex; + if ( offVertexEnd > vtxOffVertexBufferEnd ) + vtxOffVertexBufferEnd = offVertexEnd; + + if ( !vtxLod_idx ) + { + vtxOffIndex.AddToTail( offIndex ); + vtxOffIndex.AddToTail( offIndexEnd ); + vtxOffVertex.AddToTail( offVertex ); + vtxOffVertex.AddToTail( offVertexEnd ); + } + + ITERATE_END + ITERATE_END + ITERATE_END + + ITERATE_END + ITERATE_END + + // Fixup the vertex buffer + DECLARE_PTR( OptimizedModel::Vertex_t, vtxVertexBuffer, BYTE_OFF_PTR( vtxHdr, vtxOffVertexBuffer ) ); + DECLARE_PTR( OptimizedModel::Vertex_t, vtxVertexBufferEnd, BYTE_OFF_PTR( vtxHdr, vtxOffVertexBufferEnd ) ); + CUtlVector< int > vtxIndexDeltas; + vtxIndexDeltas.EnsureCapacity( vtxVertexBufferEnd - vtxVertexBuffer ); + int vtxNumVertexRemoved = 0; + for ( OptimizedModel::Vertex_t *vtxVertexElement = vtxVertexBuffer; vtxVertexElement < vtxVertexBufferEnd; ++ vtxVertexElement ) + { + size_t const off = BYTE_DIFF_PTR( vtxHdr, vtxVertexElement ); + bool bUsed = false; + for ( int k = 0; k < vtxOffVertex.Count(); k += 2 ) + { + if ( off >= vtxOffVertex[ k ] && off < vtxOffVertex[ k + 1 ] ) + { + bUsed = true; + break; + } + } + if ( !bUsed ) + { + // Index is not in use + vtxRemove.RemoveElements( vtxVertexElement ); + vtxIndexDeltas.AddToTail( 0 ); + vtxNumVertexRemoved ++; + } + else + { // Index is in use and must be remapped + // Find the mesh where this index belongs + int iMesh = arrMdlOffsets.FindLessOrEqual( CMdlStripInfo::MdlRangeItem( 0, 0, vtxVertexElement - vtxVertexBuffer ) ); + Assert( iMesh >= 0 && iMesh < arrMdlOffsets.Count() ); + + CMdlStripInfo::MdlRangeItem &mri = arrMdlOffsets[ iMesh ]; + Assert( ( vtxVertexElement - vtxVertexBuffer >= mri.m_offNew ) && ( vtxVertexElement - vtxVertexBuffer < mri.m_offNew + mri.m_numNew ) ); + + Assert( mapVtxIndex.IsBitSet( vtxVertexElement->origMeshVertID + mri.m_offOld ) ); + vtxVertexElement->origMeshVertID = srcIndices.Find( vtxVertexElement->origMeshVertID + mri.m_offOld ) - mri.m_offNew; + Assert( vtxVertexElement->origMeshVertID < mri.m_numNew ); + vtxIndexDeltas.AddToTail( vtxNumVertexRemoved ); + } + } + + // Fixup the index buffer + DECLARE_PTR( unsigned short, vtxIndexBuffer, BYTE_OFF_PTR( vtxHdr, vtxOffIndexBuffer ) ); + DECLARE_PTR( unsigned short, vtxIndexBufferEnd, BYTE_OFF_PTR( vtxHdr, vtxOffIndexBufferEnd ) ); + for ( unsigned short *vtxIndexElement = vtxIndexBuffer; vtxIndexElement < vtxIndexBufferEnd; ++ vtxIndexElement ) + { + size_t const off = BYTE_DIFF_PTR( vtxHdr, vtxIndexElement ); + bool bUsed = false; + for ( int k = 0; k < vtxOffIndex.Count(); k += 2 ) + { + if ( off >= vtxOffIndex[ k ] && off < vtxOffIndex[ k + 1 ] ) + { + bUsed = true; + break; + } + } + if ( !bUsed ) + { + // Index is not in use + vtxRemove.RemoveElements( vtxIndexElement ); + } + else + { + // Index is in use and must be remapped + *vtxIndexElement -= vtxIndexDeltas[ *vtxIndexElement ]; + } + } + + // By now should have scheduled all removal information + vtxRemove.Finalize(); + DLog( "mdllib", 3, " Stripped %d vtx bytes.\n", vtxRemove.GetNumBytesRemoved() ); + + // + // Fixup all the offsets + // + ITERATE_CHILDREN( OptimizedModel::MaterialReplacementListHeader_t, vtxMatList, vtxHdr, pMaterialReplacementList, numLODs ) + ITERATE_CHILDREN( OptimizedModel::MaterialReplacementHeader_t, vtxMat, vtxMatList, pMaterialReplacement, numReplacements ) + vtxMat->replacementMaterialNameOffset = vtxRemove.ComputeOffset( vtxMat, vtxMat->replacementMaterialNameOffset ); + ITERATE_END + vtxMatList->replacementOffset = vtxRemove.ComputeOffset( vtxMatList, vtxMatList->replacementOffset ); + ITERATE_END + ITERATE_CHILDREN( OptimizedModel::BodyPartHeader_t, vtxBodyPart, vtxHdr, pBodyPart, numBodyParts ) + ITERATE_CHILDREN( OptimizedModel::ModelHeader_t, vtxModel, vtxBodyPart, pModel, numModels ) + ITERATE_CHILDREN( OptimizedModel::ModelLODHeader_t, vtxLod, vtxModel, pLOD, numLODs ) + ITERATE_CHILDREN( OptimizedModel::MeshHeader_t, vtxMesh, vtxLod, pMesh, numMeshes ) + ITERATE_CHILDREN( OptimizedModel::StripGroupHeader_t, vtxStripGroup, vtxMesh, pStripGroup, numStripGroups ) + + ITERATE_CHILDREN( OptimizedModel::StripHeader_t, vtxStrip, vtxStripGroup, pStrip, numStrips ) + vtxStrip->indexOffset = + vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->indexOffset + vtxStrip->indexOffset ) - + vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->indexOffset ); + vtxStrip->vertOffset = + vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->vertOffset + vtxStrip->vertOffset ) - + vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->vertOffset ); + vtxStrip->boneStateChangeOffset = vtxRemove.ComputeOffset( vtxStrip, vtxStrip->boneStateChangeOffset ); + ITERATE_END + + vtxStripGroup->vertOffset = vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->vertOffset ); + vtxStripGroup->indexOffset = vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->indexOffset ); + vtxStripGroup->stripOffset = vtxRemove.ComputeOffset( vtxStripGroup, vtxStripGroup->stripOffset ); + ITERATE_END + vtxMesh->stripGroupHeaderOffset = vtxRemove.ComputeOffset( vtxMesh, vtxMesh->stripGroupHeaderOffset ); + ITERATE_END + vtxLod->meshOffset = vtxRemove.ComputeOffset( vtxLod, vtxLod->meshOffset ); + ITERATE_END + vtxModel->lodOffset = vtxRemove.ComputeOffset( vtxModel, vtxModel->lodOffset ); + vtxModel->numLODs = 1; + ITERATE_END + vtxBodyPart->modelOffset = vtxRemove.ComputeOffset( vtxBodyPart, vtxBodyPart->modelOffset ); + ITERATE_END + vtxHdr->materialReplacementListOffset = vtxRemove.ComputeOffset( vtxHdr, vtxHdr->materialReplacementListOffset ); + vtxHdr->bodyPartOffset = vtxRemove.ComputeOffset( vtxHdr, vtxHdr->bodyPartOffset ); + vtxHdr->numLODs = 1; + + // Perform final memory move + vtxRemove.MemMove( vtxHdr, vtxLength ); + + + // + // =================== + // =================== Truncate buffer sizes + // =================== + // + + vvdBuffer.SeekPut( CUtlBuffer::SEEK_CURRENT, vvdBuffer.TellGet() + vvdLength - vvdBuffer.TellPut() ); + vtxBuffer.SeekPut( CUtlBuffer::SEEK_CURRENT, vtxBuffer.TellGet() + vtxLength - vtxBuffer.TellPut() ); + + + DLog( "mdllib", 2, " Reduced model buffers by %d bytes.\n", vtxRemove.GetNumBytesRemoved() + ( vvdLengthOld - vvdLength ) ); + + // Done + return true; +} + |