bool CRunTimeKeyValuesStringTable::ReadStringTable( int numStrings, CUtlBuffer& buf ) { Assert( m_Strings.Count() == 0 ); CUtlVector< int > offsets; offsets.EnsureCapacity( numStrings ); offsets.CopyArray( (int *)( buf.PeekGet() ), numStrings ); // Skip over data buf.SeekGet( CUtlBuffer::SEEK_HEAD, buf.TellGet() + numStrings * sizeof( int ) ); int stringSize = buf.GetInt(); // Read in the string table m_Strings.EnsureCapacity( numStrings ); int i; for ( i = 0 ; i < numStrings; ++i ) { m_Strings.AddToTail( (const char *)buf.PeekGet( offsets[ i ] ) ); } buf.SeekGet( CUtlBuffer::SEEK_HEAD, buf.TellGet() + stringSize ); return true; }
void CCompileCaptionsApp::DescribeCaptions( char const *file ) { CUtlBuffer buf; if ( !g_pFullFileSystem->ReadFile( file, NULL, buf ) ) { Error( "Unable to read '%s' into buffer\n", file ); } CompiledCaptionHeader_t header; buf.Get( &header, sizeof( header ) ); if ( header.magic != COMPILED_CAPTION_FILEID ) Error( "Invalid file id for %s\n", file ); if ( header.version != COMPILED_CAPTION_VERSION ) Error( "Invalid file version for %s\n", file ); // Read the directory CUtlSortVector< CaptionLookup_t, CCaptionLookupLess > directory; directory.EnsureCapacity( header.directorysize ); directory.CopyArray( (const CaptionLookup_t *)buf.PeekGet(), header.directorysize ); directory.RedoSort( true ); buf.SeekGet( CUtlBuffer::SEEK_HEAD, header.dataoffset ); int i; CUtlVector< CaptionBlock_t > blocks; for ( i = 0; i < header.numblocks; ++i ) { CaptionBlock_t& newBlock = blocks[ blocks.AddToTail() ]; Q_memset( newBlock.data, 0, sizeof( newBlock.data ) ); buf.Get( newBlock.data, header.blocksize ); } CUtlMap< unsigned int, StringIndex_t > inverseMap( 0, 0, DefLessFunc( unsigned int ) ); for ( StringIndex_t idx = g_pVGuiLocalize->GetFirstStringIndex(); idx != INVALID_LOCALIZE_STRING_INDEX; idx = g_pVGuiLocalize->GetNextStringIndex( idx ) ) { const char *name = g_pVGuiLocalize->GetNameByIndex( idx ); CaptionLookup_t dummy; dummy.SetHash( name ); inverseMap.Insert( dummy.hash, idx ); } // Now print everything out... for ( i = 0; i < header.directorysize; ++i ) { const CaptionLookup_t& entry = directory[ i ]; char const *name = g_pVGuiLocalize->GetNameByIndex( inverseMap.Element( inverseMap.Find( entry.hash ) ) ); const CaptionBlock_t& block = blocks[ entry.blockNum ]; const wchar_t *data = (const wchar_t *)&block.data[ entry.offset ]; wchar_t *temp = ( wchar_t * )_alloca( entry.length * sizeof( short ) ); wcsncpy( temp, data, ( entry.length / sizeof( short ) ) - 1 ); vprint( 0, "%3.3d: (%40.40s) hash(%15.15u), block(%4.4d), offset(%4.4d), len(%4.4d) %S\n", i, name, entry.hash, entry.blockNum, entry.offset, entry.length, temp ); } }
//----------------------------------------------------------------------------- // Load studio model vertex data from a file... //----------------------------------------------------------------------------- bool LoadStudioModel( char const* pModelName, char const* pEntityType, CUtlBuffer& buf ) { if ( !g_pFullFileSystem->ReadFile( pModelName, NULL, buf ) ) return false; // Check that it's valid if (strncmp ((const char *) buf.PeekGet(), "IDST", 4) && strncmp ((const char *) buf.PeekGet(), "IDAG", 4)) { return false; } studiohdr_t* pHdr = (studiohdr_t*)buf.PeekGet(); Studio_ConvertStudioHdrToNewVersion( pHdr ); if (pHdr->version != STUDIO_VERSION) { return false; } isstaticprop_ret isStaticProp = IsStaticProp(pHdr); if ( isStaticProp != RET_VALID ) { if ( isStaticProp == RET_FAIL_NOT_MARKED_STATIC_PROP ) { Warning("Error! To use model \"%s\"\n" " with %s, it must be compiled with $staticprop!\n", pModelName, pEntityType ); } else if ( isStaticProp == RET_FAIL_DYNAMIC ) { Warning("Error! %s using model \"%s\", which must be used on a dynamic entity (i.e. prop_physics). Deleted.\n", pEntityType, pModelName ); } return false; } // ensure reset pHdr->pVertexBase = NULL; pHdr->pIndexBase = NULL; return true; }
bool LoadStudioModel( char const* pModelName, CUtlBuffer& buf ) { // No luck, gotta build it // Construct the file name... if (!LoadFile( pModelName, buf )) { Warning("Error! Unable to load model \"%s\"\n", pModelName ); return false; } // Check that it's valid if (strncmp ((const char *) buf.PeekGet(), "IDST", 4) && strncmp ((const char *) buf.PeekGet(), "IDAG", 4)) { Warning("Error! Invalid model file \"%s\"\n", pModelName ); return false; } studiohdr_t* pHdr = (studiohdr_t*)buf.PeekGet(); Studio_ConvertStudioHdrToNewVersion( pHdr ); if (pHdr->version != STUDIO_VERSION) { Warning("Error! Invalid model version \"%s\"\n", pModelName ); return false; } if (!IsStaticProp(pHdr)) { Warning("Error! To use model \"%s\"\n" " as a static prop, it must be compiled with $staticprop!\n", pModelName ); return false; } // ensure reset pHdr->pVertexBase = NULL; pHdr->pIndexBase = NULL; return true; }
//----------------------------------------------------------------------------- // Creates a collision model (based on the render geometry!) //----------------------------------------------------------------------------- void CVradStaticPropMgr::CreateCollisionModel( char const* pModelName ) { CUtlBuffer buf; CUtlBuffer bufvtx; CUtlBuffer bufphy; int i = m_StaticPropDict.AddToTail( ); m_StaticPropDict[i].m_pModel = 0; if (!LoadStudioModel( pModelName, buf )) { VectorCopy( vec3_origin, m_StaticPropDict[i].m_Mins ); VectorCopy( vec3_origin, m_StaticPropDict[i].m_Maxs ); return; } // if (!LoadStudioModelVtx( pModelName, bufvtx )) // return; studiohdr_t* pHdr = (studiohdr_t*)buf.Base(); // OptimizedModel::FileHeader_t* pVtxHdr = (OptimizedModel::FileHeader_t*)bufvtx.Base(); VectorCopy( pHdr->hull_min, m_StaticPropDict[i].m_Mins ); VectorCopy( pHdr->hull_max, m_StaticPropDict[i].m_Maxs ); if ( LoadStudioCollisionModel( pModelName, bufphy ) ) { phyheader_t header; bufphy.Get( &header, sizeof(header) ); vcollide_t *pCollide = &m_StaticPropDict[i].m_loadedModel; s_pPhysCollision->VCollideLoad( pCollide, header.solidCount, (const char *)bufphy.PeekGet(), bufphy.TellPut() - bufphy.TellGet() ); m_StaticPropDict[i].m_pModel = m_StaticPropDict[i].m_loadedModel.solids[0]; /* static int propNum = 0; char tmp[128]; sprintf( tmp, "staticprop%03d.txt", propNum ); DumpCollideToGlView( pCollide, tmp ); ++propNum; */ } else { // mark this as unused m_StaticPropDict[i].m_loadedModel.solidCount = 0; // CPhysCollide* pPhys = CreatePhysCollide( pHdr, pVtxHdr ); m_StaticPropDict[i].m_pModel = ComputeConvexHull( pHdr ); } }
// Assumed to be set up by calling code bool AsyncCaption_t::LoadFromFile( const char *pRelativePath ) { char pRelativePathFixed[MAX_PATH]; Q_strncpy( pRelativePathFixed, pRelativePath, sizeof(pRelativePathFixed) ); Q_FixSlashes( pRelativePathFixed ); Q_strlower( pRelativePathFixed ); pRelativePath = pRelativePathFixed; if ( Q_IsAbsolutePath( pRelativePath ) ) { Warning( "AsyncCaption_t::LoadFromFile: Fullpath encountered! %s\n", pRelativePath ); } FileHandle_t fh = g_pFullFileSystem->Open( pRelativePath, "rb", "GAME" ); if ( FILESYSTEM_INVALID_HANDLE == fh ) return false; MEM_ALLOC_CREDIT(); CUtlBuffer dirbuffer; // Read the header g_pFullFileSystem->Read( &m_Header, sizeof( m_Header ), fh ); if ( m_Header.magic != COMPILED_CAPTION_FILEID ) Error( "Invalid file id for %s\n", pRelativePath ); if ( m_Header.version != COMPILED_CAPTION_VERSION ) Error( "Invalid file version for %s\n", pRelativePath ); if ( m_Header.directorysize < 0 || m_Header.directorysize > 64 * 1024 ) Error( "Invalid directory size %d for %s\n", m_Header.directorysize, pRelativePath ); //if ( m_Header.blocksize != MAX_BLOCK_SIZE ) // Error( "Invalid block size %d, expecting %d for %s\n", m_Header.blocksize, MAX_BLOCK_SIZE, pchFullPath ); int directoryBytes = m_Header.directorysize * sizeof( CaptionLookup_t ); m_CaptionDirectory.EnsureCapacity( m_Header.directorysize ); dirbuffer.EnsureCapacity( directoryBytes ); g_pFullFileSystem->Read( dirbuffer.Base(), directoryBytes, fh ); g_pFullFileSystem->Close( fh ); m_CaptionDirectory.CopyArray( (const CaptionLookup_t *)dirbuffer.PeekGet(), m_Header.directorysize ); m_CaptionDirectory.RedoSort( true ); m_DataBaseFile = pRelativePath; return true; }
bool LoadStudioCollisionModel( char const* pModelName, CUtlBuffer& buf ) { char tmp[1024]; Q_strncpy( tmp, pModelName, sizeof( tmp ) ); Q_SetExtension( tmp, ".phy", sizeof( tmp ) ); // No luck, gotta build it if (!LoadFile( tmp, buf )) { // this is not an error, the model simply has no PHY file return false; } phyheader_t *header = (phyheader_t *)buf.PeekGet(); if ( header->size != sizeof(*header) || header->solidCount <= 0 ) return false; return true; }
//----------------------------------------------------------------------------- // Get PSD file image resources //----------------------------------------------------------------------------- PSDImageResources PSDGetImageResources( CUtlBuffer &buf ) { int nGet = buf.TellGet(); // Header PSDHeader_t header; buf.Get( &header, sizeof( header ) ); // Then palette unsigned int numBytesPalette = BigLong( buf.GetUnsignedInt() ); buf.SeekGet( CUtlBuffer::SEEK_CURRENT, numBytesPalette ); // Then image resources unsigned int numBytesImgResources = BigLong( buf.GetUnsignedInt() ); PSDImageResources imgres( numBytesImgResources, ( unsigned char * ) buf.PeekGet() ); // Restore the seek buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet ); return imgres; }
void CBugReporter::SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src ) { out[ 0 ] = 0; char *dest = out; src.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); char const *replace = "\\BugId\\"; int replace_len = Q_strlen( replace ); for ( int pos = 0; pos <= src.TellPut() && ( ( dest - out ) < outlen ); ) { char const *str = ( char const * )src.PeekGet( pos ); if ( !Q_strnicmp( str, replace, replace_len ) ) { *dest++ = '\\'; char num[ 32 ]; Q_snprintf( num, sizeof( num ), "%i", bugid ); char *pnum = num; while ( *pnum ) { *dest++ = *pnum++; } *dest++ = '\\'; pos += replace_len; continue; } *dest++ = *str; ++pos; } *dest = 0; }
bool CBaseGameStats::LoadFromFile( void ) { if ( filesystem->FileExists( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID ) ) { char fullpath[ 512 ]; filesystem->RelativePathToFullPath( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID, fullpath, sizeof( fullpath ) ); StatsLog( "Loading stats from '%s'\n", fullpath ); } CUtlBuffer buf; if ( filesystem->ReadFile( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID, buf ) ) { bool bRetVal = true; int version = buf.GetShort(); if ( version > GAMESTATS_FILE_VERSION ) return false; //file is beyond our comprehension // Set global parse version CBGSDriver.m_iLoadedVersion = version; buf.Get( CBGSDriver.m_szLoadedUserID, 16 ); CBGSDriver.m_szLoadedUserID[ sizeof( CBGSDriver.m_szLoadedUserID ) - 1 ] = 0; if ( s_szPseudoUniqueID[ 0 ] != 0 ) { if ( Q_stricmp( CBGSDriver.m_szLoadedUserID, s_szPseudoUniqueID ) ) { //UserID changed, blow away log!!! filesystem->RemoveFile( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID ); filesystem->RemoveFile( GAMESTATS_LOG_FILE, GAMESTATS_PATHID ); Warning( "Userid changed, clearing stats file\n" ); CBGSDriver.m_szLoadedUserID[0] = '\0'; CBGSDriver.m_iLoadedVersion = -1; gamestats->m_BasicStats.Clear(); gamestats->LoadingEvent_PlayerIDDifferentThanLoadedStats(); bRetVal = false; } if ( version <= GAMESTATS_FILE_VERSION_OLD5 ) { gamestats->m_BasicStats.Clear(); bRetVal = false; } else { // Peek ahead in buffer to see if we have the "no default stats" secret flag set. int iCheckForStandardStatsInFile = *( int * )buf.PeekGet(); bool bValid = true; if ( iCheckForStandardStatsInFile != GAMESTATS_STANDARD_NOT_SAVED ) { //the GAMESTATS_STANDARD_NOT_SAVED flag coincides with user completion time, rewind so the gamestats parser can grab it bValid = gamestats->m_BasicStats.ParseFromBuffer( buf, version ); } else { // skip over the flag buf.GetInt(); } if( !bValid ) { m_BasicStats.Clear(); } if( ( buf.TellPut() - buf.TellGet() ) != 0 ) //more data left, must be custom data { gamestats->LoadCustomDataFromBuffer( buf ); } } } return bRetVal; } else { filesystem->RemoveFile( GAMESTATS_LOG_FILE, GAMESTATS_PATHID ); } return false; }
//----------------------------------------------------------------------------- // Rebuilds all of a MDL's components. //----------------------------------------------------------------------------- static bool GenerateModelFiles( const char *pMdlFilename ) { CUtlBuffer tempBuffer; int fileSize; int paddedSize; int swappedSize; // .mdl CUtlBuffer mdlBuffer; if ( !scriptlib->ReadFileToBuffer( pMdlFilename, mdlBuffer ) ) { return false; } if ( !Studio_ConvertStudioHdrToNewVersion( (studiohdr_t *)mdlBuffer.Base() )) { Msg("%s needs to be recompiled\n", pMdlFilename ); } // .vtx char szVtxFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szVtxFilename, sizeof( szVtxFilename ) ); V_strncat( szVtxFilename, ".dx90.vtx", sizeof( szVtxFilename ) ); CUtlBuffer vtxBuffer; bool bHasVtx = ReadFileToBuffer( szVtxFilename, vtxBuffer, false, true ); // .vvd char szVvdFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szVvdFilename, sizeof( szVvdFilename ) ); V_strncat( szVvdFilename, ".vvd", sizeof( szVvdFilename ) ); CUtlBuffer vvdBuffer; bool bHasVvd = ReadFileToBuffer( szVvdFilename, vvdBuffer, false, true ); if ( bHasVtx != bHasVvd ) { // paired resources, either mandates the other return false; } // a .mdl file that has .vtx/.vvd gets re-processed to cull lod data if ( bHasVtx && bHasVvd ) { // cull lod if needed IMdlStripInfo *pStripInfo = NULL; bool bResult = mdllib->StripModelBuffers( mdlBuffer, vvdBuffer, vtxBuffer, &pStripInfo ); if ( !bResult ) { return false; } if ( pStripInfo ) { // .vsi CUtlBuffer vsiBuffer; pStripInfo->Serialize( vsiBuffer ); pStripInfo->DeleteThis(); // save strip info for later processing char szVsiFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szVsiFilename, sizeof( szVsiFilename ) ); V_strncat( szVsiFilename, ".vsi", sizeof( szVsiFilename ) ); WriteBufferToFile( szVsiFilename, vsiBuffer, false, WRITE_TO_DISK_ALWAYS ); } } // .ani processing may further update .mdl buffer char szAniFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szAniFilename, sizeof( szAniFilename ) ); V_strncat( szAniFilename, ".ani", sizeof( szAniFilename ) ); CUtlBuffer aniBuffer; bool bHasAni = ReadFileToBuffer( szAniFilename, aniBuffer, false, true ); if ( bHasAni ) { // Some vestigal .ani files exist in the tree, only process valid .ani if ( ((studiohdr_t*)mdlBuffer.Base())->numanimblocks != 0 ) { // .ani processing modifies .mdl buffer fileSize = aniBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; aniBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szAniFilename, sizeof( szAniFilename ) ); V_strncat( szAniFilename, ".360.ani", sizeof( szAniFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szAniFilename, tempBuffer.Base(), aniBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .ani buffer is replaced with swapped data aniBuffer.Purge(); aniBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szAniFilename, aniBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } } // .phy char szPhyFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szPhyFilename, sizeof( szPhyFilename ) ); V_strncat( szPhyFilename, ".phy", sizeof( szPhyFilename ) ); CUtlBuffer phyBuffer; bool bHasPhy = ReadFileToBuffer( szPhyFilename, phyBuffer, false, true ); if ( bHasPhy ) { fileSize = phyBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; phyBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szPhyFilename, sizeof( szPhyFilename ) ); V_strncat( szPhyFilename, ".360.phy", sizeof( szPhyFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szPhyFilename, tempBuffer.Base(), phyBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .phy buffer is replaced with swapped data phyBuffer.Purge(); phyBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szPhyFilename, phyBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } if ( bHasVtx ) { fileSize = vtxBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; vtxBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szVtxFilename, sizeof( szVtxFilename ) ); V_strncat( szVtxFilename, ".dx90.360.vtx", sizeof( szVtxFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szVtxFilename, tempBuffer.Base(), vtxBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .vtx buffer is replaced with swapped data vtxBuffer.Purge(); vtxBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szVtxFilename, vtxBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } if ( bHasVvd ) { fileSize = vvdBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; vvdBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); V_StripExtension( pMdlFilename, szVvdFilename, sizeof( szVvdFilename ) ); V_strncat( szVvdFilename, ".360.vvd", sizeof( szVvdFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szVvdFilename, tempBuffer.Base(), vvdBuffer.PeekGet(), fileSize, (studiohdr_t*)mdlBuffer.Base(), CompressFunc ); if ( swappedSize > 0 ) { // .vvd buffer is replaced with swapped data vvdBuffer.Purge(); vvdBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szVvdFilename, vvdBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } } // swap and write final .mdl fileSize = mdlBuffer.TellPut(); paddedSize = fileSize + BYTESWAP_ALIGNMENT_PADDING; mdlBuffer.EnsureCapacity( paddedSize ); tempBuffer.EnsureCapacity( paddedSize ); char szMdlFilename[MAX_PATH]; V_StripExtension( pMdlFilename, szMdlFilename, sizeof( szMdlFilename ) ); V_strncat( szMdlFilename, ".360.mdl", sizeof( szMdlFilename ) ); swappedSize = StudioByteSwap::ByteswapStudioFile( szMdlFilename, tempBuffer.Base(), mdlBuffer.PeekGet(), fileSize, NULL, CompressFunc ); if ( swappedSize > 0 ) { // .mdl buffer is replaced with swapped data mdlBuffer.Purge(); mdlBuffer.Put( tempBuffer.Base(), swappedSize ); WriteBufferToFile( szMdlFilename, mdlBuffer, false, WRITE_TO_DISK_ALWAYS ); } else { return false; } return true; }
//----------------------------------------------------------------------------- // Creates a collision model (based on the render geometry!) //----------------------------------------------------------------------------- void CVradStaticPropMgr::CreateCollisionModel( char const* pModelName ) { CUtlBuffer buf; CUtlBuffer bufvtx; CUtlBuffer bufphy; int i = m_StaticPropDict.AddToTail(); m_StaticPropDict[i].m_pModel = NULL; m_StaticPropDict[i].m_pStudioHdr = NULL; if ( !LoadStudioModel( pModelName, buf ) ) { VectorCopy( vec3_origin, m_StaticPropDict[i].m_Mins ); VectorCopy( vec3_origin, m_StaticPropDict[i].m_Maxs ); return; } studiohdr_t* pHdr = (studiohdr_t*)buf.Base(); // necessary for vertex access SetCurrentModel( pHdr ); VectorCopy( pHdr->hull_min, m_StaticPropDict[i].m_Mins ); VectorCopy( pHdr->hull_max, m_StaticPropDict[i].m_Maxs ); if ( LoadStudioCollisionModel( pModelName, bufphy ) ) { phyheader_t header; bufphy.Get( &header, sizeof(header) ); vcollide_t *pCollide = &m_StaticPropDict[i].m_loadedModel; s_pPhysCollision->VCollideLoad( pCollide, header.solidCount, (const char *)bufphy.PeekGet(), bufphy.TellPut() - bufphy.TellGet() ); m_StaticPropDict[i].m_pModel = m_StaticPropDict[i].m_loadedModel.solids[0]; /* static int propNum = 0; char tmp[128]; sprintf( tmp, "staticprop%03d.txt", propNum ); DumpCollideToGlView( pCollide, tmp ); ++propNum; */ } else { // mark this as unused m_StaticPropDict[i].m_loadedModel.solidCount = 0; // CPhysCollide* pPhys = CreatePhysCollide( pHdr, pVtxHdr ); m_StaticPropDict[i].m_pModel = ComputeConvexHull( pHdr ); } // clone it m_StaticPropDict[i].m_pStudioHdr = (studiohdr_t *)malloc( buf.Size() ); memcpy( m_StaticPropDict[i].m_pStudioHdr, (studiohdr_t*)buf.Base(), buf.Size() ); if ( !LoadVTXFile( pModelName, m_StaticPropDict[i].m_pStudioHdr, m_StaticPropDict[i].m_VtxBuf ) ) { // failed, leave state identified as disabled m_StaticPropDict[i].m_VtxBuf.Purge(); } }
//----------------------------------------------------------------------------- // Add, find collision model in cache //----------------------------------------------------------------------------- static CPhysCollide* GetCollisionModel( char const* pModelName ) { // Convert to a common string char* pTemp = (char*)_alloca(strlen(pModelName) + 1); strcpy( pTemp, pModelName ); _strlwr( pTemp ); char* pSlash = strchr( pTemp, '\\' ); while( pSlash ) { *pSlash = '/'; pSlash = strchr( pTemp, '\\' ); } // Find it in the cache ModelCollisionLookup_t lookup; lookup.m_Name = pTemp; int i = s_ModelCollisionCache.Find( lookup ); if (i != s_ModelCollisionCache.InvalidIndex()) return s_ModelCollisionCache[i].m_pCollide; // Load the studio model file CUtlBuffer buf; if (!LoadStudioModel(pModelName, "prop_static", buf)) { Warning("Error loading studio model \"%s\"!\n", pModelName ); // This way we don't try to load it multiple times lookup.m_pCollide = 0; s_ModelCollisionCache.Insert( lookup ); return 0; } // Compute the convex hull of the model... studiohdr_t* pStudioHdr = (studiohdr_t*)buf.PeekGet(); // necessary for vertex access SetCurrentModel( pStudioHdr ); lookup.m_pCollide = ComputeConvexHull( pStudioHdr ); s_ModelCollisionCache.Insert( lookup ); if ( !lookup.m_pCollide ) { Warning("Bad geometry on \"%s\"!\n", pModelName ); } // Debugging if (g_DumpStaticProps) { static int propNum = 0; char tmp[128]; sprintf( tmp, "staticprop%03d.txt", propNum ); DumpCollideToGlView( lookup.m_pCollide, tmp ); ++propNum; } FreeCurrentModelVertexes(); // Insert into cache... return lookup.m_pCollide; }