Team Fortress 2 Source Code as on 22/4/2020
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.

1842 lines
61 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "vcollide_parse.h"
  10. #include "ivp_listener_object.hxx"
  11. #include "vphysics/constraints.h"
  12. #include "isaverestore.h"
  13. // HACKHACK: Mathlib defines this too!
  14. #undef clamp
  15. #undef max
  16. #undef min
  17. // There's some constructor problems in the hk stuff...
  18. // The classes inherit from other classes with private constructor
  19. #pragma warning (disable : 4510 )
  20. #pragma warning (disable : 4610 )
  21. // new havana constraint class
  22. #include "hk_physics/physics.h"
  23. #include "hk_physics/constraint/constraint.h"
  24. #include "hk_physics/constraint/breakable_constraint/breakable_constraint_bp.h"
  25. #include "hk_physics/constraint/breakable_constraint/breakable_constraint.h"
  26. #include "hk_physics/constraint/limited_ball_socket/limited_ball_socket_bp.h"
  27. #include "hk_physics/constraint/limited_ball_socket/limited_ball_socket_constraint.h"
  28. #include "hk_physics/constraint/fixed/fixed_bp.h"
  29. #include "hk_physics/constraint/fixed/fixed_constraint.h"
  30. #include "hk_physics/constraint/stiff_spring/stiff_spring_bp.h"
  31. #include "hk_physics/constraint/stiff_spring/stiff_spring_constraint.h"
  32. #include "hk_physics/constraint/ball_socket/ball_socket_bp.h"
  33. #include "hk_physics/constraint/ball_socket/ball_socket_constraint.h"
  34. #include "hk_physics/constraint/prismatic/prismatic_bp.h"
  35. #include "hk_physics/constraint/prismatic/prismatic_constraint.h"
  36. #include "hk_physics/constraint/ragdoll/ragdoll_constraint.h"
  37. #include "hk_physics/constraint/ragdoll/ragdoll_constraint_bp.h"
  38. #include "hk_physics/constraint/ragdoll/ragdoll_constraint_bp_builder.h"
  39. #include "hk_physics/constraint/hinge/hinge_constraint.h"
  40. #include "hk_physics/constraint/hinge/hinge_bp.h"
  41. #include "hk_physics/constraint/hinge/hinge_bp_builder.h"
  42. #include "hk_physics/constraint/pulley/pulley_constraint.h"
  43. #include "hk_physics/constraint/pulley/pulley_bp.h"
  44. #include "hk_physics/constraint/local_constraint_system/local_constraint_system.h"
  45. #include "hk_physics/constraint/local_constraint_system/local_constraint_system_bp.h"
  46. #include "ivp_cache_object.hxx"
  47. #include "ivp_template_constraint.hxx"
  48. extern void qh_srand( int seed);
  49. #include "qhull_user.hxx"
  50. // memdbgon must be the last include file in a .cpp file!!!
  51. #include "tier0/memdbgon.h"
  52. const float UNBREAKABLE_BREAK_LIMIT = 1e12f;
  53. hk_Vector3 TransformHLWorldToHavanaLocal( const Vector &hlWorld, IVP_Real_Object *pObject )
  54. {
  55. IVP_U_Float_Point tmp;
  56. IVP_U_Point pointOut;
  57. ConvertPositionToIVP( hlWorld, tmp );
  58. TransformIVPToLocal( tmp, pointOut, pObject, true );
  59. return hk_Vector3( pointOut.k[0], pointOut.k[1], pointOut.k[2] );
  60. }
  61. Vector TransformHavanaLocalToHLWorld( const hk_Vector3 &input, IVP_Real_Object *pObject, bool translate )
  62. {
  63. IVP_U_Float_Point ivpLocal( input.x, input.y, input.z );
  64. IVP_U_Float_Point ivpWorld;
  65. TransformLocalToIVP( ivpLocal, ivpWorld, pObject, translate );
  66. Vector hlOut;
  67. if ( translate )
  68. {
  69. ConvertPositionToHL( ivpWorld, hlOut );
  70. }
  71. else
  72. {
  73. ConvertDirectionToHL( ivpWorld, hlOut );
  74. }
  75. return hlOut;
  76. }
  77. inline hk_Vector3 vec( const IVP_U_Point &point )
  78. {
  79. hk_Vector3 tmp(point.k[0], point.k[1], point.k[2] );
  80. return tmp;
  81. }
  82. // UNDONE: if vector were aligned we could simply cast these.
  83. inline hk_Vector3 vec( const Vector &point )
  84. {
  85. hk_Vector3 tmp(point.x, point.y, point.z );
  86. return tmp;
  87. }
  88. void ConvertHLLocalMatrixToHavanaLocal( const matrix3x4_t& hlMatrix, hk_Transform &out )
  89. {
  90. IVP_U_Matrix ivpMatrix;
  91. ConvertMatrixToIVP( hlMatrix, ivpMatrix );
  92. ivpMatrix.get_4x4_column_major( (hk_real *)&out );
  93. }
  94. void set_4x4_column_major( IVP_U_Matrix &ivpMatrix, const float *in4x4 )
  95. {
  96. ivpMatrix.set_elem( 0, 0, in4x4[0] );
  97. ivpMatrix.set_elem( 1, 0, in4x4[1] );
  98. ivpMatrix.set_elem( 2, 0, in4x4[2] );
  99. ivpMatrix.set_elem( 0, 1, in4x4[4] );
  100. ivpMatrix.set_elem( 1, 1, in4x4[5] );
  101. ivpMatrix.set_elem( 2, 1, in4x4[6] );
  102. ivpMatrix.set_elem( 0, 2, in4x4[8] );
  103. ivpMatrix.set_elem( 1, 2, in4x4[9] );
  104. ivpMatrix.set_elem( 2, 2, in4x4[10] );
  105. ivpMatrix.vv.k[0] = in4x4[12];
  106. ivpMatrix.vv.k[1] = in4x4[13];
  107. ivpMatrix.vv.k[2] = in4x4[14];
  108. }
  109. inline void ConvertPositionToIVP( const Vector &point, hk_Vector3 &out )
  110. {
  111. IVP_U_Float_Point ivp;
  112. ConvertPositionToIVP( point, ivp );
  113. out = vec( ivp );
  114. }
  115. inline void ConvertPositionToHL( const hk_Vector3 &point, Vector& out )
  116. {
  117. float tmpY = IVP2HL(point.z);
  118. out.z = -IVP2HL(point.y);
  119. out.y = tmpY;
  120. out.x = IVP2HL(point.x);
  121. }
  122. inline void ConvertDirectionToHL( const hk_Vector3 &point, Vector& out )
  123. {
  124. float tmpY = point.z;
  125. out.z = -point.y;
  126. out.y = tmpY;
  127. out.x = point.x;
  128. }
  129. void ConvertHavanaLocalMatrixToHL( const hk_Transform &in, matrix3x4_t& hlMatrix, IVP_Real_Object *pObject )
  130. {
  131. IVP_U_Matrix ivpMatrix;
  132. set_4x4_column_major( ivpMatrix, (const hk_real *)&in );
  133. ConvertMatrixToHL( ivpMatrix, hlMatrix );
  134. }
  135. static bool IsBreakableConstraint( const constraint_breakableparams_t &constraint )
  136. {
  137. return ( (constraint.forceLimit != 0 && constraint.forceLimit < UNBREAKABLE_BREAK_LIMIT) ||
  138. (constraint.torqueLimit != 0 && constraint.torqueLimit < UNBREAKABLE_BREAK_LIMIT) ||
  139. (constraint.bodyMassScale[0] != 1.0f && constraint.bodyMassScale[0] != 0.0f) ||
  140. (constraint.bodyMassScale[1] != 1.0f && constraint.bodyMassScale[1] != 0.0f) ) ? true : false;
  141. }
  142. struct vphysics_save_cphysicsconstraintgroup_t : public constraint_groupparams_t
  143. {
  144. bool isActive;
  145. DECLARE_SIMPLE_DATADESC();
  146. };
  147. BEGIN_SIMPLE_DATADESC( vphysics_save_cphysicsconstraintgroup_t )
  148. DEFINE_FIELD( isActive, FIELD_BOOLEAN ),
  149. DEFINE_FIELD( additionalIterations, FIELD_INTEGER ),
  150. DEFINE_FIELD( minErrorTicks, FIELD_INTEGER ),
  151. DEFINE_FIELD( errorTolerance, FIELD_FLOAT ),
  152. END_DATADESC()
  153. // a little list that holds active groups so they can activate after
  154. // the constraints are restored and added to the groups
  155. static CUtlVector<CPhysicsConstraintGroup *> g_ConstraintGroupActivateList;
  156. class CPhysicsConstraintGroup: public IPhysicsConstraintGroup
  157. {
  158. public:
  159. hk_Local_Constraint_System *GetLCS() { return m_pLCS; }
  160. void WriteToTemplate( vphysics_save_cphysicsconstraintgroup_t &groupParams )
  161. {
  162. hk_Local_Constraint_System_BP bp;
  163. m_pLCS->write_to_blueprint( &bp );
  164. groupParams.additionalIterations = bp.m_n_iterations;
  165. groupParams.isActive = bp.m_active;
  166. groupParams.minErrorTicks = bp.m_minErrorTicks;
  167. groupParams.errorTolerance = ConvertDistanceToHL(bp.m_errorTolerance);
  168. }
  169. public:
  170. CPhysicsConstraintGroup( IVP_Environment *pEnvironment, const constraint_groupparams_t &group );
  171. ~CPhysicsConstraintGroup();
  172. virtual void Activate();
  173. virtual bool IsInErrorState();
  174. virtual void ClearErrorState();
  175. void GetErrorParams( constraint_groupparams_t *pParams );
  176. void SetErrorParams( const constraint_groupparams_t &params );
  177. void SolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1 );
  178. private:
  179. hk_Local_Constraint_System *m_pLCS;
  180. };
  181. void CPhysicsConstraintGroup::Activate()
  182. {
  183. if (m_pLCS)
  184. {
  185. m_pLCS->activate();
  186. }
  187. }
  188. bool CPhysicsConstraintGroup::IsInErrorState()
  189. {
  190. if (m_pLCS)
  191. {
  192. return m_pLCS->has_error();
  193. }
  194. return false;
  195. }
  196. void CPhysicsConstraintGroup::ClearErrorState()
  197. {
  198. if (m_pLCS)
  199. {
  200. m_pLCS->clear_error();
  201. }
  202. }
  203. void CPhysicsConstraintGroup::GetErrorParams( constraint_groupparams_t *pParams )
  204. {
  205. if ( !m_pLCS )
  206. return;
  207. vphysics_save_cphysicsconstraintgroup_t tmp;
  208. WriteToTemplate( tmp );
  209. *pParams = tmp;
  210. }
  211. void CPhysicsConstraintGroup::SetErrorParams( const constraint_groupparams_t &params )
  212. {
  213. if ( !m_pLCS )
  214. return;
  215. m_pLCS->set_error_ticks( params.minErrorTicks );
  216. m_pLCS->set_error_tolerance( ConvertDistanceToIVP(params.errorTolerance) );
  217. }
  218. void CPhysicsConstraintGroup::SolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1 )
  219. {
  220. if ( m_pLCS && pObj0 && pObj1 )
  221. {
  222. CPhysicsObject *pPhys0 = static_cast<CPhysicsObject *>(pObj0);
  223. CPhysicsObject *pPhys1 = static_cast<CPhysicsObject *>(pObj1);
  224. m_pLCS->solve_penetration(pPhys0->GetObject(), pPhys1->GetObject());
  225. }
  226. }
  227. CPhysicsConstraintGroup::~CPhysicsConstraintGroup()
  228. {
  229. delete m_pLCS;
  230. }
  231. CPhysicsConstraintGroup::CPhysicsConstraintGroup( IVP_Environment *pEnvironment, const constraint_groupparams_t &group )
  232. {
  233. hk_Local_Constraint_System_BP cs_bp;
  234. cs_bp.m_n_iterations = group.additionalIterations;
  235. cs_bp.m_minErrorTicks = group.minErrorTicks;
  236. cs_bp.m_errorTolerance = ConvertDistanceToIVP(group.errorTolerance);
  237. m_pLCS = new hk_Local_Constraint_System( static_cast<hk_Environment *>(pEnvironment), &cs_bp );
  238. m_pLCS->set_client_data( (void *)this );
  239. }
  240. enum vphysics_save_constrainttypes_t
  241. {
  242. CONSTRAINT_UNKNOWN = 0,
  243. CONSTRAINT_RAGDOLL,
  244. CONSTRAINT_HINGE,
  245. CONSTRAINT_FIXED,
  246. CONSTRAINT_BALLSOCKET,
  247. CONSTRAINT_SLIDING,
  248. CONSTRAINT_PULLEY,
  249. CONSTRAINT_LENGTH,
  250. };
  251. struct vphysics_save_cphysicsconstraint_t
  252. {
  253. int constraintType;
  254. CPhysicsConstraintGroup *pGroup;
  255. CPhysicsObject *pObjReference;
  256. CPhysicsObject *pObjAttached;
  257. DECLARE_SIMPLE_DATADESC();
  258. };
  259. BEGIN_SIMPLE_DATADESC( vphysics_save_cphysicsconstraint_t )
  260. DEFINE_FIELD( constraintType, FIELD_INTEGER ),
  261. DEFINE_VPHYSPTR( pGroup ),
  262. DEFINE_VPHYSPTR( pObjReference ),
  263. DEFINE_VPHYSPTR( pObjAttached ),
  264. END_DATADESC()
  265. struct vphysics_save_constraintbreakable_t : public constraint_breakableparams_t
  266. {
  267. DECLARE_SIMPLE_DATADESC();
  268. };
  269. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintbreakable_t )
  270. DEFINE_FIELD( strength, FIELD_FLOAT ),
  271. DEFINE_FIELD( forceLimit, FIELD_FLOAT ),
  272. DEFINE_FIELD( torqueLimit, FIELD_FLOAT ),
  273. DEFINE_AUTO_ARRAY( bodyMassScale, FIELD_FLOAT ),
  274. DEFINE_FIELD( isActive, FIELD_BOOLEAN ),
  275. END_DATADESC()
  276. struct vphysics_save_constraintaxislimit_t : public constraint_axislimit_t
  277. {
  278. DECLARE_SIMPLE_DATADESC();
  279. };
  280. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintaxislimit_t )
  281. DEFINE_FIELD( minRotation, FIELD_FLOAT ),
  282. DEFINE_FIELD( maxRotation, FIELD_FLOAT ),
  283. DEFINE_FIELD( angularVelocity, FIELD_FLOAT ),
  284. DEFINE_FIELD( torque, FIELD_FLOAT ),
  285. END_DATADESC()
  286. struct vphysics_save_constraintfixed_t : public constraint_fixedparams_t
  287. {
  288. DECLARE_SIMPLE_DATADESC();
  289. };
  290. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintfixed_t )
  291. DEFINE_AUTO_ARRAY2D( attachedRefXform, FIELD_FLOAT ),
  292. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  293. END_DATADESC()
  294. struct vphysics_save_constrainthinge_t : public constraint_hingeparams_t
  295. {
  296. DECLARE_SIMPLE_DATADESC();
  297. };
  298. BEGIN_SIMPLE_DATADESC( vphysics_save_constrainthinge_t )
  299. DEFINE_FIELD( worldPosition, FIELD_POSITION_VECTOR ),
  300. DEFINE_FIELD( worldAxisDirection, FIELD_VECTOR ),
  301. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  302. DEFINE_EMBEDDED_OVERRIDE( hingeAxis, vphysics_save_constraintaxislimit_t ),
  303. END_DATADESC()
  304. struct vphysics_save_constraintsliding_t : public constraint_slidingparams_t
  305. {
  306. DECLARE_SIMPLE_DATADESC();
  307. };
  308. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintsliding_t )
  309. DEFINE_AUTO_ARRAY2D( attachedRefXform, FIELD_FLOAT ),
  310. DEFINE_FIELD( slideAxisRef, FIELD_VECTOR ),
  311. DEFINE_FIELD( limitMin, FIELD_FLOAT ),
  312. DEFINE_FIELD( limitMax, FIELD_FLOAT ),
  313. DEFINE_FIELD( friction, FIELD_FLOAT ),
  314. DEFINE_FIELD( velocity, FIELD_FLOAT ),
  315. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  316. END_DATADESC()
  317. struct vphysics_save_constraintpulley_t : public constraint_pulleyparams_t
  318. {
  319. DECLARE_SIMPLE_DATADESC();
  320. };
  321. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintpulley_t )
  322. DEFINE_AUTO_ARRAY( pulleyPosition, FIELD_POSITION_VECTOR ),
  323. DEFINE_AUTO_ARRAY( objectPosition, FIELD_VECTOR ),
  324. DEFINE_FIELD( totalLength, FIELD_FLOAT ),
  325. DEFINE_FIELD( gearRatio, FIELD_FLOAT ),
  326. DEFINE_FIELD( isRigid, FIELD_BOOLEAN ),
  327. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  328. END_DATADESC()
  329. struct vphysics_save_constraintlength_t : public constraint_lengthparams_t
  330. {
  331. DECLARE_SIMPLE_DATADESC();
  332. };
  333. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintlength_t )
  334. DEFINE_AUTO_ARRAY( objectPosition, FIELD_VECTOR ),
  335. DEFINE_FIELD( totalLength, FIELD_FLOAT ),
  336. DEFINE_FIELD( minLength, FIELD_FLOAT ),
  337. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  338. END_DATADESC()
  339. struct vphysics_save_constraintballsocket_t : public constraint_ballsocketparams_t
  340. {
  341. DECLARE_SIMPLE_DATADESC();
  342. };
  343. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintballsocket_t )
  344. DEFINE_AUTO_ARRAY( constraintPosition, FIELD_VECTOR ),
  345. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  346. END_DATADESC()
  347. struct vphysics_save_constraintragdoll_t : public constraint_ragdollparams_t
  348. {
  349. DECLARE_SIMPLE_DATADESC();
  350. };
  351. BEGIN_SIMPLE_DATADESC( vphysics_save_constraintragdoll_t )
  352. DEFINE_EMBEDDED_OVERRIDE( constraint, vphysics_save_constraintbreakable_t ),
  353. DEFINE_AUTO_ARRAY2D( constraintToReference, FIELD_FLOAT ),
  354. DEFINE_AUTO_ARRAY2D( constraintToAttached, FIELD_FLOAT ),
  355. DEFINE_EMBEDDED_OVERRIDE( axes[0], vphysics_save_constraintaxislimit_t ),
  356. DEFINE_EMBEDDED_OVERRIDE( axes[1], vphysics_save_constraintaxislimit_t ),
  357. DEFINE_EMBEDDED_OVERRIDE( axes[2], vphysics_save_constraintaxislimit_t ),
  358. DEFINE_FIELD( onlyAngularLimits, FIELD_BOOLEAN ),
  359. DEFINE_FIELD( isActive, FIELD_BOOLEAN ),
  360. DEFINE_FIELD( useClockwiseRotations, FIELD_BOOLEAN ),
  361. END_DATADESC()
  362. struct vphysics_save_constraint_t
  363. {
  364. vphysics_save_constraintfixed_t fixed;
  365. vphysics_save_constrainthinge_t hinge;
  366. vphysics_save_constraintsliding_t sliding;
  367. vphysics_save_constraintpulley_t pulley;
  368. vphysics_save_constraintlength_t length;
  369. vphysics_save_constraintballsocket_t ballsocket;
  370. vphysics_save_constraintragdoll_t ragdoll;
  371. };
  372. // UNDONE: May need to change interface to specify limits before construction
  373. // UNDONE: Refactor constraints to contain a separate object for the various constraint types?
  374. class CPhysicsConstraint: public IPhysicsConstraint, public IVP_Listener_Object
  375. {
  376. public:
  377. CPhysicsConstraint( CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject );
  378. ~CPhysicsConstraint( void );
  379. // init as ragdoll constraint
  380. void InitRagdoll( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_ragdollparams_t &ragdoll );
  381. // init as hinge
  382. void InitHinge( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_limitedhingeparams_t &hinge );
  383. // init as fixed (BUGBUG: This is broken)
  384. void InitFixed( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_fixedparams_t &fixed );
  385. // init as ballsocket
  386. void InitBallsocket( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_ballsocketparams_t &ballsocket );
  387. // init as sliding constraint
  388. void InitSliding( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_slidingparams_t &sliding );
  389. // init as pulley
  390. void InitPulley( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_pulleyparams_t &pulley );
  391. // init as stiff spring / length constraint
  392. void InitLength( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_lengthparams_t &length );
  393. void WriteToTemplate( vphysics_save_cphysicsconstraint_t &header, vphysics_save_constraint_t &constraintTemplate ) const;
  394. void WriteRagdoll( constraint_ragdollparams_t &ragdoll ) const;
  395. void WriteHinge( constraint_hingeparams_t &hinge ) const;
  396. void WriteFixed( constraint_fixedparams_t &fixed ) const;
  397. void WriteSliding( constraint_slidingparams_t &sliding ) const;
  398. void WriteBallsocket( constraint_ballsocketparams_t &ballsocket ) const;
  399. void WritePulley( constraint_pulleyparams_t &pulley ) const;
  400. void WriteLength( constraint_lengthparams_t &length ) const;
  401. CPhysicsConstraintGroup *GetConstraintGroup() const;
  402. hk_Constraint *CreateBreakableConstraint( hk_Constraint *pRealConstraint, hk_Local_Constraint_System *pLcs, const constraint_breakableparams_t &constraint )
  403. {
  404. m_isBreakable = true;
  405. hk_Breakable_Constraint_BP bp;
  406. bp.m_real_constraint = pRealConstraint;
  407. float forceLimit = ConvertDistanceToIVP( constraint.forceLimit );
  408. bp.m_linear_strength = forceLimit > 0 ? forceLimit : UNBREAKABLE_BREAK_LIMIT;
  409. bp.m_angular_strength = constraint.torqueLimit > 0 ? DEG2RAD(constraint.torqueLimit) : UNBREAKABLE_BREAK_LIMIT;
  410. bp.m_bodyMassScale[0] = constraint.bodyMassScale[0] > 0 ? constraint.bodyMassScale[0] : 1.0f;
  411. bp.m_bodyMassScale[1] = constraint.bodyMassScale[1] > 0 ? constraint.bodyMassScale[1] : 1.0f;;
  412. return new hk_Breakable_Constraint( pLcs, &bp );
  413. }
  414. void ReadBreakableConstraint( constraint_breakableparams_t &params ) const;
  415. hk_Constraint *GetRealConstraint() const
  416. {
  417. if ( m_isBreakable )
  418. {
  419. hk_Breakable_Constraint_BP bp;
  420. ((hk_Breakable_Constraint *)m_HkConstraint)->write_to_blueprint( &bp );
  421. return bp.m_real_constraint;
  422. }
  423. return m_HkConstraint;
  424. }
  425. void Activate( void );
  426. void Deactivate( void );
  427. void SetupRagdollAxis( int axis, const constraint_axislimit_t &axisData, hk_Limited_Ball_Socket_BP *ballsocketBP );
  428. // UNDONE: Implement includeStatic for havana
  429. void SetGameData( void *gameData ) { m_pGameData = gameData; }
  430. void *GetGameData( void ) const { return m_pGameData; }
  431. IPhysicsObject *GetReferenceObject( void ) const;
  432. IPhysicsObject *GetAttachedObject( void ) const;
  433. void SetLinearMotor( float speed, float maxForce );
  434. void SetAngularMotor( float rotSpeed, float maxAngularImpulse );
  435. void UpdateRagdollTransforms( const matrix3x4_t &constraintToReference, const matrix3x4_t &constraintToAttached );
  436. bool GetConstraintTransform( matrix3x4_t *pConstraintToReference, matrix3x4_t *pConstraintToAttached ) const;
  437. bool GetConstraintParams( constraint_breakableparams_t *pParams ) const;
  438. void OutputDebugInfo()
  439. {
  440. hk_Local_Constraint_System *pLCS = m_HkLCS;
  441. if ( m_HkConstraint )
  442. {
  443. pLCS = m_HkConstraint->get_constraint_system();
  444. }
  445. if ( pLCS )
  446. {
  447. int count = 0;
  448. hk_Array<hk_Constraint *> list;
  449. pLCS->get_constraints_in_system( list );
  450. Msg("System of %d constraints\n", list.length());
  451. for ( hk_Array<hk_Constraint*>::iterator i = list.start(); list.is_valid(i); i = list.next(i) )
  452. {
  453. hk_Constraint *pConstraint = list.get_element(i);
  454. Msg("\tConstraint %d) %s\n", count, pConstraint->get_constraint_type() );
  455. count++;
  456. }
  457. }
  458. }
  459. void DetachListener();
  460. // Object listener
  461. virtual void event_object_deleted( IVP_Event_Object *);
  462. virtual void event_object_created( IVP_Event_Object *) {}
  463. virtual void event_object_revived( IVP_Event_Object *) {}
  464. virtual void event_object_frozen ( IVP_Event_Object *) {}
  465. private:
  466. CPhysicsObject *m_pObjReference;
  467. CPhysicsObject *m_pObjAttached;
  468. // havana constraints
  469. hk_Constraint *m_HkConstraint;
  470. hk_Local_Constraint_System *m_HkLCS;
  471. void *m_pGameData;
  472. // these are used to crack the abstract pointers on save/load
  473. short m_constraintType;
  474. short m_isBreakable;
  475. };
  476. CPhysicsConstraint::CPhysicsConstraint( CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject )
  477. {
  478. m_pGameData = NULL;
  479. m_HkConstraint = NULL;
  480. m_HkLCS = NULL;
  481. m_constraintType = CONSTRAINT_UNKNOWN;
  482. m_isBreakable = false;
  483. if ( pReferenceObject && pAttachedObject )
  484. {
  485. m_pObjReference = (CPhysicsObject *)pReferenceObject;
  486. m_pObjAttached = (CPhysicsObject *)pAttachedObject;
  487. if ( !(m_pObjReference->CallbackFlags() & CALLBACK_NEVER_DELETED) )
  488. {
  489. m_pObjReference->GetObject()->add_listener_object( this );
  490. }
  491. if ( !(m_pObjAttached->CallbackFlags() & CALLBACK_NEVER_DELETED) )
  492. {
  493. m_pObjAttached->GetObject()->add_listener_object( this );
  494. }
  495. }
  496. else
  497. {
  498. m_pObjReference = NULL;
  499. m_pObjAttached = NULL;
  500. }
  501. }
  502. // Check to see if this is a single degree of freedom joint, if so, convert to a hinge
  503. static bool ConvertRagdollToHinge( constraint_limitedhingeparams_t *pHingeOut, const constraint_ragdollparams_t &ragdoll, IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject )
  504. {
  505. int nDOF = 0;
  506. int dofIndex = 0;
  507. for ( int i = 0; i < 3; i++ )
  508. {
  509. if ( ragdoll.axes[i].minRotation != ragdoll.axes[i].maxRotation )
  510. {
  511. dofIndex = i;
  512. nDOF++;
  513. }
  514. }
  515. // found multiple degrees of freedom
  516. if ( nDOF != 1 )
  517. return false;
  518. // convert params to hinge
  519. pHingeOut->Defaults();
  520. pHingeOut->constraint = ragdoll.constraint;
  521. // get the hinge axis in world space
  522. matrix3x4_t refToWorld, constraintToWorld;
  523. pReferenceObject->GetPositionMatrix( &refToWorld );
  524. ConcatTransforms( refToWorld, ragdoll.constraintToReference, constraintToWorld );
  525. // many ragdoll constraints don't set this and the ragdoll solver ignores it
  526. // force it to the default
  527. pHingeOut->constraint.strength = 1.0f;
  528. MatrixGetColumn( constraintToWorld, 3, &pHingeOut->worldPosition );
  529. MatrixGetColumn( constraintToWorld, dofIndex, &pHingeOut->worldAxisDirection );
  530. pHingeOut->referencePerpAxisDirection.Init();
  531. pHingeOut->referencePerpAxisDirection[(dofIndex+1)%3] = 1;
  532. Vector perpCS;
  533. VectorIRotate( pHingeOut->referencePerpAxisDirection, ragdoll.constraintToReference, perpCS );
  534. VectorRotate( perpCS, ragdoll.constraintToAttached, pHingeOut->attachedPerpAxisDirection );
  535. pHingeOut->hingeAxis = ragdoll.axes[dofIndex];
  536. // Funky math to insure that the friction is preserved after the math that the hinge code uses.
  537. pHingeOut->hingeAxis.torque = RAD2DEG( pHingeOut->hingeAxis.torque * pReferenceObject->GetMass() );
  538. // need to flip the limits, just flip the axis instead
  539. if ( !ragdoll.useClockwiseRotations )
  540. {
  541. float tmp = pHingeOut->hingeAxis.minRotation;
  542. pHingeOut->hingeAxis.minRotation = -pHingeOut->hingeAxis.maxRotation;
  543. pHingeOut->hingeAxis.maxRotation = -tmp;
  544. }
  545. return true;
  546. }
  547. // ragdoll constraint
  548. void CPhysicsConstraint::InitRagdoll( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_ragdollparams_t &ragdoll )
  549. {
  550. // UNDONE: If this is a hinge parameterized using the ragdoll params, use a hinge instead!
  551. constraint_limitedhingeparams_t hinge;
  552. if ( ConvertRagdollToHinge( &hinge, ragdoll, m_pObjReference, m_pObjAttached ) )
  553. {
  554. InitHinge( pEnvironment, constraint_group, hinge );
  555. return;
  556. }
  557. m_constraintType = CONSTRAINT_RAGDOLL;
  558. hk_Rigid_Body *ref = (hk_Rigid_Body*)m_pObjReference->GetObject();
  559. hk_Rigid_Body *att = (hk_Rigid_Body*)m_pObjAttached->GetObject();
  560. hk_Limited_Ball_Socket_BP ballsocketBP;
  561. ConvertHLLocalMatrixToHavanaLocal( ragdoll.constraintToReference, ballsocketBP.m_transform_os_ks[0] );
  562. ConvertHLLocalMatrixToHavanaLocal( ragdoll.constraintToAttached, ballsocketBP.m_transform_os_ks[1] );
  563. bool breakable = IsBreakableConstraint( ragdoll.constraint );
  564. int i;
  565. // BUGBUG: Handle incorrect clockwise rotations here
  566. for ( i = 0; i < 3; i++ )
  567. {
  568. SetupRagdollAxis( i, ragdoll.axes[i], &ballsocketBP );
  569. }
  570. ballsocketBP.m_constrainTranslation = ragdoll.onlyAngularLimits ? false : true;
  571. // swap the input limits if they are clockwise (angles are counter-clockwise)
  572. if ( ragdoll.useClockwiseRotations )
  573. {
  574. for ( i = 0; i < 3; i++ )
  575. {
  576. float tmp = ballsocketBP.m_angular_limits[i].m_min;
  577. ballsocketBP.m_angular_limits[i].m_min = -ballsocketBP.m_angular_limits[i].m_max;
  578. ballsocketBP.m_angular_limits[i].m_max = -tmp;
  579. }
  580. }
  581. hk_Ragdoll_Constraint_BP_Builder r_builder;
  582. r_builder.initialize_from_limited_ball_socket_bp( &ballsocketBP, ref, att );
  583. hk_Ragdoll_Constraint_BP *bp = (hk_Ragdoll_Constraint_BP *)r_builder.get_blueprint(); // get non const bp
  584. int revAxisMapHK[3];
  585. revAxisMapHK[bp->m_axisMap[0]] = 0;
  586. revAxisMapHK[bp->m_axisMap[1]] = 1;
  587. revAxisMapHK[bp->m_axisMap[2]] = 2;
  588. for ( i = 0; i < 3; i++ )
  589. {
  590. // remap HL axis to IVP axis
  591. int ivpAxis = ConvertCoordinateAxisToIVP( i );
  592. // initialize_from_limited_ball_socket_bp remapped the axes too! So remap again.
  593. int hkAxis = revAxisMapHK[ivpAxis];
  594. const constraint_axislimit_t &axisData = ragdoll.axes[i];
  595. bp->m_limits[hkAxis].set_motor( DEG2RAD(axisData.angularVelocity), axisData.torque * m_pObjReference->GetMass() );
  596. bp->m_tau = 1.0f;
  597. }
  598. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  599. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  600. if ( !lcs )
  601. {
  602. hk_Local_Constraint_System_BP bp;
  603. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  604. m_HkLCS = lcs;
  605. }
  606. if ( breakable )
  607. {
  608. hk_Ragdoll_Constraint *pConstraint = new hk_Ragdoll_Constraint( hkEnvironment, bp, ref, att);
  609. m_HkConstraint = CreateBreakableConstraint( pConstraint, lcs, ragdoll.constraint );
  610. }
  611. else
  612. {
  613. m_HkConstraint = new hk_Ragdoll_Constraint( lcs, bp, ref, att);
  614. }
  615. if ( m_HkLCS && ragdoll.isActive )
  616. {
  617. m_HkLCS->activate();
  618. }
  619. m_HkConstraint->set_client_data( (void *)this );
  620. }
  621. // hinge constraint
  622. void CPhysicsConstraint::InitHinge( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_limitedhingeparams_t &hinge )
  623. {
  624. m_constraintType = CONSTRAINT_HINGE;
  625. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  626. bool breakable = IsBreakableConstraint( hinge.constraint );
  627. hk_Hinge_BP_Builder builder;
  628. IVP_U_Point axisIVP_ws, axisPerpIVP_os, axisStartIVP_ws, axisStartIVP_os;
  629. ConvertDirectionToIVP( hinge.worldAxisDirection, axisIVP_ws );
  630. builder.set_axis_ws( (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject(), vec(axisIVP_ws) );
  631. builder.set_position_os( 0, TransformHLWorldToHavanaLocal( hinge.worldPosition, m_pObjReference->GetObject() ) );
  632. builder.set_position_os( 1, TransformHLWorldToHavanaLocal( hinge.worldPosition, m_pObjAttached->GetObject() ) );
  633. ConvertDirectionToIVP( hinge.referencePerpAxisDirection, axisPerpIVP_os );
  634. builder.set_axis_perp_os( 0, vec(axisPerpIVP_os) );
  635. ConvertDirectionToIVP( hinge.attachedPerpAxisDirection, axisPerpIVP_os );
  636. builder.set_axis_perp_os( 1, vec(axisPerpIVP_os) );
  637. builder.set_tau( hinge.constraint.strength );
  638. // torque is an impulse radians/sec * inertia
  639. if ( hinge.hingeAxis.torque != 0 )
  640. {
  641. builder.set_angular_motor( DEG2RAD(hinge.hingeAxis.angularVelocity), DEG2RAD(hinge.hingeAxis.torque) );
  642. }
  643. if ( hinge.hingeAxis.minRotation != hinge.hingeAxis.maxRotation )
  644. {
  645. builder.set_angular_limits( DEG2RAD(hinge.hingeAxis.minRotation), DEG2RAD(hinge.hingeAxis.maxRotation) );
  646. }
  647. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  648. if ( !lcs )
  649. {
  650. hk_Local_Constraint_System_BP bp;
  651. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  652. m_HkLCS = lcs;
  653. }
  654. if ( breakable )
  655. {
  656. hk_Hinge_Constraint *pHinge = new hk_Hinge_Constraint( hkEnvironment, builder.get_blueprint(), (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  657. m_HkConstraint = CreateBreakableConstraint( pHinge, lcs, hinge.constraint );
  658. }
  659. else
  660. {
  661. m_HkConstraint = new hk_Hinge_Constraint( lcs, builder.get_blueprint(), (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  662. }
  663. if ( m_HkLCS && hinge.constraint.isActive )
  664. {
  665. m_HkLCS->activate();
  666. }
  667. m_HkConstraint->set_client_data( (void *)this );
  668. }
  669. // fixed constraint
  670. void CPhysicsConstraint::InitFixed( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_fixedparams_t &fixed )
  671. {
  672. m_constraintType = CONSTRAINT_FIXED;
  673. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  674. bool breakable = IsBreakableConstraint( fixed.constraint );
  675. hk_Fixed_BP fixed_bp;
  676. ConvertHLLocalMatrixToHavanaLocal( fixed.attachedRefXform, fixed_bp.m_transform_os_ks );
  677. fixed_bp.m_tau = fixed.constraint.strength;
  678. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  679. if ( !lcs )
  680. {
  681. hk_Local_Constraint_System_BP bp;
  682. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  683. m_HkLCS = lcs;
  684. }
  685. if ( breakable )
  686. {
  687. hk_Constraint *pFixed = new hk_Fixed_Constraint( hkEnvironment, &fixed_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  688. m_HkConstraint = CreateBreakableConstraint( pFixed, lcs, fixed.constraint );
  689. }
  690. else
  691. {
  692. m_HkConstraint = new hk_Fixed_Constraint( lcs, &fixed_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  693. }
  694. if ( m_HkLCS && fixed.constraint.isActive )
  695. {
  696. m_HkLCS->activate();
  697. }
  698. m_HkConstraint->set_client_data( (void *)this );
  699. }
  700. void CPhysicsConstraint::InitBallsocket( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_ballsocketparams_t &ballsocket )
  701. {
  702. m_constraintType = CONSTRAINT_BALLSOCKET;
  703. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  704. bool breakable = IsBreakableConstraint( ballsocket.constraint );
  705. hk_Ball_Socket_BP builder;
  706. for ( int i = 0; i < 2; i++ )
  707. {
  708. hk_Vector3 hkConstraintLocal;
  709. ConvertPositionToIVP( ballsocket.constraintPosition[i], hkConstraintLocal );
  710. builder.set_position_os( i, hkConstraintLocal );
  711. }
  712. builder.m_strength = ballsocket.constraint.strength;
  713. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  714. if ( !lcs )
  715. {
  716. hk_Local_Constraint_System_BP bp;
  717. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  718. m_HkLCS = lcs;
  719. }
  720. if ( breakable )
  721. {
  722. hk_Ball_Socket_Constraint *pConstraint = new hk_Ball_Socket_Constraint( hkEnvironment, &builder, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  723. m_HkConstraint = CreateBreakableConstraint( pConstraint, lcs, ballsocket.constraint );
  724. }
  725. else
  726. {
  727. m_HkConstraint = new hk_Ball_Socket_Constraint( lcs, &builder, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  728. }
  729. if ( m_HkLCS && ballsocket.constraint.isActive )
  730. {
  731. m_HkLCS->activate();
  732. }
  733. m_HkConstraint->set_client_data( (void *)this );
  734. }
  735. void CPhysicsConstraint::InitSliding( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_slidingparams_t &sliding )
  736. {
  737. m_constraintType = CONSTRAINT_SLIDING;
  738. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  739. bool breakable = IsBreakableConstraint( sliding.constraint );
  740. hk_Prismatic_BP prismatic_bp;
  741. hk_Transform t;
  742. ConvertHLLocalMatrixToHavanaLocal( sliding.attachedRefXform, t );
  743. prismatic_bp.m_transform_Ros_Aos.m_translation = t.get_translation();
  744. prismatic_bp.m_transform_Ros_Aos.m_rotation.set( t );
  745. IVP_U_Float_Point refAxisDir;
  746. ConvertDirectionToIVP( sliding.slideAxisRef, refAxisDir );
  747. prismatic_bp.m_axis_Ros = vec(refAxisDir);
  748. prismatic_bp.m_tau = sliding.constraint.strength;
  749. hk_Constraint_Limit_BP bp;
  750. if ( sliding.limitMin != sliding.limitMax )
  751. {
  752. bp.set_limits( ConvertDistanceToIVP(sliding.limitMin), ConvertDistanceToIVP(sliding.limitMax) );
  753. }
  754. if ( sliding.friction )
  755. {
  756. if ( sliding.velocity )
  757. {
  758. bp.set_motor( ConvertDistanceToIVP(sliding.velocity), ConvertDistanceToIVP(sliding.friction) );
  759. }
  760. else
  761. {
  762. bp.set_friction( ConvertDistanceToIVP(sliding.friction) );
  763. }
  764. }
  765. prismatic_bp.m_limit.init_limit( bp, 1.0 );
  766. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  767. if ( !lcs )
  768. {
  769. hk_Local_Constraint_System_BP bp;
  770. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  771. m_HkLCS = lcs;
  772. }
  773. if ( breakable )
  774. {
  775. hk_Constraint *pFixed = new hk_Prismatic_Constraint( hkEnvironment, &prismatic_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  776. m_HkConstraint = CreateBreakableConstraint( pFixed, lcs, sliding.constraint );
  777. }
  778. else
  779. {
  780. m_HkConstraint = new hk_Prismatic_Constraint( lcs, &prismatic_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  781. }
  782. if ( m_HkLCS && sliding.constraint.isActive )
  783. {
  784. m_HkLCS->activate();
  785. }
  786. m_HkConstraint->set_client_data( (void *)this );
  787. }
  788. void CPhysicsConstraint::InitPulley( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_pulleyparams_t &pulley )
  789. {
  790. m_constraintType = CONSTRAINT_PULLEY;
  791. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  792. bool breakable = IsBreakableConstraint( pulley.constraint );
  793. hk_Pulley_BP pulley_bp;
  794. pulley_bp.m_tau = pulley.constraint.strength;
  795. //pulley_bp.m_strength = pulley.constraint.strength;
  796. pulley_bp.m_gearing = pulley.gearRatio;
  797. pulley_bp.m_is_rigid = pulley.isRigid;
  798. // Get the current length of rope
  799. pulley_bp.m_length = ConvertDistanceToIVP( pulley.totalLength );
  800. // set the anchor positions in object space
  801. ConvertPositionToIVP( pulley.objectPosition[0], pulley_bp.m_translation_os_ks[0] );
  802. ConvertPositionToIVP( pulley.objectPosition[1], pulley_bp.m_translation_os_ks[1] );
  803. // set the pully positions in world space
  804. ConvertPositionToIVP( pulley.pulleyPosition[0], pulley_bp.m_worldspace_point[0] );
  805. ConvertPositionToIVP( pulley.pulleyPosition[1], pulley_bp.m_worldspace_point[1] );
  806. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  807. if ( !lcs )
  808. {
  809. hk_Local_Constraint_System_BP bp;
  810. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  811. m_HkLCS = lcs;
  812. }
  813. if ( breakable )
  814. {
  815. hk_Constraint *pPulley = new hk_Pulley_Constraint( hkEnvironment, &pulley_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  816. m_HkConstraint = CreateBreakableConstraint( pPulley, lcs, pulley.constraint );
  817. }
  818. else
  819. {
  820. m_HkConstraint = new hk_Pulley_Constraint( lcs, &pulley_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  821. }
  822. if ( m_HkLCS && pulley.constraint.isActive )
  823. {
  824. m_HkLCS->activate();
  825. }
  826. m_HkConstraint->set_client_data( (void *)this );
  827. }
  828. void CPhysicsConstraint::InitLength( IVP_Environment *pEnvironment, CPhysicsConstraintGroup *constraint_group, const constraint_lengthparams_t &length )
  829. {
  830. m_constraintType = CONSTRAINT_LENGTH;
  831. hk_Environment *hkEnvironment = static_cast<hk_Environment *>(pEnvironment);
  832. bool breakable = IsBreakableConstraint( length.constraint );
  833. hk_Stiff_Spring_BP stiff_bp;
  834. stiff_bp.m_tau = length.constraint.strength;
  835. //stiff_bp.m_strength = length.constraint.strength;
  836. // Get the current length of rope
  837. stiff_bp.m_length = ConvertDistanceToIVP( length.totalLength );
  838. stiff_bp.m_min_length = ConvertDistanceToIVP( length.minLength );
  839. // set the anchor positions in object space
  840. ConvertPositionToIVP( length.objectPosition[0], stiff_bp.m_translation_os_ks[0] );
  841. ConvertPositionToIVP( length.objectPosition[1], stiff_bp.m_translation_os_ks[1] );
  842. hk_Local_Constraint_System *lcs = constraint_group ? constraint_group->GetLCS() : NULL;
  843. if ( !lcs )
  844. {
  845. hk_Local_Constraint_System_BP bp;
  846. lcs = new hk_Local_Constraint_System( hkEnvironment, &bp );
  847. m_HkLCS = lcs;
  848. }
  849. if ( breakable )
  850. {
  851. hk_Constraint *pLength = new hk_Stiff_Spring_Constraint( hkEnvironment, &stiff_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  852. m_HkConstraint = CreateBreakableConstraint( pLength, lcs, length.constraint );
  853. }
  854. else
  855. {
  856. m_HkConstraint = new hk_Stiff_Spring_Constraint( lcs, &stiff_bp, (hk_Rigid_Body*)m_pObjReference->GetObject(), (hk_Rigid_Body*)m_pObjAttached->GetObject() );
  857. }
  858. if ( m_HkLCS && length.constraint.isActive )
  859. {
  860. m_HkLCS->activate();
  861. }
  862. m_HkConstraint->set_client_data( (void *)this );
  863. }
  864. // Serialization: Write out a description for this constraint
  865. void CPhysicsConstraint::WriteToTemplate( vphysics_save_cphysicsconstraint_t &header, vphysics_save_constraint_t &constraintTemplate ) const
  866. {
  867. header.constraintType = m_constraintType;
  868. // this constraint is inert due to one of it's objects getting deleted
  869. if ( !m_HkConstraint )
  870. return;
  871. header.pGroup = GetConstraintGroup();
  872. header.pObjReference = m_pObjReference;
  873. header.pObjAttached = m_pObjAttached;
  874. switch( header.constraintType )
  875. {
  876. case CONSTRAINT_UNKNOWN:
  877. Assert(0);
  878. break;
  879. case CONSTRAINT_HINGE:
  880. WriteHinge( constraintTemplate.hinge );
  881. break;
  882. case CONSTRAINT_FIXED:
  883. WriteFixed( constraintTemplate.fixed );
  884. break;
  885. case CONSTRAINT_SLIDING:
  886. WriteSliding( constraintTemplate.sliding );
  887. break;
  888. case CONSTRAINT_PULLEY:
  889. WritePulley( constraintTemplate.pulley );
  890. break;
  891. case CONSTRAINT_LENGTH:
  892. WriteLength( constraintTemplate.length );
  893. break;
  894. case CONSTRAINT_BALLSOCKET:
  895. WriteBallsocket( constraintTemplate.ballsocket );
  896. break;
  897. case CONSTRAINT_RAGDOLL:
  898. WriteRagdoll( constraintTemplate.ragdoll );
  899. break;
  900. }
  901. }
  902. void CPhysicsConstraint::SetLinearMotor( float speed, float maxLinearImpulse )
  903. {
  904. if ( m_constraintType != CONSTRAINT_SLIDING )
  905. return;
  906. hk_Prismatic_Constraint *pConstraint = (hk_Prismatic_Constraint *)GetRealConstraint();
  907. pConstraint->set_motor( ConvertDistanceToIVP( speed ), ConvertDistanceToIVP( maxLinearImpulse ) );
  908. }
  909. void CPhysicsConstraint::SetAngularMotor( float rotSpeed, float maxAngularImpulse )
  910. {
  911. if ( m_constraintType == CONSTRAINT_RAGDOLL && rotSpeed == 0 )
  912. {
  913. hk_Ragdoll_Constraint *pConstraint = (hk_Ragdoll_Constraint *)GetRealConstraint();
  914. pConstraint->update_friction( ConvertAngleToIVP( maxAngularImpulse ) );
  915. }
  916. else if ( m_constraintType == CONSTRAINT_HINGE )
  917. {
  918. hk_Hinge_Constraint *pConstraint = (hk_Hinge_Constraint *)GetRealConstraint();
  919. pConstraint->set_motor( ConvertAngleToIVP( rotSpeed ), ConvertAngleToIVP( fabs(maxAngularImpulse) ) );
  920. }
  921. }
  922. void CPhysicsConstraint::UpdateRagdollTransforms( const matrix3x4_t &constraintToReference, const matrix3x4_t &constraintToAttached )
  923. {
  924. if ( m_constraintType != CONSTRAINT_RAGDOLL )
  925. return;
  926. hk_Transform os_ks_0, os_ks_1;
  927. ConvertHLLocalMatrixToHavanaLocal( constraintToReference, os_ks_0 );
  928. ConvertHLLocalMatrixToHavanaLocal( constraintToAttached, os_ks_1 );
  929. hk_Ragdoll_Constraint *pConstraint = (hk_Ragdoll_Constraint *)GetRealConstraint();
  930. pConstraint->update_transforms( os_ks_0, os_ks_1 );
  931. }
  932. bool CPhysicsConstraint::GetConstraintTransform( matrix3x4_t *pConstraintToReference, matrix3x4_t *pConstraintToAttached ) const
  933. {
  934. if ( m_constraintType == CONSTRAINT_RAGDOLL )
  935. {
  936. hk_Ragdoll_Constraint *pConstraint = (hk_Ragdoll_Constraint *)GetRealConstraint();
  937. if ( pConstraintToReference )
  938. {
  939. ConvertHavanaLocalMatrixToHL( pConstraint->get_transform(0), *pConstraintToReference, NULL );
  940. }
  941. if ( pConstraintToAttached )
  942. {
  943. ConvertHavanaLocalMatrixToHL( pConstraint->get_transform(1), *pConstraintToAttached, NULL );
  944. }
  945. return true;
  946. }
  947. else if ( m_constraintType == CONSTRAINT_BALLSOCKET )
  948. {
  949. hk_Ball_Socket_Constraint *pConstraint = (hk_Ball_Socket_Constraint *)GetRealConstraint();
  950. Vector pos;
  951. if ( pConstraintToReference )
  952. {
  953. ConvertPositionToHL( pConstraint->get_transform(0), pos );
  954. AngleMatrix( vec3_angle, pos, *pConstraintToReference );
  955. }
  956. if ( pConstraintToAttached )
  957. {
  958. ConvertPositionToHL( pConstraint->get_transform(1), pos );
  959. AngleMatrix( vec3_angle, pos, *pConstraintToAttached );
  960. }
  961. return true;
  962. }
  963. else if ( m_constraintType == CONSTRAINT_FIXED )
  964. {
  965. hk_Fixed_Constraint *pConstraint = (hk_Fixed_Constraint *)GetRealConstraint();
  966. if ( pConstraintToReference )
  967. {
  968. ConvertHavanaLocalMatrixToHL( pConstraint->get_transform(0), *pConstraintToReference, NULL );
  969. }
  970. if ( pConstraintToAttached )
  971. {
  972. ConvertHavanaLocalMatrixToHL( pConstraint->get_transform(1), *pConstraintToAttached, NULL );
  973. }
  974. return true;
  975. }
  976. return false;
  977. }
  978. // header.pGroup is optionally NULL, all other fields must be valid!
  979. static bool IsValidConstraint( const vphysics_save_cphysicsconstraint_t &header )
  980. {
  981. if ( header.constraintType != CONSTRAINT_UNKNOWN && header.pObjAttached && header.pObjReference )
  982. return true;
  983. return false;
  984. }
  985. bool CPhysicsConstraint::GetConstraintParams( constraint_breakableparams_t *pParams ) const
  986. {
  987. if ( !pParams )
  988. return false;
  989. vphysics_save_cphysicsconstraint_t header;
  990. vphysics_save_constraint_t constraintTemplate;
  991. memset( &header, 0, sizeof(header) );
  992. memset( &constraintTemplate, 0, sizeof(constraintTemplate) );
  993. WriteToTemplate( header, constraintTemplate );
  994. if ( IsValidConstraint( header ) )
  995. {
  996. switch ( header.constraintType )
  997. {
  998. case CONSTRAINT_UNKNOWN:
  999. break;
  1000. case CONSTRAINT_HINGE:
  1001. *pParams = constraintTemplate.hinge.constraint;
  1002. return true;
  1003. case CONSTRAINT_FIXED:
  1004. *pParams = constraintTemplate.fixed.constraint;
  1005. return true;
  1006. case CONSTRAINT_SLIDING:
  1007. *pParams = constraintTemplate.sliding.constraint;
  1008. return true;
  1009. case CONSTRAINT_PULLEY:
  1010. *pParams = constraintTemplate.pulley.constraint;
  1011. return true;
  1012. case CONSTRAINT_LENGTH:
  1013. *pParams = constraintTemplate.length.constraint;
  1014. return true;
  1015. case CONSTRAINT_BALLSOCKET:
  1016. *pParams = constraintTemplate.ballsocket.constraint;
  1017. return true;
  1018. case CONSTRAINT_RAGDOLL:
  1019. *pParams = constraintTemplate.ragdoll.constraint;
  1020. return true;
  1021. }
  1022. }
  1023. return false;
  1024. }
  1025. CPhysicsConstraintGroup *CPhysicsConstraint::GetConstraintGroup() const
  1026. {
  1027. if ( !m_HkConstraint )
  1028. return NULL;
  1029. hk_Local_Constraint_System *plcs = m_HkConstraint->get_constraint_system();
  1030. Assert(plcs);
  1031. return (CPhysicsConstraintGroup *)plcs->get_client_data();
  1032. }
  1033. void CPhysicsConstraint::ReadBreakableConstraint( constraint_breakableparams_t &params ) const
  1034. {
  1035. if ( m_isBreakable )
  1036. {
  1037. hk_Breakable_Constraint_BP bp;
  1038. ((hk_Breakable_Constraint *)m_HkConstraint)->write_to_blueprint( &bp );
  1039. params.forceLimit = ConvertDistanceToHL( bp.m_linear_strength );
  1040. params.torqueLimit = RAD2DEG( bp.m_angular_strength );
  1041. params.strength = 1.0;
  1042. params.bodyMassScale[0] = bp.m_bodyMassScale[0];
  1043. params.bodyMassScale[1] = bp.m_bodyMassScale[1];
  1044. //Assert( m_HkLCS != NULL ); // this is allowed now although breaking inside an LCS won't work yet
  1045. }
  1046. else
  1047. {
  1048. params.Defaults();
  1049. }
  1050. if ( m_HkLCS )
  1051. {
  1052. params.isActive = m_HkLCS->is_active();
  1053. }
  1054. }
  1055. void CPhysicsConstraint::WriteFixed( constraint_fixedparams_t &fixed ) const
  1056. {
  1057. hk_Fixed_Constraint *pConstraint = (hk_Fixed_Constraint *)GetRealConstraint();
  1058. ReadBreakableConstraint( fixed.constraint );
  1059. hk_Fixed_BP fixed_bp;
  1060. pConstraint->write_to_blueprint( &fixed_bp );
  1061. // save fixed bp into params
  1062. ConvertHavanaLocalMatrixToHL( fixed_bp.m_transform_os_ks, fixed.attachedRefXform, m_pObjReference->GetObject() );
  1063. }
  1064. void CPhysicsConstraint::WriteRagdoll( constraint_ragdollparams_t &ragdoll ) const
  1065. {
  1066. hk_Ragdoll_Constraint *pConstraint = (hk_Ragdoll_Constraint *)GetRealConstraint();
  1067. ReadBreakableConstraint( ragdoll.constraint );
  1068. hk_Ragdoll_Constraint_BP ragdoll_bp;
  1069. // BUGBUG: Write this and figure out how to recreate
  1070. // or change init func to setup this bp directly
  1071. pConstraint->write_to_blueprint( &ragdoll_bp );
  1072. ConvertHavanaLocalMatrixToHL( ragdoll_bp.m_transform_os_ks[0], ragdoll.constraintToReference, m_pObjReference->GetObject() );
  1073. ConvertHavanaLocalMatrixToHL( ragdoll_bp.m_transform_os_ks[1], ragdoll.constraintToAttached, m_pObjAttached->GetObject() );
  1074. int revAxisMapHK[3];
  1075. revAxisMapHK[ragdoll_bp.m_axisMap[0]] = 0;
  1076. revAxisMapHK[ragdoll_bp.m_axisMap[1]] = 1;
  1077. revAxisMapHK[ragdoll_bp.m_axisMap[2]] = 2;
  1078. for ( int i = 0; i < 3; i ++ )
  1079. {
  1080. constraint_axislimit_t &ragdollAxis = ragdoll.axes[i];
  1081. int ivpAxis = ConvertCoordinateAxisToIVP( i );
  1082. int hkAxis = revAxisMapHK[ ivpAxis ];
  1083. hk_Constraint_Limit_BP &bpAxis = ragdoll_bp.m_limits[ hkAxis ];
  1084. ragdollAxis.angularVelocity = RAD2DEG(bpAxis.m_desired_velocity);
  1085. ragdollAxis.torque = bpAxis.m_joint_friction * m_pObjReference->GetInvMass();
  1086. // X&Y
  1087. if ( i != 2 )
  1088. {
  1089. ragdollAxis.minRotation = RAD2DEG(bpAxis.m_limit_min);
  1090. ragdollAxis.maxRotation = RAD2DEG(bpAxis.m_limit_max);
  1091. }
  1092. // Z
  1093. else
  1094. {
  1095. ragdollAxis.minRotation = -RAD2DEG(bpAxis.m_limit_max);
  1096. ragdollAxis.maxRotation = -RAD2DEG(bpAxis.m_limit_min);
  1097. }
  1098. }
  1099. ragdoll.childIndex = -1;
  1100. ragdoll.parentIndex = -1;
  1101. ragdoll.isActive = true;
  1102. ragdoll.onlyAngularLimits = ragdoll_bp.m_constrainTranslation ? false : true;
  1103. ragdoll.useClockwiseRotations = false;
  1104. }
  1105. void CPhysicsConstraint::WriteHinge( constraint_hingeparams_t &hinge ) const
  1106. {
  1107. hk_Hinge_Constraint *pConstraint = (hk_Hinge_Constraint *)GetRealConstraint();
  1108. ReadBreakableConstraint( hinge.constraint );
  1109. hk_Hinge_BP hinge_bp;
  1110. pConstraint->write_to_blueprint( &hinge_bp );
  1111. // save hinge bp into params
  1112. hinge.worldPosition = TransformHavanaLocalToHLWorld( hinge_bp.m_axis_os[0].get_origin(), m_pObjReference->GetObject(), true );
  1113. hinge.worldAxisDirection = TransformHavanaLocalToHLWorld( hinge_bp.m_axis_os[0].get_direction(), m_pObjReference->GetObject(), false );
  1114. hinge.hingeAxis.SetAxisFriction( 0,0,0 );
  1115. if ( hinge_bp.m_limit.m_limit_is_enabled )
  1116. {
  1117. hinge.hingeAxis.minRotation = RAD2DEG(hinge_bp.m_limit.m_limit_min);
  1118. hinge.hingeAxis.maxRotation = RAD2DEG(hinge_bp.m_limit.m_limit_max);
  1119. }
  1120. if ( hinge_bp.m_limit.m_friction_is_enabled )
  1121. {
  1122. hinge.hingeAxis.angularVelocity = RAD2DEG(hinge_bp.m_limit.m_desired_velocity);
  1123. hinge.hingeAxis.torque = RAD2DEG(hinge_bp.m_limit.m_joint_friction);
  1124. }
  1125. }
  1126. void CPhysicsConstraint::WriteSliding( constraint_slidingparams_t &sliding ) const
  1127. {
  1128. sliding.Defaults();
  1129. hk_Prismatic_Constraint *pConstraint = (hk_Prismatic_Constraint *)GetRealConstraint();
  1130. ReadBreakableConstraint( sliding.constraint );
  1131. hk_Prismatic_BP prismatic_bp;
  1132. pConstraint->write_to_blueprint( &prismatic_bp );
  1133. // save bp into params
  1134. hk_Transform t;
  1135. t.set_translation( prismatic_bp.m_transform_Ros_Aos.m_translation );
  1136. t.set_rotation( prismatic_bp.m_transform_Ros_Aos.m_rotation );
  1137. ConvertHavanaLocalMatrixToHL( t, sliding.attachedRefXform, m_pObjReference->GetObject() );
  1138. if ( prismatic_bp.m_limit.m_friction_is_enabled )
  1139. {
  1140. sliding.friction = ConvertDistanceToHL( prismatic_bp.m_limit.m_joint_friction );
  1141. sliding.velocity = ConvertDistanceToHL( prismatic_bp.m_limit.m_desired_velocity );
  1142. }
  1143. if ( prismatic_bp.m_limit.m_limit_is_enabled )
  1144. {
  1145. sliding.limitMin = ConvertDistanceToHL( prismatic_bp.m_limit.m_limit_min );
  1146. sliding.limitMax = ConvertDistanceToHL( prismatic_bp.m_limit.m_limit_max );
  1147. }
  1148. ConvertDirectionToHL( prismatic_bp.m_axis_Ros, sliding.slideAxisRef );
  1149. }
  1150. void CPhysicsConstraint::WritePulley( constraint_pulleyparams_t &pulley ) const
  1151. {
  1152. pulley.Defaults();
  1153. hk_Pulley_Constraint *pConstraint = (hk_Pulley_Constraint *)GetRealConstraint();
  1154. ReadBreakableConstraint( pulley.constraint );
  1155. hk_Pulley_BP pulley_bp;
  1156. pConstraint->write_to_blueprint( &pulley_bp );
  1157. // save bp into params
  1158. for ( int i = 0; i < 2; i++ )
  1159. {
  1160. ConvertPositionToHL( pulley_bp.m_worldspace_point[i], pulley.pulleyPosition[i] );
  1161. ConvertPositionToHL( pulley_bp.m_translation_os_ks[i], pulley.objectPosition[i] );
  1162. }
  1163. pulley.gearRatio = pulley_bp.m_gearing;
  1164. pulley.totalLength = ConvertDistanceToHL(pulley_bp.m_length);
  1165. pulley.isRigid = pulley_bp.m_is_rigid;
  1166. }
  1167. void CPhysicsConstraint::WriteLength( constraint_lengthparams_t &length ) const
  1168. {
  1169. length.Defaults();
  1170. hk_Stiff_Spring_Constraint *pConstraint = (hk_Stiff_Spring_Constraint *)GetRealConstraint();
  1171. ReadBreakableConstraint( length.constraint );
  1172. hk_Stiff_Spring_BP stiff_bp;
  1173. pConstraint->write_to_blueprint( &stiff_bp );
  1174. // save bp into params
  1175. for ( int i = 0; i < 2; i++ )
  1176. {
  1177. ConvertPositionToHL( stiff_bp.m_translation_os_ks[i], length.objectPosition[i] );
  1178. }
  1179. length.totalLength = ConvertDistanceToHL(stiff_bp.m_length);
  1180. length.minLength = ConvertDistanceToHL(stiff_bp.m_min_length);
  1181. }
  1182. void CPhysicsConstraint::WriteBallsocket( constraint_ballsocketparams_t &ballsocket ) const
  1183. {
  1184. ballsocket.Defaults();
  1185. hk_Ball_Socket_Constraint *pConstraint = (hk_Ball_Socket_Constraint *)GetRealConstraint();
  1186. ReadBreakableConstraint( ballsocket.constraint );
  1187. hk_Ball_Socket_BP ballsocket_bp;
  1188. pConstraint->write_to_blueprint( &ballsocket_bp );
  1189. // save bp into params
  1190. for ( int i = 0; i < 2; i++ )
  1191. {
  1192. ConvertPositionToHL( ballsocket_bp.m_translation_os_ks[i], ballsocket.constraintPosition[i] );
  1193. }
  1194. }
  1195. void CPhysicsConstraint::DetachListener()
  1196. {
  1197. if ( !(m_pObjReference->CallbackFlags() & CALLBACK_NEVER_DELETED) )
  1198. {
  1199. m_pObjReference->GetObject()->remove_listener_object( this );
  1200. }
  1201. if ( !(m_pObjAttached->CallbackFlags() & CALLBACK_NEVER_DELETED) )
  1202. {
  1203. m_pObjAttached->GetObject()->remove_listener_object( this );
  1204. }
  1205. m_pObjReference = NULL;
  1206. m_pObjAttached = NULL;
  1207. }
  1208. void CPhysicsConstraint::event_object_deleted( IVP_Event_Object *pEvent )
  1209. {
  1210. if ( m_HkLCS && pEvent->real_object->get_core()->physical_unmoveable )
  1211. {
  1212. // HACKHACK: This makes the behavior consistent
  1213. m_HkLCS->core_is_going_to_be_deleted_event( pEvent->real_object->get_core() );
  1214. }
  1215. DetachListener();
  1216. // the underlying constraint is no longer valid, delete it.
  1217. delete m_HkConstraint;
  1218. m_HkConstraint = NULL;
  1219. delete m_HkLCS;
  1220. m_HkLCS = NULL;
  1221. if ( pEvent->environment )
  1222. {
  1223. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)pEvent->environment->client_data;
  1224. pEnvironment->NotifyConstraintDisabled( this );
  1225. }
  1226. }
  1227. CPhysicsConstraint::~CPhysicsConstraint( void )
  1228. {
  1229. // arg. There should be a better way to do this
  1230. if ( m_HkConstraint || m_HkLCS )
  1231. {
  1232. DetachListener();
  1233. delete m_HkLCS;
  1234. delete m_HkConstraint;
  1235. }
  1236. }
  1237. void CPhysicsConstraint::Activate( void )
  1238. {
  1239. if ( m_HkLCS )
  1240. {
  1241. m_HkLCS->activate();
  1242. }
  1243. }
  1244. void CPhysicsConstraint::Deactivate( void )
  1245. {
  1246. if ( m_HkLCS )
  1247. {
  1248. m_HkLCS->deactivate();
  1249. }
  1250. }
  1251. void CPhysicsConstraint::SetupRagdollAxis( int axis, const constraint_axislimit_t &axisData, hk_Limited_Ball_Socket_BP *ballsocketBP )
  1252. {
  1253. // X & Y
  1254. if ( axis != 2 )
  1255. {
  1256. ballsocketBP->m_angular_limits[ ConvertCoordinateAxisToIVP(axis) ].set( DEG2RAD(axisData.minRotation), DEG2RAD(axisData.maxRotation) );
  1257. }
  1258. // Z
  1259. else
  1260. {
  1261. ballsocketBP->m_angular_limits[ ConvertCoordinateAxisToIVP(axis) ].set( DEG2RAD(-axisData.maxRotation), DEG2RAD(-axisData.minRotation) );
  1262. }
  1263. }
  1264. // UNDONE: Keep this around to clip "includeStatic" code
  1265. #if 0
  1266. void CPhysicsConstraint::SetBreakLimit( float breakLimitForce, float breakLimitTorque, bool includeStatic )
  1267. {
  1268. float factor = ConvertDistanceToIVP( 1.0f );
  1269. // convert to ivp
  1270. IVP_Environment *pEnvironment = m_pConstraint->get_associated_controlled_cores()->element_at(0)->environment;
  1271. float gravity = pEnvironment->get_gravity()->real_length();
  1272. breakLimitTorque = breakLimitTorque * gravity * factor; // proportional to distance
  1273. breakLimitForce = breakLimitForce * gravity;
  1274. if ( breakLimitForce != 0 )
  1275. {
  1276. if ( includeStatic )
  1277. {
  1278. breakLimitForce += m_pObjAttached->GetMass() * gravity * pEnvironment->get_delta_PSI_time();
  1279. }
  1280. m_pConstraint->change_max_translation_impulse( IVP_CFE_BREAK, breakLimitForce );
  1281. }
  1282. else
  1283. {
  1284. m_pConstraint->change_max_translation_impulse( IVP_CFE_NONE, 0 );
  1285. }
  1286. if ( breakLimitTorque != 0 )
  1287. {
  1288. if ( includeStatic )
  1289. {
  1290. const IVP_U_Point *massCenter = m_pObjAttached->GetObject()->get_core()->get_position_PSI();
  1291. IVP_U_Point tmp;
  1292. tmp.set( massCenter );
  1293. tmp.subtract( &m_constraintOrigin );
  1294. float dist = tmp.real_length();
  1295. breakLimitTorque += (m_pObjAttached->GetMass() * gravity * dist * pEnvironment->get_delta_PSI_time());
  1296. }
  1297. m_pConstraint->change_max_rotation_impulse( IVP_CFE_BREAK, breakLimitTorque );
  1298. }
  1299. else
  1300. {
  1301. m_pConstraint->change_max_rotation_impulse( IVP_CFE_NONE, 0 );
  1302. }
  1303. }
  1304. #endif
  1305. IPhysicsObject *CPhysicsConstraint::GetReferenceObject( void ) const
  1306. {
  1307. return m_pObjReference;
  1308. }
  1309. IPhysicsObject *CPhysicsConstraint::GetAttachedObject( void ) const
  1310. {
  1311. return m_pObjAttached;
  1312. }
  1313. void SeedRandomGenerators()
  1314. {
  1315. ivp_srand(1);
  1316. hk_Math::srand01('h'+'a'+'v'+'o'+'k');
  1317. qh_RANDOMseed_(1);
  1318. }
  1319. extern int ivp_srand_read(void);
  1320. void ReadRandom( int buffer[4] )
  1321. {
  1322. buffer[0] = (int)hk_Math::hk_random_seed;
  1323. buffer[1] = ivp_srand_read();
  1324. }
  1325. void WriteRandom( int buffer[4] )
  1326. {
  1327. hk_Math::srand01((unsigned int)buffer[0]);
  1328. ivp_srand(buffer[1]);
  1329. }
  1330. IPhysicsConstraint *GetClientDataForHkConstraint( class hk_Breakable_Constraint *pHkConstraint )
  1331. {
  1332. return static_cast<CPhysicsConstraint *>( pHkConstraint->get_client_data() );
  1333. }
  1334. // Create a container for a group of constraints
  1335. IPhysicsConstraintGroup *CreatePhysicsConstraintGroup( IVP_Environment *pEnvironment, const constraint_groupparams_t &group )
  1336. {
  1337. MEM_ALLOC_CREDIT();
  1338. return new CPhysicsConstraintGroup( pEnvironment, group );
  1339. }
  1340. IPhysicsConstraint *CreateRagdollConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ragdollparams_t &ragdoll )
  1341. {
  1342. MEM_ALLOC_CREDIT();
  1343. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1344. pConstraint->InitRagdoll( pEnvironment, (CPhysicsConstraintGroup *)pGroup, ragdoll );
  1345. return pConstraint;
  1346. }
  1347. IPhysicsConstraint *CreateHingeConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_limitedhingeparams_t &hinge )
  1348. {
  1349. MEM_ALLOC_CREDIT();
  1350. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1351. pConstraint->InitHinge( pEnvironment, (CPhysicsConstraintGroup *)pGroup, hinge );
  1352. return pConstraint;
  1353. }
  1354. IPhysicsConstraint *CreateFixedConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_fixedparams_t &fixed )
  1355. {
  1356. MEM_ALLOC_CREDIT();
  1357. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1358. pConstraint->InitFixed( pEnvironment, (CPhysicsConstraintGroup *)pGroup, fixed );
  1359. return pConstraint;
  1360. }
  1361. IPhysicsConstraint *CreateSlidingConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_slidingparams_t &sliding )
  1362. {
  1363. MEM_ALLOC_CREDIT();
  1364. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1365. pConstraint->InitSliding( pEnvironment, (CPhysicsConstraintGroup *)pGroup, sliding );
  1366. return pConstraint;
  1367. }
  1368. IPhysicsConstraint *CreateBallsocketConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ballsocketparams_t &ballsocket )
  1369. {
  1370. MEM_ALLOC_CREDIT();
  1371. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1372. pConstraint->InitBallsocket( pEnvironment, (CPhysicsConstraintGroup *)pGroup, ballsocket );
  1373. return pConstraint;
  1374. }
  1375. IPhysicsConstraint *CreatePulleyConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_pulleyparams_t &pulley )
  1376. {
  1377. MEM_ALLOC_CREDIT();
  1378. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1379. pConstraint->InitPulley( pEnvironment, (CPhysicsConstraintGroup *)pGroup, pulley );
  1380. return pConstraint;
  1381. }
  1382. IPhysicsConstraint *CreateLengthConstraint( IVP_Environment *pEnvironment, CPhysicsObject *pReferenceObject, CPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_lengthparams_t &length )
  1383. {
  1384. MEM_ALLOC_CREDIT();
  1385. CPhysicsConstraint *pConstraint = new CPhysicsConstraint( pReferenceObject, pAttachedObject );
  1386. pConstraint->InitLength( pEnvironment, (CPhysicsConstraintGroup *)pGroup, length );
  1387. return pConstraint;
  1388. }
  1389. bool IsExternalConstraint( IVP_Controller *pLCS, void *pGameData )
  1390. {
  1391. IVP_U_Vector<IVP_Core> *pCores = pLCS->get_associated_controlled_cores();
  1392. if ( pCores )
  1393. {
  1394. for ( int i = 0; i < pCores->n_elems; i++ )
  1395. {
  1396. if ( pCores->element_at(i) )
  1397. {
  1398. IVP_Real_Object *pivp = pCores->element_at(i)->objects.element_at(0);
  1399. if ( pivp)
  1400. {
  1401. IPhysicsObject *pObject = static_cast<IPhysicsObject *>(pivp->client_data);
  1402. if ( pObject && pObject->GetGameData() != pGameData )
  1403. return true;
  1404. }
  1405. }
  1406. }
  1407. }
  1408. return false;
  1409. }
  1410. bool SavePhysicsConstraint( const physsaveparams_t &params, CPhysicsConstraint *pConstraint )
  1411. {
  1412. vphysics_save_cphysicsconstraint_t header;
  1413. vphysics_save_constraint_t constraintTemplate;
  1414. memset( &header, 0, sizeof(header) );
  1415. memset( &constraintTemplate, 0, sizeof(constraintTemplate) );
  1416. pConstraint->WriteToTemplate( header, constraintTemplate );
  1417. params.pSave->WriteAll( &header );
  1418. if ( IsValidConstraint( header ) )
  1419. {
  1420. switch ( header.constraintType )
  1421. {
  1422. case CONSTRAINT_UNKNOWN:
  1423. Assert(0);
  1424. break;
  1425. case CONSTRAINT_HINGE:
  1426. params.pSave->WriteAll( &constraintTemplate.hinge );
  1427. break;
  1428. case CONSTRAINT_FIXED:
  1429. params.pSave->WriteAll( &constraintTemplate.fixed );
  1430. break;
  1431. case CONSTRAINT_SLIDING:
  1432. params.pSave->WriteAll( &constraintTemplate.sliding );
  1433. break;
  1434. case CONSTRAINT_PULLEY:
  1435. params.pSave->WriteAll( &constraintTemplate.pulley );
  1436. break;
  1437. case CONSTRAINT_LENGTH:
  1438. params.pSave->WriteAll( &constraintTemplate.length );
  1439. break;
  1440. case CONSTRAINT_BALLSOCKET:
  1441. params.pSave->WriteAll( &constraintTemplate.ballsocket );
  1442. break;
  1443. case CONSTRAINT_RAGDOLL:
  1444. params.pSave->WriteAll( &constraintTemplate.ragdoll );
  1445. break;
  1446. }
  1447. return true;
  1448. }
  1449. // inert constraint, just save header
  1450. return true;
  1451. }
  1452. bool RestorePhysicsConstraint( const physrestoreparams_t &params, CPhysicsConstraint **ppConstraint )
  1453. {
  1454. vphysics_save_cphysicsconstraint_t header;
  1455. memset( &header, 0, sizeof(header) );
  1456. params.pRestore->ReadAll( &header );
  1457. if ( IsValidConstraint( header ) )
  1458. {
  1459. switch ( header.constraintType )
  1460. {
  1461. case CONSTRAINT_UNKNOWN:
  1462. Assert(0);
  1463. break;
  1464. case CONSTRAINT_HINGE:
  1465. {
  1466. vphysics_save_constrainthinge_t hinge;
  1467. memset( &hinge, 0, sizeof(hinge) );
  1468. params.pRestore->ReadAll( &hinge );
  1469. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1470. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreateHingeConstraint( header.pObjReference, header.pObjAttached, header.pGroup, hinge );
  1471. }
  1472. break;
  1473. case CONSTRAINT_FIXED:
  1474. {
  1475. vphysics_save_constraintfixed_t fixed;
  1476. memset( &fixed, 0, sizeof(fixed) );
  1477. params.pRestore->ReadAll( &fixed );
  1478. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1479. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreateFixedConstraint( header.pObjReference, header.pObjAttached, header.pGroup, fixed );
  1480. }
  1481. break;
  1482. case CONSTRAINT_SLIDING:
  1483. {
  1484. vphysics_save_constraintsliding_t sliding;
  1485. memset( &sliding, 0, sizeof(sliding) );
  1486. params.pRestore->ReadAll( &sliding );
  1487. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1488. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreateSlidingConstraint( header.pObjReference, header.pObjAttached, header.pGroup, sliding );
  1489. }
  1490. break;
  1491. case CONSTRAINT_PULLEY:
  1492. {
  1493. vphysics_save_constraintpulley_t pulley;
  1494. memset( &pulley, 0, sizeof(pulley) );
  1495. params.pRestore->ReadAll( &pulley );
  1496. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1497. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreatePulleyConstraint( header.pObjReference, header.pObjAttached, header.pGroup, pulley );
  1498. }
  1499. break;
  1500. case CONSTRAINT_LENGTH:
  1501. {
  1502. vphysics_save_constraintlength_t length;
  1503. memset( &length, 0, sizeof(length) );
  1504. params.pRestore->ReadAll( &length );
  1505. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1506. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreateLengthConstraint( header.pObjReference, header.pObjAttached, header.pGroup, length );
  1507. }
  1508. break;
  1509. case CONSTRAINT_BALLSOCKET:
  1510. {
  1511. vphysics_save_constraintballsocket_t ballsocket;
  1512. memset( &ballsocket, 0, sizeof(ballsocket) );
  1513. params.pRestore->ReadAll( &ballsocket );
  1514. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1515. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreateBallsocketConstraint( header.pObjReference, header.pObjAttached, header.pGroup, ballsocket );
  1516. }
  1517. break;
  1518. case CONSTRAINT_RAGDOLL:
  1519. {
  1520. vphysics_save_constraintragdoll_t ragdoll;
  1521. memset( &ragdoll, 0, sizeof(ragdoll) );
  1522. params.pRestore->ReadAll( &ragdoll );
  1523. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1524. *ppConstraint = (CPhysicsConstraint *)pEnvironment->CreateRagdollConstraint( header.pObjReference, header.pObjAttached, header.pGroup, ragdoll );
  1525. }
  1526. break;
  1527. }
  1528. if ( *ppConstraint )
  1529. {
  1530. (*ppConstraint)->SetGameData( params.pGameData );
  1531. }
  1532. return true;
  1533. }
  1534. // inert constraint, create an empty shell
  1535. *ppConstraint = new CPhysicsConstraint( NULL, NULL );
  1536. return true;
  1537. }
  1538. bool SavePhysicsConstraintGroup( const physsaveparams_t &params, CPhysicsConstraintGroup *pConstraintGroup )
  1539. {
  1540. vphysics_save_cphysicsconstraintgroup_t groupTemplate;
  1541. memset( &groupTemplate, 0, sizeof(groupTemplate) );
  1542. pConstraintGroup->WriteToTemplate( groupTemplate );
  1543. params.pSave->WriteAll( &groupTemplate );
  1544. return true;
  1545. }
  1546. bool RestorePhysicsConstraintGroup( const physrestoreparams_t &params, CPhysicsConstraintGroup **ppConstraintGroup )
  1547. {
  1548. vphysics_save_cphysicsconstraintgroup_t groupTemplate;
  1549. memset( &groupTemplate, 0, sizeof(groupTemplate) );
  1550. params.pRestore->ReadAll( &groupTemplate );
  1551. if ( groupTemplate.errorTolerance == 0.0f && groupTemplate.minErrorTicks == 0 )
  1552. {
  1553. constraint_groupparams_t tmp;
  1554. tmp.Defaults();
  1555. groupTemplate.minErrorTicks = tmp.minErrorTicks;
  1556. groupTemplate.errorTolerance = tmp.errorTolerance;
  1557. }
  1558. CPhysicsEnvironment *pEnvironment = (CPhysicsEnvironment *)params.pEnvironment;
  1559. *ppConstraintGroup = (CPhysicsConstraintGroup *)pEnvironment->CreateConstraintGroup( groupTemplate );
  1560. if ( *ppConstraintGroup && groupTemplate.isActive )
  1561. {
  1562. g_ConstraintGroupActivateList.AddToTail( *ppConstraintGroup );
  1563. }
  1564. return true;
  1565. }
  1566. void PostRestorePhysicsConstraintGroup()
  1567. {
  1568. MEM_ALLOC_CREDIT();
  1569. for ( int i = 0; i < g_ConstraintGroupActivateList.Count(); i++ )
  1570. {
  1571. g_ConstraintGroupActivateList[i]->Activate();
  1572. }
  1573. g_ConstraintGroupActivateList.Purge();
  1574. }