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
231 lines
7.3 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "physics_fluid.h" |
|
|
|
|
|
#include "ivp_compact_surface.hxx" |
|
#include "ivp_surman_polygon.hxx" |
|
#include "ivp_phantom.hxx" |
|
#include "ivp_controller_buoyancy.hxx" |
|
#include "ivp_liquid_surface_descript.hxx" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
// NOTE: This is auto-deleted by the phantom controller |
|
class CBuoyancyAttacher : public IVP_Attacher_To_Cores_Buoyancy |
|
{ |
|
public: |
|
virtual IVP_Template_Buoyancy *get_parameters_per_core( IVP_Core *pCore ); |
|
CBuoyancyAttacher(IVP_Template_Buoyancy &templ, IVP_U_Set_Active<IVP_Core> *set_of_cores_, IVP_Liquid_Surface_Descriptor *liquid_surface_descriptor_); |
|
|
|
float m_density; |
|
}; |
|
|
|
CPhysicsFluidController::CPhysicsFluidController( CBuoyancyAttacher *pBuoy, IVP_Liquid_Surface_Descriptor *pLiquid, CPhysicsObject *pObject, int nContents ) |
|
{ |
|
m_pBuoyancy = pBuoy; |
|
m_pLiquidSurface = pLiquid; |
|
m_pObject = pObject; |
|
m_nContents = nContents; |
|
} |
|
|
|
CPhysicsFluidController::~CPhysicsFluidController( void ) |
|
{ |
|
delete m_pLiquidSurface; |
|
} |
|
|
|
void CPhysicsFluidController::SetGameData( void *pGameData ) |
|
{ |
|
m_pGameData = pGameData; |
|
} |
|
|
|
void *CPhysicsFluidController::GetGameData( void ) const |
|
{ |
|
return m_pGameData; |
|
} |
|
|
|
void CPhysicsFluidController::GetSurfacePlane( Vector *pNormal, float *pDist ) const |
|
{ |
|
IVP_U_Float_Hesse surface; |
|
IVP_U_Float_Point abs_speed_of_current; |
|
|
|
m_pLiquidSurface->calc_liquid_surface( GetIVPObject()->get_core()->environment, |
|
GetIVPObject()->get_core(), &surface, &abs_speed_of_current ); |
|
ConvertPlaneToHL( surface, pNormal, pDist ); |
|
if ( pNormal ) |
|
{ |
|
*pNormal *= -1; |
|
} |
|
if ( pDist ) |
|
{ |
|
*pDist *= -1; |
|
} |
|
} |
|
|
|
IVP_Real_Object *CPhysicsFluidController::GetIVPObject() |
|
{ |
|
return m_pObject->GetObject(); |
|
} |
|
|
|
const IVP_Real_Object *CPhysicsFluidController::GetIVPObject() const |
|
{ |
|
return m_pObject->GetObject(); |
|
} |
|
|
|
float CPhysicsFluidController::GetDensity() const |
|
{ |
|
return m_pBuoyancy->m_density; |
|
} |
|
|
|
void CPhysicsFluidController::WakeAllSleepingObjects() |
|
{ |
|
GetIVPObject()->get_controller_phantom()->wake_all_sleeping_objects(); |
|
} |
|
|
|
int CPhysicsFluidController::GetContents() const |
|
{ |
|
return m_nContents; |
|
} |
|
|
|
IVP_Template_Buoyancy *CBuoyancyAttacher::get_parameters_per_core( IVP_Core *pCore ) |
|
{ |
|
if ( pCore ) |
|
{ |
|
IVP_Real_Object *pivp = pCore->objects.element_at(0); |
|
CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pivp->client_data); |
|
|
|
// This ratio is for objects whose mass / (collision model) volume is not equal to their density. |
|
// Keep the fluid pressure/friction solution for the volume, but scale the buoyant force calculations |
|
// to be in line with the object's real density. This is accompilshed by changing the fluid's density |
|
// on a per-object basis. |
|
float ratio = pPhys->GetBuoyancyRatio(); |
|
|
|
if ( pPhys->GetShadowController() || !(pPhys->CallbackFlags() & CALLBACK_DO_FLUID_SIMULATION) ) |
|
{ |
|
// NOTE: don't do buoyancy on these guys for now! |
|
template_buoyancy.medium_density = 0; |
|
} |
|
else |
|
{ |
|
template_buoyancy.medium_density = m_density * ratio; |
|
} |
|
} |
|
else |
|
{ |
|
template_buoyancy.medium_density = m_density; |
|
} |
|
|
|
return &template_buoyancy; |
|
} |
|
|
|
CBuoyancyAttacher::CBuoyancyAttacher(IVP_Template_Buoyancy &templ, IVP_U_Set_Active<IVP_Core> *set_of_cores_, IVP_Liquid_Surface_Descriptor *liquid_surface_descriptor_) |
|
:IVP_Attacher_To_Cores_Buoyancy(templ, set_of_cores_, liquid_surface_descriptor_) |
|
{ |
|
m_density = templ.medium_density; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Defines the surface descriptor in local space |
|
//----------------------------------------------------------------------------- |
|
class CLiquidSurfaceDescriptor : public IVP_Liquid_Surface_Descriptor |
|
{ |
|
public: |
|
CLiquidSurfaceDescriptor( CPhysicsObject *pFluidObject, const Vector4D &plane, const Vector ¤t ) |
|
{ |
|
cplane_t worldPlane; |
|
worldPlane.normal = plane.AsVector3D(); |
|
worldPlane.dist = plane[3]; |
|
|
|
matrix3x4_t matObjectToWorld; |
|
pFluidObject->GetPositionMatrix( &matObjectToWorld ); |
|
MatrixITransformPlane( matObjectToWorld, worldPlane, m_objectSpacePlane ); |
|
|
|
VectorIRotate( current, matObjectToWorld, m_vecObjectSpaceCurrent ); |
|
m_pFluidObject = pFluidObject; |
|
} |
|
|
|
virtual void calc_liquid_surface( IVP_Environment * /*environment*/, |
|
IVP_Core * /*core*/, |
|
IVP_U_Float_Hesse *surface_normal_out, |
|
IVP_U_Float_Point *abs_speed_of_current_out) |
|
{ |
|
cplane_t worldPlane; |
|
matrix3x4_t matObjectToWorld; |
|
m_pFluidObject->GetPositionMatrix( &matObjectToWorld ); |
|
MatrixTransformPlane( matObjectToWorld, m_objectSpacePlane, worldPlane ); |
|
|
|
worldPlane.normal *= -1.0f; |
|
worldPlane.dist *= -1.0f; |
|
|
|
IVP_U_Float_Hesse worldSurface; |
|
ConvertPlaneToIVP( worldPlane.normal, worldPlane.dist, worldSurface ); |
|
surface_normal_out->set(&worldSurface); |
|
surface_normal_out->hesse_val = worldSurface.hesse_val; |
|
|
|
Vector worldSpaceCurrent; |
|
VectorRotate( m_vecObjectSpaceCurrent, matObjectToWorld, worldSpaceCurrent ); |
|
|
|
IVP_U_Float_Point ivpWorldSpaceCurrent; |
|
ConvertDirectionToIVP( worldSpaceCurrent, ivpWorldSpaceCurrent ); |
|
abs_speed_of_current_out->set( &ivpWorldSpaceCurrent ); |
|
} |
|
|
|
private: |
|
Vector m_vecObjectSpaceCurrent; |
|
cplane_t m_objectSpacePlane; |
|
CPhysicsObject *m_pFluidObject; |
|
}; |
|
|
|
|
|
CPhysicsFluidController *CreateFluidController( IVP_Environment *pEnvironment, CPhysicsObject *pFluidObject, fluidparams_t *pParams ) |
|
{ |
|
pFluidObject->BecomeTrigger(); |
|
|
|
IVP_Controller_Phantom *pPhantom = pFluidObject->GetObject()->get_controller_phantom(); |
|
if ( !pPhantom ) |
|
return NULL; |
|
|
|
IVP_Liquid_Surface_Descriptor *lsd = new CLiquidSurfaceDescriptor( pFluidObject, pParams->surfacePlane, pParams->currentVelocity ); |
|
int surfaceprops = pFluidObject->GetMaterialIndex(); |
|
float density = physprops->GetSurfaceData( surfaceprops )->physics.density; |
|
// --------------------------------------------- |
|
// create parameter template for Buoyancy_Solver |
|
// --------------------------------------------- |
|
// UNDONE: Expose these other parametersd |
|
IVP_Template_Buoyancy buoyancy_input; |
|
buoyancy_input.medium_density = ConvertDensityToIVP(density); // density of water (unit: kg/m^3) |
|
buoyancy_input.pressure_damp_factor = pParams->damping; |
|
buoyancy_input.viscosity_factor = 0.0f; |
|
buoyancy_input.torque_factor = 0.01f; |
|
buoyancy_input.viscosity_input_factor = 0.1f; |
|
// ------------------------------------------------------------------------------- |
|
// create "water" (i.e. buoyancy solver) and attach a dynamic list of object cores |
|
// ------------------------------------------------------------------------------- |
|
CBuoyancyAttacher *attacher_to_cores_buoyancy = new CBuoyancyAttacher( buoyancy_input, pPhantom->get_intruding_cores(), lsd ); |
|
|
|
CPhysicsFluidController *pFluid = new CPhysicsFluidController( attacher_to_cores_buoyancy, lsd, pFluidObject, pParams->contents ); |
|
pFluid->SetGameData( pParams->pGameData ); |
|
pPhantom->client_data = static_cast<void *>(pFluid); |
|
|
|
return pFluid; |
|
} |
|
|
|
|
|
bool SavePhysicsFluidController( const physsaveparams_t ¶ms, CPhysicsFluidController *pFluidObject ) |
|
{ |
|
return false; |
|
} |
|
|
|
bool RestorePhysicsFluidController( const physrestoreparams_t ¶ms, CPhysicsFluidController **ppFluidObject ) |
|
{ |
|
return false; |
|
} |
|
|
|
|