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.

1424 lines
44 KiB

  1. //========== Copyright (c) Valve Corporation. All Rights Reserved. ============
  2. #ifndef AUTHPHYSMODEL_HDR
  3. #define AUTHPHYSMODEL_HDR
  4. #ifdef COMPILER_MSVC
  5. #pragma once
  6. #endif
  7. #include "tier1/utlincrementalvector.h"
  8. #include "tier1/utlstringtoken.h"
  9. #include "resourcefile/resourcestream.h"
  10. #include "mathlib/aabb.h"
  11. #include "mathlib/vertexcolor.h"
  12. #include "rubikon/param_types.h"
  13. #include "mathlib/femodeldesc.h"
  14. #include "mathlib/femodelbuilder.h"
  15. #include "tier1/utlhashtable.h"
  16. #include "bitvec.h"
  17. #include "tier1/utlstringmap.h"
  18. #include "tier1/utlsortvector.h"
  19. #include "mdlobjects/vpropbreakabledata.h"
  20. struct VPhysXBodyPart_t;
  21. struct RnSphereDesc_t;
  22. struct RnCapsuleDesc_t;
  23. struct RnHullDesc_t;
  24. struct RnMeshDesc_t;
  25. struct RnShapeDesc_t;
  26. struct AABB_t;
  27. struct RnHull_t;
  28. class CToolSceneTraceEnvironment;
  29. class CMesh;
  30. struct GizmoTransform_t;
  31. struct RnHullSimplificationParams_t;
  32. struct PhysSoftbodyDesc_t;
  33. class CUtlSymbolTable;
  34. template <class T >class CUtlStringMap;
  35. class CPhysModelSource;
  36. /*schema*/ class CAuthPhysBody;
  37. class KeyValues;
  38. struct VPhysXAggregateData_t;
  39. struct VPhysXJoint_t;
  40. class CResourceStream;
  41. struct VertexPositionNormal_t;
  42. struct VertexPositionColor_t;
  43. struct AuthHullSimplificationParams_t;
  44. class CVClothProxyMeshOptions;
  45. /*schema*/ enum AuthPhysCollisionAttributesModeEnum_t
  46. {
  47. AUTH_PHYS_COLL_ATTR_IGNORE, META( MPropertyFriendlyName = "Default/Derived" )
  48. AUTH_PHYS_COLL_ATTR_OVERRIDE, META( MPropertyFriendlyName = "Override" )
  49. AUTH_PHYS_COLL_ATTR_APPEND META( MPropertyFriendlyName = "Append" )
  50. };
  51. DECLARE_SCHEMA_ENUM( AuthPhysCollisionAttributesModeEnum_t );
  52. enum AuthPhysFxCollisionTypeEnum_t
  53. {
  54. AUTH_PHYS_FX_SPHERE,
  55. AUTH_PHYS_FX_PLANE
  56. };
  57. /*schema*/ class CAuthPhysCollisionAttributesOverride;
  58. /*schema*/ struct VPhysXCollisionAttributes_t;
  59. class CAuthPhysCompileContext;
  60. /*schema*/ class CAuthPhysCollisionAttributes
  61. {
  62. public:
  63. CAuthPhysCollisionAttributes()
  64. {
  65. m_CollisionGroup = "default";
  66. }
  67. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysCollisionAttributes )
  68. void ApplyOverride( const CAuthPhysCollisionAttributesOverride &collOverride );
  69. void Compile( CAuthPhysCompileContext &context, VPhysXCollisionAttributes_t &entry )const;
  70. CUtlString m_CollisionGroup; META( MPropertyFriendlyName = "Collision Group"; MPropertyChoiceProviderFn = GetCollisionGroupList );
  71. CUtlVector< CUtlString > m_InteractAs; META( MPropertyFriendlyName = "Interact As"; MPropertyChoiceProviderFn = GetInteractionLayerList );
  72. CUtlVector< CUtlString > m_InteractWith; META( MPropertyFriendlyName = "Interact With"; MPropertyChoiceProviderFn = GetInteractionLayerList );
  73. bool operator == ( const CAuthPhysCollisionAttributes & other )const;
  74. };
  75. /*schema*/ class CAuthPhysCollisionAttributesOverride: public CAuthPhysCollisionAttributes
  76. {
  77. public:
  78. CAuthPhysCollisionAttributesOverride()
  79. {
  80. m_nMode = AUTH_PHYS_COLL_ATTR_IGNORE; // ignore by default
  81. }
  82. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysCollisionAttributesOverride )
  83. AuthPhysCollisionAttributesModeEnum_t m_nMode; META( MPropertyFriendlyName = "Mode" );
  84. };
  85. class CLockecResourceHashFunctor
  86. {
  87. public:
  88. uint operator() ( const CLockedResource<char> &res )const
  89. {
  90. CRC32_t nCrc;
  91. CRC32_Init( &nCrc );
  92. CRC32_ProcessBuffer( &nCrc, res, res.Count( ) );
  93. CRC32_Final( &nCrc );
  94. return nCrc;
  95. }
  96. };
  97. class CLockedResourceEqualFunctor
  98. {
  99. public:
  100. bool operator() ( const CLockedResource<char> &a, const CLockedResource<char> & b )const
  101. {
  102. return a.Count( ) == b.Count( ) && !V_memcmp( a, b, a.Count( ) );
  103. }
  104. };
  105. typedef CUtlHashtable< CLockedResource< char >, empty_t, CLockecResourceHashFunctor, CLockedResourceEqualFunctor > CLockedResourceHashtable;
  106. class CAuthPhysCompileContext
  107. {
  108. public:
  109. CAuthPhysCompileContext( CResourceStream *pStream )
  110. : m_pStream( pStream ), m_DefaultSurfaceProperty( "default" )
  111. {}
  112. int ResolveCollisionAttributesIndex();
  113. const CAuthPhysCollisionAttributes &GetDefaultCollisionAttributes() { return m_DefaultCollisionAttributes; }
  114. void ApplyOverrideToDefault( const CAuthPhysCollisionAttributesOverride &collAttr ) { m_DefaultCollisionAttributes.ApplyOverride( collAttr ); }
  115. void SetDefaultCollisionAttributes( const CAuthPhysCollisionAttributes &attr ) { m_DefaultCollisionAttributes = attr; }
  116. int GetCollAttrPaletteSize( )const { return m_CollAttrPalette.Count();}
  117. const CAuthPhysCollisionAttributes &GetCollAttrPaletteEntry( int i ) { return m_CollAttrPalette[i]; }
  118. CResourceStream *GetStream() { return m_pStream; }
  119. CLockedResource<char> WriteString( const char *pString, uint32 *pHashOut = NULL ); // writes a non-unique string (saving space) , returns its hash
  120. template <typename T> CLockedResource< T > FindOrWrite( const T *pData, uint nElements )
  121. {
  122. CLockedResource< char > res( ( char* ) pData, nElements * sizeof( T ) );
  123. UtlHashHandle_t hFind = m_WrittenResources.Find( res );
  124. if ( hFind == m_WrittenResources.InvalidHandle( ) )
  125. {
  126. CLockedResource<T> written = m_pStream->Allocate< T>( nElements );
  127. V_memcpy( written, pData, sizeof ( T ) *nElements );
  128. m_WrittenResources.Insert( CLockedResource<char>( ( char* ) ( T* ) written, nElements * sizeof( T ) ));
  129. return written;
  130. }
  131. else
  132. {
  133. CLockedResource<char> found = m_WrittenResources[ hFind ];
  134. return CLockedResource< T >( ( T* ) ( char* ) found, nElements ); // found a copy, no need to write it out again
  135. }
  136. }
  137. const CUtlString &GetDefaultSurfaceProperty()const { return m_DefaultSurfaceProperty; }
  138. void SetDefaultSurfaceProperty( const char *pSurfacePropertyOverride ){ m_DefaultSurfaceProperty = pSurfacePropertyOverride ; }
  139. int ResolveSurfacePropertyIndex();
  140. int GetSurfacePropertyPaletteSize() { return m_SurfacePropPalette.Count(); }
  141. const CUtlString &GetSurfacePropertyPaletteEntry( int i ) { return m_SurfacePropPalette[i]; }
  142. protected:
  143. CAuthPhysCollisionAttributes m_DefaultCollisionAttributes;
  144. CResourceStream *m_pStream;
  145. CUtlVector< CAuthPhysCollisionAttributes > m_CollAttrPalette;
  146. CLockedResourceHashtable m_WrittenResources;
  147. CUtlVector< CUtlString > m_SurfacePropPalette;
  148. CUtlString m_DefaultSurfaceProperty;
  149. };
  150. class CAuthPhysCollisionAttributeScope
  151. {
  152. public:
  153. CAuthPhysCollisionAttributeScope( CAuthPhysCompileContext* pContext, CAuthPhysCollisionAttributesOverride &collOverride )
  154. {
  155. m_pContext = pContext;
  156. m_SavedDefaults = pContext->GetDefaultCollisionAttributes();
  157. pContext->ApplyOverrideToDefault( collOverride );
  158. }
  159. ~CAuthPhysCollisionAttributeScope()
  160. {
  161. m_pContext->SetDefaultCollisionAttributes( m_SavedDefaults );
  162. }
  163. protected:
  164. CAuthPhysCompileContext* m_pContext;
  165. CAuthPhysCollisionAttributes m_SavedDefaults;
  166. };
  167. class CAuthPhysSurfacePropertyScope
  168. {
  169. public:
  170. CAuthPhysSurfacePropertyScope( CAuthPhysCompileContext* pContext, const CUtlString &surfacePropOverride )
  171. {
  172. m_pContext = pContext;
  173. m_SavedDefault = pContext->GetDefaultSurfaceProperty();
  174. if( !surfacePropOverride.IsEmpty() )
  175. {
  176. pContext->SetDefaultSurfaceProperty( surfacePropOverride );
  177. }
  178. }
  179. ~CAuthPhysSurfacePropertyScope()
  180. {
  181. m_pContext->SetDefaultSurfaceProperty( m_SavedDefault );
  182. }
  183. protected:
  184. CAuthPhysCompileContext* m_pContext;
  185. CUtlString m_SavedDefault;
  186. };
  187. enum PhysicsShapeType_t;
  188. /*schema*/ enum AuthPhysShapeTypeEnum_t
  189. {
  190. AUTH_PHYS_SHAPE_SPHERE = SHAPE_SPHERE, META( MPropertyFriendlyName = "Sphere" )
  191. AUTH_PHYS_SHAPE_CAPSULE = SHAPE_CAPSULE, META( MPropertyFriendlyName = "Capsule" )
  192. AUTH_PHYS_SHAPE_HULL = SHAPE_HULL, META( MPropertyFriendlyName = "Convex Hull" )
  193. AUTH_PHYS_SHAPE_MESH = SHAPE_MESH, META( MPropertyFriendlyName = "Triangle Mesh" )
  194. };
  195. DECLARE_SCHEMA_ENUM( AuthPhysShapeTypeEnum_t );
  196. /*schema*/ class CPhysPartBreakableData
  197. {
  198. //DECLARE_SCHEMA_DATA_CLASS( CPhysPartBreakableData )
  199. CPhysPartBreakableData()
  200. {
  201. m_bMotionDisabled = false;
  202. m_nHealth = 1;
  203. m_flBurstScale = 1.0;
  204. m_flBurstRandomize = 0.0f;
  205. m_nFadeTime = 20.0;
  206. m_nFadeMin = 0;
  207. m_nFadeMax = 0.0;
  208. m_bNoShadows = false;
  209. }
  210. CUtlString m_CollisionGroup; META( MPropertyFriendlyName = "Collision Group"; MPropertyChoiceProviderFn = GetCollisionGroupList; );
  211. bool m_bMotionDisabled; META( MPropertyFriendlyName = "Motion Disabled" );
  212. int m_nHealth;META( MPropertyFriendlyName = "Health" );
  213. int m_nFadeTime;META( MPropertyFriendlyName = "Fade Time" );
  214. int m_nFadeMin;META( MPropertyFriendlyName = "Fade Min Distance" );
  215. int m_nFadeMax;META( MPropertyFriendlyName = "Fade Max Distance" );
  216. float m_flBurstScale; META( MPropertyFriendlyName = "Burst Scale" );
  217. float m_flBurstRandomize; META( MPropertyFriendlyName = "Burst Randomize" );
  218. bool m_bNoShadows; META( MPropertyFriendlyName = "Do Not Cast Shadows" );
  219. CUtlString m_SurfaceProp; META( MPropertyFriendlyName = "Surface Prop"; MPropertyChoiceProviderFn = GetSurfacePropertyList; );
  220. CLockedResource< VpropBreakablePartData_t > Compile( CResourceStream *pStream )
  221. {
  222. CLockedResource< VpropBreakablePartData_t > pData = pStream->Allocate< VpropBreakablePartData_t >();
  223. pData->m_nCollisionGroupHash = m_CollisionGroup.IsEmpty() ? 0 : MakeStringToken( m_CollisionGroup.Get() ).GetHashCode();
  224. pData->m_bMotionDisabled = m_bMotionDisabled;
  225. pData->m_nHealth = m_nHealth;
  226. pData->m_nFadeTime = m_nFadeTime;
  227. pData->m_nFadeMin = m_nFadeMin;
  228. pData->m_nFadeMax = m_nFadeMax;
  229. pData->m_flBurstScale = m_flBurstScale;
  230. pData->m_flBurstRandomize = m_flBurstRandomize;
  231. pData->m_bNoShadows = m_bNoShadows;
  232. pData->m_nSurfaceProp = m_SurfaceProp.IsEmpty() ? 0 : MakeStringToken( m_SurfaceProp ).GetHashCode();
  233. return pData;
  234. }
  235. };
  236. /*schema*/ enum AuthPhysJointTypeEnum_t
  237. {
  238. AUTH_PHYS_SPHERICAL_JOINT = SPHERICAL_JOINT, META( MPropertyFriendlyName = "Spherical Joint" )
  239. AUTH_PHYS_REVOLUTE_JOINT = REVOLUTE_JOINT, META( MPropertyFriendlyName = "Revolute Joint" )
  240. AUTH_PHYS_PRISMATIC_JOINT = PRISMATIC_JOINT, META( MPropertyFriendlyName = "Prismatic Joint" )
  241. AUTH_PHYS_ORTHOTWIST_JOINT = QUAT_ORTHOTWIST_JOINT, META( MPropertyFriendlyName = "Ragdoll Joint" )
  242. AUTH_PHYS_WELD_JOINT = WELD_JOINT, META( MPropertyFriendlyName = "Weld Joint" )
  243. AUTH_PHYS_NULL_JOINT = NULL_JOINT META( MPropertyFriendlyName = "Null Joint" )
  244. };
  245. DECLARE_SCHEMA_ENUM( AuthPhysJointTypeEnum_t );
  246. struct AuthPhysRange_t
  247. {
  248. TYPEMETA( MNoScatter )
  249. //DECLARE_SCHEMA_DATA_CLASS( AuthPhysRange_t );
  250. float32 m_flMin;
  251. float32 m_flMax;
  252. AuthPhysRange_t() {}
  253. AuthPhysRange_t( float flMin, float flMax )
  254. : m_flMin( flMin )
  255. , m_flMax( flMax )
  256. {}
  257. };
  258. class CBoneParseParams;
  259. /*schema*/ struct AuthPhysSphereCollision_t
  260. {
  261. //DECLARE_SCHEMA_DATA_CLASS( AuthPhysSphereCollision_t );
  262. public:
  263. AuthPhysSphereCollision_t()
  264. {
  265. m_bInclusive = false;
  266. m_flRadius = 16;
  267. m_vOrigin = vec3_origin;
  268. m_flStickiness = 0;
  269. }
  270. bool m_bInclusive;
  271. float m_flRadius;
  272. Vector m_vOrigin;
  273. float m_flStickiness;
  274. };
  275. class CAuthPhysFxRodMap : public CUtlVector < CUtlSortVector< int > * >
  276. {
  277. public:
  278. CAuthPhysFxRodMap(){ }
  279. ~CAuthPhysFxRodMap() { PurgeAndDeleteElements(); }
  280. void Init( int nNodes )
  281. {
  282. PurgeAndDeleteElements();
  283. SetCount( nNodes );
  284. FillWithValue( NULL );
  285. }
  286. void Append( int nNodeA, int nNodeB )
  287. {
  288. CUtlSortVector< int > * &list = ( *this )[ nNodeA ];
  289. if ( !list )
  290. {
  291. list = new CUtlSortVector < int > ;
  292. list->Insert( nNodeB );
  293. }
  294. else
  295. {
  296. list->InsertIfNotFound( nNodeB );
  297. }
  298. }
  299. };
  300. /*schema*/ class CAuthPhysFx
  301. {
  302. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx );
  303. public:
  304. CAuthPhysFx( )
  305. {
  306. InitDefaults( );
  307. }
  308. ~CAuthPhysFx(){}
  309. int Cleanup();
  310. template <typename TBitVec>
  311. void AlignNodes( const TBitVec &nodes );
  312. void AlignNodes()
  313. {
  314. struct IdentityMap_t { bool operator[]( int i ) const { return true; } } identityMap;
  315. AlignNodes( identityMap );
  316. }
  317. public:
  318. /*schema*/ class CDagEdge
  319. {
  320. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CDagEdge );
  321. public:
  322. CDagEdge( )
  323. {
  324. m_nParentBone = -1;
  325. m_nChildBone = -1;
  326. }
  327. bool UsesNode( int nNode ) const
  328. {
  329. return m_nParentBone == nNode || m_nChildBone == nNode;
  330. }
  331. void ChangeNode( int nOldNode, int nNewNode )
  332. {
  333. if ( m_nParentBone == nOldNode )
  334. m_nParentBone = nNewNode;
  335. if ( m_nChildBone == nOldNode )
  336. m_nChildBone = nNewNode;
  337. }
  338. void RebaseNodes( int nBaseNode )
  339. {
  340. m_nParentBone += nBaseNode;
  341. m_nChildBone += nBaseNode;
  342. }
  343. void RemapNodes( const CUtlVector< int > &remap )
  344. {
  345. RemapNode( m_nParentBone, remap );
  346. RemapNode( m_nChildBone, remap );
  347. }
  348. bool IsValid( int nNodeCount )const
  349. {
  350. return m_nParentBone < nNodeCount && m_nChildBone < nNodeCount;
  351. }
  352. bool operator == ( const CDagEdge &other ) const { return m_nParentBone == other.m_nParentBone && m_nChildBone == other.m_nChildBone; }
  353. int m_nParentBone;
  354. int m_nChildBone;
  355. };
  356. /*schema*/ class CCollisionSphere: public CDagEdge
  357. {
  358. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CCollisionSphere );
  359. public:
  360. CCollisionSphere( )
  361. {
  362. m_bInclusive = false;
  363. m_flRadius = 0;
  364. m_vOrigin = vec3_origin;
  365. m_flStickiness = 0;
  366. }
  367. void Assign( const AuthPhysSphereCollision_t &that )
  368. {
  369. m_bInclusive = that.m_bInclusive;
  370. m_flRadius = that.m_flRadius;
  371. m_vOrigin = that.m_vOrigin;
  372. m_flStickiness = that.m_flStickiness;
  373. }
  374. public:
  375. bool m_bInclusive;
  376. float m_flRadius;
  377. Vector m_vOrigin;
  378. float m_flStickiness;
  379. };
  380. /*schema*/ class CCollisionPlane: public CDagEdge
  381. {
  382. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CCollisionPlane );
  383. public:
  384. CCollisionPlane( )
  385. {
  386. m_Plane.m_vNormal = Vector( 0, 0, 1 );
  387. m_Plane.m_flOffset = 0;
  388. m_flStickiness = 0;
  389. }
  390. bool operator == ( const CCollisionPlane &other )const
  391. {
  392. return static_cast< const CDagEdge& >( *this ) == static_cast< const CDagEdge& >( other )
  393. && m_Plane == other.m_Plane;
  394. }
  395. RnPlane_t m_Plane;
  396. float m_flStickiness;
  397. };
  398. /*schema*/ class CCtrlOffset : public CDagEdge
  399. {
  400. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CCtrlOffset );
  401. public:
  402. CCtrlOffset()
  403. {
  404. m_vOffset = Vector( 0, 8, 0 ); // zero offset isn't really useful
  405. }
  406. bool operator == ( const CCtrlOffset &other )const
  407. {
  408. return static_cast< const CDagEdge& >( *this ) == static_cast< const CDagEdge& >( other ) && m_vOffset == other.m_vOffset;
  409. }
  410. operator const FeCtrlOffset_t()const
  411. {
  412. FeCtrlOffset_t offset;
  413. offset.nCtrlChild = m_nChildBone;
  414. offset.nCtrlParent = m_nParentBone;
  415. offset.vOffset = m_vOffset;
  416. return offset;
  417. }
  418. Vector m_vOffset;
  419. };
  420. /*schema*/ class CBone
  421. {
  422. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CBone )
  423. public:
  424. CBone( )
  425. {
  426. m_nParent = -1;
  427. m_bVirtual = false;
  428. m_bNeedNodeBase = false;
  429. m_bHasMassOverride = false;
  430. m_bSimulated = true;
  431. m_bForceSimulated = false;
  432. m_bFreeRotation = true;
  433. m_bAnimRotation = false;
  434. m_bOsOffset = false;
  435. m_Transform = g_TransformIdentity;
  436. m_flMass = 1.0f;
  437. m_flMassBias = 0.0f;
  438. m_bNeedsWorldCollision = false;
  439. m_Integrator.Init( );
  440. m_nFollowParent = -1;
  441. m_flFollowWeight = 0;
  442. m_flWorldFriction = 0;
  443. m_flGroundFriction = 0;
  444. m_flLegacyStretchForce = 0;
  445. m_bUseRods = false;
  446. m_flCollisionRadius = 0;
  447. m_nCollisionMask = 0xFFFF;
  448. m_flLocalForce = 1.0f;
  449. m_flLocalRotation = 0.0f;
  450. m_flVolumetricSolveAmount = 0.0f;
  451. }
  452. CFeModelBuilder::BuildNode_t AsBuildNode()const;
  453. uint32 GetNameHash() { return MakeStringToken( m_Name.Get() ).GetHashCode(); }
  454. bool ApplyDotaFlags( const char *pFlags, CBoneParseParams *pParamsOut );
  455. bool ChangeNode( int nOldNode, int nNewNode )
  456. {
  457. bool bChanged = false;
  458. if ( m_nParent == nOldNode )
  459. {
  460. m_nParent = nNewNode;
  461. bChanged = true;
  462. }
  463. if ( m_nFollowParent == nOldNode )
  464. {
  465. m_nFollowParent = nNewNode;
  466. bChanged = true;
  467. }
  468. return bChanged;
  469. }
  470. CTransform GetOffsetTransform( const Vector &vOffset )
  471. {
  472. return CTransform( m_Transform.TransformVector( vOffset ), m_Transform.m_orientation );
  473. }
  474. void RebaseNodes( int nBaseNode )
  475. {
  476. if( m_nFollowParent >= 0 )
  477. m_nFollowParent += nBaseNode;
  478. if ( m_nParent >= 0 )
  479. m_nParent += nBaseNode;
  480. }
  481. void RemapNodes( const CUtlVector< int > &remap )
  482. {
  483. RemapNode( m_nFollowParent, remap );
  484. RemapNode( m_nParent, remap );
  485. }
  486. public:
  487. bool m_bSimulated; // this is an fx particle comprising jiggle bones, chains, cloths, or any other soft body
  488. bool m_bForceSimulated; // if true, this node may not be deduced to be non-simulated
  489. bool m_bFreeRotation;
  490. bool m_bAnimRotation;
  491. bool m_bVirtual;
  492. bool m_bNeedNodeBase;
  493. bool m_bNeedsWorldCollision;
  494. bool m_bOsOffset; // object-space offset, used for compatibility with S1 cloth
  495. float m_flWorldFriction; META( MPropertyFriendlyName = "Ground NOT-Collide" );// this is not a friction coefficient! this is the "WorldFriction" parameter from source1 cloth
  496. float m_flGroundFriction;
  497. float m_flLegacyStretchForce; // premultiplied by invMass here
  498. float m_flMass;
  499. float m_flMassBias;
  500. int m_nFollowParent;
  501. float m_flFollowWeight;
  502. float m_flCollisionRadius;
  503. FeNodeIntegrator_t m_Integrator;
  504. bool m_bHasMassOverride;
  505. uint32 m_nCollisionMask;
  506. int m_nParent; // parent bone index
  507. CUtlString m_Name; // bone name, the same as in model, the same as used in animation
  508. CTransform m_Transform; META( MPropertySuppressField );// bind pose, relaxed pose
  509. bool m_bUseRods; // UI convenience: when checked, affects generation of quads or rods around this node
  510. float m_flLocalForce;
  511. float m_flLocalRotation;
  512. float m_flVolumetricSolveAmount;
  513. };
  514. /*schema*/ class CConstraint
  515. {
  516. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CConstraint )
  517. public:
  518. CConstraint( int nBone0 = -1, int nBone1 = -1 ) { m_nBones[0] = nBone0; m_nBones[1] = nBone1; }
  519. bool Equals( int nBone0, int nBone1 ) const { return ( m_nBones[0] == nBone0 && m_nBones[1] == nBone1 ) || ( m_nBones[1] == nBone0 && m_nBones[0] == nBone1 ); }
  520. int m_nBones[2]; // bone indices of the connected particles
  521. public:
  522. bool UsesNode( int nNode ) const
  523. {
  524. return m_nBones[ 0 ] == nNode || m_nBones[ 1 ] == nNode;
  525. }
  526. void ChangeNode( int nOldNode, int nNewNode )
  527. {
  528. if ( m_nBones[ 0 ] == nOldNode )
  529. m_nBones[ 0 ] = nNewNode;
  530. if ( m_nBones[ 1 ] == nOldNode )
  531. m_nBones[ 1 ] = nNewNode;
  532. }
  533. void RebaseNodes( int nBaseNode )
  534. {
  535. m_nBones[ 0 ] += nBaseNode;
  536. m_nBones[ 1 ] += nBaseNode;
  537. }
  538. void RemapNodes( const CUtlVector< int > &remap )
  539. {
  540. RemapNode( m_nBones[ 0 ], remap );
  541. RemapNode( m_nBones[ 1 ], remap );
  542. }
  543. };
  544. /*schema*/ class CCapsule
  545. {
  546. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CCapsule )
  547. public:
  548. int m_nBone[2];
  549. Vector m_vCenter[2]; // each capsule center in the corresponding bone's local coordinates
  550. float m_flRadius;
  551. public:
  552. bool UsesNode( int nNode ) const
  553. {
  554. return m_nBone[ 0 ] == nNode || m_nBone[ 1 ] == nNode;
  555. }
  556. void ChangeNode( int nOldNode, int nNewNode )
  557. {
  558. if ( m_nBone[ 0 ] == nOldNode )
  559. m_nBone[ 0 ] = nNewNode;
  560. if ( m_nBone[ 1 ] == nOldNode )
  561. m_nBone[ 1 ] = nNewNode;
  562. }
  563. void RebaseNodes( int nBaseNode )
  564. {
  565. m_nBone[ 0 ] += nBaseNode;
  566. m_nBone[ 1 ] += nBaseNode;
  567. }
  568. void RemapNodes( const CUtlVector< int > &remap )
  569. {
  570. RemapNode( m_nBone[ 0 ], remap );
  571. RemapNode( m_nBone[ 1 ], remap );
  572. }
  573. };
  574. /*schema*/ class CQuad
  575. {
  576. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CQuad )
  577. public:
  578. uint m_nNodes[ 4 ];
  579. bool m_bUseRods;
  580. CQuad() { m_bUseRods = false; }
  581. CQuad( uint nNode0, uint nNode1, uint nNode2, uint nNode3 )
  582. {
  583. m_nNodes[ 0 ] = nNode0;
  584. m_nNodes[ 1 ] = nNode1;
  585. m_nNodes[ 2 ] = nNode2;
  586. m_nNodes[ 3 ] = nNode3;
  587. m_bUseRods = false;
  588. }
  589. CFeModelBuilder::BuildElem_t AsBuildElem()const;
  590. bool operator == ( const CQuad &right ) const
  591. {
  592. return m_nNodes[ 0 ] == right.m_nNodes[ 0 ] && m_nNodes[ 1 ] == right.m_nNodes[ 1 ] && m_nNodes[ 2 ] == right.m_nNodes[ 2 ] && m_nNodes[ 3 ] == right.m_nNodes[ 3 ];
  593. }
  594. bool UsesNode( uint nNode ) const
  595. {
  596. return m_nNodes[ 0 ] == nNode || m_nNodes[ 1 ] == nNode || m_nNodes[ 2 ] == nNode || m_nNodes[ 3 ] == nNode;
  597. }
  598. template <typename TBitVec >
  599. bool UsesAnyNode( const TBitVec &nodes )
  600. {
  601. return nodes[ m_nNodes[ 0 ] ] || nodes[ m_nNodes[ 1 ] ] || nodes[ m_nNodes[ 2 ] ] || nodes[ m_nNodes[ 3 ] ] ;
  602. }
  603. void ChangeNode( uint nOldNode, uint nNewNode )
  604. {
  605. if ( m_nNodes[ 0 ] == nOldNode )
  606. m_nNodes[ 0 ] = nNewNode;
  607. if ( m_nNodes[ 1 ] == nOldNode )
  608. m_nNodes[ 1 ] = nNewNode;
  609. if ( m_nNodes[ 2 ] == nOldNode )
  610. m_nNodes[ 2 ] = nNewNode;
  611. if ( m_nNodes[ 3 ] == nOldNode )
  612. m_nNodes[ 3 ] = nNewNode;
  613. }
  614. bool IsValid( uint nNodeCount )const
  615. {
  616. return m_nNodes[ 0 ] < nNodeCount && m_nNodes[ 1 ] < nNodeCount && m_nNodes[ 2 ] < nNodeCount && m_nNodes[ 3 ] < nNodeCount;
  617. }
  618. void RebaseNodes( int nBaseNode )
  619. {
  620. m_nNodes[ 0 ] += nBaseNode;
  621. m_nNodes[ 1 ] += nBaseNode;
  622. m_nNodes[ 2 ] += nBaseNode;
  623. m_nNodes[ 3 ] += nBaseNode;
  624. }
  625. void RemapNodes( const CUtlVector< int > &remap )
  626. {
  627. RemapNode( m_nNodes[ 0 ], remap );
  628. RemapNode( m_nNodes[ 1 ], remap );
  629. RemapNode( m_nNodes[ 2 ], remap );
  630. RemapNode( m_nNodes[ 3 ], remap );
  631. }
  632. };
  633. /*schema*/ class CRod
  634. {
  635. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CRod )
  636. public:
  637. uint m_nNodes[ 2 ];
  638. float32 m_flMotionBias[ 2 ]; //
  639. float32 m_flRelaxationFactor;
  640. bool m_bExplicitLength;
  641. float32 m_flLength;
  642. float32 m_flContractionFactor;
  643. CRod( )
  644. {
  645. m_bExplicitLength = false;
  646. m_flContractionFactor = 0.05f; // in Source1, rods may contract to 0
  647. m_flLength = 0;
  648. m_nNodes[ 0 ] = m_nNodes[ 1 ] = 0;
  649. m_flRelaxationFactor = 1.0f;
  650. m_flMotionBias[ 0 ] = m_flMotionBias[ 1 ] = 1.0f;
  651. }
  652. CRod( uint nNode0, uint nNode1, float flRelaxationFactor = 1.0f )
  653. {
  654. m_nNodes[ 0 ] = nNode0;
  655. m_nNodes[ 1 ] = nNode1;
  656. m_flRelaxationFactor = flRelaxationFactor;
  657. m_flMotionBias[ 0 ] = m_flMotionBias[ 1 ] = 1.0f;
  658. }
  659. bool operator < ( const CRod &other )const
  660. {
  661. return m_nNodes[ 0 ] == other.m_nNodes[ 0 ] ? m_nNodes[ 1 ] < other.m_nNodes[ 1 ] : m_nNodes[ 0 ] < other.m_nNodes[ 0 ];
  662. }
  663. bool operator == ( const CRod &other )const
  664. {
  665. return ( m_nNodes[ 0 ] == other.m_nNodes[ 0 ] && m_nNodes[ 1 ] == other.m_nNodes[ 1 ] ) || ( m_nNodes[ 0 ] == other.m_nNodes[ 1 ] && m_nNodes[ 1 ] == other.m_nNodes[ 0 ] );
  666. }
  667. bool Equals( uint nNode0, uint nNode1 )const
  668. {
  669. return ( m_nNodes[ 0 ] == nNode0 && m_nNodes[ 1 ] == nNode1 ) || ( m_nNodes[ 1 ] == nNode0 && m_nNodes[ 0 ] == nNode1 );
  670. }
  671. bool UsesNode( uint nNode ) const
  672. {
  673. return m_nNodes[ 0 ] == nNode || m_nNodes[ 1 ] == nNode;
  674. }
  675. void ChangeNode( uint nOldNode, uint nNewNode )
  676. {
  677. if ( m_nNodes[ 0 ] == nOldNode )
  678. m_nNodes[ 0 ] = nNewNode;
  679. if ( m_nNodes[ 1 ] == nOldNode )
  680. m_nNodes[ 1 ] = nNewNode;
  681. }
  682. void RebaseNodes( int nBaseNode )
  683. {
  684. m_nNodes[ 0 ] += nBaseNode;
  685. m_nNodes[ 1 ] += nBaseNode;
  686. }
  687. void RemapNodes( const CUtlVector< int > &remap )
  688. {
  689. RemapNode( m_nNodes[ 0 ], remap );
  690. RemapNode( m_nNodes[ 1 ], remap );
  691. }
  692. void Reverse()
  693. {
  694. ::Swap( m_nNodes[ 0 ], m_nNodes[ 1 ] );
  695. ::Swap( m_flMotionBias[ 0 ], m_flMotionBias[ 1 ] );
  696. }
  697. uint GetOtherNode( uint nNode )const
  698. {
  699. if ( m_nNodes[ 1 ] == nNode )
  700. {
  701. return m_nNodes[ 0 ];
  702. }
  703. else
  704. {
  705. Assert( m_nNodes[ 0 ] == nNode );
  706. return m_nNodes[ 1 ];
  707. }
  708. }
  709. bool IsValid( uint nNodeCount )const
  710. {
  711. return m_nNodes[ 0 ] < nNodeCount && m_nNodes[ 1 ] < nNodeCount;
  712. }
  713. };
  714. /*schema*/ class CSpring
  715. {
  716. public:
  717. //DECLARE_SCHEMA_DATA_CLASS( CAuthPhysFx::CSpring )
  718. uint m_nNodes[ 2 ];
  719. float32 m_flSpringConstant;
  720. float32 m_flSpringDamping;
  721. float32 m_flStretchiness; // Not Implemented
  722. CSpring( ){}
  723. CSpring( uint nNode0, uint nNode1, float flSpringConstant, float flSpringDamping, float flStretchForce, float flStretchiness )
  724. {
  725. m_nNodes[ 0 ] = nNode0;
  726. m_nNodes[ 1 ] = nNode1;
  727. m_flSpringConstant = flSpringConstant + 60 * flStretchForce * flStretchiness; // I think this may be approximately how it effectively works in Source1;;
  728. m_flSpringDamping = flSpringDamping;
  729. m_flStretchiness = flStretchiness; // Note: so far this is not used, saving mainly for documentation
  730. }
  731. bool operator < ( const CRod &other )
  732. {
  733. return m_nNodes[ 0 ] == other.m_nNodes[ 0 ] ? m_nNodes[ 1 ] < other.m_nNodes[ 1 ] : m_nNodes[ 0 ] < other.m_nNodes[ 0 ];
  734. }
  735. bool UsesNode( uint nNode ) const { return m_nNodes[ 0 ] == nNode || m_nNodes[ 1 ] == nNode; }
  736. void ChangeNode( uint nOldNode, uint nNewNode )
  737. {
  738. if ( m_nNodes[ 0 ] == nOldNode )
  739. m_nNodes[ 0 ] = nNewNode;
  740. if ( m_nNodes[ 1 ] == nOldNode )
  741. m_nNodes[ 1 ] = nNewNode;
  742. }
  743. void RebaseNodes( int nBaseNode )
  744. {
  745. m_nNodes[ 0 ] += nBaseNode;
  746. m_nNodes[ 1 ] += nBaseNode;
  747. }
  748. void RemapNodes( const CUtlVector< int > &remap )
  749. {
  750. RemapNode( m_nNodes[ 0 ], remap );
  751. RemapNode( m_nNodes[ 1 ], remap );
  752. }
  753. };
  754. public:
  755. bool IsEmpty() const { return m_Quads.IsEmpty() && m_Rods.IsEmpty() && m_Nodes.IsEmpty() && m_CollisionSpheres.IsEmpty() && m_CollisionPlanes.IsEmpty() && m_SphereRigids.IsEmpty() && m_TaperedCapsuleStretches.IsEmpty() && m_TaperedCapsuleRigids.IsEmpty() && m_Capsules.IsEmpty() && m_Constraints.IsEmpty() && m_Springs.IsEmpty(); }
  756. bool ImportDotaCloth( const char *pClothFile, CPhysModelSource &physicsModel/*CUtlStringMap< int, CUtlSymbolTable > *pBoneToIndex*/ );
  757. void Load( const CFeModel *pFeModel );
  758. void AddRod( const CUtlVector< CBone > &nodes, uint nNode0, uint nNode1, float flRelaxationFactor );
  759. void SetBones( const CUtlVector< CBone > &bones );
  760. int AddConstraint( int nBone0, int nBone1 );
  761. const CBone *GetBone( int nBone ) const { return &m_Nodes[nBone]; }
  762. CBone *GetBone( int nBone ) { return &m_Nodes[nBone]; }
  763. int FindNodeIndex( const char *pName );
  764. CBone *GetOrCreateBone( const char *pName );
  765. int GetBoneCount() const { return m_Nodes.Count(); }
  766. int GetSimParticleCount()const;
  767. int GetStaticParticleCount( )const { return m_Nodes.Count( ) - GetSimParticleCount( ); }
  768. CLockedResource< PhysFeModelDesc_t > Compile( CResourceStream *pStream, const CVClothProxyMeshOptions *pOptions = NULL )const;
  769. bool IsSimilarTo( const CFeModel *pFeModel )const;
  770. bool IsConstraintSimulated( int nConstraint ) const ;
  771. bool IsSpringSimulated( int nSpring ) const;
  772. int GetRodCount( ) const { return m_Rods.Count( ); }
  773. CRod *GetRod( int i ) { return &m_Rods[ i ]; }
  774. float GetRodLength( int nRod )const;
  775. int GetQuadCount( ) const { return m_Quads.Count( ); }
  776. CQuad *GetQuad( int i ) { return &m_Quads[ i ]; }
  777. int GetConstraintCount() const { return m_Constraints.Count(); }
  778. CConstraint* GetConstraint( int i ) { return &m_Constraints[i]; }
  779. int GetSpringCount( ) const { return m_Springs.Count( ); }
  780. CSpring* GetSpring( int i ) { return &m_Springs[ i ]; }
  781. int GetCapsuleCount() const { return m_Capsules.Count(); }
  782. CCapsule* GetCapsule( int i ) { return &m_Capsules[i]; }
  783. bool IsNewSpringAllowed( int nBone0, int nBone1 );
  784. bool IsNewRodAllowed( int nBone0, int nBone1 );
  785. void SortAndRemoveDuplicates( );
  786. void RemoveRodsConnecting( const CVarBitVec &nodes );
  787. void RemoveQuadsConnecting( const CVarBitVec &nodes );
  788. int BuildIslandMap( CUtlVector< int > &nodeToIsland )const;
  789. void Swap( CAuthPhysFx &other )
  790. {
  791. m_Quads.Swap( other.m_Quads );
  792. m_Rods.Swap( other.m_Rods );
  793. m_Springs.Swap( other.m_Springs );
  794. m_Constraints.Swap( other.m_Constraints ); // springs and constraints between fx particles
  795. m_Capsules.Swap( other.m_Capsules ); // capsules repelling the particles
  796. m_Nodes.Swap( other.m_Nodes ); // bones, including dynamic particles
  797. m_TaperedCapsuleRigids.Swap( other.m_TaperedCapsuleRigids );
  798. m_TaperedCapsuleStretches.Swap( other.m_TaperedCapsuleStretches );
  799. m_SphereRigids.Swap( other.m_SphereRigids );
  800. m_CollisionSpheres.Swap( other.m_CollisionSpheres );
  801. m_CollisionPlanes.Swap( other.m_CollisionPlanes );
  802. m_PresetNodeBases.Swap( other.m_PresetNodeBases );
  803. m_FitInfluences.Swap( other.m_FitInfluences );
  804. ::Swap( m_flDefaultSurfaceStretch, other.m_flDefaultSurfaceStretch );
  805. ::Swap( m_flDefaultThreadStretch, other.m_flDefaultThreadStretch );
  806. ::Swap( m_flDefaultGravityScale, other.m_flDefaultGravityScale );
  807. ::Swap( m_flDefaultVelAirDrag, other.m_flDefaultVelAirDrag );
  808. ::Swap( m_flDefaultExpAirDrag, other.m_flDefaultExpAirDrag );
  809. ::Swap( m_flDefaultVelQuadAirDrag, other.m_flDefaultVelQuadAirDrag );
  810. ::Swap( m_flDefaultExpQuadAirDrag, other.m_flDefaultExpQuadAirDrag );
  811. ::Swap( m_flDefaultVelRodAirDrag, other.m_flDefaultVelRodAirDrag );
  812. ::Swap( m_flDefaultExpRodAirDrag, other.m_flDefaultExpRodAirDrag );
  813. ::Swap( m_flQuadVelocitySmoothRate, other.m_flQuadVelocitySmoothRate );
  814. ::Swap( m_flRodVelocitySmoothRate, other.m_flRodVelocitySmoothRate );
  815. ::Swap( m_flWindage, other.m_flWindage );
  816. ::Swap( m_flWindDrag, other.m_flWindDrag );
  817. ::Swap( m_nQuadVelocitySmoothIterations, other.m_nQuadVelocitySmoothIterations );
  818. ::Swap( m_nRodVelocitySmoothIterations, other.m_nRodVelocitySmoothIterations );
  819. ::Swap( m_flDefaultGroundFriction, other.m_flDefaultGroundFriction );
  820. ::Swap( m_flDefaultWorldCollisionPenetration, other.m_flDefaultWorldCollisionPenetration );
  821. ::Swap( m_bForceWorldCollisionOnAllNodes, other.m_bForceWorldCollisionOnAllNodes );
  822. ::Swap( m_flAddWorldCollisionRadius, other.m_flAddWorldCollisionRadius );
  823. ::Swap( m_flAddCurvature, other.m_flAddCurvature );
  824. ::Swap( m_flQuadBendTolerance, other.m_flQuadBendTolerance );
  825. ::Swap( m_flLocalForce, other.m_flLocalForce );
  826. ::Swap( m_flLocalRotation, other.m_flLocalRotation );
  827. ::Swap( m_flVolumetricSolveAmount, other.m_flVolumetricSolveAmount );
  828. ::Swap( m_bFollowTheLead, other.m_bFollowTheLead );
  829. ::Swap( m_bUsePerNodeLocalForceAndRotation, other.m_bUsePerNodeLocalForceAndRotation );
  830. ::Swap( m_bUninertialRods, other.m_bUninertialRods );
  831. ::Swap( m_bExplicitMasses, other.m_bExplicitMasses );
  832. ::Swap( m_bCanCollideWithWorldCapsulesAndSpheres, other.m_bCanCollideWithWorldCapsulesAndSpheres );
  833. ::Swap( m_bCanCollideWithWorldHulls, other.m_bCanCollideWithWorldHulls );
  834. ::Swap( m_bCanCollideWithWorldMeshes, other.m_bCanCollideWithWorldMeshes );
  835. ::Swap( m_bUnitlessDamping, other.m_bUnitlessDamping );
  836. ::Swap( m_nMergePriority, other.m_nMergePriority );
  837. ::Swap( m_bNewStyle, other.m_bNewStyle );
  838. ::Swap( m_bAddStiffnessRods, other.m_bAddStiffnessRods );
  839. ::Swap( m_bRigidEdgeHinges, other.m_bRigidEdgeHinges );
  840. }
  841. template <typename T >
  842. static void AppendAndRebaseNodes( CUtlVector< T > &arrThis, const CUtlVector< T > &arrThat, int nNodeBase )
  843. {
  844. int nScan = arrThis.Count();
  845. arrThis.AddMultipleToTail( arrThat.Count(), arrThat.Base() );
  846. for ( ; nScan < arrThis.Count(); ++nScan )
  847. {
  848. arrThis[ nScan ].RebaseNodes( nNodeBase );
  849. }
  850. }
  851. template <typename T >
  852. static void AppendAndRemapNodes( CUtlVector< T > &arrThis, const CUtlVector< T > &arrThat, const CUtlVector< int > &remap )
  853. {
  854. int nScan = arrThis.Count();
  855. arrThis.AddMultipleToTail( arrThat.Count(), arrThat.Base() );
  856. for ( ; nScan < arrThis.Count(); ++nScan )
  857. {
  858. arrThis[ nScan ].RemapNodes( remap );
  859. }
  860. }
  861. void Append( const CAuthPhysFx &other )
  862. {
  863. int nBaseNodes = m_Nodes.Count();
  864. if ( m_nMergePriority < other.m_nMergePriority )
  865. {
  866. m_flDefaultSurfaceStretch = other.m_flDefaultSurfaceStretch;
  867. m_flDefaultThreadStretch = other.m_flDefaultThreadStretch;
  868. m_flDefaultGravityScale = other.m_flDefaultGravityScale;
  869. m_flDefaultVelAirDrag = other.m_flDefaultVelAirDrag;
  870. m_flDefaultExpAirDrag = other.m_flDefaultExpAirDrag;
  871. m_flDefaultVelQuadAirDrag = other.m_flDefaultVelQuadAirDrag;
  872. m_flDefaultExpQuadAirDrag = other.m_flDefaultExpQuadAirDrag;
  873. m_flDefaultVelRodAirDrag = other.m_flDefaultVelRodAirDrag;
  874. m_flDefaultExpRodAirDrag = other.m_flDefaultExpRodAirDrag;
  875. m_flQuadVelocitySmoothRate = other.m_flQuadVelocitySmoothRate;
  876. m_flRodVelocitySmoothRate = other.m_flRodVelocitySmoothRate;
  877. m_flWindage = other.m_flWindage;
  878. m_flWindDrag = other.m_flWindage;
  879. m_nQuadVelocitySmoothIterations = other.m_nQuadVelocitySmoothIterations;
  880. m_nRodVelocitySmoothIterations = other.m_nRodVelocitySmoothIterations;
  881. m_flDefaultGroundFriction = other.m_flDefaultGroundFriction;
  882. m_flDefaultWorldCollisionPenetration = other.m_flDefaultWorldCollisionPenetration;
  883. m_bForceWorldCollisionOnAllNodes = other.m_bForceWorldCollisionOnAllNodes;
  884. m_flAddWorldCollisionRadius = other.m_flAddWorldCollisionRadius;
  885. m_flAddCurvature = other.m_flAddCurvature;
  886. m_flQuadBendTolerance = other.m_flQuadBendTolerance;
  887. m_flLocalForce = other.m_flLocalForce;
  888. m_flLocalRotation = other.m_flLocalRotation;
  889. m_flVolumetricSolveAmount = other.m_flVolumetricSolveAmount;
  890. m_bFollowTheLead = other.m_bFollowTheLead;
  891. m_bUsePerNodeLocalForceAndRotation = other.m_bUsePerNodeLocalForceAndRotation;
  892. m_bUninertialRods = other.m_bUninertialRods;
  893. m_bExplicitMasses = other.m_bExplicitMasses;
  894. m_bCanCollideWithWorldHulls = other.m_bCanCollideWithWorldHulls;
  895. m_bCanCollideWithWorldMeshes = other.m_bCanCollideWithWorldMeshes;
  896. m_bCanCollideWithWorldCapsulesAndSpheres = other.m_bCanCollideWithWorldCapsulesAndSpheres;
  897. m_bUnitlessDamping = other.m_bUnitlessDamping;
  898. m_nMergePriority = other.m_nMergePriority;
  899. m_bNewStyle = other.m_bNewStyle;
  900. m_bAddStiffnessRods = other.m_bAddStiffnessRods;
  901. m_bRigidEdgeHinges = other.m_bRigidEdgeHinges;
  902. }
  903. CUtlVector< int > remap;
  904. remap.SetCount( other.m_Nodes.Count() );
  905. // merge the Nodes
  906. m_Nodes.EnsureCapacity( m_Nodes.Count() + other.m_Nodes.Count() );
  907. for ( int nOtherNode = 0; nOtherNode < other.m_Nodes.Count(); ++nOtherNode )
  908. {
  909. const CBone &otherNode = other.m_Nodes[ nOtherNode ];
  910. int nMapNode = -1;
  911. if ( !otherNode.m_Name.IsEmpty() )
  912. {
  913. nMapNode = FindNodeIndex( otherNode.m_Name );
  914. }
  915. if ( nMapNode < 0 )
  916. {
  917. // couldn't find node to map, create a new one
  918. remap[ nOtherNode ] = m_Nodes.AddToTail( otherNode );
  919. }
  920. else
  921. {
  922. remap[ nOtherNode ] = nMapNode;
  923. }
  924. }
  925. // the remap array is ready; use it to remap all the node indices
  926. for ( int nNewNode = nBaseNodes; nNewNode < m_Nodes.Count(); ++nNewNode )
  927. {
  928. m_Nodes[ nNewNode ].RemapNodes( remap );
  929. }
  930. AppendAndRemapNodes( m_Quads, other.m_Quads, remap );
  931. AppendAndRemapNodes( m_Rods, other.m_Rods, remap );
  932. AppendAndRemapNodes( m_Springs, other.m_Springs, remap );
  933. AppendAndRemapNodes( m_Constraints, other.m_Constraints, remap ); // springs and constraints between fx particles
  934. AppendAndRemapNodes( m_Capsules, other.m_Capsules, remap ); // capsules repelling the particles
  935. AppendAndRemapNodes( m_TaperedCapsuleRigids, other.m_TaperedCapsuleRigids, remap );
  936. AppendAndRemapNodes( m_TaperedCapsuleStretches, other.m_TaperedCapsuleStretches, remap );
  937. AppendAndRemapNodes( m_SphereRigids, other.m_SphereRigids, remap );
  938. AppendAndRemapNodes( m_CollisionSpheres, other.m_CollisionSpheres, remap );
  939. AppendAndRemapNodes( m_CollisionPlanes, other.m_CollisionPlanes, remap );
  940. AppendAndRemapNodes( m_PresetNodeBases, other.m_PresetNodeBases, remap );
  941. AppendAndRemapNodes( m_FitInfluences, other.m_FitInfluences, remap );
  942. }
  943. void Purge( )
  944. {
  945. m_Quads.Purge();
  946. m_Rods.Purge();
  947. m_Springs.Purge();
  948. m_Constraints.Purge(); // springs and constraints between fx particles
  949. m_Capsules.Purge(); // capsules repelling the particles
  950. m_Nodes.Purge(); // bones, including dynamic particles
  951. m_TaperedCapsuleRigids.Purge();
  952. m_TaperedCapsuleStretches.Purge();
  953. m_SphereRigids.Purge();
  954. m_CollisionSpheres.Purge();
  955. m_CollisionPlanes.Purge();
  956. m_PresetNodeBases.Purge();
  957. m_FitInfluences.Purge();
  958. InitDefaults();
  959. }
  960. void InitDefaults()
  961. {
  962. m_flDefaultSurfaceStretch = 0;
  963. m_flDefaultThreadStretch = 0;
  964. m_flLocalForce = 1.0f;
  965. m_flLocalRotation = 0.0f;
  966. m_flVolumetricSolveAmount = 0.0f;
  967. m_bUninertialRods = false;
  968. m_bExplicitMasses = false;
  969. m_bCanCollideWithWorldHulls = false;
  970. m_bCanCollideWithWorldMeshes = false;
  971. m_bCanCollideWithWorldCapsulesAndSpheres = false;
  972. m_bUnitlessDamping = true;
  973. m_bFollowTheLead = false;
  974. m_bUsePerNodeLocalForceAndRotation = false;
  975. m_flAddCurvature = 0;
  976. m_flQuadBendTolerance = 0.05f;
  977. m_flDefaultGravityScale = 1.0f;
  978. m_flDefaultVelAirDrag = 0;
  979. m_flDefaultExpAirDrag = 0;
  980. m_flDefaultVelQuadAirDrag = 0;
  981. m_flDefaultExpQuadAirDrag = 0;
  982. m_flDefaultVelRodAirDrag = 0;
  983. m_flDefaultExpRodAirDrag = 0;
  984. m_flQuadVelocitySmoothRate = 0;
  985. m_flRodVelocitySmoothRate = 0;
  986. m_flWindage = 1.0f;
  987. m_flWindDrag = 0;
  988. m_nQuadVelocitySmoothIterations = 0;
  989. m_nRodVelocitySmoothIterations = 0;
  990. m_bForceWorldCollisionOnAllNodes = false;
  991. m_flDefaultGroundFriction = 0;
  992. m_flDefaultWorldCollisionPenetration = 0;
  993. m_flAddWorldCollisionRadius = 2.0f;
  994. m_nMergePriority = 0;
  995. m_bNewStyle = true;
  996. m_bAddStiffnessRods = true;
  997. m_bRigidEdgeHinges = false;
  998. }
  999. void CreateRodMap( CAuthPhysFxRodMap &rodMap )
  1000. {
  1001. rodMap.Init( GetBoneCount() );
  1002. for ( int nRod = 0; nRod < m_Rods.Count(); ++nRod )
  1003. {
  1004. rodMap.Append( m_Rods[ nRod ].m_nNodes[ 0 ], nRod );
  1005. rodMap.Append( m_Rods[ nRod ].m_nNodes[ 1 ], nRod );
  1006. }
  1007. }
  1008. void CreateConnMap( CAuthPhysFxRodMap &connMap )
  1009. {
  1010. connMap.Init( GetBoneCount() );
  1011. for ( int nRod = 0; nRod < m_Rods.Count(); ++nRod )
  1012. {
  1013. const uint *n = m_Rods[ nRod ].m_nNodes;
  1014. //if ( filter( n[ 0 ] ) && filter( n[ 1 ] ) )
  1015. {
  1016. connMap.Append( n[ 0 ], n[ 1 ] );
  1017. connMap.Append( n[ 1 ], n[ 0 ] );
  1018. }
  1019. }
  1020. for ( const CQuad &quad : m_Quads )
  1021. {
  1022. for ( int i = 0; i < 3; ++i )
  1023. {
  1024. uint n0 = quad.m_nNodes[ i ];
  1025. for ( int j = i + 1; j < 4; ++j )
  1026. {
  1027. uint n1 = quad.m_nNodes[ j ];
  1028. if ( n0 != n1 )
  1029. {
  1030. connMap.Append( n0, n1 );
  1031. connMap.Append( n1, n0 );
  1032. }
  1033. }
  1034. }
  1035. }
  1036. }
  1037. CBone *GetDriverBone( int fxBone )
  1038. {
  1039. CAuthPhysFx::CBone *pFxBone;
  1040. for ( ;; )
  1041. {
  1042. AssertDbg( fxBone >= 0 && fxBone < GetBoneCount() );
  1043. pFxBone = GetBone( fxBone );
  1044. // bones that move by themselves are driving themselves
  1045. if ( pFxBone->m_bSimulated )
  1046. break;
  1047. if ( pFxBone->m_bFreeRotation )
  1048. break;
  1049. // try to find the true parent that controls all movements of this bone
  1050. if ( pFxBone->m_nParent >= 0 )
  1051. {
  1052. fxBone = pFxBone->m_nParent;
  1053. }
  1054. else if ( pFxBone->m_nFollowParent >= 0 && pFxBone->m_flFollowWeight >= 1.0f )
  1055. {
  1056. fxBone = pFxBone->m_nFollowParent;
  1057. }
  1058. else
  1059. break; // didn't find true parent
  1060. }
  1061. return pFxBone;
  1062. }
  1063. public:
  1064. CUtlVector< CQuad > m_Quads;
  1065. CUtlVector< CRod > m_Rods;
  1066. CUtlVector< CSpring > m_Springs;
  1067. CUtlVector< CConstraint > m_Constraints; // springs and constraints between fx particles
  1068. CUtlVector< CCapsule > m_Capsules; // capsules repelling the particles
  1069. CUtlVector< CBone > m_Nodes; // bones, including dynamic particles
  1070. CUtlVector< CCollisionSphere > m_CollisionSpheres;
  1071. CUtlVector< CCollisionPlane > m_CollisionPlanes;
  1072. CUtlVector< FeNodeBase_t > m_PresetNodeBases;
  1073. CUtlVector< FeTaperedCapsuleStretch_t > m_TaperedCapsuleStretches;
  1074. CUtlVector< FeTaperedCapsuleRigid_t > m_TaperedCapsuleRigids;
  1075. CUtlVector< FeSphereRigid_t > m_SphereRigids;
  1076. CUtlVector< CCtrlOffset > m_CtrlOffsets;
  1077. CUtlVector< FeFitInfluence_t > m_FitInfluences;
  1078. float m_flDefaultSurfaceStretch;
  1079. float m_flDefaultThreadStretch;
  1080. float m_flDefaultGravityScale;
  1081. float m_flDefaultVelAirDrag;
  1082. float m_flDefaultExpAirDrag;
  1083. float m_flDefaultVelQuadAirDrag;
  1084. float m_flDefaultExpQuadAirDrag;
  1085. float m_flDefaultVelRodAirDrag;
  1086. float m_flDefaultExpRodAirDrag;
  1087. float m_flQuadVelocitySmoothRate;
  1088. float m_flRodVelocitySmoothRate;
  1089. float m_flWindage;
  1090. float m_flWindDrag;
  1091. int m_nQuadVelocitySmoothIterations;
  1092. int m_nRodVelocitySmoothIterations;
  1093. float m_flDefaultGroundFriction;
  1094. float m_flDefaultWorldCollisionPenetration; META( MPropertyFriendlyName = "World Velocity Penetration (Source1) 0.0 = velocity goes to 0 on contact" );
  1095. float m_flAddWorldCollisionRadius;
  1096. float m_flLocalForce;
  1097. float m_flLocalRotation;
  1098. float m_flVolumetricSolveAmount;
  1099. float m_flAddCurvature;
  1100. float m_flQuadBendTolerance; META( MPropertyFriendlyName = "Triangulate Quads bent more than" );
  1101. bool m_bFollowTheLead;
  1102. bool m_bUsePerNodeLocalForceAndRotation;
  1103. bool m_bUninertialRods;
  1104. bool m_bExplicitMasses;
  1105. bool m_bUnitlessDamping;
  1106. bool m_bForceWorldCollisionOnAllNodes; // convenience function: just slam all nodes' world collision flag, useful for quick testing
  1107. int m_nMergePriority;
  1108. bool m_bNewStyle;
  1109. bool m_bCanCollideWithWorldMeshes;
  1110. bool m_bCanCollideWithWorldCapsulesAndSpheres;
  1111. bool m_bCanCollideWithWorldHulls;
  1112. bool m_bAddStiffnessRods;
  1113. bool m_bRigidEdgeHinges;
  1114. };
  1115. // typedef CAuthPhysFx::CQuad CAuthPhysFxQuad;
  1116. // typedef CAuthPhysFx::CRod CAuthPhysFxRod;
  1117. // typedef CAuthPhysFx::CSpring CAuthPhysFxSpring ;
  1118. // typedef CAuthPhysFx::CConstraint CAuthPhysFxConstraint ;
  1119. // typedef CAuthPhysFx::CCapsule CAuthPhysFxCapsule ;
  1120. // typedef CAuthPhysFx::CBone CAuthPhysFxBone ;
  1121. // typedef CAuthPhysFx::CCollisionSphere CAuthPhysFxCollisionSphere ;
  1122. // typedef CAuthPhysFx::CCollisionPlane CAuthPhysFxCollisionPlane ;
  1123. class CBoneParseParams
  1124. {
  1125. public:
  1126. CBoneParseParams( KeyValues *pSubKey, int nCompatibilityMode );
  1127. typedef CAuthPhysFx::CBone CBone;
  1128. void ApplyDefaultParams( CBone &node );
  1129. bool ApplyDotaFlags( CAuthPhysFx::CBone &bone, const char *pszParms );
  1130. public:
  1131. float m_flWorldFriction;
  1132. float m_flAnimationForceAttraction;
  1133. float m_flAnimationVertexAttraction;
  1134. float m_flDamping;
  1135. float m_flFixedPointDamping;
  1136. float m_flSpringStretchiness;
  1137. float m_flRelaxationFactor;
  1138. float m_flStretchForce;
  1139. float m_flStructSpringConstant;
  1140. float m_flStructSpringDamping;
  1141. float m_flGravityScale;
  1142. public:
  1143. bool m_bPrevColumnParent;
  1144. Vector m_vOffset; // offset relative to the animation transform
  1145. const char *m_pBonePrefix;
  1146. int m_nNominalColumnCount;
  1147. int m_nRowCount;
  1148. int m_nVirtColumnCount;
  1149. float m_flFollowRootBegin;
  1150. float m_flFollowRootEnd;
  1151. bool m_bIsRopeS1;
  1152. int m_nBoneIndex;
  1153. typedef CAuthPhysFx::CCollisionPlane CCollisionPlane;
  1154. typedef CAuthPhysFx::CCollisionSphere CCollisionSphere;
  1155. CUtlVector< CCollisionSphere > *m_pCollisionSpheres;
  1156. CUtlVector< CCollisionPlane > *m_pCollisionPlanes;
  1157. };
  1158. class CNodeIdx
  1159. {
  1160. public:
  1161. CNodeIdx( uint nBase, uint nRows, uint nColumns ): m_nBase( nBase ), m_nRows( nRows ), m_nColumns( nColumns ) {}
  1162. uint operator() ( uint nRow, uint nColumn )const
  1163. {
  1164. AssertDbg( nRow < m_nRows && nColumn < m_nColumns );
  1165. return m_nBase + nRow * m_nColumns + nColumn;
  1166. }
  1167. protected:
  1168. uint m_nBase;
  1169. uint m_nRows;
  1170. uint m_nColumns;
  1171. };
  1172. class CAuthClothParser: public CAuthPhysFx
  1173. {
  1174. public:
  1175. void SetBones( CPhysModelSource &physicsModel );
  1176. bool Parse( KeyValues *kv );
  1177. bool ParseDefaults( KeyValues *pSubkey );
  1178. bool ParsePiece( KeyValues *pSubkey );
  1179. void ParseExplicitDefinitions( KeyValues *pSubkey, CBoneParseParams &parseParm );
  1180. bool ParseLegacyDotaNodeGrid( KeyValues *pSubKey, CBoneParseParams &parseParms, const CNodeIdx &nodeIdx );
  1181. bool CreateLegacyDotaRodGrid( CBoneParseParams &parseParms, const CNodeIdx &nodeIdx, int );
  1182. bool TieModelToNewNode( int nNewNode );
  1183. void ReconstructHierarchy( );
  1184. void ParseExplicitNode( KeyValues *kv, CBoneParseParams &parseParm );
  1185. void ParseExplicitElem( KeyValues *kv, CBoneParseParams &parseParm );
  1186. template <typename T>
  1187. void ParseExplicitColl( KeyValues *kv, CBoneParseParams &parseParm, CUtlVector< T > &collArray );
  1188. int FindNodeByName( const char *pName );
  1189. void AddDotaRod( uint nNode0, uint nNode1, CBoneParseParams &parseParm );
  1190. protected:
  1191. int m_nDefaultCompatibilityMode;
  1192. int m_nCompatibilityMode;
  1193. CUtlStringMap< int > m_NodeNameMap;
  1194. int m_nNodeNameMapNodes;
  1195. CUtlStringMap< int > m_BoneToIndex;
  1196. CUtlVector< int > m_BoneToParent;
  1197. CUtlVector< int > m_ModelBoneToNode;
  1198. CUtlVector< CTransform >m_BoneTransforms;
  1199. };
  1200. struct AuthHullSimplificationParams_t: public RnHullSimplificationParams_t
  1201. {
  1202. float m_flMinSkinWeight;
  1203. bool m_bIncludSubtree;
  1204. AuthHullSimplificationParams_t( )
  1205. {
  1206. m_bIncludSubtree = false;
  1207. m_flMinSkinWeight = 0.5f;
  1208. }
  1209. };
  1210. template <typename TBitVec>
  1211. void CAuthPhysFx::AlignNodes( const TBitVec &useNodes )
  1212. {
  1213. CUtlVectorAligned< CFeModelBuilder::BuildNode_t > nodes;
  1214. nodes.SetCount( m_Nodes.Count() );
  1215. for ( int nNode = 0; nNode < nodes.Count(); ++nNode )
  1216. {
  1217. nodes[ nNode ] = m_Nodes[ nNode ].AsBuildNode();
  1218. }
  1219. CUtlVector< CFeModelBuilder::BuildElem_t > elems;
  1220. elems.EnsureCapacity( m_Quads.Count() );
  1221. for ( int nQuad = 0; nQuad < m_Quads.Count(); ++nQuad )
  1222. {
  1223. if ( m_Quads[ nQuad ].UsesAnyNode( useNodes ) )
  1224. {
  1225. elems.AddToTail( m_Quads[ nQuad ].AsBuildElem() );
  1226. }
  1227. }
  1228. if ( !elems.IsEmpty() )
  1229. {
  1230. CUtlVector < FeNodeBase_t > presets, bases;
  1231. CUtlVectorOfPointers< CUtlSortVector< int > > neighbors;
  1232. CFeModelBuilder::BuildNodeBases( nodes, elems, presets, bases, neighbors );
  1233. for ( const FeNodeBase_t &base : bases )
  1234. {
  1235. if ( useNodes[ base.nNode ] )
  1236. {
  1237. CBone &bone = m_Nodes[ base.nNode ];
  1238. bone.m_Transform.m_orientation = bone.m_Transform.m_orientation * Conjugate( base.qAdjust ); // qAdjust = ~predict * old_orient; so, to make qAdjust = idenity we need to make new_orient = predict = old_orient * ~(~predict * old_orient )
  1239. }
  1240. }
  1241. }
  1242. }
  1243. #endif