Browse Source

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.
Skoader 13 years ago committed by Adam Johnson
parent
commit
769cd60617
  1. 2
      Sources/Plasma/FeatureLib/pfAudio/plListener.cpp
  2. 2
      Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp
  3. 2
      Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp
  4. 4
      Sources/Plasma/PubUtilLib/plAvatar/CMakeLists.txt
  5. 1
      Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp
  6. 171
      Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp
  7. 79
      Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h
  8. 1
      Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp
  9. 17
      Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp
  10. 1
      Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h
  11. 20
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp
  12. 6
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h
  13. 1
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp
  14. 4
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp
  15. 2
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h
  16. 157
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp
  17. 4
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h
  18. 13
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp
  19. 2
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h
  20. 137
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp
  21. 6
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h
  22. 579
      Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp
  23. 217
      Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h
  24. 4
      Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp
  25. 6
      Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp
  26. 2
      Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp
  27. 4
      Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp
  28. 1393
      Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp
  29. 448
      Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h
  30. 2
      Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp
  31. 1
      Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp
  32. 10
      Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp
  33. 19
      Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h

2
Sources/Plasma/FeatureLib/pfAudio/plListener.cpp

@ -57,7 +57,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvatar/plAvatarMgr.h"
#include "plAvatar/plArmatureMod.h"
#include "plAvatar/plAvCallbackAction.h"
#include "plAvatar/plPhysicalControllerCore.h"
bool plListener::fPrintDbgInfo = false;

2
Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp

@ -63,7 +63,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "pnSceneObject/plSimulationInterface.h"
#include "plAvatar/plAvatarMgr.h"
#include "plAvatar/plArmatureMod.h"
#include "plAvatar/plAvCallbackAction.h"
#include "plAvatar/plPhysicalControllerCore.h"
// new stuff

2
Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp

