1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-20 20:29:10 +00:00

Refactor avatar movement code

plMovementStrategy classes have been reworked and completely replace all plAvatarControllers.
While based on the old implementation, plPhysicalControllerCore has essentially been rewritten.
Remnants of long gone physical "actions" have been removed.

4 files removed -
plAVCallbackAction.h & plAVCallbackAction.cpp
plAntiGravAction.h & plAntiGravAction.cpp

This revision will not compile, requires new plPXPhysicalControllerCore implementation.
This commit is contained in:
Skoader
2012-06-24 12:51:45 +10:00
committed by Adam Johnson
parent 75793e5182
commit 769cd60617
33 changed files with 1019 additions and 2356 deletions

View File

@ -41,310 +41,284 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#ifndef PLPHYSICALCONTROLLERCORE_H
#define PLPHYSICALCONTROLLERCORE_H
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsQuat.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
#include "plPhysical/plSimDefs.h"
#include "pnMessage/plMessage.h"
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
#define kSLOPELIMIT (cosf(hsDegreesToRadians(45.f)))
#include <vector>
class plCoordinateInterface;
class plPhysical;
class plPXPhysical;
class plMovementStrategy;
class plAGApplicator;
class plSwimRegionInterface;
//Replacement for for plPhysicalController stripped out some walk specific code
//plPhysicalControllerCore needs to have movement strategies registered to it these will then
//be called by the controller during the simulation steps. The Strategies need to at least have an
// Apply and Update definition. Everything else should be movement specific. I hope to come back and
//and refactor when I have time this in the future.
#define kSlopeLimit (cosf(hsDegreesToRadians(55.f)))
enum plControllerCollisionFlags
{
kSides=1,
kTop= (1<<1),
kBottom=(1<<2),
{
kSides = 1,
kTop = (1 << 1),
kBottom = (1 << 2)
};
class plMovementStrategySimulationInterface
struct plControllerSweepRecord
{
public:
virtual void Apply(float delSecs)=0;
virtual void Update(float delSecs)=0;
//most strategies don't require this. Only the ones that require behavior like a physical or need
//something after the sim step. this used to be taken care of by Update, but this was moved to take care of
//some of the frame lag
virtual void PostStep(float delSecs){};
virtual void IAddContactNormals(hsVector3& vec){fContactNormals.Append(vec);}
virtual void AddOnTopOfObject(plPhysical* phys){ fOnTopOf.Append(phys);}
virtual void LeaveAge()
{
fContactNormals.SetCount(0);
fOnTopOf.SetCount(0);
}
protected:
hsTArray<hsVector3> fContactNormals;
hsTArray<plPhysical* > fOnTopOf;
};
class plControllerSweepRecord
{
public:
plPhysical *ObjHit;
hsPoint3 locHit;//World space
float TimeHit;//Normalized between 0 and 1
hsVector3 Norm;
hsPoint3 Point;
hsVector3 Normal;
};
bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right);
class plPhysicalControllerCore
{
public:
virtual ~plPhysicalControllerCore();
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)=0;
virtual void SetMovementSimulationInterface(plMovementStrategySimulationInterface* strat){fMovementInterface=strat;}
virtual void Apply(float delSecs);
virtual void Update(float delSecs);
virtual void PostStep(float delSecs);
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
plPhysicalControllerCore(plKey ownerSceneObject, float height, float radius);
virtual ~plPhysicalControllerCore() { }
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
// Use plArmatureModBase::EnablePhysics() instead.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() {return fEnabled;}
virtual plKey GetSubworld() {return fWorldKey;}
virtual bool IsEnabled() { return fEnabled; }
// Subworld
virtual plKey GetSubworld() { return fWorldKey; }
virtual void SetSubworld(plKey world) = 0;
virtual const plCoordinateInterface* GetSubworldCI() const = 0;
virtual const plCoordinateInterface* GetSubworldCI();
// For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot) = 0;
virtual void SetState(const hsPoint3& pos, float zRot) = 0;
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state) = 0;
virtual bool IsKinematic() = 0;
virtual void GetKinematicPosition(hsPoint3& pos) = 0;
virtual const hsMatrix44& GetPrevSubworldW2L() = 0;
//when seeking no longer want to interact with exclusion regions
virtual void SetSeek(bool seek){fSeeking=seek;}
virtual bool IsSeeking(){return fSeeking;}
static plPhysicalControllerCore* Create(plKey ownerSO, float height, float radius);
virtual plMovementStrategySimulationInterface* GetMovementInterface(){return fMovementInterface;}
plPhysicalControllerCore(plKey ownerSceneObject, float height, float radius);
virtual plKey GetOwner(){return fOwner;};
// Set the LOS DB this avatar will be in (only one)
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; } ;
virtual plSimDefs::plLOSDB GetLOSDB() {return fLOSDB ; }
virtual const hsMatrix44& GetLastGlobalLoc()=0;
virtual void SetKinematicLoc(const hsMatrix44& l2w)=0;
virtual void SetGlobalLoc(const hsMatrix44& l2w)=0;
virtual bool IsEnabledChanged(){return fEnableChanged;}
virtual void HandleEnableChanged()=0;
virtual bool IsKinematicChanged(){return fKinematicChanged;}
virtual void GetPositionSim(hsPoint3& pos)=0;
virtual void HandleKinematicChanged()=0;
virtual bool IsKinematicEnableNextUpdate(){return fKinematicEnableNextUpdate;}
virtual void HandleKinematicEnableNextUpdate()=0;
virtual void MoveKinematicToController(hsPoint3& pos)=0;
virtual void UpdateControllerAndPhysicalRep()=0;
virtual void CheckAndHandleAnyStateChanges();
virtual void UpdateSubstepNonPhysical();
virtual const hsPoint3& GetLocalPosition()=0;
const hsQuat& GetLocalRotation() { return fLocalRotation; }
virtual void MoveActorToSim();
virtual void OverrideAchievedVelocity(hsVector3 newAchievedVel)
{//because of things like superjumps this is needed I'd rather not, but can't help it
fAchievedLinearVelocity=newAchievedVel;
}
//any clean up for the controller should go here
virtual void LeaveAge()=0;
hsVector3 DisplacementLastStep(){return fDisplacementThisStep;}
hsVector3 MeanVelocityForLastStep()
{
hsVector3 vel=fDisplacementThisStep;
return vel/fSimLength;
}
void SendCorrectionMessages();
// The LOS DB this avatar is in (only one)
virtual plSimDefs::plLOSDB GetLOSDB() { return fLOSDB; }
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
// Movement strategy
virtual void SetMovementStrategy(plMovementStrategy* strategy) = 0;
// Global location
virtual const hsMatrix44& GetLastGlobalLoc() { return fLastGlobalLoc; }
virtual void SetGlobalLoc(const hsMatrix44& l2w) = 0;
// Local sim position
virtual void GetPositionSim(hsPoint3& pos) = 0;
// Move kinematic controller
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults) = 0;
// Set linear velocity on dynamic controller
virtual void SetLinearVelocitySim(const hsVector3& linearVel) = 0;
// Sweep the controller path from startPos through endPos
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, bool vsDynamics, bool vsStatics,
uint32_t& vsSimGroups, std::vector<plControllerSweepRecord>& hits) = 0;
// any clean up for the controller should go here
virtual void LeaveAge() = 0;
// Local rotation
const hsQuat& GetLocalRotation() const { return fLocalRotation; }
void IncrementAngle(float deltaAngle);
void UpdateWorldRelativePos();
virtual void SetLinearVelocity(const hsVector3& linearVel){fLinearVelocity=linearVel;}
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void SetAngularVelocity(const float angvel){ fAngularVelocity=angvel;}
virtual void SetVelocities(const hsVector3& linearVel, float angVel)
{
fLinearVelocity=linearVel;
fAngularVelocity=angVel;
}
virtual const hsVector3& GetLinearVelocity() ;
virtual float GetAngularVelocity(){return fAngularVelocity;}
virtual const hsVector3& GetAchievedLinearVelocity()const {return fAchievedLinearVelocity;}
plPhysical* GetPushingPhysical();
bool GetFacingPushingPhysical();
virtual void SetPushingPhysical(plPhysical* pl){fPushingPhysical=pl;}
virtual void SetFacingPushingPhysical(bool ans){fFacingPushingPhysical=ans;}
//To be Used during runtime conversions, say to switch a tall controller to a ball for swimming
virtual void SetControllerDimensions(float radius, float height)=0;
virtual float GetControllerWidth(){return fRadius;}
virtual float GetControllerHeight(){return fHeight;}
virtual void ResetAchievedLinearVelocity()
{
fAchievedLinearVelocity.Set(0.f,0.f,0.f);
}
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, bool vsDynamics, bool vsStatics, uint32_t& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut)=0;
//this should only be used to force a move it could place your head into a wall and that would be good
virtual float GetHeight() {return fHeight;}
virtual float GetRadius() {return fRadius;}
//Wether the avatar thing has mass and forces things down or not, and changes the way things move
//This is an attempt fix things like riding on an animated physical
virtual void BehaveLikeAnimatedPhysical(bool actLikeAnAnimatedPhys)=0;
virtual bool BehavingLikeAnAnimatedPhysical()=0;
// Linear velocity
void SetLinearVelocity(const hsVector3& linearVel) { fLinearVelocity = linearVel; }
const hsVector3& GetLinearVelocity() const { return fLinearVelocity; }
// Acheived linear velocity
const hsVector3& GetAchievedLinearVelocity() const { return fAchievedLinearVelocity; }
void OverrideAchievedLinearVelocity(const hsVector3& linearVel) { fAchievedLinearVelocity = linearVel; }
void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
// SceneObject
plKey GetOwner() { return fOwner; }
// When seeking no longer want to interact with exclude regions
void SetSeek(bool seek) { fSeeking = seek; }
bool IsSeeking() const { return fSeeking; }
// Pushing physical
plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
void SetPushingPhysical(plPhysical* phys) { fPushingPhysical = phys; }
bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
void SetFacingPushingPhysical(bool facing) { fFacingPushingPhysical = facing; }
// Controller dimensions
float GetRadius() const { return fRadius; }
float GetHeight() const { return fHeight; }
// Create a new controller instance - Implemented in the physics system
static plPhysicalControllerCore* Create(plKey ownerSO, float height, float radius);
protected:
virtual void IHandleEnableChanged() = 0;
void IApply(float delSecs);
void IUpdate(int numSubSteps, float alpha);
void IUpdateNonPhysical(float alpha);
void ISendCorrectionMessages(bool dirtySynch = false);
plKey fOwner;
plKey fWorldKey;
float fHeight;
float fRadius;
plKey fWorldKey;
plSimDefs::plLOSDB fLOSDB;
plMovementStrategy* fMovementStrategy;
float fSimLength;
hsQuat fLocalRotation;
hsPoint3 fLocalPosition;
hsPoint3 fLastLocalPosition;
hsMatrix44 fLastGlobalLoc;
hsMatrix44 fPrevSubworldW2L;
hsVector3 fLinearVelocity;
hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
bool fSeeking;
bool fEnabled;
bool fEnableChanged;
bool fKinematic;
bool fKinematicEnableNextUpdate;
bool fKinematicChanged;
plMovementStrategySimulationInterface* fMovementInterface;
hsMatrix44 fLastGlobalLoc;
hsPoint3 fLocalPosition;
hsQuat fLocalRotation;
hsMatrix44 fPrevSubworldW2L;
hsVector3 fDisplacementThisStep;
float fSimLength;
//physical properties
hsVector3 fLinearVelocity;
float fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
bool fNeedsResize;
};
class plMovementStrategy: public plMovementStrategySimulationInterface
class plMovementStrategy
{
public:
virtual void SetControllerCore(plPhysicalControllerCore* core)
{
fCore=core;
fCore->SetMovementSimulationInterface(this);
}
virtual void RefreshConnectionToControllerCore()
{
fCore->SetMovementSimulationInterface(this);
//fCore->SetControllerDimensions(fPreferedControllerWidth,fPreferedControllerHeight);
fCore->BehaveLikeAnimatedPhysical(this->IRequireBehaviourLikeAnAnimatedPhysical());
}
plMovementStrategy(plPhysicalControllerCore* core);
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void SetLinearAcceleration(const hsVector3& accel){fLinearAcceleration=accel;}
virtual const hsVector3& GetLinearAcceleration()const{return fLinearAcceleration;}
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void ResetAchievedLinearVelocity()
{
hsVector3 AchievedLinearVelocity(0.f,0.f,0.f);
if(fCore)fCore->OverrideAchievedVelocity(AchievedLinearVelocity);
}
//proxy functions for Controller Core
virtual float GetAirTime() const { return fTimeInAir; }
virtual void ResetAirTime() { fTimeInAir = 0.f; }
plMovementStrategy(plPhysicalControllerCore* controller);
virtual ~plMovementStrategy() { }
virtual void Apply(float delSecs) = 0;
virtual void Update(float delSecs) { }
virtual void AddContactNormals(hsVector3& vec) { }
virtual void Reset(bool newAge);
virtual bool IsKinematic() { return true; }
protected:
virtual bool IRequireBehaviourLikeAnAnimatedPhysical()=0;
virtual void IApplyKinematic();
plPhysicalControllerCore* fCore;
hsVector3 fLinearAcceleration;
float fAngularAcceleration;
plKey fOwner;
static const float kAirTimeThreshold;
float fTimeInAir;
float fPreferedControllerWidth;
float fPreferedControllerHeight;
plPhysicalControllerCore* fController;
};
class plWalkingStrategy: public plMovementStrategy
class plAnimatedMovementStrategy : public plMovementStrategy
{
public:
plWalkingStrategy(plPhysicalControllerCore* core):plMovementStrategy(core)
{
fGroundHit=false;
fFalseGround=false;
fHitHead=false;
fCore->SetMovementSimulationInterface(this);
fPreferedControllerWidth=core->GetControllerWidth();
fPreferedControllerHeight=core->GetControllerHeight();
fOnTopOfAnimatedPhysLastFrame=false;
}
virtual ~plWalkingStrategy(){};
plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plAnimatedMovementStrategy() { }
void RecalcVelocity(double timeNow, float elapsed, bool useAnim = true);
void SetTurnStrength(float val) { fTurnStr = val; }
float GetTurnStrength() const { return fTurnStr; }
private:
void IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
void IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
plAGApplicator* fRootApp;
hsVector3 fAnimLinearVel;
float fAnimAngularVel;
float fTurnStr;
};
class plWalkingStrategy : public plAnimatedMovementStrategy
{
public:
plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plWalkingStrategy() { }
virtual void Apply(float delSecs);
virtual void Update(float delSecs);
virtual void Update(float delSecs);
virtual void AddContactNormals(hsVector3& vec);
virtual void Reset(bool newAge);
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
void GroundHit() { fGroundHit = true; }
virtual void IAddContactNormals(hsVector3& vec);
virtual void StartJump(){};
float GetAirTime() const { return fTimeInAir; }
void ResetAirTime() { fTimeInAir = 0.0f; }
float GetImpactTime() const { return fImpactTime; }
const hsVector3& GetImpactVelocity() const { return fImpactVelocity; }
bool EnableControlledFlight(bool status);
bool IsControlledFlight() const { return fControlledFlight != 0; }
plPhysical* GetPushingPhysical() const;
bool GetFacingPushingPhysical() const;
protected:
void ICheckForFalseGround();
static const float kAirTimeThreshold;
static const float kControlledFlightThreshold;
hsTArray<hsVector3> fSlidingNormals;
hsVector3 fImpactVelocity;
float fImpactTime;
float fTimeInAir;
float fControlledFlightTime;
int fControlledFlight;
bool fGroundHit;
bool fFalseGround;
bool fHitHead;
bool fOnTopOfAnimatedPhysLastFrame;
hsTArray<hsVector3> fPrevSlidingNormals;
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
bool fHeadHit;
bool fSliding;
bool fClearImpact;
bool fHitGroundInThisAge;
};
class plSwimStrategy: public plMovementStrategy
class plSwimStrategy : public plAnimatedMovementStrategy
{
public:
plSwimStrategy(plPhysicalControllerCore *core);
virtual ~plSwimStrategy(){};
void SetSurface(plSwimRegionInterface *region, float surfaceHeight);
plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plSwimStrategy() { }
virtual void Apply(float delSecs);
virtual void Update(float delSecs);
float GetBuoyancy() { return fBuoyancy; }
bool IsOnGround() { return fOnGround; }
bool HadContacts() { return fHadContacts; }
virtual void IAddContactNormals(hsVector3& vec);
virtual void AddContactNormals(hsVector3& vec);
void SetSurface(plSwimRegionInterface* region, float surfaceHeight);
float GetBuoyancy() const { return fBuoyancy; }
bool IsOnGround() const { return fOnGround; }
bool HadContacts() const { return fHadContacts; }
protected:
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
private:
void IAdjustBuoyancy();
float fBuoyancy;
float fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
bool fOnGround;
bool fHadContacts;
float fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
class plDynamicWalkingStrategy : public plWalkingStrategy
{
public:
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) :
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){};
virtual ~plRidingAnimatedPhysicalStrategy(){};
plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plDynamicWalkingStrategy() { }
virtual void Apply(float delSecs);
virtual void Update(float delSecs);
virtual void PostStep(float delSecs);
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
void GroundHit() { fGroundHit = true; }
virtual void StartJump(){fStartJump = true;}
virtual bool IsKinematic() { return false; }
protected:
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return false;}
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
bool fNeedVelocityOverride;
hsVector3 fOverrideVelocity;
bool fStartJump;
bool ICheckForGround(float& zVelocity);
};
#endif// PLPHYSICALCONTROLLERCORE_H