diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vphysics/physics_motioncontroller.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'vphysics/physics_motioncontroller.cpp')
| -rw-r--r-- | vphysics/physics_motioncontroller.cpp | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/vphysics/physics_motioncontroller.cpp b/vphysics/physics_motioncontroller.cpp new file mode 100644 index 0000000..75d62da --- /dev/null +++ b/vphysics/physics_motioncontroller.cpp @@ -0,0 +1,333 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifdef _WIN32 +#pragma warning (disable:4127) +#pragma warning (disable:4244) +#endif + +#include "cbase.h" +#include "ivp_controller.hxx" + +#include "physics_motioncontroller.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +struct vphysics_save_motioncontroller_t +{ + CUtlVector<IPhysicsObject *> m_objectList; + int m_nPriority; + + DECLARE_SIMPLE_DATADESC(); +}; + + +BEGIN_SIMPLE_DATADESC( vphysics_save_motioncontroller_t ) + DEFINE_VPHYSPTR_UTLVECTOR( m_objectList ), + DEFINE_FIELD( m_nPriority, FIELD_INTEGER ), +END_DATADESC() + + + +class CPhysicsMotionController : public IVP_Controller_Independent, public IPhysicsMotionController +{ +public: + CPhysicsMotionController( IMotionEvent *pHandler, CPhysicsEnvironment *pVEnv ); + virtual ~CPhysicsMotionController( void ); + virtual void do_simulation_controller(IVP_Event_Sim *event,IVP_U_Vector<IVP_Core> *core_list); + virtual IVP_CONTROLLER_PRIORITY get_controller_priority(); + virtual void core_is_going_to_be_deleted_event(IVP_Core *core) + { + m_coreList.FindAndRemove( core ); + } + virtual const char *get_controller_name() { return "vphysics:motion"; } + + virtual void SetEventHandler( IMotionEvent *handler ); + virtual void AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached ); + virtual void DetachObject( IPhysicsObject *pObject ); + + void RemoveCore( IVP_Core *pCore ); + + // Save/load + void WriteToTemplate( vphysics_save_motioncontroller_t &controllerTemplate ); + void InitFromTemplate( const vphysics_save_motioncontroller_t &controllerTemplate ); + + // returns the number of objects currently attached to the controller + virtual int CountObjects( void ) + { + return m_coreList.Count(); + } + // NOTE: pObjectList is an array with at least CountObjects() allocated + virtual void GetObjects( IPhysicsObject **pObjectList ) + { + for ( int i = 0; i < m_coreList.Count(); i++ ) + { + IVP_Core *pCore = m_coreList[i]; + + IVP_Real_Object *pivp = pCore->objects.element_at(0); + IPhysicsObject *pPhys = static_cast<IPhysicsObject *>(pivp->client_data); + // copy out + pObjectList[i] = pPhys; + } + } + + // detaches all attached objects + virtual void ClearObjects( void ) + { + while ( m_coreList.Count() ) + { + int x = m_coreList.Count()-1; + IVP_Core *pCore = m_coreList[x]; + RemoveCore( pCore ); + } + } + + // wakes up all attached objects + virtual void WakeObjects( void ) + { + for ( int i = 0; i < m_coreList.Count(); i++ ) + { + IVP_Core *pCore = m_coreList[i]; + pCore->ensure_core_to_be_in_simulation(); + } + } + virtual void SetPriority( priority_t priority ); + +private: + IMotionEvent *m_handler; + CUtlVector<IVP_Core *> m_coreList; + CPhysicsEnvironment *m_pVEnv; + int m_priority; +}; + + +CPhysicsMotionController::CPhysicsMotionController( IMotionEvent *pHandler, CPhysicsEnvironment *pVEnv ) +{ + m_handler = pHandler; + m_pVEnv = pVEnv; + SetPriority( MEDIUM_PRIORITY ); +} + +CPhysicsMotionController::~CPhysicsMotionController( void ) +{ + Assert( !m_pVEnv->IsInSimulation() ); + for ( int i = 0; i < m_coreList.Count(); i++ ) + { + m_coreList[i]->rem_core_controller( (IVP_Controller *)this ); + } +} + +void CPhysicsMotionController::do_simulation_controller(IVP_Event_Sim *event,IVP_U_Vector<IVP_Core> *core_list) +{ + if ( m_handler ) + { + for ( int i = 0; i < core_list->len(); i++ ) + { + IVP_U_Float_Point ivpSpeed, ivpRot; + IVP_Core *pCore = core_list->element_at(i); + + IVP_Real_Object *pivp = pCore->objects.element_at(0); + IPhysicsObject *pPhys = static_cast<IPhysicsObject *>(pivp->client_data); + if ( !pPhys->IsMoveable() ) + continue; + + Vector speed; + AngularImpulse rot; + speed.Init(); + rot.Init(); + + IMotionEvent::simresult_e ret = m_handler->Simulate( this, pPhys, event->delta_time, speed, rot ); + + switch( ret ) + { + case IMotionEvent::SIM_NOTHING: + break; + case IMotionEvent::SIM_LOCAL_ACCELERATION: + { + ConvertForceImpulseToIVP( speed, ivpSpeed ); + ConvertAngularImpulseToIVP( rot, ivpRot ); + const IVP_U_Matrix *m_world_f_core = pCore->get_m_world_f_core_PSI(); + // transform to world space + m_world_f_core->inline_vmult3( &ivpSpeed, &ivpSpeed ); + // UNDONE: Put these values into speed change / rot_speed_change instead? + pCore->speed.add_multiple( &ivpSpeed, event->delta_time ); + pCore->rot_speed.add_multiple( &ivpRot, event->delta_time ); + } + break; + case IMotionEvent::SIM_LOCAL_FORCE: + { + ConvertForceImpulseToIVP( speed, ivpSpeed ); + ConvertAngularImpulseToIVP( rot, ivpRot ); + const IVP_U_Matrix *m_world_f_core = pCore->get_m_world_f_core_PSI(); + // transform to world space + m_world_f_core->inline_vmult3( &ivpSpeed, &ivpSpeed ); + pCore->center_push_core_multiple_ws( &ivpSpeed, event->delta_time ); + pCore->rot_push_core_multiple_cs( &ivpRot, event->delta_time ); + } + break; + case IMotionEvent::SIM_GLOBAL_ACCELERATION: + { + ConvertAngularImpulseToIVP( rot, ivpRot ); + ConvertForceImpulseToIVP( speed, ivpSpeed ); + pCore->speed.add_multiple( &ivpSpeed, event->delta_time ); + pCore->rot_speed.add_multiple( &ivpRot, event->delta_time ); + } + break; + case IMotionEvent::SIM_GLOBAL_FORCE: + { + ConvertAngularImpulseToIVP( rot, ivpRot ); + ConvertForceImpulseToIVP( speed, ivpSpeed ); + pCore->center_push_core_multiple_ws( &ivpSpeed, event->delta_time ); + pCore->rot_push_core_multiple_cs( &ivpRot, event->delta_time ); + } + break; + } + pCore->apply_velocity_limit(); + } + } +} + + +IVP_CONTROLLER_PRIORITY CPhysicsMotionController::get_controller_priority() +{ + return (IVP_CONTROLLER_PRIORITY) m_priority; +} + +void CPhysicsMotionController::SetPriority( priority_t priority ) +{ + switch ( priority ) + { + case LOW_PRIORITY: + m_priority = IVP_CP_CONSTRAINTS_MIN; + break; + default: + case MEDIUM_PRIORITY: + m_priority = IVP_CP_MOTION; + break; + case HIGH_PRIORITY: + m_priority = IVP_CP_FORCEFIELDS+1; + break; + } +} + +void CPhysicsMotionController::SetEventHandler( IMotionEvent *handler ) +{ + m_handler = handler; +} + +void CPhysicsMotionController::AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached ) +{ + // BUGBUG: Sometimes restore comes back with a NULL, REVISIT + if ( !pObject || pObject->IsStatic() ) + return; + + CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pObject); + IVP_Real_Object *pIVP = pPhys->GetObject(); + IVP_Core *pCore = pIVP->get_core(); + + // UNDONE: On save/load, trigger-based motion controllers re-attach their objects. + // UNDONE: Do something cheaper about this? + // OPTIMIZE: Linear search here? + if ( checkIfAlreadyAttached ) + { + int index = m_coreList.Find(pCore); + if ( m_coreList.IsValidIndex(index) ) + { + DevMsg(1,"Attached core twice!!!\n"); + return; + } + } + + m_coreList.AddToTail( pCore ); + + MEM_ALLOC_CREDIT(); + pCore->add_core_controller( (IVP_Controller *)this ); +} + + +void CPhysicsMotionController::RemoveCore( IVP_Core *pCore ) +{ + int index = m_coreList.Find(pCore); + if ( !m_coreList.IsValidIndex(index) ) + { +#if DEBUG + Msg("removed invalid core !!!\n"); +#endif + return; + } + //Assert( !m_pVEnv->IsInSimulation() ); + m_coreList.Remove( index ); + pCore->rem_core_controller( static_cast<IVP_Controller_Independent *>(this) ); +} + + +void CPhysicsMotionController::DetachObject( IPhysicsObject *pObject ) +{ + CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pObject); + IVP_Real_Object *pIVP = pPhys->GetObject(); + IVP_Core *core = pIVP->get_core(); + + RemoveCore(core); +} + +// Save/load +void CPhysicsMotionController::WriteToTemplate( vphysics_save_motioncontroller_t &controllerTemplate ) +{ + controllerTemplate.m_nPriority = m_priority; + + int nObjectCount = CountObjects(); + controllerTemplate.m_objectList.AddMultipleToTail( nObjectCount ); + GetObjects( controllerTemplate.m_objectList.Base() ); +} + +void CPhysicsMotionController::InitFromTemplate( const vphysics_save_motioncontroller_t &controllerTemplate ) +{ + m_priority = controllerTemplate.m_nPriority; + + int nObjectCount = controllerTemplate.m_objectList.Count(); + for ( int i = 0; i < nObjectCount; ++i ) + { + AttachObject( controllerTemplate.m_objectList[i], true ); + } +} + + +IPhysicsMotionController *CreateMotionController( CPhysicsEnvironment *pPhysEnv, IMotionEvent *pHandler ) +{ + if ( !pHandler ) + return NULL; + + return new CPhysicsMotionController( pHandler, pPhysEnv ); +} + +bool SavePhysicsMotionController( const physsaveparams_t ¶ms, IPhysicsMotionController *pMotionController ) +{ + vphysics_save_motioncontroller_t controllerTemplate; + memset( &controllerTemplate, 0, sizeof(controllerTemplate) ); + + CPhysicsMotionController *pControllerImp = static_cast<CPhysicsMotionController*>(pMotionController); + pControllerImp->WriteToTemplate( controllerTemplate ); + params.pSave->WriteAll( &controllerTemplate ); + + return true; +} + +bool RestorePhysicsMotionController( const physrestoreparams_t ¶ms, IPhysicsMotionController **ppMotionController ) +{ + CPhysicsMotionController *pControllerImp = new CPhysicsMotionController( NULL, static_cast<CPhysicsEnvironment *>(params.pEnvironment) ); + + vphysics_save_motioncontroller_t controllerTemplate; + memset( &controllerTemplate, 0, sizeof(controllerTemplate) ); + params.pRestore->ReadAll( &controllerTemplate ); + + pControllerImp->InitFromTemplate( controllerTemplate ); + *ppMotionController = pControllerImp; + + return true; +} |