@ -554,7 +554,7 @@ bool pySceneObject::IsAvatar()
return false;
}
#include "plAvatar/plAvCallbackAction.h"
#include "plAvatar/plPhysicalControllerCore.h"
PyObject* pySceneObject::GetAvatarVelocity()
{

4
Sources/Plasma/PubUtilLib/plAvatar/CMakeLists.txt

@ -15,7 +15,6 @@ set(plAvatar_SOURCES
plAGMasterSDLModifier.cpp
plAGModifier.cpp
plAnimStage.cpp
plAntiGravAction.cpp
plArmatureEffects.cpp
plArmatureMod.cpp
plAvatarClothing.cpp
@ -32,7 +31,6 @@ set(plAvatar_SOURCES
plAvBrainHuman.cpp
plAvBrainRideAnimatedPhysical.cpp
plAvBrainSwim.cpp
plAvCallbackAction.cpp
plAvLadderModifier.cpp
plAvTaskBrain.cpp
plAvTaskSeek.cpp
@ -60,7 +58,6 @@ set(plAvatar_HEADERS
plAGMasterSDLModifier.h
plAGModifier.h
plAnimStage.h
plAntiGravAction.h
plArmatureEffects.h
plArmatureMod.h
plAvatarClothing.h
@ -78,7 +75,6 @@ set(plAvatar_HEADERS
plAvBrainHuman.h
plAvBrainRideAnimatedPhysical.h
plAvBrainSwim.h
plAvCallbackAction.h
plAvDefs.h
plAvLadderModifier.h
plAvTask.h

1
Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h" // must be first: references havok new
// singular
#include "plAnimStage.h"

171
Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp

@ -1,171 +0,0 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#if 0
// havok first
#include <hkdynamics/entity/rigidbody.h>
#include <hkdynamics/world/subspace.h>
#include "plAntiGravAction.h"
#include "pnSceneObject/plSceneObject.h"
#include "plHavok1/plHKPhysical.h"
#include "plAvatar/plSwimRegion.h"
#include "hsTimer.h"
// This is meant to be a specific physicsAction for the swim behavior
plAntiGravAction::plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp) :
plAnimatedCallbackAction(physical, rootApp),
fOnGround(false),
fBuoyancy(1.f),
fSurfaceHeight(0.f),
fCurrentRegion(nil),
fHadContacts(false)
{
}
plSimDefs::ActionType plAntiGravAction::GetType()
{
return plSimDefs::kAntiGravAction;
}
void plAntiGravAction::apply(Havok::Subspace &space, Havok::hkTime time)
{
double elapsed = time.asDouble() - getRefresh().asDouble();
setRefresh(time);
IAdjustBuoyancy();
Havok::RigidBody *body = fPhysical->GetBody();
float mass = body->getMass();
Havok::Vector3 gravity = space.getGravity();
Havok::Vector3 force = -gravity * (mass * fBuoyancy);
body->applyForce(force);
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
fAnimPosVel.fZ = vel.fZ;
hsVector3 linCurrent(0.f, 0.f, 0.f);
float angCurrent = 0.f;
if (fCurrentRegion != nil)
fCurrentRegion->GetCurrent(fPhysical, linCurrent, angCurrent, (float)elapsed);
int numContacts = fPhysical->GetNumContacts();
fHadContacts = (numContacts > 0);
const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
fOnGround = false;
int i;
for (i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
float dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
{
fOnGround = true;
break;
}
}
fPhysical->SetLinearVelocitySim(fAnimPosVel + linCurrent);
fPhysical->SetAngularVelocitySim(hsVector3(0.f, 0.f, fAnimAngVel + fTurnStr + angCurrent));
}
void plAntiGravAction::SetSurface(plSwimRegionInterface *region, float surfaceHeight)
{
fCurrentRegion = region;
if (region != nil)
fSurfaceHeight = surfaceHeight;
}
void plAntiGravAction::IAdjustBuoyancy()
{
// "surface depth" refers to the depth our handle object should be below
// the surface for the avatar to be "at the surface"
static const float surfaceDepth = 4.0f;
// 1.0 = neutral buoyancy
// 0 = no buoyancy (normal gravity)
// 2.0 = opposite of gravity, floating upwards
static const float buoyancyAtSurface = 1.0f;
if (fCurrentRegion == nil)
{
fBuoyancy = 0.f;
return;
}
hsMatrix44 l2w, w2l;
fPhysical->GetTransform(l2w, w2l);
float depth = fSurfaceHeight - surfaceDepth - l2w.GetTranslate().fZ;
if (depth < -1)
fBuoyancy = 0.f; // Same as being above ground. Plain old gravity.
else if (depth < 0)
fBuoyancy = 1 + depth;
else
{
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
if (vel.fZ > 0)
{
if (vel.fZ > fCurrentRegion->fMaxUpwardVel)
{
vel.fZ = fCurrentRegion->fMaxUpwardVel;
fPhysical->SetLinearVelocitySim(vel);
}
else
{
if (depth > 1)
fBuoyancy = fCurrentRegion->fUpBuoyancy;
else
fBuoyancy = (fCurrentRegion->fUpBuoyancy - 1) * depth + 1;
}
}
else
{
if (depth > 1)
fBuoyancy = fCurrentRegion->fDownBuoyancy;
else
fBuoyancy = (fCurrentRegion->fDownBuoyancy - 1) * depth + 1;
}
}
}
#endif

79
Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h

@ -1,79 +0,0 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#if 0//ndef PL_ANTI_GRAV_ACTION_H
#define PL_ANTI_GRAV_ACTION_H
#include "plAvCallbackAction.h"
class plSwimRegionInterface;
class plAntiGravAction : public plAnimatedCallbackAction
{
public:
plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp);
/** Return the type of the action as defined in the enum plSimDefs::ActionType.
Used to retrieve actions by entity/type indexing, and to
reuse actions that can be shared between entities. */
virtual plSimDefs::ActionType GetType();
/** Called by Havok at substep frequency. */
void apply(Havok::Subspace &s, Havok::hkTime time);
void SetSurface(plSwimRegionInterface *region, float surfaceHeight);
float GetBuoyancy() { return fBuoyancy; }
bool IsOnGround() { return fOnGround; }
bool HadContacts() { return fHadContacts; }
protected:
void IAdjustBuoyancy();
bool fOnGround;
bool fHadContacts;
float fBuoyancy;
float fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
#endif

1
Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h"
#include "plStatusLog/plStatusLog.h"
#include "plArmatureEffects.h"

17
Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp

@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvBrainHuman.h"
#include "plMatrixChannel.h"
#include "plAvatarTasks.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plAvBrainCritter.h"
// global
@ -534,8 +534,7 @@ void plArmatureModBase::EnablePhysics(bool status, uint16_t reason /* = kDisable
// i.e. normal enabled physical
void plArmatureModBase::EnablePhysicsKinematic(bool status)
{
if (fController)
fController->Kinematic(status);
EnablePhysics(!status, kDisableReasonKinematic);
}
void plArmatureModBase::EnableDrawing(bool status, uint16_t reason /* = kDisableReasonUnknown */)
@ -2670,19 +2669,7 @@ void plArmatureMod::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
hsPoint3 kPos;
const char *kinematic = "n.a.";
const char* frozen = "n.a.";
if (fController)
{
fController->GetKinematicPosition(kPos);
kinematic = fController->IsKinematic() ? "on" : "off";
}
sprintf(strBuf, "kinematc(world): %.2f, %.2f, %.2f Kinematic: %3s",
kPos.fX, kPos.fY, kPos.fZ,kinematic);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
if (fController)
frozen = fController->IsEnabled() ? "no" : "yes";

1
Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h

@ -146,6 +146,7 @@ public:
kDisableReasonCCR = 0x0008,
kDisableReasonVehicle = 0x0010,
kDisableReasonGenericBrain = 0x0020,
kDisableReasonKinematic = 0x0040
};
void EnablePhysics(bool status, uint16_t reason = kDisableReasonUnknown);
void EnablePhysicsKinematic(bool status);

20
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp

@ -40,7 +40,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plAvBrainCritter.h"
#include "plAvBrainHuman.h"
#include "plArmatureMod.h"
@ -125,7 +125,7 @@ protected:
///////////////////////////////////////////////////////////////////////////////
plAvBrainCritter::plAvBrainCritter(): fCallbackAction(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true),
plAvBrainCritter::plAvBrainCritter(): fWalkingStrategy(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true),
fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0),
fAngRight(0)
{
@ -143,8 +143,8 @@ plAvBrainCritter::~plAvBrainCritter()
fBehaviors[i] = nil;
}
delete fCallbackAction;
fCallbackAction = nil;
delete fWalkingStrategy;
fWalkingStrategy = nil;
fUserBehaviors.clear();
fReceivers.clear();
@ -167,8 +167,8 @@ bool plAvBrainCritter::Apply(double time, float elapsed)
IProcessBehavior(time, elapsed); // just continue with the currently running one
// update our controller to keep us turned and moving to where we want to go
fCallbackAction->RecalcVelocity(time, time - elapsed);
fCallbackAction->SetTurnStrength(IGetTurnStrength(time));
fWalkingStrategy->SetTurnStrength(IGetTurnStrength(time));
fWalkingStrategy->RecalcVelocity(time, elapsed);
return plArmatureBrain::Apply(time, elapsed);
}
@ -188,13 +188,13 @@ void plAvBrainCritter::Activate(plArmatureModBase* avMod)
IInitBaseAnimations();
// create the controller if we haven't done so already
if (!fCallbackAction)
if (!fWalkingStrategy)
{
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
// tell people that care that we are good to go
@ -224,7 +224,7 @@ void plAvBrainCritter::Resume()
// fade in the idle
fNextMode = kIdle;
fCallbackAction->Reset(false);
fWalkingStrategy->Reset(false);
plArmatureBrain::Resume();
}

6
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h

@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "pnKeyedObject/plKey.h"
class plArmatureMod;
class plWalkingController;
class plWalkingStrategy;
class plAIMsg;
class plAvBrainCritter : public plArmatureBrain
@ -134,8 +134,6 @@ public:
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
plWalkingController* GetCallbackAction() {return fCallbackAction;}
// For the console
static bool fDrawDebug;
@ -159,7 +157,7 @@ protected:
std::vector<plArmatureMod*> IAvatarsICanSee() const;
std::vector<plArmatureMod*> IAvatarsICanHear() const;
plWalkingController* fCallbackAction;
plWalkingStrategy* fWalkingStrategy;
int fCurMode; // current behavior we are running
int fNextMode; // the next behavior to run (-1 if we aren't switching on next eval)
bool fFadingNextBehavior; // is the next behavior supposed to blend?

1
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp

@ -42,7 +42,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
// local includes
#include "plAvBrainDrive.h"
#include "plArmatureMod.h"
#include "plAvCallbackAction.h"
// global includes
#include "hsTimer.h"

4
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h" // havok-contaminated file: must go first
// singular
#include "plAvBrainGeneric.h"
@ -94,7 +93,6 @@ plAvBrainGeneric::plAvBrainGeneric()
fFadeIn(0.0f),
fFadeOut(0.0f),
fMoveMode(kMoveRelative),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown)
{
}
@ -122,7 +120,6 @@ plAvBrainGeneric::plAvBrainGeneric(plAnimStageVec *stages,
fFadeIn(fadeIn),
fFadeOut(fadeOut),
fMoveMode(moveMode),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown)
{
}
@ -141,7 +138,6 @@ plAvBrainGeneric::plAvBrainGeneric(uint32_t exitFlags, float fadeIn, float fadeO
fFadeIn(fadeIn),
fFadeOut(fadeOut),
fMoveMode(moveMode),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown)
{

2
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h

@ -49,7 +49,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
class plAnimStage;
class plAnimStageVec;
class plAvBrainGenericMsg;
class plHorizontalFreezeAction;
class plNotifyMsg;
/** \class plAvBrainGeneric
@ -300,7 +299,6 @@ protected:
int fCurStage; // which stage are we playing? (zero-based)
BrainType fType; // what type of brain are we?
uint32_t fExitFlags; // what will cause us to exit?
plHorizontalFreezeAction *fCallbackAction;
bool fForward; // are we currently moving forward or backward through the stages?
// this is used by the "auto-" movement types in the stages

157
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp

@ -40,9 +40,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include "plAvCallbackAction.h" // subclasses a havok object; must be in first include section
#include "HeadSpin.h"
#include "plPhysicalControllerCore.h"
#include "plAvBrainHuman.h"
#include "plAvBrainClimb.h"
#include "plAvBrainDrive.h"
@ -140,7 +140,7 @@ plAvBrainHuman::TurnCurve plAvBrainHuman::GetTurnCurve(bool walk)
plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) :
fHandleAGMod(nil),
fStartedTurning(-1.0f),
fCallbackAction(nil),
fWalkingStrategy(nil),
fPreconditions(0),
fIsActor(isActor)
{
@ -154,9 +154,9 @@ bool plAvBrainHuman::Apply(double timeNow, float elapsed)
#endif
// SetTurnStrength runs first to make sure it's set to a sane value
// (or cleared). RunStandardBehaviors may overwrite it.
fCallbackAction->SetTurnStrength(IGetTurnStrength(timeNow));
fWalkingStrategy->SetTurnStrength(IGetTurnStrength(timeNow));
RunStandardBehaviors(timeNow, elapsed);
fCallbackAction->RecalcVelocity(timeNow, timeNow - elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
fWalkingStrategy->RecalcVelocity(timeNow, elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
plArmatureBrain::Apply(timeNow, elapsed);
#ifndef _DEBUG
@ -177,13 +177,13 @@ void plAvBrainHuman::Activate(plArmatureModBase *avMod)
IInitBoneMap();
IInitAnimations();
if (!fCallbackAction)
if (!fWalkingStrategy)
{
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
@ -328,8 +328,8 @@ plAvBrainHuman::~plAvBrainHuman()
delete fBehaviors[i];
fBehaviors.Reset();
delete fCallbackAction;
fCallbackAction = nil;
delete fWalkingStrategy;
fWalkingStrategy = nil;
}
void plAvBrainHuman::Deactivate()
@ -361,7 +361,7 @@ void plAvBrainHuman::Resume()
if (fAvMod->GetInputFlag(S_PUSH_TO_TALK))
IChatOn();
fCallbackAction->Reset(false);
fWalkingStrategy->Reset(false);
plArmatureBrain::Resume();
}
@ -465,25 +465,23 @@ bool plAvBrainHuman::MsgReceive(plMessage * msg)
{
if(ride->Entering())
{
//plAvBrainRideAnimatedPhysical *rideBrain = new plAvBrainRideAnimatedPhysical();
//fAvMod->PushBrain(rideBrain);
delete fCallbackAction;
// Switch to dynamic walking strategy
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = fAvMod->GetController();
fCallbackAction= new plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = new plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
else
{
delete fCallbackAction;
// Restore default walking strategy
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = fAvMod->GetController();
fCallbackAction= new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
//hsStatusMessage("Got an exiting ride animated physical message");
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
}
@ -557,8 +555,8 @@ float plAvBrainHuman::IGetTurnStrength(double timeNow)
// Turning based on keypress
if ((turnLeftStrength > 0.f)
|| (turnRightStrength > 0.f)
|| (!fCallbackAction->IsOnGround()
&& !fCallbackAction->IsControlledFlight())
|| (!fWalkingStrategy->IsOnGround()
&& !fWalkingStrategy->IsControlledFlight())
) {
float t = (float)(timeNow - fStartedTurning);
float turnSpeed;
@ -590,7 +588,7 @@ float plAvBrainHuman::IGetTurnStrength(double timeNow)
result += fAvMod->GetKeyTurnStrength() * turnSpeed;
}
if (!fCallbackAction->IsControlledFlight())
if (!fWalkingStrategy->IsControlledFlight())
result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed;
return result;
@ -647,7 +645,7 @@ void plAvBrainHuman::ResetIdle()
void plAvBrainHuman::IdleOnly(bool instantOff)
{
if (!fCallbackAction)
if (!fWalkingStrategy)
return;
float rate = instantOff ? 0.f : 1.f;
@ -673,7 +671,7 @@ bool plAvBrainHuman::IsMovementZeroBlend()
void plAvBrainHuman::TurnToPoint(hsPoint3 point)
{
if (!fCallbackAction->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
if (!fWalkingStrategy->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
return;
hsPoint3 avPos;
@ -869,23 +867,23 @@ void plAvBrainHuman::Spawn(double timeNow)
bool plAvBrainHuman::LeaveAge()
{
plPhysicalControllerCore* controller = fAvMod->GetController();
if(!controller->BehavingLikeAnAnimatedPhysical())
// If our current walking strategy is dynamic, restore the default kinematic strategy.
if (!fWalkingStrategy->IsKinematic())
{
controller->BehaveLikeAnimatedPhysical(true);
delete fCallbackAction;
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
fCallbackAction= new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
}
fWalkingStrategy->Reset(true);
plArmatureBrain::LeaveAge();
// pin the physical so it doesn't fall when the world is deleted
fAvMod->EnablePhysics(false);
// this will get set to true when we hit ground
fCallbackAction->Reset(true);
return false;
}
@ -895,11 +893,10 @@ void plAvBrainHuman::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *st
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
const char *grounded = fCallbackAction->IsOnGround() ? "yes" : "no";
const char *falseGrounded = fCallbackAction->IsOnFalseGround() ? "yes" : "no";
const char *pushing = (fCallbackAction->GetPushingPhysical() ? (fCallbackAction->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
sprintf(strBuf, "Ground: %3s, FalseGround: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
grounded, falseGrounded, fCallbackAction->GetAirTime(), fCallbackAction->GetImpactTime(), pushing);
const char *grounded = fWalkingStrategy->IsOnGround() ? "yes" : "no";
const char *pushing = (fWalkingStrategy->GetPushingPhysical() ? (fWalkingStrategy->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
sprintf(strBuf, "Ground: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
grounded, fWalkingStrategy->GetAirTime(), fWalkingStrategy->GetImpactTime(), pushing);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
@ -1012,8 +1009,8 @@ bool Run::PreCondition(double time, float elapsed)
{
if (fAnim)
{
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1023,8 +1020,8 @@ bool Walk::PreCondition(double time, float elapsed)
{
if (fAnim)
{
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1034,8 +1031,8 @@ bool WalkBack::PreCondition(double time, float elapsed)
{
if (fAnim)
{
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1048,7 +1045,7 @@ bool StepLeft::PreCondition(double time, float elapsed)
return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
!(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
fHuBrain->fCallbackAction->IsOnGround());
fHuBrain->fWalkingStrategy->IsOnGround());
}
return false;
}
@ -1060,7 +1057,7 @@ bool StepRight::PreCondition(double time, float elapsed)
return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
!(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
fHuBrain->fCallbackAction->IsOnGround());
fHuBrain->fWalkingStrategy->IsOnGround());
}
return false;
}
@ -1101,8 +1098,8 @@ bool MovingTurnLeft::PreCondition(double time, float elapsed)
{
if (fAvMod->GetTurnStrength() > 0)
{
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1112,8 +1109,8 @@ bool MovingTurnRight::PreCondition(double time, float elapsed)
{
if (fAvMod->GetTurnStrength() < 0)
{
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
@ -1122,14 +1119,14 @@ bool MovingTurnRight::PreCondition(double time, float elapsed)
void Jump::IStart()
{
fHuBrain->fCallbackAction->EnableControlledFlight(true);
fHuBrain->fWalkingStrategy->EnableControlledFlight(true);
plHBehavior::IStart();
}
void Jump::IStop()
{
fHuBrain->fCallbackAction->EnableControlledFlight(false);
fHuBrain->fWalkingStrategy->EnableControlledFlight(false);
plHBehavior::IStop();
}
@ -1140,7 +1137,7 @@ bool StandingJump::PreCondition(double time, float elapsed)
{
if (GetStrength() > 0.f)
{
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{
return false;
@ -1152,7 +1149,7 @@ bool StandingJump::PreCondition(double time, float elapsed)
if (fAvMod->JumpKeyDown() &&
!fAvMod->ForwardKeyDown() &&
fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround())
fHuBrain->fWalkingStrategy->IsOnGround())
{
if (fAvMod->ConsumeJump())
return true;
@ -1168,7 +1165,7 @@ bool WalkingJump::PreCondition(double time, float elapsed)
{
if (GetStrength() > 0.f)
{
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{
return false;
@ -1181,8 +1178,8 @@ bool WalkingJump::PreCondition(double time, float elapsed)
!fAvMod->FastKeyDown() &&
fAvMod->ForwardKeyDown() &&
fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
{
if (fAvMod->ConsumeJump())
return true;
@ -1198,7 +1195,7 @@ bool RunningJump::PreCondition(double time, float elapsed)
{
if (GetStrength() > 0.f)
{
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{
return false;
@ -1211,8 +1208,8 @@ bool RunningJump::PreCondition(double time, float elapsed)
fAvMod->ForwardKeyDown() &&
fAvMod->FastKeyDown() &&
fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
{
if (fAvMod->ConsumeJump())
return true;
@ -1237,13 +1234,13 @@ bool RunningImpact::PreCondition(double time, float elapsed)
{
if (fDuration > 0.0f)
fDuration = fDuration - elapsed;
else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime)
else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fY < kRunningImpactThresh)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY < kRunningImpactThresh)
{
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
if (fMaxBlend > 1)
fMaxBlend = 1;
fDuration = 1.0f / fFadeIn;
@ -1267,13 +1264,13 @@ bool GroundImpact::PreCondition(double time, float elapsed)
bool result = false;
if (fDuration > 0.0f)
fDuration = fDuration - elapsed;
else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime)
else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fY >= kRunningImpactThresh)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY >= kRunningImpactThresh)
{
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
if (fMaxBlend > 1)
fMaxBlend = 1;
fDuration = 1.0f / fFadeIn;
@ -1292,7 +1289,7 @@ void GroundImpact::IStop()
bool Fall::PreCondition(double time, float elapsed)
{
return !fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->HitGroundInThisAge();
return !fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->HitGroundInThisAge();
}
void Fall::Process(double time, float elapsed)
@ -1304,7 +1301,7 @@ void Fall::Process(double time, float elapsed)
if (fAnim && fAnim->GetBlend() > 0.8)
{
float panicThresh = plAvBrainHuman::kAirTimePanicThreshold;
if (panicThresh > 0.0f && fHuBrain->fCallbackAction->GetAirTime() > panicThresh)
if (panicThresh > 0.0f && fHuBrain->fWalkingStrategy->GetAirTime() > panicThresh)
{
fHuBrain->IdleOnly(); // clear the fall state; we're going somewhere new
fAvMod->PanicLink();
@ -1321,7 +1318,7 @@ void Push::Process(double time, float elapsed)
fAvMod->GetPositionAndRotationSim(&pos, &rot);
hsPoint3 lookAt;
fHuBrain->fCallbackAction->GetPushingPhysical()->GetPositionSim(lookAt);
fHuBrain->fWalkingStrategy->GetPushingPhysical()->GetPositionSim(lookAt);
hsVector3 up(0.f, 0.f, 1.f);
float angle = atan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + M_PI / 2;
hsQuat targRot(angle, &up);
@ -1335,23 +1332,23 @@ void Push::Process(double time, float elapsed)
globFwd = rot.Rotate(&globFwd);
if (globFwd.fX < 0)
fHuBrain->fCallbackAction->SetTurnStrength(-turnSpeed);
fHuBrain->fWalkingStrategy->SetTurnStrength(-turnSpeed);
else
fHuBrain->fCallbackAction->SetTurnStrength(turnSpeed);
fHuBrain->fWalkingStrategy->SetTurnStrength(turnSpeed);
}
//bool PushIdle::PreCondition(double time, float elapsed)
//{
// return (fHuBrain->fCallbackAction->GetPushingPhysical() &&
// fHuBrain->fCallbackAction->IsOnGround() &&
// return (fHuBrain->fWalkingStrategy->GetPushingPhysical() &&
// fHuBrain->fWalkingStrategy->IsOnGround() &&
// !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown()
// && fAvMod->GetTurnStrength() == 0);
//}
bool PushWalk::PreCondition(double time, float elapsed)
{
return (fHuBrain->fCallbackAction->GetPushingPhysical() && fHuBrain->fCallbackAction->GetFacingPushingPhysical() &&
fHuBrain->fCallbackAction->IsOnGround() &&
return (fHuBrain->fWalkingStrategy->GetPushingPhysical() && fHuBrain->fWalkingStrategy->GetFacingPushingPhysical() &&
fHuBrain->fWalkingStrategy->IsOnGround() &&
fAvMod->ForwardKeyDown());
}
@ -1366,7 +1363,7 @@ bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const ch
{
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index()));
const char *names[3] = {enterAnim, idleAnim, exitAnim};
if (!huBrain || !huBrain->fCallbackAction->IsOnGround() || !huBrain->fCallbackAction->HitGroundInThisAge() || huBrain->IsRunningTask() ||
if (!huBrain || !huBrain->fWalkingStrategy->IsOnGround() || !huBrain->fWalkingStrategy->HitGroundInThisAge() || huBrain->IsRunningTask() ||
!avatar->IsPhysicsEnabled() || avatar->FindMatchingGenericBrain(names, 3))
return false;
@ -1429,7 +1426,7 @@ bool AvatarEmote(plArmatureMod *avatar, const char *emoteName)
if (swimBrain && swimBrain->IsSwimming())
return false;
if (huBrain && huBrain->fCallbackAction->IsOnGround() && huBrain->fCallbackAction->HitGroundInThisAge() && !huBrain->IsRunningTask() &&
if (huBrain && huBrain->fWalkingStrategy->IsOnGround() && huBrain->fWalkingStrategy->HitGroundInThisAge() && !huBrain->IsRunningTask() &&
emote && !alreadyActive && avatar->IsPhysicsEnabled())
{
plKey avKey = avatar->GetKey();

4
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h

@ -58,7 +58,7 @@ class plAGAnimInstance;
class plAvTask;
class plAvTaskMsg;
class plAvBrainHuman;
class plWalkingController;
class plWalkingStrategy;
class plArmatureUpdateMsg;
class plClimbMsg;
class plControlEventMsg;
@ -164,7 +164,7 @@ public:
static const float kControlledFlightThreshold;
static const float kAirTimeThreshold;
static const float kAirTimePanicThreshold;
plWalkingController* fCallbackAction;
plWalkingStrategy* fWalkingStrategy;
protected:
plAGAnim *FindCustomAnim(const char *baseName);

13
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp

@ -44,7 +44,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvBrainHuman.h"
#include "plAvBrain.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plMessage/plRideAnimatedPhysMsg.h"
@ -52,20 +52,19 @@ void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
IInitAnimations();
if (!fCallbackAction)
if (!fWalkingStrategy)
{
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = new plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = new plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
}
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
{
delete fCallbackAction;
fCallbackAction=nil;
delete fWalkingStrategy;
fWalkingStrategy = nil;
}
void plAvBrainRideAnimatedPhysical::Deactivate()

2
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h

@ -41,8 +41,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include "plAvBrainHuman.h"
class plRidingAnimatedPhysicalController;
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
{
public:

137
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp

@ -46,10 +46,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
//
/////////////////////////////////////////////////////////////////////////////////////////
//#include <hkmath/vector3.h>
//#include <hkdynamics/entity/rigidbody.h>
#include "plAntiGravAction.h" // descends from Havok class, so must be included first, like havok objects
// singular
#include "plAvBrainSwim.h"
@ -69,7 +65,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsTimer.h"
#include "plPhysical.h"
#include "plPhysicalControllerCore.h"
#include "plAvCallbackAction.h"
// other
#include "plPhysical/plCollisionDetector.h"
#include "plPipeline/plDebugText.h"
@ -180,18 +175,16 @@ public:
static const float timeToMaxTurn = 0.5f;
static const float incPerSec = maxTurnSpeed / timeToMaxTurn;
// hsAssert(0, "fixme physx");
float oldSpeed = fabs(fSwimBrain->fCallbackAction->GetTurnStrength());
float oldSpeed = fabs(fSwimBrain->fSwimStrategy->GetTurnStrength());
float thisInc = elapsed * incPerSec;
float newSpeed = min(oldSpeed + thisInc, maxTurnSpeed);
fSwimBrain->fCallbackAction->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength());
fSwimBrain->fSwimStrategy->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength());
// the turn is actually applied during PhysicsUpdate
}
virtual void IStop()
{
// hsAssert(0, "fixme physx");
if (fSwimBrain->fCallbackAction)
fSwimBrain->fCallbackAction->SetTurnStrength(0.0f);
if (fSwimBrain->fSwimStrategy)
fSwimBrain->fSwimStrategy->SetTurnStrength(0.0f);
plSwimBehavior::IStop();
}
};
@ -237,7 +230,7 @@ public:
const float plAvBrainSwim::kMinSwimDepth = 4.0f;
plAvBrainSwim::plAvBrainSwim() :
fCallbackAction(nil),
fSwimStrategy(nil),
fMode(kWalking),
fSurfaceDistance(0.f)
{
@ -250,12 +243,9 @@ plAvBrainSwim::plAvBrainSwim() :
plAvBrainSwim::~plAvBrainSwim()
{
if(fCallbackAction)
{
IDetachAction();
delete fCallbackAction;
fCallbackAction=nil;
}
delete fSwimStrategy;
fSwimStrategy = nil;
fSurfaceProbeMsg->UnRef();
int i;
@ -273,8 +263,7 @@ bool plAvBrainSwim::Apply(double time, float elapsed)
fMode = kWading;
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this));
// hsAssert(0, "fixme physx");
if (huBrain && !huBrain->fCallbackAction->IsOnGround())
if (huBrain && !huBrain->fWalkingStrategy->IsOnGround())
{
// We're jumping in! Trigger splash effect (sound)
plArmatureEffectMsg *msg = new plArmatureEffectMsg(fAvMod->GetArmatureEffects()->GetKey(), kTime);
@ -318,8 +307,7 @@ bool plAvBrainSwim::Apply(double time, float elapsed)
// The contact check is so that if buoyancy bobs us a little too high, we don't
// switch to wading only to fall again.
// hsAssert(0, "fixme physx");
if (fSurfaceDistance < kMinSwimDepth-.5 && fCallbackAction->HadContacts())
if (fSurfaceDistance < kMinSwimDepth-.5 && fSwimStrategy->HadContacts())
IStartWading();
}
else if (fMode == kSwimming3D)
@ -346,13 +334,12 @@ bool plAvBrainSwim::MsgReceive(plMessage *msg)
else
fSurfaceDistance = -100.f;
// hsAssert(0, "fixme physx");
if (fCallbackAction)
if (fSwimStrategy)
{
if (region)
fCallbackAction->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
fSwimStrategy->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
else
fCallbackAction->SetSurface(nil, 0.f);
fSwimStrategy->SetSurface(nil, 0.f);
}
return true;
}
@ -419,20 +406,16 @@ void plAvBrainSwim::Activate(plArmatureModBase* avMod)
void plAvBrainSwim::Deactivate()
{
plArmatureBrain::Deactivate();
IDetachAction();
}
void plAvBrainSwim::Suspend()
{
if (fMode == kSwimming2D)
IDetachAction();
}
void plAvBrainSwim::Resume()
{
if (fMode == kSwimming2D)
IAttachAction();
fSwimStrategy->Reset(false);
}
bool plAvBrainSwim::IsWalking()
@ -460,8 +443,6 @@ void plAvBrainSwim::IStartWading()
for (i = 0; i < fBehaviors.GetCount(); i++)
fBehaviors[i]->SetStrength(0.f, 2.f);
IDetachAction();
if (fAvMod->IsLocalAvatar())
{
plCameraMsg* pMsg = new plCameraMsg;
@ -479,7 +460,16 @@ void plAvBrainSwim::IStartSwimming(bool is2D)
plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this);
nextBrain->Suspend();
IAttachAction();
if (!fSwimStrategy)
{
plSceneObject * avObj = fArmature->GetTarget(0);
plAGModifier *agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore *controller = fAvMod->GetController();
fSwimStrategy = new plSwimStrategy(agMod->GetApplicator(kAGPinTransform), controller);
}
fSwimStrategy->Reset(false);
if (is2D)
fMode = kSwimming2D;
else
@ -509,8 +499,8 @@ bool plAvBrainSwim::IProcessSwimming2D(double time, float elapsed)
else
behavior->SetStrength(0.f, 2.f);
}
// hsAssert(0, "fixme physx");
fCallbackAction->RecalcVelocity(time, time - elapsed);
fSwimStrategy->RecalcVelocity(time, elapsed);
return true;
}
@ -568,59 +558,6 @@ bool plAvBrainSwim::IInitAnimations()
return true;
}
bool plAvBrainSwim::IAttachAction()
{
bool result = false;
if(fAvMod)
{
// hsAssert(0, "fixme physx");
plPhysicalControllerCore *physical = fAvMod->GetController();
if (physical)
{
if (!fCallbackAction)
{
plSceneObject * avObj = fArmature->GetTarget(0);
plAGModifier *agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
fCallbackAction = new plSwimmingController(avObj, agMod->GetApplicator(kAGPinTransform),physical);
// physical->AttachAction(fCallbackAction, true, false);
result = true;
}
else
{
fCallbackAction->ActivateController();
}
}
}
return result;
}
bool plAvBrainSwim::IDetachAction()
{
bool result = false;
if (fCallbackAction)
{
// hsAssert(0, "fixme physx");
// plPhysical *physical = fAvMod->GetPhysical();
//
// if(physical)
// {
// physical->RemoveAction(fCallbackAction);
// result = true; // there was an action and we removed it
// }
// TODO: We get a compiler warning about deleting a pointer to an
// undefined class. So, who knows what the code is actually doing.
// Seems bad. Just putting a note in here for whoever fixes the
// physx issue.
//delete fCallbackAction;
//fCallbackAction = nil;
}
return result;
}
void plAvBrainSwim::IProbeSurface()
{
hsPoint3 ourPos = fAvMod->GetTarget(0)->GetLocalToWorld().GetTranslate();
@ -676,21 +613,15 @@ void plAvBrainSwim::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
float buoy = fSwimStrategy ? fSwimStrategy->GetBuoyancy() : 0.0f;
sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
// hsAssert(0, "fixme physx");
// float buoy = fCallbackAction? fCallbackAction->GetBuoyancy() : 0.0f;
// sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy);
// debugTxt.DrawString(x, y, strBuf);
// y += lineHeight;
//
// hsVector3 linV;
// fAvMod->GetPhysical()->GetLinearVelocitySim(linV);
// hsVector3 angV;
// fAvMod->GetPhysical()->GetAngularVelocitySim(angV);
// float angle = angV.fZ > 0 ? angV.Magnitude() : -angV.Magnitude();
// sprintf(strBuf, "Velocity: Linear (%5.2f, %5.2f, %5.2f), Angular %5.2f", linV.fX, linV.fY, linV.fZ, angle);
// debugTxt.DrawString(x, y, strBuf);
// y += lineHeight;
hsVector3 linV = fAvMod->GetController()->GetAchievedLinearVelocity();
sprintf(strBuf, "Linear Velocity: (%5.2f, %5.2f, %5.2f)", linV.fX, linV.fY, linV.fZ);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
int i;
for (i = 0; i < fBehaviors.GetCount(); i++)

6
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h

@ -51,7 +51,7 @@ class plAntiGravAction;
class plControlEventMsg;
class plLOSRequestMsg;
class plSwimRegionInterface;
class plSwimmingController;
class plSwimStrategy;
class plAvBrainSwim : public plArmatureBrain
{
public:
@ -73,7 +73,7 @@ public:
bool IsSwimming();
float GetSurfaceDistance() { return fSurfaceDistance; }
plSwimmingController *fCallbackAction;
plSwimStrategy *fSwimStrategy;
static const float kMinSwimDepth;
protected:
@ -86,8 +86,6 @@ protected:
bool IProcessBehaviors(double time, float elapsed);
virtual bool IInitAnimations();
bool IAttachAction();
bool IDetachAction();
void IProbeSurface();
bool IHandleControlMsg(plControlEventMsg* msg);
float IGetTargetZ();

579
Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp

@ -1,579 +0,0 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h"
#include "plMessage/plLOSHitMsg.h"
#include "plArmatureMod.h" // for LOS enum type
#include "plMatrixChannel.h"
#include "hsTimer.h"
#include "plPhysicalControllerCore.h"
// Generic geom utils.
static bool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
static void AngularVelocity(float &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
static float AngleRad2d (float x1, float y1, float x3, float y3);
inline hsVector3 GetYAxis(hsMatrix44 &mat)
{
return hsVector3(mat.fMap[1][0], mat.fMap[1][1], mat.fMap[1][2]);
}
plAnimatedController::plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: fRootObject(rootObject)
, fRootApp(rootApp)
, fController(controller)
, fTurnStr(0.f)
, fAnimAngVel(0.f)
, fAnimPosVel(0.f, 0.f, 0.f)
{
}
void plAnimatedController::RecalcVelocity(double timeNow, double timePrev, bool useAnim /* = true */)
{
if (useAnim)
{
// while you may think it would be correct to cache this,
// what we're actually asking is "what would the animation's
// position be at the previous time given its *current*
// parameters (particularly blends)"
hsMatrix44 prevMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timePrev, true);
hsMatrix44 curMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timeNow, true);
// If we get a valid linear velocity (ie, we didn't wrap around in the anim),
// use it. Otherwise just reuse the previous frames velocity.
hsVector3 linearVel;
if (LinearVelocity(linearVel, (float)(timeNow - timePrev), prevMat, curMat))
fAnimPosVel = linearVel;
// Automatically sets fAnimAngVel
AngularVelocity(fAnimAngVel, (float)(timeNow - timePrev), prevMat, curMat);
}
else
{
fAnimPosVel.Set(0.f, 0.f, 0.f);
fAnimAngVel = 0.f;
}
if (fController)
fController->SetVelocities(fAnimPosVel, fAnimAngVel + fTurnStr);
}
///////////////////////////////////////////////////////////////////////////
const float plWalkingController::kControlledFlightThreshold = 1.f; // seconds
plWalkingController::plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: plAnimatedController(rootObject, rootApp, controller)
, fHitGroundInThisAge(false)
, fWaitingForGround(false)
, fControlledFlightTime(0)
, fControlledFlight(0)
, fImpactTime(0.f)
, fImpactVelocity(0.f, 0.f, 0.f)
, fClearImpact(false)
, fGroundLastFrame(false)
{
if (fController)
{
fWalkingStrategy= new plWalkingStrategy(fController);
fController->SetMovementSimulationInterface(fWalkingStrategy);
}
else
fWalkingStrategy = nil;
}
void plWalkingController::RecalcVelocity(double timeNow, double timePrev, bool useAnim)
{
if (!fHitGroundInThisAge && fController && fController->IsEnabled() && fWalkingStrategy->IsOnGround())
fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now.
if (fClearImpact)
{
fImpactTime = 0.f;
fImpactVelocity.Set(0.f, 0.f, 0.f);
}
if (fController && !fWalkingStrategy->IsOnGround())
{
// PhysX Hack: AchievedLinearVelocity is a Cyanic fix for superjumps. LinearVelocity is
// always (0,0,0) outside of the controller update proc
fImpactTime = fWalkingStrategy->GetAirTime();
fImpactVelocity = fController->GetAchievedLinearVelocity();
// convert orientation from subworld to avatar-local coordinates
fImpactVelocity = (hsVector3)fController->GetLocalRotation().Rotate(&fImpactVelocity);
fClearImpact = false;
}
else
fClearImpact = true;
if (IsControlledFlight())
{
if (fWalkingStrategy && fWalkingStrategy->IsOnGround())
fControlledFlightTime = fWalkingStrategy->GetAirTime();
if(fGroundLastFrame&&(fWalkingStrategy && !fWalkingStrategy->IsOnGround()))
{
//we have started to leave the ground tell the movement strategy in case it cares
fWalkingStrategy->StartJump();
}
if (fControlledFlightTime > kControlledFlightThreshold)
EnableControlledFlight(false);
}
if (fWalkingStrategy)
fGroundLastFrame = fWalkingStrategy->IsOnGround();
else
fGroundLastFrame=false;
plAnimatedController::RecalcVelocity(timeNow, timePrev, useAnim);
}
void plWalkingController::Reset(bool newAge)
{
ActivateController();
if (newAge)
{
if (fWalkingStrategy)
fWalkingStrategy->ResetAirTime();
fHitGroundInThisAge = false;
}
}
void plWalkingController::ActivateController()
{
if (fWalkingStrategy)
{
fWalkingStrategy->RefreshConnectionToControllerCore();
}
else
{
fWalkingStrategy= new plWalkingStrategy(fController);
fWalkingStrategy->RefreshConnectionToControllerCore();
}
}
bool plWalkingController::EnableControlledFlight(bool status)
{
if (status)
{
if (fControlledFlight == 0)
fControlledFlightTime = 0.f;
++fControlledFlight;
fWaitingForGround = true;
}
else
fControlledFlight = max(--fControlledFlight, 0);
return status;
}
plWalkingController::~plWalkingController()
{
delete fWalkingStrategy;
if (fController)
fController->SetMovementSimulationInterface(nil);
}
#if 0
void plWalkingController::Update()
{
// double elapsed = time.asDouble() - getRefresh().asDouble();
// setRefresh(time);
//
// bool isPhysical = !fPhysical->GetProperty(plSimulationInterface::kPinned);
// const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
// bool alreadyInAge = fHitGroundInThisAge;
//
// int numContacts = fPhysical->GetNumContacts();
// bool ground = false;
// fPushingPhysical = nil;
// int i, j;
/* for(i = 0; i < numContacts; i++)
{
plHKPhysical *contactPhys = fPhysical->GetContactPhysical(i);
if (!contactPhys)
continue; // Physical no longer exists. Skip it.
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
float dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
ground = true;
else if (contactPhys->GetProperty(plSimulationInterface::kAvAnimPushable))
{
hsPoint3 position;
hsQuat rotation;
fPhysical->GetPositionAndRotationSim(&position, &rotation);
hsQuat inverseRotation = rotation.Inverse();
hsVector3 normal(contact->m_normal.x, contact->m_normal.y, contact->m_normal.z);
fFacingPushingPhysical = (inverseRotation.Rotate(&kAvatarForward).InnerProduct(normal) < 0 ? true : false);
fPushingPhysical = contactPhys;
}
}
// We need to check for the case where the avatar hasn't collided with "ground", but is colliding
// with a few other objects so that he's not actually falling (wedged in between some slopes).
// We do this by answering the following question (in 2d top-down space): "If you sort the contact
// normals by angle, is there a large enough gap between normals?"
//
// If you think in terms of geometry, this means a collection of surfaces are all pushing on you.
// If they're pushing from all sides, you have nowhere to go, and you won't fall. There needs to be
// a gap, so that you're pushed out and have somewhere to fall. This is the same as finding a gap
// larger than 180 degrees between sorted normals.
//
// The problem is that on top of that, the avatar needs enough force to shove him out that gap (he
// has to overcome friction). I deal with that by making the threshold (360 - (180 - 60) = 240). I've
// seen up to 220 reached in actual gameplay in a situation where we'd want this to take effect.
// This is the same running into 2 walls where the angle between them is 60.
const float threshold = hsDegreesToRadians(240);
if (!ground && numContacts >= 2)
{
// Can probably do a special case for exactly 2 contacts. Not sure if it's worth it...
fCollisionAngles.SetCount(numContacts);
for (i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
fCollisionAngles[i] = atan2(contact->m_normal.y, contact->m_normal.x);
}
// numContacts is rarely larger than 6, so let's do a simple bubble sort.
for (i = 0; i < numContacts; i++)
{
for (j = i + 1; j < numContacts; j++)
{
if (fCollisionAngles[i] > fCollisionAngles[j])
{
float tempAngle = fCollisionAngles[i];
fCollisionAngles[i] = fCollisionAngles[j];
fCollisionAngles[j] = tempAngle;
}
}
}
// sorted, now we check.
for (i = 1; i < numContacts; i++)
{
if (fCollisionAngles[i] - fCollisionAngles[i - 1] >= threshold)
break;
}
if (i == numContacts)
{
// We got to the end. Check the last with the first and make your decision.
if (!(fCollisionAngles[0] - fCollisionAngles[numContacts - 1] >= (threshold - 2 * M_PI)))
ground = true;
}
}
*/
bool ground = fController ? fController->GotGroundHit() : true;
bool isPhysical = true;
if (!fHitGroundInThisAge && isPhysical)
fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now.
if (IsControlledFlight())
fControlledFlightTime += (float)elapsed;
if (fControlledFlightTime > kControlledFlightThreshold && numContacts > 0)
EnableControlledFlight(false);
if (ground || !isPhysical)
{
if (!IsControlledFlight() && !IsOnGround())
{
// The first ground contact in an age doesn't count.
// if (alreadyInAge)
// {
// hsVector3 vel;
// fPhysical->GetLinearVelocitySim(vel);
// fImpactVel = vel.fZ;
// fTimeInAirPeak = (float)(fTimeInAir + elapsed);
// }
fWaitingForGround = false;
}
fTimeInAir = 0;
}
else if (elapsed < plSimulationMgr::GetInstance()->GetMaxDelta())
{
// If the simultation skipped a huge chunk of time, we didn't process the
// collisions, which could trick us into thinking we've just gone a long
// time without hitting ground. So we only count the time if this wasn't
// the case.
fTimeInAir += (float)elapsed;
}
// Tweakage so that we still fall under the right conditions.
// If we're in controlled flight, or standing still with ground solidly under us (probe hit). We only use anim velocity.
// if (!IsControlledFlight() && !(ground && fProbeHitGround && fAnimPosVel.fX == 0 && fAnimPosVel.fY == 0))
// {
// hsVector3 curV;
// fPhysical->GetLinearVelocitySim(curV);
// fAnimPosVel.fZ = curV.fZ;
//
// // Prevents us from going airborn from running up bumps/inclines.
// if (IsOnGround() && fAnimPosVel.fZ > 0.f)
// fAnimPosVel.fZ = 0.f;
//
// // Unless we're on the ground and moving, or standing still with a probe hit, we use the sim's other axes too.
// if (!(IsOnGround() && (fProbeHitGround || fAnimPosVel.fX != 0 || fAnimPosVel.fY != 0)))
// {
// fAnimPosVel.fX = curV.fX;
// fAnimPosVel.fY = curV.fY;
// }
// }
//
// fPhysical->SetLinearVelocitySim(fAnimPosVel);
// fPhysical->SetSpin(fAnimAngVel + fTurnStr, hsVector3(0.0f, 0.0f, 1.0f));
}
#endif
#if 0
/////////////////////////////////////////////////////////////////////////
plSimDefs::ActionType plHorizontalFreezeAction::GetType()
{
return plSimDefs::kHorizontalFreeze;
}
void plHorizontalFreezeAction::apply(Havok::Subspace &s, Havok::hkTime time)
{
double elapsed = time.asDouble() - getRefresh().asDouble();
setRefresh(time);
int numContacts = fPhysical->GetNumContacts();
bool ground = false;
const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
int i;
for(i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
float dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
ground = true;
}
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
vel.fX = 0.0;
vel.fY = 0.0;
if (ground)
vel.fZ = 0;
fPhysical->SetLinearVelocitySim(vel);
fPhysical->ClearContacts();
}
#endif
plSwimmingController::plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
:plAnimatedController(rootObject,rootApp,controller)
{
if (controller)
fSwimmingStrategy= new plSwimStrategy(controller);
else
fSwimmingStrategy = nil;
}
plSwimmingController::~plSwimmingController()
{
delete fSwimmingStrategy;
}
plRidingAnimatedPhysicalController::plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: plWalkingController(rootObject, rootApp, controller)
{
if(controller)
fWalkingStrategy = new plRidingAnimatedPhysicalStrategy(controller);
else
fWalkingStrategy = nil;
}
plRidingAnimatedPhysicalController::~plRidingAnimatedPhysicalController()
{
delete fWalkingStrategy;
fWalkingStrategy=nil;
}
//////////////////////////////////////////////////////////////////////////
/*
Purpose:
ANGLE_RAD_2D returns the angle in radians swept out between two rays in 2D.
Discussion:
Except for the zero angle case, it should be true that
ANGLE_RAD_2D(X1,Y1,X2,Y2,X3,Y3)
+ ANGLE_RAD_2D(X3,Y3,X2,Y2,X1,Y1) = 2 * PI
Modified:
19 April 1999
Author:
John Burkardt
Parameters:
Input, float X1, Y1, X2, Y2, X3, Y3, define the rays
( X1-X2, Y1-Y2 ) and ( X3-X2, Y3-Y2 ) which in turn define the
angle, counterclockwise from ( X1-X2, Y1-Y2 ).
Output, float ANGLE_RAD_2D, the angle swept out by the rays, measured
in radians. 0 <= ANGLE_DEG_2D < 2 PI. If either ray has zero length,
then ANGLE_RAD_2D is set to 0.
*/
static float AngleRad2d ( float x1, float y1, float x3, float y3 )
{
float value;
float x;
float y;
x = ( x1 ) * ( x3 ) + ( y1 ) * ( y3 );
y = ( x1 ) * ( y3 ) - ( y1 ) * ( x3 );
if ( x == 0.0 && y == 0.0 ) {
value = 0.0;
}
else
{
value = atan2 ( y, x );
if ( value < 0.0 )
{
value = (float)(value + TWO_PI);
}
}
return value;
}
static bool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
bool result = false;
hsPoint3 startPos(0.0f, 0.0f, 0.0f); // default position (at start of anim)
hsPoint3 prevPos = prevMat.GetTranslate(); // position previous frame
hsPoint3 nowPos = curMat.GetTranslate(); // position current frame
hsVector3 prev2Now = (hsVector3)(nowPos - prevPos); // frame-to-frame delta
if (fabs(prev2Now.fX) < 0.0001f && fabs(prev2Now.fY) < 0.0001f && fabs(prev2Now.fZ) < 0.0001f)
{
outputV.Set(0.f, 0.f, 0.f);
result = true;
}
else
{
hsVector3 start2Now = (hsVector3)(nowPos - startPos); // start-to-frame delta
float prev2NowMagSqr = prev2Now.MagnitudeSquared();
float start2NowMagSqr = start2Now.MagnitudeSquared();
float dot = prev2Now.InnerProduct(start2Now);
// HANDLING ANIMATION WRAPPING:
// the vector from the animation origin to the current frame should point in roughly
// the same direction as the vector from the previous animation position to the
// current animation position.
//
// If they don't agree (dot < 0,) then we probably mpst wrapped around.
// The right answer would be to compare the current frame to the start of
// the anim loop, but it's cheaper to cheat and return false,
// telling the caller to use the previous frame's velocity.
if (dot > 0.0f)
{
prev2Now /= elapsed;
float xfabs = fabs(prev2Now.fX);
float yfabs = fabs(prev2Now.fY);
float zfabs = fabs(prev2Now.fZ);
static const float maxVel = 20.0f;
bool valid = xfabs < maxVel && yfabs < maxVel && zfabs < maxVel;
if (valid)
{
outputV = prev2Now;
result = true;
}
}
}
return result;
}
static void AngularVelocity(float &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
outputV = 0.f;
float appliedVelocity = 0.0f;
hsVector3 prevForward = GetYAxis(prevMat);
hsVector3 curForward = GetYAxis(curMat);
float angleSincePrev = AngleRad2d(curForward.fX, curForward.fY, prevForward.fX, prevForward.fY);
bool sincePrevSign = angleSincePrev > 0.0f;
if (angleSincePrev > M_PI)
angleSincePrev = angleSincePrev - TWO_PI;
const hsVector3 startForward = hsVector3(0, -1.0, 0); // the Y orientation of a "resting" armature....
float angleSinceStart = AngleRad2d(curForward.fX, curForward.fY, startForward.fX, startForward.fY);
bool sinceStartSign = angleSinceStart > 0.0f;
if (angleSinceStart > M_PI)
angleSinceStart = angleSinceStart - TWO_PI;
// HANDLING ANIMATION WRAPPING:
// under normal conditions, the angle from rest to the current frame will have the same
// sign as the angle from the previous frame to the current frame.
// if it does not, we have (most likely) wrapped the motivating animation from frame n back
// to frame zero, creating a large angle from the previous frame to the current one
if (sincePrevSign == sinceStartSign)
{
// signs are the same; didn't wrap; use the frame-to-frame angle difference
appliedVelocity = angleSincePrev / elapsed; // rotation / time
if (fabs(appliedVelocity) < 3)
{
outputV = appliedVelocity;
}
}
}

