211 lines
6.8 KiB
C++
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__
|