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.

231 lines
7.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "physics_fluid.h"
  10. #include "ivp_compact_surface.hxx"
  11. #include "ivp_surman_polygon.hxx"
  12. #include "ivp_phantom.hxx"
  13. #include "ivp_controller_buoyancy.hxx"
  14. #include "ivp_liquid_surface_descript.hxx"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. // NOTE: This is auto-deleted by the phantom controller
  18. class CBuoyancyAttacher : public IVP_Attacher_To_Cores_Buoyancy
  19. {
  20. public:
  21. virtual IVP_Template_Buoyancy *get_parameters_per_core( IVP_Core *pCore );
  22. CBuoyancyAttacher(IVP_Template_Buoyancy &templ, IVP_U_Set_Active<IVP_Core> *set_of_cores_, IVP_Liquid_Surface_Descriptor *liquid_surface_descriptor_);
  23. float m_density;
  24. };
  25. CPhysicsFluidController::CPhysicsFluidController( CBuoyancyAttacher *pBuoy, IVP_Liquid_Surface_Descriptor *pLiquid, CPhysicsObject *pObject, int nContents )
  26. {
  27. m_pBuoyancy = pBuoy;
  28. m_pLiquidSurface = pLiquid;
  29. m_pObject = pObject;
  30. m_nContents = nContents;
  31. }
  32. CPhysicsFluidController::~CPhysicsFluidController( void )
  33. {
  34. delete m_pLiquidSurface;
  35. }
  36. void CPhysicsFluidController::SetGameData( void *pGameData )
  37. {
  38. m_pGameData = pGameData;
  39. }
  40. void *CPhysicsFluidController::GetGameData( void ) const
  41. {
  42. return m_pGameData;
  43. }
  44. void CPhysicsFluidController::GetSurfacePlane( Vector *pNormal, float *pDist ) const
  45. {
  46. IVP_U_Float_Hesse surface;
  47. IVP_U_Float_Point abs_speed_of_current;
  48. m_pLiquidSurface->calc_liquid_surface( GetIVPObject()->get_core()->environment,
  49. GetIVPObject()->get_core(), &surface, &abs_speed_of_current );
  50. ConvertPlaneToHL( surface, pNormal, pDist );
  51. if ( pNormal )
  52. {
  53. *pNormal *= -1;
  54. }
  55. if ( pDist )
  56. {
  57. *pDist *= -1;
  58. }
  59. }
  60. IVP_Real_Object *CPhysicsFluidController::GetIVPObject()
  61. {
  62. return m_pObject->GetObject();
  63. }
  64. const IVP_Real_Object *CPhysicsFluidController::GetIVPObject() const
  65. {
  66. return m_pObject->GetObject();
  67. }
  68. float CPhysicsFluidController::GetDensity() const
  69. {
  70. return m_pBuoyancy->m_density;
  71. }
  72. void CPhysicsFluidController::WakeAllSleepingObjects()
  73. {
  74. GetIVPObject()->get_controller_phantom()->wake_all_sleeping_objects();
  75. }
  76. int CPhysicsFluidController::GetContents() const
  77. {
  78. return m_nContents;
  79. }
  80. IVP_Template_Buoyancy *CBuoyancyAttacher::get_parameters_per_core( IVP_Core *pCore )
  81. {
  82. if ( pCore )
  83. {
  84. IVP_Real_Object *pivp = pCore->objects.element_at(0);
  85. CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pivp->client_data);
  86. // This ratio is for objects whose mass / (collision model) volume is not equal to their density.
  87. // Keep the fluid pressure/friction solution for the volume, but scale the buoyant force calculations
  88. // to be in line with the object's real density. This is accompilshed by changing the fluid's density
  89. // on a per-object basis.
  90. float ratio = pPhys->GetBuoyancyRatio();
  91. if ( pPhys->GetShadowController() || !(pPhys->CallbackFlags() & CALLBACK_DO_FLUID_SIMULATION) )
  92. {
  93. // NOTE: don't do buoyancy on these guys for now!
  94. template_buoyancy.medium_density = 0;
  95. }
  96. else
  97. {
  98. template_buoyancy.medium_density = m_density * ratio;
  99. }
  100. }
  101. else
  102. {
  103. template_buoyancy.medium_density = m_density;
  104. }
  105. return &template_buoyancy;
  106. }
  107. CBuoyancyAttacher::CBuoyancyAttacher(IVP_Template_Buoyancy &templ, IVP_U_Set_Active<IVP_Core> *set_of_cores_, IVP_Liquid_Surface_Descriptor *liquid_surface_descriptor_)
  108. :IVP_Attacher_To_Cores_Buoyancy(templ, set_of_cores_, liquid_surface_descriptor_)
  109. {
  110. m_density = templ.medium_density;
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Defines the surface descriptor in local space
  114. //-----------------------------------------------------------------------------
  115. class CLiquidSurfaceDescriptor : public IVP_Liquid_Surface_Descriptor
  116. {
  117. public:
  118. CLiquidSurfaceDescriptor( CPhysicsObject *pFluidObject, const Vector4D &plane, const Vector &current )
  119. {
  120. cplane_t worldPlane;
  121. worldPlane.normal = plane.AsVector3D();
  122. worldPlane.dist = plane[3];
  123. matrix3x4_t matObjectToWorld;
  124. pFluidObject->GetPositionMatrix( &matObjectToWorld );
  125. MatrixITransformPlane( matObjectToWorld, worldPlane, m_objectSpacePlane );
  126. VectorIRotate( current, matObjectToWorld, m_vecObjectSpaceCurrent );
  127. m_pFluidObject = pFluidObject;
  128. }
  129. virtual void calc_liquid_surface( IVP_Environment * /*environment*/,
  130. IVP_Core * /*core*/,
  131. IVP_U_Float_Hesse *surface_normal_out,
  132. IVP_U_Float_Point *abs_speed_of_current_out)
  133. {
  134. cplane_t worldPlane;
  135. matrix3x4_t matObjectToWorld;
  136. m_pFluidObject->GetPositionMatrix( &matObjectToWorld );
  137. MatrixTransformPlane( matObjectToWorld, m_objectSpacePlane, worldPlane );
  138. worldPlane.normal *= -1.0f;
  139. worldPlane.dist *= -1.0f;
  140. IVP_U_Float_Hesse worldSurface;
  141. ConvertPlaneToIVP( worldPlane.normal, worldPlane.dist, worldSurface );
  142. surface_normal_out->set(&worldSurface);
  143. surface_normal_out->hesse_val = worldSurface.hesse_val;
  144. Vector worldSpaceCurrent;
  145. VectorRotate( m_vecObjectSpaceCurrent, matObjectToWorld, worldSpaceCurrent );
  146. IVP_U_Float_Point ivpWorldSpaceCurrent;
  147. ConvertDirectionToIVP( worldSpaceCurrent, ivpWorldSpaceCurrent );
  148. abs_speed_of_current_out->set( &ivpWorldSpaceCurrent );
  149. }
  150. private:
  151. Vector m_vecObjectSpaceCurrent;
  152. cplane_t m_objectSpacePlane;
  153. CPhysicsObject *m_pFluidObject;
  154. };
  155. CPhysicsFluidController *CreateFluidController( IVP_Environment *pEnvironment, CPhysicsObject *pFluidObject, fluidparams_t *pParams )
  156. {
  157. pFluidObject->BecomeTrigger();
  158. IVP_Controller_Phantom *pPhantom = pFluidObject->GetObject()->get_controller_phantom();
  159. if ( !pPhantom )
  160. return NULL;
  161. IVP_Liquid_Surface_Descriptor *lsd = new CLiquidSurfaceDescriptor( pFluidObject, pParams->surfacePlane, pParams->currentVelocity );
  162. int surfaceprops = pFluidObject->GetMaterialIndex();
  163. float density = physprops->GetSurfaceData( surfaceprops )->physics.density;
  164. // ---------------------------------------------
  165. // create parameter template for Buoyancy_Solver
  166. // ---------------------------------------------
  167. // UNDONE: Expose these other parametersd
  168. IVP_Template_Buoyancy buoyancy_input;
  169. buoyancy_input.medium_density = ConvertDensityToIVP(density); // density of water (unit: kg/m^3)
  170. buoyancy_input.pressure_damp_factor = pParams->damping;
  171. buoyancy_input.viscosity_factor = 0.0f;
  172. buoyancy_input.torque_factor = 0.01f;
  173. buoyancy_input.viscosity_input_factor = 0.1f;
  174. // -------------------------------------------------------------------------------
  175. // create "water" (i.e. buoyancy solver) and attach a dynamic list of object cores
  176. // -------------------------------------------------------------------------------
  177. CBuoyancyAttacher *attacher_to_cores_buoyancy = new CBuoyancyAttacher( buoyancy_input, pPhantom->get_intruding_cores(), lsd );
  178. CPhysicsFluidController *pFluid = new CPhysicsFluidController( attacher_to_cores_buoyancy, lsd, pFluidObject, pParams->contents );
  179. pFluid->SetGameData( pParams->pGameData );
  180. pPhantom->client_data = static_cast<void *>(pFluid);
  181. return pFluid;
  182. }
  183. bool SavePhysicsFluidController( const physsaveparams_t &params, CPhysicsFluidController *pFluidObject )
  184. {
  185. return false;
  186. }
  187. bool RestorePhysicsFluidController( const physrestoreparams_t &params, CPhysicsFluidController **ppFluidObject )
  188. {
  189. return false;
  190. }