217
Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h

@ -1,217 +0,0 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_HK_CALLBACK_ACTION_H
#define PL_HK_CALLBACK_ACTION_H
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
#include "plPhysical/plSimDefs.h"
#include "pnMessage/plMessage.h"
#include "plPhysicalControllerCore.h"
class plLOSHitMsg;
class plAGApplicator;
class plSceneObject;
class plPhysical;
class plAvatarController;
class plCoordinateInterface;
class plPhysicalControllerCore;
// Used by the other controllers to actually move the avatar. The actual
// implementation is in the physics system.
/*class plPhysicalController
{
public:
// Implemented in the physics system. If you're linking this without that for
// some reason, just stub this function out.
//
// Pass in the key to the root sceneobject for the avatar
static plPhysicalController* Create(plKey ownerSO, float height, float width);
virtual ~plPhysicalController() {}
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() const = 0;
// Set the LOS DB this avatar will be in (only one)
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) = 0;
// Call this once per frame with the velocities of the avatar in avatar space.
virtual void SetVelocities(const hsVector3& linearVel, float angVel) = 0;
// Gets the actual velocity we achieved in the last step (relative to our subworld)
virtual const hsVector3& GetLinearVelocity() const = 0;
virtual void ResetAchievedLinearVelocity() = 0;
// Get and set the current subworld for the avatar. Use nil for the main world.
virtual plKey GetSubworld() const = 0;
virtual void SetSubworld(plKey world) = 0;
// If IsOnGround returns false, GetAirTime will tell you how long the avatar
// has been airborne. Use ResetAirTime to reset the air time to zero, for
// cases like when the avatar spawns into a new age.
virtual bool IsOnGround() const = 0;
virtual bool IsOnFalseGround() const = 0;
virtual float GetAirTime() const = 0;
virtual void ResetAirTime() = 0;
virtual plPhysical* GetPushingPhysical() const = 0;
virtual bool GetFacingPushingPhysical() const = 0;
// A helper function to get the coordinate interface for the avatars current
// world. Handy if you need to convert points to and from that. This will
// return nil if the avatar is in the main world (ie, you don't need to do
// any translation).
virtual const plCoordinateInterface* GetSubworldCI() const = 0;
// 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)=0;
};
*/
class plAvatarController
{
public:
virtual ~plAvatarController() {}
};
class plAnimatedController : public plAvatarController
{
public:
plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual void RecalcVelocity(double timeNow, double timePrev, bool useAnim = true);
void SetTurnStrength(float val) { fTurnStr = val; }
float GetTurnStrength() { return fTurnStr; }
virtual void ActivateController()=0;
protected:
plSceneObject* fRootObject;
plPhysicalControllerCore* fController;
plAGApplicator* fRootApp;
float fAnimAngVel;
hsVector3 fAnimPosVel;
float fTurnStr; // Explicit turning, separate from animations
};
class plWalkingController : public plAnimatedController
{
public:
plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plWalkingController();
virtual void RecalcVelocity(double timeNow, double timePrev, bool useAnim = true);
void Reset(bool newAge);
bool IsControlledFlight() const { return fControlledFlight != 0; }
bool IsOnGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnGround() : true; }
bool IsOnFalseGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnFalseGround() : true; }
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
bool EnableControlledFlight(bool status);
float GetAirTime() const { return fWalkingStrategy ? fWalkingStrategy->GetAirTime() : 0.f; }
void ResetAirTime() { if (fWalkingStrategy) fWalkingStrategy->ResetAirTime(); }
float GetForwardVelocity() const;
void ActivateController();
// Check these after the avatar the avatar hits the ground for his total
// hangtime and impact velocity.
float GetImpactTime() const { return fImpactTime; }
const hsVector3& GetImpactVelocity() const { return fImpactVelocity; }
plPhysical* GetPushingPhysical() const
{
if(fController)return fController->GetPushingPhysical();
else return nil;
}
bool GetFacingPushingPhysical() const
{ if(fController)return fController->GetFacingPushingPhysical();
else return false;
}
protected:
bool fHitGroundInThisAge;
bool fWaitingForGround; // We've gone airborne. IsOnGround() returns false until we hit ground again.
float fControlledFlightTime;
int fControlledFlight; // Count of how many are currently forcing flight
plWalkingStrategy* fWalkingStrategy;
float fImpactTime;
hsVector3 fImpactVelocity;
bool fClearImpact;
bool fGroundLastFrame;//used for a test to pass the event of first getting air during a jump
static const float kControlledFlightThreshold;
};
class plSwimmingController: public plAnimatedController
{
public :
plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plSwimmingController();
void SetSurface(plSwimRegionInterface *region, float surfaceHeight){
fSwimmingStrategy->SetSurface(region,surfaceHeight);
}
float GetBuoyancy() { return fSwimmingStrategy->GetBuoyancy(); }
bool IsOnGround() { return fSwimmingStrategy->IsOnGround(); }
bool HadContacts() { return fSwimmingStrategy->HadContacts();}
void Enable(bool en){if (fController) fController->Enable(en);}
plPhysicalControllerCore* GetController(){return fController;}
virtual void ActivateController(){fSwimmingStrategy->RefreshConnectionToControllerCore();}
protected:
plSwimStrategy* fSwimmingStrategy;
};
class plRidingAnimatedPhysicalController: public plWalkingController
{
public:
plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plRidingAnimatedPhysicalController();
};
#endif // PL_HK_CALLBACK_ACTION_H

