Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

211 lines
6.8 KiB
C++

/********************************************************************
filename: Propeller.h
created: 01/10/2009
author: jack.potter
purpose: Code for handling rendering and collision processing
of vehicle propellers
*********************************************************************/
#ifndef __PROPELLER_H__
#define __PROPELLER_H__
// Rage headers
#include "phcore/materialmgr.h"
#include "physics/contactiterator.h"
#include "vector/vector3.h"
#include "data/base.h"
#if __BANK
#include "bank/bank.h"
#endif
// Game headers
#include "renderer/HierarchyIds.h"
#include "scene/RegdRefTypes.h"
#include "vehicles/VehicleDefines.h"
class CVehicle;
#define PROPELLER_INVALID_BONE_INDEX (0xffff)
// TODO: A lot of the members of CPropeller and CPropellerBlurred are type data, not instance
// and should be split into the model info
//////////////////////////////////////////////////////////////////////////
// Class: CPropeller
// Purpose:
// Little class to deal with rotating propellers
// Could be a vehicle gadget I guess
class CPropeller: public datBase // Declaring data and virtuals in a base class causes bizarre code generation on x64?
{
public:
CPropeller();
virtual ~CPropeller() {}
virtual void Init(eHierarchyId nComponent, eRotationAxis nRotateAxis, CVehicle* pParentVehicle);
virtual void UpdatePropeller(float fPropSpeed, float fTimestep);
virtual void SetPropellerSpeed(float fPropSpeed);
virtual void PreRender(CVehicle* pParentVehicle);
s32 GetBoneIndex() const { return m_uMainPropellerBone; }
float GetSubmergeFraction(CVehicle* pParent);
float GetSpeed() const { return m_fPropellerSpeed; }
void SetSpeed(float fPropSpeed){ m_fPropellerSpeed = fPropSpeed;}
float GetAngle() const { return m_fPropellerAngle; }
u32 GetAxis() const { return m_nRotationAxis; }
virtual void SetPropellerVisible( bool visible ) { m_nVisible = visible; }
#if __BANK
static void InitWidgets(bkBank& pBank);
#endif
void ApplyDeformation(CVehicle* pParentVehicle, const void* basePtr);
Vector3 GetDeformation() const { return m_vDeformation; }
void Fix() { m_vDeformation.Zero(); }
protected:
float m_fPropellerSpeed;
float m_fPropellerAngle;
Vector3 m_vDeformation;
u16 m_uMainPropellerBone;
u32 m_nRotationAxis : 3;
u32 m_nReverse : 1;
u32 m_nVisible : 1;
};
//////////////////////////////////////////////////////////////////////////
// Class: CPropellerBlurred
// Purpose:
// Extension of CPropeller to support rotor blades which are to blur at high speed.
// Propellers need to be set up with child bones of the same name as their parent
// appended with _fast and _slow.
// The propeller will switch to these at a certain speed threshold.
class CPropellerBlurred : public CPropeller
{
public:
CPropellerBlurred();
virtual ~CPropellerBlurred() {}
virtual void Init(eHierarchyId nComponent, eRotationAxis nRotateAxis, CVehicle* pParentVehicle);
virtual void PreRender(CVehicle* pParentVehicle);
virtual void UpdatePropeller(float fPropSpeed, float fTimestep);
virtual void SetPropellerSpeed(float fPropSpeed);
#if __BANK
static void AddWidgetsToBank(bkBank& bank);
#endif
protected:
// These are children of the main properller bone
// They containt render geometry to swap to when the blades spin fast
u16 m_uFastBoneIndex;
u16 m_uSlowBoneIndex;
float m_fTimeInBlurredState;
// At what propeller speed do we switch to fast propellers ?
static bank_float ms_fTransitionAngleChangeThreshold;
static bank_float ms_fBlurredSpeedReduceFactor; // Should be in range 0 to 1
};
//////////////////////////////////////////////////////////////////////////
// Class: CPropellerCollision
// Purpose:
// One of these is stored for every bit of propeller collision on a vehicle
// Handles impact processing with for a single vehicle component.
// It is assumed that the CPropellerCollision is owned by the CVehicle!
class CPropellerCollision
{
public:
CPropellerCollision();
void Init(int iFragChild) { Assert(iFragChild < 128); m_iFragChild = (s8)iFragChild; m_iFragGroup = -1; m_iFragDisc = m_iFragChild;}
void Init(eHierarchyId nId, CVehicle* pOwner);
// Processes a SINGLE impact
// This does NOT iterate over the entire iterator
// This is called within the sim update, causing impact data to be stored
// and the impact disabled
void ProcessPreComputeImpacts(CVehicle* pPropellerOwner, phContactIterator impact, float fPropSpeedMult = 1.0f);
bool ShouldDisableImpact(CVehicle *pOwnerVehicle, CEntity *pOtherEntity, int nOwnerComponent, float fPropSpeedMult);
bool ShouldDisableAndIgnoreImpact(CVehicle *pOwnerVehicle, CEntity *pOtherEntity, float fCollisionDepth) const;
// Apply propeller collision to pOtherEntity
// Note the vehicle itself processes this collision separately
void ApplyImpact(CVehicle* pOwnerVehicle, CEntity* pOtherEntity, const Vector3& vecNormal, const Vector3& vecPos, const Vector3& vecOtherPos,
int nOtherComp, int nPartIndex, phMaterialMgr::Id nMaterialId, float fPropSpeedMult, float fTimeStep, bool bIsPositiveDepth, bool bIsNewContact);
s8 GetFragChild() const { return m_iFragChild; }
s8 GetFragGroup() const { return m_iFragGroup; }
s8 GetFragDisc() const {return m_iFragDisc;}
void UpdateBound(CVehicle *pOwnerVehicle, int iBoneIndex, float fAngle, int iAxis, bool fullUpdate);
bool IsPropellerComponent(const CVehicle *pOwnerVehicle, int nComponent) const;
protected:
s8 m_iFragChild;
s8 m_iFragGroup;
s8 m_iFragDisc;
};
#define NUM_STORED_PROPELLER_IMPACTS (20)
//////////////////////////////////////////////////////////////////////////
// Class: CPropellerCollisionProcessor
// Purpose:
// This class stores impacts with rotors over a frame and
// processes them at an appropriate time
// This is necessary because we can't touch the physics level
// during collision detection
class CPropellerCollisionProcessor
{
protected:
class CPropellerImpactData
{
public:
CPropellerImpactData();
void Reset();
RegdVeh m_pPropOwner;
RegdEnt m_pOtherEntity;
Vector3 m_vecHitNorm;
Vector3 m_vecHitPos;
Vector3 m_vecOtherPosOffset;
CPropellerCollision* m_pPropellerCollision;
int m_nOtherComponent;
int m_nPartId;
phMaterialMgr::Id m_nMaterialId;
float m_fPropSpeedMult; // range 0 - 1
bool m_bIsPositiveDepth;
bool m_bIsNewContact;
};
public:
CPropellerCollisionProcessor();
void Reset();
void ProcessImpacts(float fTimeStep);
void AddPropellerImpact(CVehicle* pPropOwner, CEntity* pHitEntity, const Vector3& vecNorm, const Vector3& vecPos,
CPropellerCollision* pPropellerCollision, int nOtherComponent, int nPartId, phMaterialMgr::Id nMaterialId, float fPropSpeedMult, bool bIsPositiveDepth, bool bIsNewContact);
static CPropellerCollisionProcessor& GetInstance() { return sm_Instance; }
protected:
int m_nNumRotorImpacts;
CPropellerImpactData m_aStoredImpacts[NUM_STORED_PROPELLER_IMPACTS];
static CPropellerCollisionProcessor sm_Instance;
};
#endif // __PROPELLER_H__