Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

436 lines
14 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ==========
  2. #ifndef CLOTHPROXYCOMPILER_HDR
  3. #define CLOTHPROXYCOMPILER_HDR
  4. #include "movieobjects/dmevertexdata.h"
  5. #include "bitvec.h"
  6. #include "tier1/utlstringmap.h"
  7. #include "mdlobjects/authphysfx.h"
  8. #include "mdlobjects/clothproxymesh.h"
  9. #include "movieobjects/dmefaceset.h"
  10. #include "meshutils/mesh.h"
  11. #include "movieobjects/dmemeshtypes.h"
  12. class CDmeModel;
  13. class CAuthPhysFx;
  14. class CVClothProxyMesh;
  15. class CDmeDag;
  16. class CClothProxyCompiler
  17. {
  18. public:
  19. CVClothProxyMeshOptions m_Options;
  20. CClothProxyCompiler( CAuthPhysFx *pAuthFx );
  21. ~CClothProxyCompiler(){}
  22. bool IsEmpty() const
  23. {
  24. return m_pAuthFx->m_Nodes.Count() == 0;
  25. }
  26. CAuthPhysFx *GetFx() { return m_pAuthFx; }
  27. void Init( const CVClothProxyMeshOptions &clothProxyMeshList );
  28. int GetOrCreateClothRootBone();
  29. void Append( CDmeModel *pModel, float flClothEnableThreshold, const CVClothProxyMesh &proxy);
  30. void AppendPlaneCollision( CDmeModel *pModel );
  31. void Cook( );
  32. CLockedResource< PhysFeModelDesc_t > Compile( CResourceStream *pStream )const;
  33. void MarkFreeRotatingNodes( const CAuthPhysFx::CQuad &quad );
  34. void AlignNodes();
  35. int GetAuthFxBone( const char *pName );
  36. template <typename T>
  37. class CIndexedAttr
  38. {
  39. public:
  40. CDmrArrayConst< T > m_Data;
  41. CDmrArrayConst< int > m_IndexData;
  42. public:
  43. CIndexedAttr() {}
  44. CIndexedAttr( CDmeVertexData *pBindState, FieldIndex_t nField )
  45. {
  46. Init( pBindState, nField );
  47. }
  48. CIndexedAttr( CDmeVertexData *pBindState, CDmeVertexDataBase::StandardFields_t nField )
  49. {
  50. Init( pBindState, nField );
  51. }
  52. void Init( CDmeVertexData *pBindState, CDmeVertexDataBase::StandardFields_t nField )
  53. {
  54. Init( pBindState, pBindState->FindFieldIndex( nField ) );
  55. }
  56. CIndexedAttr( CDmeVertexData *pBindState, const char *pField )
  57. {
  58. Init( pBindState, pBindState->FindFieldIndex( pField ) );
  59. }
  60. void Init( CDmeVertexData *pBindState, FieldIndex_t nField )
  61. {
  62. if ( nField >= 0 )
  63. {
  64. m_Data = pBindState->GetVertexData( nField );
  65. m_IndexData = pBindState->GetIndexData( nField );
  66. }
  67. }
  68. operator bool() const { return m_IndexData.IsValid() && m_Data.IsValid() && m_Data.Count() > 0 && m_IndexData.Count() > 0; }
  69. const T& operator []( int i ) const { return m_Data[ m_IndexData[ i ] ]; }
  70. int GetDataCount() const{ return m_Data.Count(); }
  71. int GetElementCount()const { return m_IndexData.Count(); } // not really vertex count
  72. int GetAttrCount()const { return 1; } // TODO: find the number of attributes per vertex
  73. void Reset()
  74. {
  75. m_Data = CDmrArrayConst< T >();
  76. m_IndexData = CDmrArrayConst< int >();
  77. }
  78. };
  79. struct Binding_t
  80. {
  81. int nAuthFxBone;
  82. float flWeight;
  83. Binding_t() : nAuthFxBone( -1 ), flWeight( 0 ) {}
  84. };
  85. struct ProjItem_t
  86. {
  87. ProjItem_t( int i = -1, float f = 0 ) : nIndex( i ), flEnvelope( f ){}
  88. ProjItem_t( const ProjItem_t &other ) : nIndex( other.nIndex ), flEnvelope( other.flEnvelope ){}
  89. int nIndex;
  90. float flEnvelope;
  91. };
  92. struct QuadProjection_t
  93. {
  94. Vector m_vContact; // projected point on the quad
  95. Vector m_vNormal;
  96. float m_flDistance; // negative if behind the plane
  97. int m_nBindings;
  98. Binding_t m_Binding[ 4 ];
  99. bool IsEmpty() const { return m_nBindings == 0; }
  100. Vector GetOriginalPoint()const { return m_vContact + m_vNormal * m_flDistance; }
  101. void AddBinding( uint nIndex, float flWeight )
  102. {
  103. Binding_t &b = m_Binding[ m_nBindings++ ];
  104. b.nAuthFxBone = nIndex;
  105. b.flWeight = flWeight;
  106. }
  107. bool operator < ( const QuadProjection_t &other )const
  108. {
  109. return m_flDistance < other.m_flDistance;
  110. }
  111. };
  112. class CModelContext
  113. {
  114. public:
  115. CModelContext( CClothProxyCompiler *pCompiler, CDmeModel *pModel, float flClothEnableThreshold, const CVClothProxyMesh &proxy );
  116. int MapJointToFxBone( int nJoint, bool bSimulated );
  117. int GetJointCount()const { return m_JointToFxBone.Count(); }
  118. public:
  119. CDmeModel *m_pModel;
  120. CUtlVector< UtlSymId_t > m_JointToBoneSubset;
  121. CUtlVector< int > m_JointToFxBone;
  122. CAuthPhysFx * m_pAuthFx;
  123. float m_flClothEnableThreshold;
  124. const CVClothProxyMesh &m_Proxy;
  125. };
  126. friend class CModelContext;
  127. class CMeshContext
  128. {
  129. public:
  130. CMeshContext( CClothProxyCompiler *pCompiler, CModelContext *pModelContext, CDmeMesh *pMesh, const matrix3x4_t &tm, int nDmeMesh );
  131. public:
  132. int m_nDmeMesh;
  133. CDmeMesh *m_pDmeMesh;
  134. matrix3x4_t m_MeshTransform;
  135. CDmeVertexData *m_pBindState;
  136. CIndexedAttr< Vector > m_AttrPos, m_AttrNormal, m_AttrTangent;
  137. CAuthPhysFx *m_pAuthFx;
  138. CModelContext *m_pModelContext;
  139. CUtlVector< int > m_DmePosToFxBone; // position (index in the position array in DmeVertex) to FxBone (index of CBone in AuthFx) map
  140. CClothProxyCompiler *m_pCompiler;
  141. public:
  142. int FindMostBoundJoint( int nDmePos, float flBonusForExisting );
  143. int GetSkinningJointCount();
  144. int GetOrCreateClothBoneIndex( int nDmePos, bool bSimulated );
  145. int GetClothBoneIndex( int nDmePos );
  146. CAuthPhysFx::CBone *GetOrCreateClothBone( int nDmePos, bool bSimulated );
  147. CAuthPhysFx::CBone *GetClothBone( int nDmePos );
  148. };
  149. friend class CMeshContext;
  150. int GetMaxBonesPerVertex()const { return Max( 1, Min( 4, m_Options.m_nMaxBonesPerVertex ) ); }
  151. bool Project( const Vector &vPos, UtlSymId_t*pFindSubset, int nFindSubsetCount, CUtlVector<Binding_t> &outBindings, int nIslandFilter );
  152. void ProjectAndAddToQueue( const ProjItem_t &q, const Vector & vPos, CUtlSortVector< QuadProjection_t > &bestProj, int nIslandFilter );
  153. int NodeToIsland( int nNode );
  154. int GetIslandCount() const { return m_nIslandCount; }
  155. protected:
  156. void AppendPlaneCollisionDag( CModelContext &modelContext, CDmeDag *pDmeDag );
  157. void AppendPlaneCollisionMesh( CModelContext &modelContext, CDmeMesh *pMesh, const matrix3x4_t &tm );
  158. void AppendDag( CModelContext &context, CDmeDag *pDmeDag );
  159. void AppendMesh( CModelContext &modelContext, CDmeMesh *pMesh, const matrix3x4_t &tm );
  160. void CreateClothBones( CMeshContext &context );
  161. void AddFitWeights( CMeshContext &context );
  162. void BindNodeOffsetParents( CMeshContext &context );
  163. void OrientClothBones( CMeshContext &context );
  164. void CreateClothQuads( CMeshContext &context );
  165. void ApplyClothBoneAttributes( CMeshContext &context );
  166. QuadProjection_t ProjectOnQuad( const Vector &vPos, const CAuthPhysFx::CQuad &quad );
  167. QuadProjection_t ProjectOnTri( const Vector &vPos, const CAuthPhysFx::CQuad &quad );
  168. public:
  169. class CVertex
  170. {
  171. public:
  172. Vector m_vPos; // world position
  173. };
  174. class CPolygon
  175. {
  176. public:
  177. CUtlVectorFixedGrowable< CVertex*, 4 > m_Verts;
  178. Vector m_vNormal;
  179. };
  180. class CAuthFxSubset
  181. {
  182. public:
  183. CUtlVectorFixedGrowable< ProjItem_t, 4 > m_Quads;
  184. CUtlVectorFixedGrowable< ProjItem_t, 4 > m_Rods;
  185. void Append( const CAuthFxSubset &other );
  186. };
  187. class CAuthFxBoneSubset : public CAuthFxSubset
  188. {
  189. public:
  190. CAuthFxBoneSubset( int nModelJoint ) : m_nModelJoint( nModelJoint ){}
  191. int m_nModelJoint;
  192. };
  193. UtlSymId_t FindBoneSym( const char *pName )
  194. {
  195. return m_BoneSubsets.Find( pName );
  196. }
  197. CUtlVector< CUtlString > m_MeshNames; // names of meshes that comprise this proxy mesh, for debugging
  198. protected:
  199. CAuthPhysFx *m_pAuthFx;
  200. CUtlStringMapAutoPurge< CAuthFxBoneSubset* > m_BoneSubsets; // for each AuthFx bone, a subset of quads and rods to project to
  201. CAuthFxSubset m_DefaultSubset;
  202. int m_nProxyMeshes;
  203. int m_nRootFxNode;
  204. private:
  205. int m_nIslandCount;
  206. CUtlVector< int > m_NodeToIslandMap;
  207. };
  208. template <typename Functor >
  209. inline void EnumerateFaces( CDmeMesh *pDmeMesh, CDmeVertexData * pBindState, const CVarBitVec *pUsefulDmeVerts, Functor &fn )
  210. {
  211. //const CUtlVector< Vector > & arrDmeVert = pBindState->GetPositionData();// the most original and un-split position array
  212. const CUtlVector< int > & arrVertIndex = pBindState->GetVertexIndexData( CDmeVertexDataBase::FIELD_POSITION );
  213. // find connecting (static) bones, and the bones that will drive them (add those, too, taking care not to add them twice)
  214. //pBindState->FindFieldIndex( CDmeVertexDataBase::FIELD_POSITION )
  215. int nFaceSetCount = pDmeMesh->FaceSetCount();
  216. int nSkippedDegenerate = 0, nSkippedManygons = 0;
  217. for ( int nFaceSet = 0; nFaceSet < nFaceSetCount; ++nFaceSet )
  218. {
  219. CDmeFaceSet *pFaceSet = pDmeMesh->GetFaceSet( nFaceSet );
  220. int nIndexCount = pFaceSet->NumIndices(); // for each face (N-gon), there are N indices and -1 in this array
  221. int nFirstIndex = 0;
  222. while ( nFirstIndex < nIndexCount )
  223. {
  224. int nVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  225. if ( nVertexCount < 2 )
  226. {
  227. nSkippedDegenerate++;
  228. continue;
  229. }
  230. int nUsefulVertexCount = nVertexCount;
  231. if ( nVertexCount > 4 )
  232. {
  233. nUsefulVertexCount = 4;
  234. nSkippedManygons++;
  235. }
  236. int nPosVerts[ 4 ] = { -1,-1,-1,-1};
  237. //DmeVertexIndex_t nFaceVerts[ 4 ];
  238. CAuthPhysFx::CQuad quad;
  239. bool bUseful = false;
  240. for ( int nV = 0; nV < nUsefulVertexCount; ++nV )
  241. {
  242. DmeVertexIndex_t nFaceVertIndex = pFaceSet->GetIndex( nFirstIndex + nV );
  243. //nFaceVerts[ nV ] = nFaceVertIndex;
  244. int nDmeVert = arrVertIndex[ nFaceVertIndex ];
  245. nPosVerts[ nV ] = nDmeVert;
  246. if ( !pUsefulDmeVerts || ( nDmeVert < pUsefulDmeVerts->GetNumBits() && pUsefulDmeVerts->IsBitSet( nDmeVert ) ) )
  247. {// it's all useful if we don't have a bitmap; otherwise, consult the bitmap - at least one vertex of the polygon must be useful
  248. bUseful = true;
  249. }
  250. }
  251. if ( bUseful ) // skip irrelevant polygons
  252. {
  253. for ( int nV = nUsefulVertexCount; nV < 4; ++nV )
  254. {
  255. nPosVerts[ nV ] = nPosVerts[ nUsefulVertexCount - 1 ];
  256. //nFaceVerts[ nV ] = nFaceVerts[ nUsefulVertexCount - 1 ];
  257. }
  258. fn( nPosVerts, nUsefulVertexCount );
  259. }
  260. nFirstIndex += nVertexCount + 1; // skip N-gon indices and the -1 terminator
  261. }
  262. }
  263. if ( nSkippedDegenerate || nSkippedManygons )
  264. {
  265. Warning( "Cloth: %d degenerate and %d 5+gons\n", nSkippedDegenerate, nSkippedManygons );
  266. }
  267. }
  268. /*
  269. template <typename Functor >
  270. inline void EnumerateFaces( CDmeMesh *pDmeMesh, CDmeVertexData * pBindState, Functor &fn )
  271. {
  272. //const CUtlVector< Vector > & arrDmeVert = pBindState->GetPositionData();// the most original and un-split position array
  273. const CUtlVector< int > & arrVertIndex = pBindState->GetVertexIndexData( CDmeVertexDataBase::FIELD_POSITION );
  274. int nFaceSetCount = pDmeMesh->FaceSetCount();
  275. for ( int nFaceCount = 0; nFaceCount < nFaceSetCount; ++nFaceCount )
  276. {
  277. CDmeFaceSet *pFaceSet = pDmeMesh->GetFaceSet( nFaceCount );
  278. int nIndexCount = pFaceSet->NumIndices(); // for each face (N-gon), there are N indices and -1 in this array
  279. int nFirstIndex = 0;
  280. while ( nFirstIndex < nIndexCount )
  281. {
  282. int nTotalVertexCount = pFaceSet->GetNextPolygonVertexCount( nFirstIndex );
  283. int nPolyIndex0 = arrVertIndex[ pFaceSet->GetIndex( nFirstIndex ) ];
  284. //Vector vApex = arrDmeVert[ nPolyIndex0 ]; // we're going around the first vertex and split the poly into quads and tris
  285. for ( int nBase = 1; nBase < nTotalVertexCount; nBase += 2 )
  286. {
  287. int nPosVerts[ 4 ] = { nPolyIndex0 };
  288. int nFoundVerts = 1;
  289. //Vector vPrevVert = vApex;
  290. for ( int m = Min( nTotalVertexCount - 1, nBase + 2 ); m >= nBase; m-- )
  291. {
  292. int nPolyIndexM = arrVertIndex[ pFaceSet->GetIndex( nFirstIndex + m ) ];
  293. Vector vVertM = arrVertIndex[ nPolyIndexM ];
  294. //if ( ( vPrevVert - vVertM ).Length() > flCollapseEdgesThreshold )
  295. {
  296. nPosVerts[ nFoundVerts++ ] = nPolyIndexM;
  297. //vPrevVert = vVertM;
  298. }
  299. }
  300. if ( nFoundVerts > 1 )
  301. {
  302. for ( int m = nFoundVerts; m < 4; ++nFoundVerts )
  303. nPosVerts[ m ] = nPosVerts[ nFoundVerts - 1 ];
  304. fn( nPosVerts, nFoundVerts );
  305. }
  306. }
  307. nFirstIndex += nVertexCount + 1; // skip N-gon indices and the -1 terminator
  308. }
  309. }
  310. }
  311. */
  312. template < typename Attr >
  313. class ClothAttributes
  314. {
  315. public:
  316. Attr m_animation_attraction ;
  317. Attr m_animation_force_attraction ;
  318. Attr m_drag ;
  319. Attr m_mass ;
  320. Attr m_gravity ;
  321. Attr m_collision_radius ;
  322. Attr m_ground_collision ;
  323. Attr m_ground_friction ;
  324. Attr m_use_rods;
  325. Attr m_anchor_free_rotate;
  326. protected:
  327. float Get( const CMesh::CSingleVertexFieldAccessor< float > &accessor )
  328. {
  329. return *accessor;
  330. }
  331. float Get( float x )
  332. {
  333. return x;
  334. }
  335. public:
  336. template < typename Map >
  337. ClothAttributes( Map map )
  338. {
  339. m_animation_attraction = map( "cloth_animation_attract" );
  340. m_animation_force_attraction = map( "cloth_animation_force_attract" );
  341. m_drag = map( "cloth_drag" );
  342. m_mass = map( "cloth_mass" );
  343. m_gravity = map( "cloth_gravity" );
  344. m_collision_radius = map( "cloth_collision_radius" );
  345. m_ground_collision = map( "cloth_ground_collision" );
  346. m_ground_friction = map( "cloth_ground_friction" );
  347. m_use_rods = map( "cloth_use_rods" );
  348. m_anchor_free_rotate = map( "cloth_anchor_free_rotate" );
  349. }
  350. void Apply( int nVert, CAuthPhysFx::CBone &authFxBone )
  351. {
  352. if ( m_animation_attraction )
  353. authFxBone.m_Integrator.flAnimationVertexAttraction = 30 * Get( m_animation_attraction[ nVert ] );
  354. if ( m_animation_force_attraction )
  355. authFxBone.m_Integrator.flAnimationForceAttraction = 30 * Get( m_animation_force_attraction[ nVert ] );
  356. if ( m_drag )
  357. authFxBone.m_Integrator.flPointDamping = 30 * Get( m_drag[ nVert ] );
  358. if ( m_mass )
  359. authFxBone.m_flMassBias = expf( Get( m_mass[ nVert ] ) );
  360. if ( m_gravity )
  361. authFxBone.m_Integrator.flGravity = Get( m_gravity[ nVert ] );
  362. if ( m_collision_radius )
  363. authFxBone.m_flCollisionRadius = Get( m_collision_radius[ nVert ] );
  364. if ( m_ground_collision )
  365. {
  366. authFxBone.m_flWorldFriction = 1.0f - Get( m_ground_collision[ nVert ] ); // ground_collision 0 maps to "worldFriction(source1 misnomer)" 1
  367. if ( authFxBone.m_flWorldFriction < 0.999f )
  368. {
  369. authFxBone.m_bNeedsWorldCollision = true;
  370. }
  371. }
  372. if ( m_ground_friction )
  373. {
  374. authFxBone.m_flGroundFriction = Get( m_ground_friction[ nVert ] );
  375. }
  376. if ( m_use_rods )
  377. {
  378. authFxBone.m_bUseRods = Get( m_use_rods[ nVert ] )> 0.5f;
  379. }
  380. if ( m_anchor_free_rotate )
  381. {
  382. authFxBone.m_bFreeRotation = Get( m_anchor_free_rotate[ nVert ] )> 0.5f;
  383. }
  384. }
  385. };
  386. extern const char *g_pDefaultClothRootBoneName;
  387. extern CClothProxyCompiler *g_pClothProxyCompiler ;
  388. #endif // CLOTHPROXYCOMPILER_HDR