//========= Copyright c 1996-2011, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //====================================================================================// #ifndef __MDLCOMBINE_H #define __MDLCOMBINE_H #ifdef _WIN32 #pragma once #endif #include "utlbuffer.h" struct studiohdr2_t; struct studiodata_t; struct mstudiobone_t; struct mstudioanimdesc_t; struct mstudiomodel_t; class CModelCombine; class KeyValues; namespace OptimizedModel { struct StripGroupHeader_t; struct StripHeader_t; struct MeshHeader_t; struct ModelLODHeader_t; struct ModelHeader_t; struct BodyPartHeader_t; } //#define DEBUG_COMBINE 1 #define COMBINER_MAX_STRINGS 2000 #define COMBINER_MAX_BONES ( 53 * 2 ) #define COMBINER_MAX_SUB_MODELS 20 #define COMBINER_WORK_BUFFER_SIZE ( 2 * 1024 * 1024 ) #define COMBINER_MAX_MATERIALS ( COMBINER_MAX_MATERIALS_PER_INPUT_MODEL * COMBINER_MAX_MODELS ) #define COMBINER_MAX_BODYPARTS_PER_MODEL 5 typedef struct SAtlasGroup { unsigned char *m_pCombinedTextures[ COMBINER_MAX_TEXTURES_PER_MATERIAL ]; int m_nCombinedTextureSizes[ COMBINER_MAX_TEXTURES_PER_MATERIAL ]; KeyValues *m_pCombinedMaterial; char m_szCombinedMaterialName[ MAX_PATH ]; } TAtlasGroup; typedef struct SCombinedStudioData { studiodata_t *m_pPlaceholderStudioData; MDLHandle_t m_PlaceholderHandle; studiodata_t *m_pFinalStudioData; MDLHandle_t m_FinalHandle; void *m_pCombinedUserData; unsigned int m_nReferenceFlags; CombinedModelLoadedCallback m_CallbackFunc; CModelCombine *m_pCombineData; SCombinerModelInput_t m_ModelInputData[ COMBINER_MAX_MODELS ]; int m_nNumModels; int m_nModelMaterialCounts[ COMBINER_MAX_MODELS ]; int m_nModelMaterialIndices[ COMBINER_MAX_MODELS ][ COMBINER_MAX_MATERIALS ]; int m_MeshToMaterialMap[ COMBINER_MAX_MODELS ][ COMBINER_MAX_BODYPARTS_PER_MODEL ][ COMBINER_MAX_MATERIALS_PER_INPUT_MODEL ]; TAtlasGroup m_AtlasGroups[ COMBINER_MAX_ATLAS_GROUPS ]; int m_nNumAtlasGroups; char m_szNonAtlasedMaterialPaths[ COMBINER_MAX_MODELS ][ MAX_PATH ]; int m_nNumNonAtlasedMaterialPaths; KeyValues *m_pNonAtlasedMaterialKVs[ COMBINER_MAX_MODELS ]; char m_szNonAtlasedMaterialBaseName[ COMBINER_MAX_MODELS ][ MAX_PATH ]; int m_nNumNonAtlasedMaterialBaseNames; char m_szCombinedModelName[ MAX_PATH ]; // returned results TCombinedResults m_Results; } TCombinedStudioData; enum { WRITE_AREA_MDL = 0, WRITE_AREA_VTX, WRITE_AREA_VVD, WRITE_AREA_VTF, MAX_WRITE_AREAS }; class CCombinerMemoryWriter { public: CCombinerMemoryWriter( ); ~CCombinerMemoryWriter( ); void Init( ); void InitWriteArea( int nArea, char *pPosition ); void SetWriteArea( int nArea ); char *AllocWrite( int nSize ); char *WriteOffset( int &nOffsetIndex ); char *WriteOffset( int &nOffsetIndex, void *pBasePtr ); char *WriteOffset( short &nOffsetIndex, void *pBasePtr ); char *WriteBuffer( const void *pData, int nSize ); char *WriteBufferWithOffset( const void *pData, int nSize, int &nOffsetIndex ); char *WriteString( const char *pszString ); // adds NULL terminator char *WriteText( const char *pszString ); // does not add NULL terminator void AlignWrite( int nAlignSize ); char *GetSaveWritePos( int nArea ) { return m_pSaveWritePos[ nArea ]; } char *GetWritePos( ) { return m_pWritePos; } char *GetWriteArea( ) { return m_pWriteArea; } private: char *m_pWorkBuffer; char *m_pEndBuffer; char *m_pWriteArea; char *m_pSaveWriteArea[ MAX_WRITE_AREAS ]; char *m_pWritePos; char *m_pSaveWritePos[ MAX_WRITE_AREAS ]; int m_nWriteArea; #ifdef DEBUG_COMBINE char *m_pErrorPos; #endif }; extern CCombinerMemoryWriter g_CombinerWriter; class CModelCombine { public: CModelCombine( ); ~CModelCombine( ); void Init( TCombinedStudioData *pCombinedStudioData ); bool Resolve( ); void *GetCombinedMDLPtr( ) { return ( void * )m_pCombinedStudioHdr; } int GetCombinedMDLSize( ) { return g_CombinerWriter.GetSaveWritePos( WRITE_AREA_MDL ) - ( char *)m_pCombinedStudioHdr; } bool GetCombinedMDLAvailability( ) { return GetCombinedMDLSize() != 0; } void *GetCombinedVTXPtr( ) { return ( void * )m_pCombinedHardwareHeader; } int GetCombinedVTXSize( ) { return g_CombinerWriter.GetSaveWritePos( WRITE_AREA_VTX ) - ( char *)m_pCombinedHardwareHeader; } bool GetCombinedVTXAvailability( ) { return GetCombinedVTXSize() != 0; } void *GetCombinedVVDPtr( ) { return ( void * )m_pCombinedVertex; } int GetCombinedVVDSize( ) { return g_CombinerWriter.GetSaveWritePos( WRITE_AREA_VVD ) - ( char *)m_pCombinedVertex; } bool GetCombinedVVDAvailability( ) { return GetCombinedVVDSize() != 0; } TCombinedResults *GetResults( ) { return &m_pCombinedStudioData->m_Results; } static int GetNextAssetID( ) { return ++m_nNextAssetID; } private: static int BoneNameCompare( const void *elem1, const void *elem2 ); void BeginStringTable( ); void AddToStringTable( void *base, int *ptr, const char *string ); void WriteStringTable( ); void VerifyField( int nField, const char *pszDescription ); void VerifyField2( int nField, const char *pszDescription ); void VerifyOffset( void *pPtr, const char *pszDescription, void *pWritePos = 0 ); void DetermineMasterBoneList( ); // void CombineMDL_PreintStrings( ); void RemapBone( int nModel, int &nBone ) { nBone = m_nBoneRemap[ nModel ][ nBone ]; } void WriteBoneProc( int nSize, int nType1, int nType2 = -999 ); void WriteBoneQuatInterp( ); void WriteBoneTwist( ); void WriteBoneConstraints( ); void WriteBoneAttachments( ); void WriteHitBoxes( ); void WriteBoneTable( ); void CombineMDL_Bones( ); void WriteAnimation( mstudioanimdesc_t *pOrigAnim, void *pAnimData, int nFrameSize ); void CombineMDL_Anims( ); void CombineMDL_SequenceInfo( ); void WriteModel( int nModel ); void CombineMDL_Model( ); void CombineMDL_Textures( ); void CombineMDL_KeyValues( ); void CombineMDL_BoneTransforms( ); void CombineMDL_BoneFlexDrivers( ); void CombineMDL_AssignMeshIDs( ); void CombineMDL( bool bNoStringTable ); #ifdef DEBUG_COMBINE void TestCombineMDL( ); #endif // DEBUG_COMBINE void CalcVTXInfo(); void WriteStrip( OptimizedModel::StripGroupHeader_t *pNewStripGroup, int nModel, OptimizedModel::StripGroupHeader_t *pOrigStripGroup, OptimizedModel::StripHeader_t *pOrigStrip ); void MergeStripGroup( int nLOD, OptimizedModel::StripGroupHeader_t *pNewStripGroup, int nModel, OptimizedModel::StripGroupHeader_t *pOrigStripGroup ); void WriteStripGroup( int nLOD, int nMaterialIndex, unsigned char nStripGroupFlags, OptimizedModel::MeshHeader_t *pNewMesh ); void WriteMeshes( int nLOD, int nMaterialIndex, OptimizedModel::ModelLODHeader_t *pNewModelLOD, OptimizedModel::ModelLODHeader_t *pOrigModelLOD ); void WriteModelLOD( int nLOD, OptimizedModel::ModelHeader_t *pNewModel, OptimizedModel::ModelHeader_t *pOrigModel ); void WriteModel( int nModel, OptimizedModel::BodyPartHeader_t *pNewBodyPart, OptimizedModel::BodyPartHeader_t *pOrigBodyPart ); void WriteBodyPart( int nBodyPart ); void CombineVTX( ); #ifdef DEBUG_COMBINE void TestCombineVTX( ); #endif // DEBUG_COMBINE // void CombineVVD_OffsetVerts( ); void CombineVVD( ); // void CombineTextures( ); int AddMaterialToTextureCombiner( int nTextureIndex, int nModel, int nModelMaterialIndex ); void Test( ); typedef struct SHardwareData { int m_nBodyParts; int m_nMaxBodyParts; int m_nModels; int m_nModelLODs; int m_nMeshes; int m_nStripGroups; int m_nStrips; int m_nVerts; int m_nIndices; int m_nBoneStateChanges; int m_nStringTable; int m_nTopology; int m_nMaterialReplacements; } THardwareData; TCombinedStudioData *m_pCombinedStudioData; CUtlBuffer *MDL_Data[ COMBINER_MAX_MODELS ]; CUtlBuffer *VTX_Data[ COMBINER_MAX_MODELS ]; CUtlBuffer *VVD_Data[ COMBINER_MAX_MODELS ]; studiohdr_t *m_pStudioHdr[ COMBINER_MAX_MODELS ]; studiohdr2_t *m_pStudioHdr2[ COMBINER_MAX_MODELS ]; vertexFileHeader_t *m_pVertexFileHeader[ COMBINER_MAX_MODELS ]; const mstudiobone_t *m_pMasterBoneList[ COMBINER_MAX_BONES ]; int m_nBoneModelOwner[ COMBINER_MAX_BONES ]; int m_nNumMasterBones; int m_nBoneRemap[ COMBINER_MAX_MODELS ][ COMBINER_MAX_BONES ]; int m_nMasterToLocalBoneRemap[ COMBINER_MAX_MODELS ][ COMBINER_MAX_BONES ]; mstudiomodel_t *m_pMasterModels[ COMBINER_MAX_MODELS ][ COMBINER_MAX_SUB_MODELS ]; mstudiomodel_t *m_pMasterFlexModels[ COMBINER_MAX_SUB_MODELS ]; int *m_nVertexRemap[ COMBINER_MAX_MODELS ]; int m_nFlexModelSource; THardwareData m_MaxHardwareData; THardwareData m_CurrentHardwareData; THardwareData m_HardwareOffsets; studiohdr_t *m_pCombinedStudioHdr; studiohdr2_t *m_pCombinedStudioHdr2; OptimizedModel::FileHeader_t *m_pCombinedHardwareHeader; mstudiomodel_t *m_pCombinedModels; vertexFileHeader_t *m_pCombinedVertex; struct stringtable_t { byte *base; int *ptr; const char *string; int dupindex; byte *addr; }; int numStrings; stringtable_t strings[ COMBINER_MAX_STRINGS ]; static unsigned int m_nNextAssetID; }; extern CModelCombine g_ModelCombiner; #endif // __MDLCOMBINE_H