4
Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp

@ -39,7 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvatar/plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "HeadSpin.h"
@ -129,7 +129,7 @@ bool plAvLadderMod::IIsReadyToClimb()
if (armMod)
{
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
movingForward = true;
}

6
Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp

@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAGAnim.h"
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
// other
#include "plMessage/plAvatarMsg.h"
@ -463,10 +463,10 @@ bool plAvTaskSeek::IFinishPosition(hsPoint3 &newPosition,
{
// While warping, we might be hovering just above the ground. Don't want that to
// trigger any falling behavior.
if(brain&&brain->fCallbackAction)
if(brain&&brain->fWalkingStrategy)
{
brain->fCallbackAction->ResetAirTime();
brain->fWalkingStrategy->ResetAirTime();
}
// how far will we translate this frame?
float thisDist = kFloatSpeed * elapsed;

2
Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp

@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvatar/plAvBrainClimb.h"
#include "plAvatar/plAvBrainDrive.h"
#include "plAvatar/plAnimStage.h"
#include "plAvatar/plAvCallbackAction.h"
#include "plAvatar/plPhysicalControllerCore.h"
#include "pnSceneObject/plSceneObject.h"
#include "pnMessage/plSDLModifierMsg.h"
#include "plSDL/plSDL.h"

4
Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp

@ -52,7 +52,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAGAnimInstance.h"
#include "plAGModifier.h"
#include "plMatrixChannel.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plAvatarMgr.h"
// global
@ -671,7 +671,7 @@ bool plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, dou
if(fEnablePhysicsAtEnd)
{
#if 0//ndef PLASMA_EXTERNAL_RELEASE
if (!humanBrain || humanBrain->fCallbackAction->HitGroundInThisAge())
if (!humanBrain || humanBrain->fWalkingStrategy->HitGroundInThisAge())
{
// For some reason, calling CheckValidPosition at the beginning of
// an age can cause detectors to incorrectly report collisions. So

1393
Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp

File diff suppressed because it is too large Load Diff

448
Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h

@ -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.
enum plControllerCollisionFlags
{
kSides=1,
kTop= (1<<1),
kBottom=(1<<2),
};
class plMovementStrategySimulationInterface
{
public:
#define kSlopeLimit (cosf(hsDegreesToRadians(55.f)))
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;
enum plControllerCollisionFlags
{
kSides = 1,
kTop = (1 << 1),
kBottom = (1 << 2)
};
class plControllerSweepRecord
struct 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;
bool fSeeking;
bool fEnabled;
bool fEnableChanged;
bool fKinematic;
bool fKinematicEnableNextUpdate;
bool fKinematicChanged;
plMovementStrategySimulationInterface* fMovementInterface;
hsMatrix44 fLastGlobalLoc;
hsPoint3 fLocalPosition;
plMovementStrategy* fMovementStrategy;
float fSimLength;
hsQuat fLocalRotation;
hsPoint3 fLocalPosition;
hsPoint3 fLastLocalPosition;
hsMatrix44 fLastGlobalLoc;
hsMatrix44 fPrevSubworldW2L;
hsVector3 fDisplacementThisStep;
float fSimLength;
//physical properties
hsVector3 fLinearVelocity;
float fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
bool fNeedsResize;
bool fSeeking;
bool fEnabled;
bool fEnableChanged;
};
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 plAnimatedMovementStrategy : public plMovementStrategy
{
public:
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 plMovementStrategy
class plWalkingStrategy : public plAnimatedMovementStrategy
{
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(){};
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;
bool fOnGround;
bool fHadContacts;
float fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
bool fOnGround;
bool fHadContacts;
};
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

2
Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp

@ -70,7 +70,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvatar/plArmatureMod.h"
#include "plAvatar/plAvBrain.h"
#include "plAvatar/plAvatarMgr.h"
#include "plAvatar/plAvCallbackAction.h"
#include "plAvatar/plPhysicalControllerCore.h"
#include "plModifier/plInterfaceInfoModifier.h"
#include "pnModifier/plLogicModBase.h"
#include "plVault/plVault.h"

1
Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp

@ -54,7 +54,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plMessage/plAvatarMsg.h"
#include "plPhysical.h"
#include "plPhysical/plSimDefs.h"
#include "plAvatar/plAvCallbackAction.h"
#include "plAvatar/plAvBrainGeneric.h"

10
Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvatar/plAvCallbackAction.h"
#include "HeadSpin.h"
#include "plCollisionDetector.h"
@ -65,6 +64,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvatar/plAvatarMgr.h"
#include "plAvatar/plAvBrainHuman.h"
#include "plAvatar/plAvBrainDrive.h"
#include "plAvatar/plPhysicalControllerCore.h"
#include "plModifier/plDetectorLog.h"
@ -475,7 +475,7 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
// And are we walking towards it?
plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain();
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain);
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
movingForward = true;
}
else
@ -645,11 +645,11 @@ bool plPanicLinkRegion::MsgReceive(plMessage* msg)
{
if (avMod->IsLinkedIn())
{
hsPoint3 kinPos;
hsPoint3 pos;
if (avMod->GetController())
{
avMod->GetController()->GetKinematicPosition(kinPos);
DetectorLogSpecial("Avatar is panic linking. KinPos at %f,%f,%f and is %s",kinPos.fX,kinPos.fY,kinPos.fZ,avMod->GetController()->IsEnabled() ? "enabled" : "disabled");
avMod->GetController()->GetPositionSim(pos);
DetectorLogSpecial("Avatar is panic linking. Position %f,%f,%f and is %s", pos.fX, pos.fY, pos.fZ, avMod->GetController()->IsEnabled() ? "enabled" : "disabled");
}
avMod->PanicLink(fPlayLinkOutAnim);
} else

19
Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h

@ -72,25 +72,6 @@ namespace plSimDefs
kGroupMax,
};
/** A taxonomy of action types. Crucial for doing things like making sure you don't
do things like attach duplicate actions. */
enum ActionType
{
kUnknownAction = 0x01, // don't know the type (probably forgot to override GetType())
kUnknownZAction = 0x02, // unknown type of z-order action
kAntiGravityAction = 0x03, // an action that counters gravity exactly
kUprightAction = 0x04, // an action that keeps an object upright by apply force
kPhysAnimAction = 0x05, // an action that parses keyframed animation into physical information
kConstraint = 0x06, // a general constraint.
kCallbackAction = 0x07, // an action that just hands us the physics "tick"
kPseudoPhysAction = 0x08, // replacement for the physAnim
kAntiGravAction = 0x09, // makes things float in the air
kBasicGroundAction = 0x0a, // for your basic walkAroundOnGround corrections
kHorizontalFreeze = 0x0b, // Let's you fall vertically, but otherwise keeps you in place (generic brains)
kMaxAction = 0xffff // force 16-bit
};
/** Different types of line-of-sight requests. */
enum LOSReqType
{

Loading…
Cancel
Save