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.

333 lines
9.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifdef _WIN32
  9. #pragma warning (disable:4127)
  10. #pragma warning (disable:4244)
  11. #endif
  12. #include "cbase.h"
  13. #include "ivp_controller.hxx"
  14. #include "physics_motioncontroller.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. struct vphysics_save_motioncontroller_t
  18. {
  19. CUtlVector<IPhysicsObject *> m_objectList;
  20. int m_nPriority;
  21. DECLARE_SIMPLE_DATADESC();
  22. };
  23. BEGIN_SIMPLE_DATADESC( vphysics_save_motioncontroller_t )
  24. DEFINE_VPHYSPTR_UTLVECTOR( m_objectList ),
  25. DEFINE_FIELD( m_nPriority, FIELD_INTEGER ),
  26. END_DATADESC()
  27. class CPhysicsMotionController : public IVP_Controller_Independent, public IPhysicsMotionController
  28. {
  29. public:
  30. CPhysicsMotionController( IMotionEvent *pHandler, CPhysicsEnvironment *pVEnv );
  31. virtual ~CPhysicsMotionController( void );
  32. virtual void do_simulation_controller(IVP_Event_Sim *event,IVP_U_Vector<IVP_Core> *core_list);
  33. virtual IVP_CONTROLLER_PRIORITY get_controller_priority();
  34. virtual void core_is_going_to_be_deleted_event(IVP_Core *core)
  35. {
  36. m_coreList.FindAndRemove( core );
  37. }
  38. virtual const char *get_controller_name() { return "vphysics:motion"; }
  39. virtual void SetEventHandler( IMotionEvent *handler );
  40. virtual void AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached );
  41. virtual void DetachObject( IPhysicsObject *pObject );
  42. void RemoveCore( IVP_Core *pCore );
  43. // Save/load
  44. void WriteToTemplate( vphysics_save_motioncontroller_t &controllerTemplate );
  45. void InitFromTemplate( const vphysics_save_motioncontroller_t &controllerTemplate );
  46. // returns the number of objects currently attached to the controller
  47. virtual int CountObjects( void )
  48. {
  49. return m_coreList.Count();
  50. }
  51. // NOTE: pObjectList is an array with at least CountObjects() allocated
  52. virtual void GetObjects( IPhysicsObject **pObjectList )
  53. {
  54. for ( int i = 0; i < m_coreList.Count(); i++ )
  55. {
  56. IVP_Core *pCore = m_coreList[i];
  57. IVP_Real_Object *pivp = pCore->objects.element_at(0);
  58. IPhysicsObject *pPhys = static_cast<IPhysicsObject *>(pivp->client_data);
  59. // copy out
  60. pObjectList[i] = pPhys;
  61. }
  62. }
  63. // detaches all attached objects
  64. virtual void ClearObjects( void )
  65. {
  66. while ( m_coreList.Count() )
  67. {
  68. int x = m_coreList.Count()-1;
  69. IVP_Core *pCore = m_coreList[x];
  70. RemoveCore( pCore );
  71. }
  72. }
  73. // wakes up all attached objects
  74. virtual void WakeObjects( void )
  75. {
  76. for ( int i = 0; i < m_coreList.Count(); i++ )
  77. {
  78. IVP_Core *pCore = m_coreList[i];
  79. pCore->ensure_core_to_be_in_simulation();
  80. }
  81. }
  82. virtual void SetPriority( priority_t priority );
  83. private:
  84. IMotionEvent *m_handler;
  85. CUtlVector<IVP_Core *> m_coreList;
  86. CPhysicsEnvironment *m_pVEnv;
  87. int m_priority;
  88. };
  89. CPhysicsMotionController::CPhysicsMotionController( IMotionEvent *pHandler, CPhysicsEnvironment *pVEnv )
  90. {
  91. m_handler = pHandler;
  92. m_pVEnv = pVEnv;
  93. SetPriority( MEDIUM_PRIORITY );
  94. }
  95. CPhysicsMotionController::~CPhysicsMotionController( void )
  96. {
  97. Assert( !m_pVEnv->IsInSimulation() );
  98. for ( int i = 0; i < m_coreList.Count(); i++ )
  99. {
  100. m_coreList[i]->rem_core_controller( (IVP_Controller *)this );
  101. }
  102. }
  103. void CPhysicsMotionController::do_simulation_controller(IVP_Event_Sim *event,IVP_U_Vector<IVP_Core> *core_list)
  104. {
  105. if ( m_handler )
  106. {
  107. for ( int i = 0; i < core_list->len(); i++ )
  108. {
  109. IVP_U_Float_Point ivpSpeed, ivpRot;
  110. IVP_Core *pCore = core_list->element_at(i);
  111. IVP_Real_Object *pivp = pCore->objects.element_at(0);
  112. IPhysicsObject *pPhys = static_cast<IPhysicsObject *>(pivp->client_data);
  113. if ( !pPhys->IsMoveable() )
  114. continue;
  115. Vector speed;
  116. AngularImpulse rot;
  117. speed.Init();
  118. rot.Init();
  119. IMotionEvent::simresult_e ret = m_handler->Simulate( this, pPhys, event->delta_time, speed, rot );
  120. switch( ret )
  121. {
  122. case IMotionEvent::SIM_NOTHING:
  123. break;
  124. case IMotionEvent::SIM_LOCAL_ACCELERATION:
  125. {
  126. ConvertForceImpulseToIVP( speed, ivpSpeed );
  127. ConvertAngularImpulseToIVP( rot, ivpRot );
  128. const IVP_U_Matrix *m_world_f_core = pCore->get_m_world_f_core_PSI();
  129. // transform to world space
  130. m_world_f_core->inline_vmult3( &ivpSpeed, &ivpSpeed );
  131. // UNDONE: Put these values into speed change / rot_speed_change instead?
  132. pCore->speed.add_multiple( &ivpSpeed, event->delta_time );
  133. pCore->rot_speed.add_multiple( &ivpRot, event->delta_time );
  134. }
  135. break;
  136. case IMotionEvent::SIM_LOCAL_FORCE:
  137. {
  138. ConvertForceImpulseToIVP( speed, ivpSpeed );
  139. ConvertAngularImpulseToIVP( rot, ivpRot );
  140. const IVP_U_Matrix *m_world_f_core = pCore->get_m_world_f_core_PSI();
  141. // transform to world space
  142. m_world_f_core->inline_vmult3( &ivpSpeed, &ivpSpeed );
  143. pCore->center_push_core_multiple_ws( &ivpSpeed, event->delta_time );
  144. pCore->rot_push_core_multiple_cs( &ivpRot, event->delta_time );
  145. }
  146. break;
  147. case IMotionEvent::SIM_GLOBAL_ACCELERATION:
  148. {
  149. ConvertAngularImpulseToIVP( rot, ivpRot );
  150. ConvertForceImpulseToIVP( speed, ivpSpeed );
  151. pCore->speed.add_multiple( &ivpSpeed, event->delta_time );
  152. pCore->rot_speed.add_multiple( &ivpRot, event->delta_time );
  153. }
  154. break;
  155. case IMotionEvent::SIM_GLOBAL_FORCE:
  156. {
  157. ConvertAngularImpulseToIVP( rot, ivpRot );
  158. ConvertForceImpulseToIVP( speed, ivpSpeed );
  159. pCore->center_push_core_multiple_ws( &ivpSpeed, event->delta_time );
  160. pCore->rot_push_core_multiple_cs( &ivpRot, event->delta_time );
  161. }
  162. break;
  163. }
  164. pCore->apply_velocity_limit();
  165. }
  166. }
  167. }
  168. IVP_CONTROLLER_PRIORITY CPhysicsMotionController::get_controller_priority()
  169. {
  170. return (IVP_CONTROLLER_PRIORITY) m_priority;
  171. }
  172. void CPhysicsMotionController::SetPriority( priority_t priority )
  173. {
  174. switch ( priority )
  175. {
  176. case LOW_PRIORITY:
  177. m_priority = IVP_CP_CONSTRAINTS_MIN;
  178. break;
  179. default:
  180. case MEDIUM_PRIORITY:
  181. m_priority = IVP_CP_MOTION;
  182. break;
  183. case HIGH_PRIORITY:
  184. m_priority = IVP_CP_FORCEFIELDS+1;
  185. break;
  186. }
  187. }
  188. void CPhysicsMotionController::SetEventHandler( IMotionEvent *handler )
  189. {
  190. m_handler = handler;
  191. }
  192. void CPhysicsMotionController::AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached )
  193. {
  194. // BUGBUG: Sometimes restore comes back with a NULL, REVISIT
  195. if ( !pObject || pObject->IsStatic() )
  196. return;
  197. CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pObject);
  198. IVP_Real_Object *pIVP = pPhys->GetObject();
  199. IVP_Core *pCore = pIVP->get_core();
  200. // UNDONE: On save/load, trigger-based motion controllers re-attach their objects.
  201. // UNDONE: Do something cheaper about this?
  202. // OPTIMIZE: Linear search here?
  203. if ( checkIfAlreadyAttached )
  204. {
  205. int index = m_coreList.Find(pCore);
  206. if ( m_coreList.IsValidIndex(index) )
  207. {
  208. DevMsg(1,"Attached core twice!!!\n");
  209. return;
  210. }
  211. }
  212. m_coreList.AddToTail( pCore );
  213. MEM_ALLOC_CREDIT();
  214. pCore->add_core_controller( (IVP_Controller *)this );
  215. }
  216. void CPhysicsMotionController::RemoveCore( IVP_Core *pCore )
  217. {
  218. int index = m_coreList.Find(pCore);
  219. if ( !m_coreList.IsValidIndex(index) )
  220. {
  221. #if DEBUG
  222. Msg("removed invalid core !!!\n");
  223. #endif
  224. return;
  225. }
  226. //Assert( !m_pVEnv->IsInSimulation() );
  227. m_coreList.Remove( index );
  228. pCore->rem_core_controller( static_cast<IVP_Controller_Independent *>(this) );
  229. }
  230. void CPhysicsMotionController::DetachObject( IPhysicsObject *pObject )
  231. {
  232. CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pObject);
  233. IVP_Real_Object *pIVP = pPhys->GetObject();
  234. IVP_Core *core = pIVP->get_core();
  235. RemoveCore(core);
  236. }
  237. // Save/load
  238. void CPhysicsMotionController::WriteToTemplate( vphysics_save_motioncontroller_t &controllerTemplate )
  239. {
  240. controllerTemplate.m_nPriority = m_priority;
  241. int nObjectCount = CountObjects();
  242. controllerTemplate.m_objectList.AddMultipleToTail( nObjectCount );
  243. GetObjects( controllerTemplate.m_objectList.Base() );
  244. }
  245. void CPhysicsMotionController::InitFromTemplate( const vphysics_save_motioncontroller_t &controllerTemplate )
  246. {
  247. m_priority = controllerTemplate.m_nPriority;
  248. int nObjectCount = controllerTemplate.m_objectList.Count();
  249. for ( int i = 0; i < nObjectCount; ++i )
  250. {
  251. AttachObject( controllerTemplate.m_objectList[i], true );
  252. }
  253. }
  254. IPhysicsMotionController *CreateMotionController( CPhysicsEnvironment *pPhysEnv, IMotionEvent *pHandler )
  255. {
  256. if ( !pHandler )
  257. return NULL;
  258. return new CPhysicsMotionController( pHandler, pPhysEnv );
  259. }
  260. bool SavePhysicsMotionController( const physsaveparams_t &params, IPhysicsMotionController *pMotionController )
  261. {
  262. vphysics_save_motioncontroller_t controllerTemplate;
  263. memset( &controllerTemplate, 0, sizeof(controllerTemplate) );
  264. CPhysicsMotionController *pControllerImp = static_cast<CPhysicsMotionController*>(pMotionController);
  265. pControllerImp->WriteToTemplate( controllerTemplate );
  266. params.pSave->WriteAll( &controllerTemplate );
  267. return true;
  268. }
  269. bool RestorePhysicsMotionController( const physrestoreparams_t &params, IPhysicsMotionController **ppMotionController )
  270. {
  271. CPhysicsMotionController *pControllerImp = new CPhysicsMotionController( NULL, static_cast<CPhysicsEnvironment *>(params.pEnvironment) );
  272. vphysics_save_motioncontroller_t controllerTemplate;
  273. memset( &controllerTemplate, 0, sizeof(controllerTemplate) );
  274. params.pRestore->ReadAll( &controllerTemplate );
  275. pControllerImp->InitFromTemplate( controllerTemplate );
  276. *ppMotionController = pControllerImp;
  277. return true;
  278. }