mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 10:37:41 -04:00
Merge pull request #230 from Hoikas/physx
PhysX Cleanup (forward port from OU)
This commit is contained in:
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -554,7 +554,7 @@ bool pySceneObject::IsAvatar()
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "plAvatar/plAvCallbackAction.h"
|
||||
#include "plAvatar/plPhysicalControllerCore.h"
|
||||
|
||||
PyObject* pySceneObject::GetAvatarVelocity()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 */)
|
||||
@ -1994,7 +1993,11 @@ bool plArmatureMod::ValidatePhysics()
|
||||
return false;
|
||||
|
||||
if (!fController)
|
||||
fController = plPhysicalControllerCore::Create(GetTarget(0)->GetKey(), fPhysHeight, fPhysWidth);
|
||||
{
|
||||
// The kinematic actor is made taller if the avatar is human (male or female)
|
||||
fController = plPhysicalControllerCore::Create(GetTarget(0)->GetKey(), fPhysHeight,
|
||||
fPhysWidth, (fBodyType == kBoneBaseMale || fBodyType == kBoneBaseFemale));
|
||||
}
|
||||
|
||||
if (fController)
|
||||
{
|
||||
@ -2670,19 +2673,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";
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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?
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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++)
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -41,310 +41,286 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
*==LICENSE==*/
|
||||
#ifndef PLPHYSICALCONTROLLERCORE_H
|
||||
#define PLPHYSICALCONTROLLERCORE_H
|
||||
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsMatrix44.h"
|
||||
#include "hsQuat.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "pnKeyedObject/plKey.h"
|
||||
#include "plPhysical/plSimDefs.h"
|
||||
#include "pnMessage/plMessage.h"
|
||||
|
||||
#include "hsQuat.h"
|
||||
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
|
||||
#define kSLOPELIMIT (cosf(hsDegreesToRadians(45.f)))
|
||||
#include <vector>
|
||||
|
||||
class plCoordinateInterface;
|
||||
class plPhysical;
|
||||
class plPXPhysical;
|
||||
class plMovementStrategy;
|
||||
class plAGApplicator;
|
||||
class plSwimRegionInterface;
|
||||
//Replacement for for plPhysicalController stripped out some walk specific code
|
||||
//plPhysicalControllerCore needs to have movement strategies registered to it these will then
|
||||
//be called by the controller during the simulation steps. The Strategies need to at least have an
|
||||
// Apply and Update definition. Everything else should be movement specific. I hope to come back and
|
||||
//and refactor when I have time this in the future.
|
||||
|
||||
#define kSlopeLimit (cosf(hsDegreesToRadians(55.f)))
|
||||
|
||||
enum plControllerCollisionFlags
|
||||
{
|
||||
kSides = 1,
|
||||
kTop = (1 << 1),
|
||||
kBottom=(1<<2),
|
||||
kBottom = (1 << 2)
|
||||
};
|
||||
|
||||
class plMovementStrategySimulationInterface
|
||||
struct plControllerSweepRecord
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void Apply(float delSecs)=0;
|
||||
virtual void Update(float delSecs)=0;
|
||||
//most strategies don't require this. Only the ones that require behavior like a physical or need
|
||||
//something after the sim step. this used to be taken care of by Update, but this was moved to take care of
|
||||
//some of the frame lag
|
||||
virtual void PostStep(float delSecs){};
|
||||
virtual void IAddContactNormals(hsVector3& vec){fContactNormals.Append(vec);}
|
||||
virtual void AddOnTopOfObject(plPhysical* phys){ fOnTopOf.Append(phys);}
|
||||
virtual void LeaveAge()
|
||||
{
|
||||
fContactNormals.SetCount(0);
|
||||
fOnTopOf.SetCount(0);
|
||||
}
|
||||
protected:
|
||||
hsTArray<hsVector3> fContactNormals;
|
||||
hsTArray<plPhysical* > fOnTopOf;
|
||||
};
|
||||
|
||||
class plControllerSweepRecord
|
||||
{
|
||||
public:
|
||||
plPhysical *ObjHit;
|
||||
hsPoint3 locHit;//World space
|
||||
float TimeHit;//Normalized between 0 and 1
|
||||
hsVector3 Norm;
|
||||
hsPoint3 Point;
|
||||
hsVector3 Normal;
|
||||
};
|
||||
bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right);
|
||||
|
||||
class plPhysicalControllerCore
|
||||
{
|
||||
public:
|
||||
virtual ~plPhysicalControllerCore();
|
||||
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)=0;
|
||||
virtual void SetMovementSimulationInterface(plMovementStrategySimulationInterface* strat){fMovementInterface=strat;}
|
||||
virtual void Apply(float delSecs);
|
||||
virtual void Update(float delSecs);
|
||||
virtual void PostStep(float delSecs);
|
||||
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
|
||||
plPhysicalControllerCore(plKey ownerSceneObject, float height, float radius);
|
||||
virtual ~plPhysicalControllerCore() { }
|
||||
|
||||
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
|
||||
// Use plArmatureModBase::EnablePhysics() instead.
|
||||
virtual void Enable(bool enable) = 0;
|
||||
virtual bool IsEnabled() { return fEnabled; }
|
||||
|
||||
// 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;
|
||||
}
|
||||
// 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;
|
||||
hsVector3 DisplacementLastStep(){return fDisplacementThisStep;}
|
||||
hsVector3 MeanVelocityForLastStep()
|
||||
{
|
||||
hsVector3 vel=fDisplacementThisStep;
|
||||
return vel/fSimLength;
|
||||
}
|
||||
void SendCorrectionMessages();
|
||||
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;
|
||||
// Local rotation
|
||||
const hsQuat& GetLocalRotation() const { return fLocalRotation; }
|
||||
void IncrementAngle(float deltaAngle);
|
||||
|
||||
// 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, bool human);
|
||||
|
||||
protected:
|
||||
virtual void IHandleEnableChanged() = 0;
|
||||
|
||||
void IApply(float delSecs);
|
||||
void IUpdate(int numSubSteps, float alpha);
|
||||
void IUpdateNonPhysical(float alpha);
|
||||
|
||||
void ISendCorrectionMessages(bool dirtySynch = false);
|
||||
|
||||
plKey fOwner;
|
||||
plKey fWorldKey;
|
||||
|
||||
float fHeight;
|
||||
float fRadius;
|
||||
plKey fWorldKey;
|
||||
|
||||
plSimDefs::plLOSDB fLOSDB;
|
||||
|
||||
plMovementStrategy* fMovementStrategy;
|
||||
|
||||
float fSimLength;
|
||||
|
||||
hsQuat fLocalRotation;
|
||||
hsPoint3 fLocalPosition;
|
||||
hsPoint3 fLastLocalPosition;
|
||||
|
||||
hsMatrix44 fLastGlobalLoc;
|
||||
hsMatrix44 fPrevSubworldW2L;
|
||||
|
||||
hsVector3 fLinearVelocity;
|
||||
hsVector3 fAchievedLinearVelocity;
|
||||
|
||||
plPhysical* fPushingPhysical;
|
||||
bool fFacingPushingPhysical;
|
||||
|
||||
bool fSeeking;
|
||||
bool fEnabled;
|
||||
bool fEnableChanged;
|
||||
bool fKinematic;
|
||||
bool fKinematicEnableNextUpdate;
|
||||
bool fKinematicChanged;
|
||||
plMovementStrategySimulationInterface* fMovementInterface;
|
||||
hsMatrix44 fLastGlobalLoc;
|
||||
hsPoint3 fLocalPosition;
|
||||
hsQuat fLocalRotation;
|
||||
hsMatrix44 fPrevSubworldW2L;
|
||||
hsVector3 fDisplacementThisStep;
|
||||
float fSimLength;
|
||||
|
||||
//physical properties
|
||||
hsVector3 fLinearVelocity;
|
||||
float fAngularVelocity;
|
||||
hsVector3 fAchievedLinearVelocity;
|
||||
plPhysical* fPushingPhysical;
|
||||
bool fFacingPushingPhysical;
|
||||
bool fNeedsResize;
|
||||
};
|
||||
|
||||
class plMovementStrategy: public plMovementStrategySimulationInterface
|
||||
class plMovementStrategy
|
||||
{
|
||||
public:
|
||||
virtual void SetControllerCore(plPhysicalControllerCore* core)
|
||||
{
|
||||
fCore=core;
|
||||
fCore->SetMovementSimulationInterface(this);
|
||||
}
|
||||
virtual void RefreshConnectionToControllerCore()
|
||||
{
|
||||
fCore->SetMovementSimulationInterface(this);
|
||||
//fCore->SetControllerDimensions(fPreferedControllerWidth,fPreferedControllerHeight);
|
||||
fCore->BehaveLikeAnimatedPhysical(this->IRequireBehaviourLikeAnAnimatedPhysical());
|
||||
}
|
||||
plMovementStrategy(plPhysicalControllerCore* core);
|
||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
||||
virtual void SetLinearAcceleration(const hsVector3& accel){fLinearAcceleration=accel;}
|
||||
virtual const hsVector3& GetLinearAcceleration()const{return fLinearAcceleration;}
|
||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
||||
virtual void ResetAchievedLinearVelocity()
|
||||
{
|
||||
hsVector3 AchievedLinearVelocity(0.f,0.f,0.f);
|
||||
if(fCore)fCore->OverrideAchievedVelocity(AchievedLinearVelocity);
|
||||
}
|
||||
//proxy functions for Controller Core
|
||||
virtual float GetAirTime() const { return fTimeInAir; }
|
||||
virtual void ResetAirTime() { fTimeInAir = 0.f; }
|
||||
plMovementStrategy(plPhysicalControllerCore* controller);
|
||||
virtual ~plMovementStrategy() { }
|
||||
|
||||
virtual void Apply(float delSecs) = 0;
|
||||
virtual void Update(float delSecs) { }
|
||||
|
||||
virtual void AddContactNormals(hsVector3& vec) { }
|
||||
virtual void Reset(bool newAge);
|
||||
virtual bool IsKinematic() { return true; }
|
||||
|
||||
protected:
|
||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical()=0;
|
||||
virtual void IApplyKinematic();
|
||||
plPhysicalControllerCore* fCore;
|
||||
hsVector3 fLinearAcceleration;
|
||||
float fAngularAcceleration;
|
||||
plKey fOwner;
|
||||
static const float kAirTimeThreshold;
|
||||
float fTimeInAir;
|
||||
float fPreferedControllerWidth;
|
||||
float fPreferedControllerHeight;
|
||||
|
||||
|
||||
plPhysicalControllerCore* fController;
|
||||
};
|
||||
|
||||
class plWalkingStrategy: public plMovementStrategy
|
||||
class plAnimatedMovementStrategy : public plMovementStrategy
|
||||
{
|
||||
public:
|
||||
plWalkingStrategy(plPhysicalControllerCore* core):plMovementStrategy(core)
|
||||
plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||
virtual ~plAnimatedMovementStrategy() { }
|
||||
|
||||
virtual void RecalcVelocity(double timeNow, float elapsed, bool useAnim = true);
|
||||
void SetTurnStrength(float val) { fTurnStr = val; }
|
||||
float GetTurnStrength() const { return fTurnStr; }
|
||||
|
||||
private:
|
||||
void IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
|
||||
void IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
|
||||
|
||||
plAGApplicator* fRootApp;
|
||||
hsVector3 fAnimLinearVel;
|
||||
float fAnimAngularVel;
|
||||
float fTurnStr;
|
||||
};
|
||||
|
||||
class plWalkingStrategy : public plAnimatedMovementStrategy
|
||||
{
|
||||
fGroundHit=false;
|
||||
fFalseGround=false;
|
||||
fHitHead=false;
|
||||
fCore->SetMovementSimulationInterface(this);
|
||||
fPreferedControllerWidth=core->GetControllerWidth();
|
||||
fPreferedControllerHeight=core->GetControllerHeight();
|
||||
fOnTopOfAnimatedPhysLastFrame=false;
|
||||
}
|
||||
virtual ~plWalkingStrategy(){};
|
||||
public:
|
||||
plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||
virtual ~plWalkingStrategy() { }
|
||||
|
||||
virtual void Apply(float delSecs);
|
||||
virtual void Update(float delSecs);
|
||||
|
||||
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(){};
|
||||
virtual void AddContactNormals(hsVector3& vec);
|
||||
virtual void Reset(bool newAge);
|
||||
|
||||
virtual void RecalcVelocity(double timeNow, float elapsed, bool useAnim = true);
|
||||
|
||||
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
|
||||
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
|
||||
|
||||
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:
|
||||
static const float kAirTimeThreshold;
|
||||
static const float kControlledFlightThreshold;
|
||||
|
||||
hsTArray<hsVector3> fSlidingNormals;
|
||||
|
||||
hsVector3 fImpactVelocity;
|
||||
float fImpactTime;
|
||||
|
||||
float fTimeInAir;
|
||||
|
||||
float fControlledFlightTime;
|
||||
int fControlledFlight;
|
||||
|
||||
void ICheckForFalseGround();
|
||||
bool fGroundHit;
|
||||
bool fFalseGround;
|
||||
bool fHitHead;
|
||||
bool fOnTopOfAnimatedPhysLastFrame;
|
||||
hsTArray<hsVector3> fPrevSlidingNormals;
|
||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
|
||||
bool fHeadHit;
|
||||
bool fSliding;
|
||||
|
||||
bool fClearImpact;
|
||||
bool fHitGroundInThisAge;
|
||||
};
|
||||
class plSwimStrategy: public plMovementStrategy
|
||||
|
||||
class plSwimStrategy : public plAnimatedMovementStrategy
|
||||
{
|
||||
public:
|
||||
plSwimStrategy(plPhysicalControllerCore *core);
|
||||
virtual ~plSwimStrategy(){};
|
||||
void SetSurface(plSwimRegionInterface *region, float surfaceHeight);
|
||||
plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||
virtual ~plSwimStrategy() { }
|
||||
|
||||
virtual void Apply(float delSecs);
|
||||
virtual void Update(float delSecs);
|
||||
float GetBuoyancy() { return fBuoyancy; }
|
||||
bool IsOnGround() { return fOnGround; }
|
||||
bool HadContacts() { return fHadContacts; }
|
||||
virtual void IAddContactNormals(hsVector3& vec);
|
||||
|
||||
virtual void AddContactNormals(hsVector3& vec);
|
||||
|
||||
void SetSurface(plSwimRegionInterface* region, float surfaceHeight);
|
||||
|
||||
float GetBuoyancy() const { return fBuoyancy; }
|
||||
bool IsOnGround() const { return fOnGround; }
|
||||
bool HadContacts() const { return fHadContacts; }
|
||||
|
||||
protected:
|
||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
|
||||
private:
|
||||
void IAdjustBuoyancy();
|
||||
|
||||
float fBuoyancy;
|
||||
float fSurfaceHeight;
|
||||
|
||||
plSwimRegionInterface *fCurrentRegion;
|
||||
|
||||
bool fOnGround;
|
||||
bool fHadContacts;
|
||||
float fSurfaceHeight;
|
||||
plSwimRegionInterface *fCurrentRegion;
|
||||
};
|
||||
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
|
||||
|
||||
class plDynamicWalkingStrategy : public plWalkingStrategy
|
||||
{
|
||||
public:
|
||||
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) :
|
||||
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){};
|
||||
virtual ~plRidingAnimatedPhysicalStrategy(){};
|
||||
plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||
virtual ~plDynamicWalkingStrategy() { }
|
||||
|
||||
virtual void Apply(float delSecs);
|
||||
virtual void Update(float delSecs);
|
||||
virtual void PostStep(float delSecs);
|
||||
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
|
||||
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
|
||||
void GroundHit() { fGroundHit = true; }
|
||||
virtual void StartJump(){fStartJump = true;}
|
||||
|
||||
virtual bool IsKinematic() { return false; }
|
||||
|
||||
protected:
|
||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return false;}
|
||||
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
|
||||
bool fNeedVelocityOverride;
|
||||
hsVector3 fOverrideVelocity;
|
||||
bool fStartJump;
|
||||
bool ICheckForGround(float& zVelocity);
|
||||
};
|
||||
|
||||
#endif// PLPHYSICALCONTROLLERCORE_H
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -94,8 +94,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isController;
|
||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor,&isController);
|
||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor);
|
||||
if (controller)
|
||||
{
|
||||
objKey = controller->GetOwner();
|
||||
|
@ -138,14 +138,10 @@ plPXPhysical::plPXPhysical()
|
||||
, fSceneNode(nil)
|
||||
, fWorldKey(nil)
|
||||
, fSndGroup(nil)
|
||||
, fWorldHull(nil)
|
||||
, fSaveTriangles(nil)
|
||||
, fHullNumberPlanes(0)
|
||||
, fMass(0.f)
|
||||
, fWeWereHit(false)
|
||||
, fHitForce(0,0,0)
|
||||
, fHitPos(0,0,0)
|
||||
, fInsideConvexHull(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -190,11 +186,6 @@ plPXPhysical::~plPXPhysical()
|
||||
plSimulationMgr::GetInstance()->ReleaseScene(fWorldKey);
|
||||
}
|
||||
|
||||
if (fWorldHull)
|
||||
delete [] fWorldHull;
|
||||
if (fSaveTriangles)
|
||||
delete [] fSaveTriangles;
|
||||
|
||||
delete fProxyGen;
|
||||
|
||||
// remove sdl modifier
|
||||
@ -206,155 +197,6 @@ plPXPhysical::~plPXPhysical()
|
||||
delete fSDLMod;
|
||||
}
|
||||
|
||||
static void MakeBoxFromHull(NxConvexMesh* convexMesh, NxBoxShapeDesc& box)
|
||||
{
|
||||
NxConvexMeshDesc desc;
|
||||
convexMesh->saveToDesc(desc);
|
||||
|
||||
float minX, minY, minZ, maxX, maxY, maxZ;
|
||||
minX = minY = minZ = FLT_MAX;
|
||||
maxX = maxY = maxZ = -FLT_MAX;
|
||||
|
||||
for (int i = 0; i < desc.numVertices; i++)
|
||||
{
|
||||
float* point = (float*)(((char*)desc.points) + desc.pointStrideBytes*i);
|
||||
float x = point[0];
|
||||
float y = point[1];
|
||||
float z = point[2];
|
||||
|
||||
minX = hsMinimum(minX, x);
|
||||
minY = hsMinimum(minY, y);
|
||||
minZ = hsMinimum(minZ, z);
|
||||
maxX = hsMaximum(maxX, x);
|
||||
maxY = hsMaximum(maxY, y);
|
||||
maxZ = hsMaximum(maxZ, z);
|
||||
}
|
||||
|
||||
float xWidth = maxX - minX;
|
||||
float yWidth = maxY - minY;
|
||||
float zWidth = maxZ - minZ;
|
||||
box.dimensions.x = xWidth / 2;
|
||||
box.dimensions.y = yWidth / 2;
|
||||
box.dimensions.z = zWidth / 2;
|
||||
|
||||
//hsMatrix44 mat;
|
||||
//box.localPose.getRowMajor44(&mat.fMap[0][0]);
|
||||
hsPoint3 trans(minX + (xWidth / 2), minY + (yWidth / 2), minZ + (zWidth / 2));
|
||||
//mat.SetTranslate(&trans);
|
||||
//box.localPose.setRowMajor44(&mat.fMap[0][0]);
|
||||
|
||||
hsMatrix44 boxL2W;
|
||||
boxL2W.Reset();
|
||||
boxL2W.SetTranslate(&trans);
|
||||
plPXConvert::Matrix(boxL2W, box.localPose);
|
||||
|
||||
}
|
||||
|
||||
void plPXPhysical::IMakeHull(NxConvexMesh* convexMesh, hsMatrix44 l2w)
|
||||
{
|
||||
NxConvexMeshDesc desc;
|
||||
convexMesh->saveToDesc(desc);
|
||||
|
||||
// make sure there are some triangles to work with
|
||||
if (desc.numTriangles == 0)
|
||||
return;
|
||||
|
||||
// get rid of any we may have already had
|
||||
if (fSaveTriangles)
|
||||
delete [] fSaveTriangles;
|
||||
|
||||
fHullNumberPlanes = desc.numTriangles;
|
||||
fSaveTriangles = new hsPoint3[fHullNumberPlanes*3];
|
||||
|
||||
for (int i = 0; i < desc.numTriangles; i++)
|
||||
{
|
||||
uint32_t* triangle = (uint32_t*)(((char*)desc.triangles) + desc.triangleStrideBytes*i);
|
||||
float* vertex1 = (float*)(((char*)desc.points) + desc.pointStrideBytes*triangle[0]);
|
||||
float* vertex2 = (float*)(((char*)desc.points) + desc.pointStrideBytes*triangle[1]);
|
||||
float* vertex3 = (float*)(((char*)desc.points) + desc.pointStrideBytes*triangle[2]);
|
||||
hsPoint3 pt1(vertex1[0],vertex1[1],vertex1[2]);
|
||||
hsPoint3 pt2(vertex2[0],vertex2[1],vertex2[2]);
|
||||
hsPoint3 pt3(vertex3[0],vertex3[1],vertex3[2]);
|
||||
|
||||
fSaveTriangles[(i*3)+0] = pt1;
|
||||
fSaveTriangles[(i*3)+1] = pt2;
|
||||
fSaveTriangles[(i*3)+2] = pt3;
|
||||
}
|
||||
}
|
||||
|
||||
void plPXPhysical::ISetHullToWorldWTriangles()
|
||||
{
|
||||
// if we have a detector hull and the world hasn't been updated
|
||||
if (fWorldHull == nil)
|
||||
{
|
||||
fWorldHull = new hsPlane3[fHullNumberPlanes];
|
||||
// use the local2world from the physics engine so that it matches the transform of the positions from the triggerees
|
||||
hsMatrix44 l2w;
|
||||
plPXConvert::Matrix(fActor->getGlobalPose(), l2w);
|
||||
int i;
|
||||
for( i = 0; i < fHullNumberPlanes; i++ )
|
||||
{
|
||||
hsPoint3 pt1 = fSaveTriangles[i*3];
|
||||
hsPoint3 pt2 = fSaveTriangles[(i*3)+1];
|
||||
hsPoint3 pt3 = fSaveTriangles[(i*3)+2];
|
||||
|
||||
// local to world translation
|
||||
pt1 = l2w * pt1;
|
||||
pt2 = l2w * pt2;
|
||||
pt3 = l2w * pt3;
|
||||
|
||||
hsPlane3 plane(&pt1, &pt2, &pt3);
|
||||
fWorldHull[i] = plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool plPXPhysical::IsObjectInsideHull(const hsPoint3& pos)
|
||||
{
|
||||
if (fSaveTriangles)
|
||||
{
|
||||
ISetHullToWorldWTriangles();
|
||||
int i;
|
||||
for( i = 0; i < fHullNumberPlanes; i++ )
|
||||
{
|
||||
if (!ITestPlane(pos, fWorldHull[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool plPXPhysical::Should_I_Trigger(bool enter, hsPoint3& pos)
|
||||
{
|
||||
// see if we are inside the detector hull, if so, then don't trigger
|
||||
bool trigger = false;
|
||||
bool inside = IsObjectInsideHull(pos);
|
||||
if ( !inside)
|
||||
{
|
||||
trigger = true;
|
||||
fInsideConvexHull = enter;
|
||||
}
|
||||
else
|
||||
{
|
||||
// catch those rare cases on slow machines that miss the collision before avatar penetrated the face
|
||||
if (enter && !fInsideConvexHull)
|
||||
{
|
||||
#ifdef PHYSX_SAVE_TRIGGERS_WORKAROUND
|
||||
trigger = true;
|
||||
fInsideConvexHull = enter;
|
||||
DetectorLogSpecial("**>Saved a missing enter collision: %s",GetObjectKey()->GetName().c_str());
|
||||
#else
|
||||
DetectorLogSpecial("**>Could have saved a missing enter collision: %s",GetObjectKey()->GetName().c_str());
|
||||
#endif PHYSX_SAVE_TRIGGERS_WORKAROUND
|
||||
}
|
||||
}
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
||||
|
||||
bool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
{
|
||||
bool startAsleep = false;
|
||||
@ -388,29 +230,6 @@ bool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
}
|
||||
break;
|
||||
case plSimDefs::kHullBounds:
|
||||
// FIXME PHYSX - Remove when hull detection is fixed
|
||||
// If this is read time (ie, meshStream is nil), turn the convex hull
|
||||
// into a box. That way the data won't have to change when convex hulls
|
||||
// actually work right.
|
||||
if (fGroup == plSimDefs::kGroupDetector && recipe.meshStream == nil)
|
||||
{
|
||||
#ifdef USE_BOXES_FOR_DETECTOR_HULLS
|
||||
MakeBoxFromHull(recipe.convexMesh, boxDesc);
|
||||
plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*recipe.convexMesh);
|
||||
boxDesc.group = fGroup;
|
||||
actorDesc.shapes.push_back(&boxDesc);
|
||||
#else
|
||||
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
// make a hull of planes for testing IsInside
|
||||
IMakeHull(recipe.convexMesh,recipe.l2s);
|
||||
#endif // USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
convexShapeDesc.meshData = recipe.convexMesh;
|
||||
convexShapeDesc.userData = recipe.meshStream;
|
||||
convexShapeDesc.group = fGroup;
|
||||
actorDesc.shapes.pushBack(&convexShapeDesc);
|
||||
#endif // USE_BOXES_FOR_DETECTOR_HULLS
|
||||
}
|
||||
else
|
||||
{
|
||||
convexShapeDesc.meshData = recipe.convexMesh;
|
||||
convexShapeDesc.userData = recipe.meshStream;
|
||||
@ -669,9 +488,6 @@ void plPXPhysical::IEnable(bool enable)
|
||||
{
|
||||
fActor->clearActorFlag(NX_AF_DISABLE_COLLISION);
|
||||
|
||||
// PHYSX FIXME - after re-enabling a possible detector, we need to check to see if any avatar is already in the PhysX turdy hull detector region
|
||||
plSimulationMgr::GetInstance()->UpdateAvatarInDetector(fWorldKey, this);
|
||||
|
||||
if (fActor->isDynamic())
|
||||
fActor->clearBodyFlag(NX_BF_FROZEN);
|
||||
else
|
||||
|
@ -156,11 +156,6 @@ public:
|
||||
virtual uint16_t GetAllLOSDBs() { return fLOSDBs; }
|
||||
virtual bool IsInLOSDB(uint16_t flag) { return hsCheckBits(fLOSDBs, flag); }
|
||||
|
||||
virtual bool DoDetectorHullWorkaround() { return fSaveTriangles ? true : false; }
|
||||
virtual bool Should_I_Trigger(bool enter, hsPoint3& pos);
|
||||
virtual bool IsObjectInsideHull(const hsPoint3& pos);
|
||||
virtual void SetInsideConvexHull(bool inside) { fInsideConvexHull = inside; }
|
||||
|
||||
virtual plKey GetWorldKey() const { return fWorldKey; }
|
||||
|
||||
virtual plPhysicalSndGroup* GetSoundGroup() const { return fSndGroup; }
|
||||
@ -201,14 +196,6 @@ protected:
|
||||
/** Handle messages about our references. */
|
||||
bool HandleRefMsg(plGenRefMsg * refM);
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WORLDS, SUBWORLDS && CONTEXTS
|
||||
//
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
void IConvertGroups(uint32_t memberOf, uint32_t reportsOn, uint32_t collideWith);
|
||||
|
||||
/** See if the object is in a valid, non-overlapping position.
|
||||
A valid overlap is one which is approved by the collision
|
||||
masking code, i.e. my memberOf has no intersection with your
|
||||
@ -236,8 +223,6 @@ protected:
|
||||
// Enable/disable collisions and dynamic movement
|
||||
void IEnable(bool enable);
|
||||
|
||||
void IMakeHull(NxConvexMesh* convexMesh, hsMatrix44 l2w);
|
||||
|
||||
NxActor* fActor;
|
||||
plKey fWorldKey; // either a subworld or nil
|
||||
|
||||
@ -251,24 +236,6 @@ protected:
|
||||
plKey fObjectKey; // the key to our scene object
|
||||
plKey fSceneNode; // the room we're in
|
||||
|
||||
// PHYSX FIXME - need to create a plasma hull so that we can determine if inside
|
||||
hsPlane3* fWorldHull;
|
||||
uint32_t fHullNumberPlanes;
|
||||
hsPoint3* fSaveTriangles;
|
||||
bool fInsideConvexHull;
|
||||
void ISetHullToWorldWTriangles();
|
||||
inline bool ITestPlane(const hsPoint3 &pos, const hsPlane3 &plane)
|
||||
{
|
||||
float dis = plane.fN.InnerProduct(pos);
|
||||
dis += plane.fD;
|
||||
if (dis == 0.f)
|
||||
return false;
|
||||
if( dis >= 0.f )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// we need to remember the last matrices we sent to the coordinate interface
|
||||
// so that we can recognize them when we send them back and not reapply them,
|
||||
// which would reactivate our body. inelegant but effective
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,211 +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 plPXPhysicalController_h_inc
|
||||
#define plPXPhysicalController_h_inc
|
||||
|
||||
#include "plAvatar/plAvCallbackAction.h"
|
||||
#include "hsQuat.h"
|
||||
|
||||
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
|
||||
|
||||
class NxController;
|
||||
class NxCapsuleController;
|
||||
class NxActor;
|
||||
class plCoordinateInterface;
|
||||
class plPhysicalProxy;
|
||||
class plDrawableSpans;
|
||||
class hsGMaterial;
|
||||
class NxCapsule;
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
class plDbgCollisionInfo
|
||||
{
|
||||
public:
|
||||
plSceneObject *fSO;
|
||||
hsVector3 fNormal;
|
||||
bool fOverlap;
|
||||
};
|
||||
#endif // PLASMA_EXTERNAL_RELEASE
|
||||
|
||||
class plPXPhysicalController : public plPhysicalController
|
||||
{
|
||||
public:
|
||||
plPXPhysicalController(plKey ownerSO, hsScalar height, hsScalar radius);
|
||||
virtual ~plPXPhysicalController();
|
||||
|
||||
virtual void Enable(bool enable);
|
||||
virtual bool IsEnabled() const { return fEnable; }
|
||||
|
||||
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
|
||||
plSimDefs::plLOSDB GetLOSDB() const { return fLOSDB; }
|
||||
|
||||
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel)
|
||||
{
|
||||
fLinearVelocity = linearVel;
|
||||
fAngularVelocity = angVel;
|
||||
}
|
||||
|
||||
virtual const hsVector3& GetLinearVelocity() const { return fAchievedLinearVelocity; }
|
||||
virtual void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
|
||||
|
||||
virtual plKey GetSubworld() const { return fWorldKey; }
|
||||
virtual void SetSubworld(plKey world);
|
||||
|
||||
virtual bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
|
||||
virtual bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
|
||||
virtual void GroundHit() { fGroundHit = true; }
|
||||
virtual hsScalar GetAirTime() const { return fTimeInAir; }
|
||||
virtual void ResetAirTime() { fTimeInAir = 0.f; }
|
||||
virtual void AddSlidingNormal(hsVector3 vec);
|
||||
virtual hsTArray<hsVector3>* GetSlidingNormals() { return &fSlidingNormals; }
|
||||
|
||||
virtual plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
|
||||
virtual bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
|
||||
|
||||
virtual const plCoordinateInterface* GetSubworldCI() const;
|
||||
|
||||
virtual void GetState(hsPoint3& pos, float& zRot);
|
||||
virtual void SetState(const hsPoint3& pos, float zRot);
|
||||
|
||||
plKey GetOwner() const { return fOwner; }
|
||||
|
||||
// Called by the simulation mgr each frame
|
||||
static void Update(bool prestep, hsScalar delSecs);
|
||||
// Used by the LOS mgr to find the controller for an actor it hit
|
||||
static plPXPhysicalController* GetController(NxActor& actor, bool* isController);
|
||||
// test to see if there are any controllers (i.e. avatars) in this subworld
|
||||
static bool plPXPhysicalController::AnyControllersInThisWorld(plKey world);
|
||||
static int plPXPhysicalController::NumControllers();
|
||||
static int plPXPhysicalController::GetControllersInThisSubWorld(plKey world, int maxToReturn,
|
||||
plPXPhysicalController** bufferout);
|
||||
static int plPXPhysicalController::GetNumberOfControllersInThisSubWorld(plKey world);
|
||||
// Call this if a static physical in the scene has changed (unloaded,
|
||||
// collision enabled/disabled, etc)
|
||||
static void RebuildCache();
|
||||
|
||||
virtual void GetPositionSim(hsPoint3& pos) const { IGetPositionSim(pos); }
|
||||
|
||||
virtual void Kinematic(bool state);
|
||||
virtual bool IsKinematic();
|
||||
virtual void GetKinematicPosition(hsPoint3& pos);
|
||||
|
||||
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<uint32_t>& idx, plDrawableSpans* addTo);
|
||||
|
||||
virtual const hsMatrix44& GetPrevSubworldW2L() { return fPrevSubworldW2L; }
|
||||
|
||||
virtual void SetSeek(bool seek){fSeeking=seek;}
|
||||
virtual void GetWorldSpaceCapsule(NxCapsule& cap);
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
static bool fDebugDisplay;
|
||||
#endif // PLASMA_EXTERNAL_RELEASE
|
||||
|
||||
protected:
|
||||
static const hsScalar kAirTimeThreshold;
|
||||
|
||||
friend class PXControllerHitReport;
|
||||
static plPXPhysicalController* FindController(NxController* controller);
|
||||
|
||||
void IApply(hsScalar delSecs);
|
||||
void ISendUpdates(hsScalar delSecs);
|
||||
void ICheckForFalseGround();
|
||||
void ISetGlobalLoc(const hsMatrix44& l2w);
|
||||
void IMatchKinematicToController();
|
||||
void IMoveKinematicToController(hsPoint3& pos);
|
||||
void ISetKinematicLoc(const hsMatrix44& l2w);
|
||||
void IGetPositionSim(hsPoint3& pos) const;
|
||||
|
||||
void ICreateController();
|
||||
void IDeleteController();
|
||||
|
||||
void IInformDetectors(bool entering);
|
||||
|
||||
plKey fOwner;
|
||||
plKey fWorldKey;
|
||||
hsScalar fRadius, fHeight;
|
||||
NxCapsuleController* fController;
|
||||
|
||||
// this is the kinematic actor for triggering things when the avatar is collision-less during behaviors
|
||||
NxActor* fKinematicActor;
|
||||
|
||||
hsVector3 fLinearVelocity;
|
||||
hsScalar fAngularVelocity;
|
||||
|
||||
hsVector3 fAchievedLinearVelocity;
|
||||
|
||||
// The global position and rotation of the avatar last time we set it (so we
|
||||
// can detect if someone else moves him)
|
||||
hsMatrix44 fLastGlobalLoc;
|
||||
//
|
||||
hsPoint3 fLocalPosition;
|
||||
hsQuat fLocalRotation;
|
||||
|
||||
hsMatrix44 fPrevSubworldW2L;
|
||||
|
||||
bool fEnable;
|
||||
bool fEnableChanged;
|
||||
plSimDefs::plLOSDB fLOSDB;
|
||||
|
||||
bool fKinematic;
|
||||
bool fKinematicChanged;
|
||||
bool fKinematicEnableNextUpdate;
|
||||
|
||||
bool fGroundHit;
|
||||
bool fFalseGround;
|
||||
hsScalar fTimeInAir;
|
||||
hsTArray<hsVector3> fSlidingNormals;
|
||||
hsTArray<hsVector3> fPrevSlidingNormals;
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
|
||||
void IDrawDebugDisplay();
|
||||
#endif // PLASMA_EXTERNAL_RELEASE
|
||||
|
||||
plPhysical* fPushingPhysical;
|
||||
bool fFacingPushingPhysical;
|
||||
|
||||
plPhysicalProxy* fProxyGen; // visual proxy for debugging
|
||||
|
||||
bool fHitHead;
|
||||
|
||||
bool fSeeking;
|
||||
};
|
||||
|
||||
#endif // plPXPhysicalController_h_inc
|
File diff suppressed because it is too large
Load Diff
@ -40,22 +40,19 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "plAvatar/plPhysicalControllerCore.h"
|
||||
#include "hsQuat.h"
|
||||
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
|
||||
|
||||
class NxController;
|
||||
class NxCapsuleController;
|
||||
class NxActor;
|
||||
class plCoordinateInterface;
|
||||
class NxCapsule;
|
||||
class PXControllerHitReport;
|
||||
class plPhysicalProxy;
|
||||
class plDrawableSpans;
|
||||
class hsGMaterial;
|
||||
class NxCapsule;
|
||||
class plSceneObject;
|
||||
class PXControllerHitReportWalk;
|
||||
class plPXPhysical;
|
||||
class plCollideMsg;
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
class plDbgCollisionInfo
|
||||
{
|
||||
public:
|
||||
@ -64,97 +61,113 @@ public:
|
||||
bool fOverlap;
|
||||
};
|
||||
#endif // PLASMA_EXTERNAL_RELEASE
|
||||
|
||||
class plPXPhysicalControllerCore: public plPhysicalControllerCore
|
||||
{
|
||||
friend class PXControllerHitReportWalk;
|
||||
public:
|
||||
plPXPhysicalControllerCore(plKey ownerSO, float height, float radius);
|
||||
plPXPhysicalControllerCore(plKey ownerSO, float height, float radius, bool human);
|
||||
~plPXPhysicalControllerCore();
|
||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
||||
|
||||
inline virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
|
||||
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
|
||||
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
|
||||
// Use plArmatureModBase::EnablePhysics() instead.
|
||||
virtual void Enable(bool enable);
|
||||
|
||||
// Subworld
|
||||
virtual void SetSubworld(plKey world);
|
||||
virtual const plCoordinateInterface* GetSubworldCI() const ;
|
||||
|
||||
// For the avatar SDL only
|
||||
virtual void GetState(hsPoint3& pos, float& zRot);
|
||||
virtual void SetState(const hsPoint3& pos, float zRot);
|
||||
// kinematic stuff .... should be just for when playing a behavior...
|
||||
virtual void Kinematic(bool state);
|
||||
virtual bool IsKinematic();
|
||||
virtual void GetKinematicPosition(hsPoint3& pos);
|
||||
virtual const hsMatrix44& GetPrevSubworldW2L(){ return fPrevSubworldW2L; }
|
||||
//when seeking no longer want to interact with exclusion regions
|
||||
virtual void GetWorldSpaceCapsule(NxCapsule& cap) const;
|
||||
static void RebuildCache();
|
||||
virtual const hsMatrix44& GetLastGlobalLoc(){return fLastGlobalLoc;}
|
||||
virtual void SetKinematicLoc(const hsMatrix44& l2w){ISetKinematicLoc(l2w);}
|
||||
virtual void SetGlobalLoc(const hsMatrix44& l2w){ISetGlobalLoc(l2w);}
|
||||
virtual void HandleEnableChanged();
|
||||
virtual void HandleKinematicChanged();
|
||||
virtual void HandleKinematicEnableNextUpdate();
|
||||
virtual void GetPositionSim(hsPoint3& pos){IGetPositionSim(pos);}
|
||||
virtual void MoveKinematicToController(hsPoint3& pos);
|
||||
virtual const hsPoint3& GetLocalPosition(){return fLocalPosition;}
|
||||
virtual void SetControllerDimensions(float radius, float height);
|
||||
|
||||
// Movement strategy
|
||||
virtual void SetMovementStrategy(plMovementStrategy* strategy);
|
||||
|
||||
// Global location
|
||||
virtual void SetGlobalLoc(const hsMatrix44& l2w);
|
||||
|
||||
// Local Sim Position
|
||||
virtual void GetPositionSim(hsPoint3& pos);
|
||||
|
||||
// Move kinematic controller
|
||||
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
|
||||
|
||||
// Set linear velocity on dynamic controller
|
||||
virtual void SetLinearVelocitySim(const hsVector3& linearVel);
|
||||
|
||||
// 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);
|
||||
|
||||
// any clean up for the controller should go here
|
||||
virtual void LeaveAge();
|
||||
virtual void UpdateControllerAndPhysicalRep();
|
||||
|
||||
// Capsule
|
||||
void GetWorldSpaceCapsule(NxCapsule& cap) const;
|
||||
|
||||
// Create Proxy for debug rendering
|
||||
plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<uint32_t>& idx, plDrawableSpans* addTo);
|
||||
|
||||
// Dynamic hits
|
||||
void AddDynamicHit(plPXPhysical* phys);
|
||||
|
||||
//////////////////////////////////////////
|
||||
//Static Helper Functions
|
||||
////////////////////////////////////////
|
||||
// Used by the LOS mgr to find the controller for an actor it hit
|
||||
static plPXPhysicalControllerCore* GetController(NxActor& actor, bool* isController);
|
||||
// test to see if there are any controllers (i.e. avatars) in this subworld
|
||||
|
||||
// Call pre-sim to apply movement to controllers
|
||||
static void Apply(float delSecs);
|
||||
|
||||
// Call post-sim to update controllers
|
||||
static void Update(int numSubSteps, float alpha);
|
||||
|
||||
// Update controllers when not performing a physics step
|
||||
static void UpdateNonPhysical(float alpha);
|
||||
|
||||
// Rebuild the controller cache, required when a static actor in the scene has changed.
|
||||
static void RebuildCache();
|
||||
|
||||
// Returns the plPXPhysicalControllerCore associated with the given NxActor
|
||||
static plPXPhysicalControllerCore* GetController(NxActor& actor);
|
||||
|
||||
// Subworld controller queries
|
||||
static bool AnyControllersInThisWorld(plKey world);
|
||||
static int NumControllers();
|
||||
static int GetControllersInThisSubWorld(plKey world, int maxToReturn,
|
||||
plPXPhysicalControllerCore** bufferout);
|
||||
static int GetNumberOfControllersInThisSubWorld(plKey world);
|
||||
static void UpdatePrestep(float delSecs);
|
||||
static void UpdatePoststep(float delSecs);
|
||||
static void UpdatePostSimStep(float delSecs);
|
||||
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<uint32_t>& idx, plDrawableSpans* addTo);
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
static bool fDebugDisplay;
|
||||
#endif // PLASMA_EXTERNAL_RELEASE
|
||||
static int GetControllersInThisSubWorld(plKey world, int maxToReturn, plPXPhysicalControllerCore** bufferout);
|
||||
|
||||
// Controller count
|
||||
static int NumControllers();
|
||||
static void SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
|
||||
static int fPXControllersMax;
|
||||
virtual int SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, bool vsDynamics, bool vsStatics, uint32_t& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut);
|
||||
virtual void BehaveLikeAnimatedPhysical(bool actLikeAnAnimatedPhys);
|
||||
virtual bool BehavingLikeAnAnimatedPhysical();
|
||||
virtual const hsVector3& GetLinearVelocity();
|
||||
|
||||
virtual void SetLinearVelocity(const hsVector3& linearVel);
|
||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
||||
virtual void SetAngularVelocity(const float angvel);
|
||||
virtual void SetVelocities(const hsVector3& linearVel, float angVel);
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
static bool fDebugDisplay;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend class PXControllerHitReport;
|
||||
static plPXPhysicalControllerCore* FindController(NxController* controller);
|
||||
void ISetGlobalLoc(const hsMatrix44& l2w);
|
||||
void IMatchKinematicToController();
|
||||
void IMatchControllerToKinematic();
|
||||
void ISetKinematicLoc(const hsMatrix44& l2w);
|
||||
void IGetPositionSim(hsPoint3& pos) const;
|
||||
void ICreateController();
|
||||
void IDeleteController();
|
||||
void IInformDetectors(bool entering,bool deferUntilNextSim);
|
||||
|
||||
virtual void IHandleEnableChanged();
|
||||
|
||||
void IInformDetectors(bool entering);
|
||||
|
||||
void ICreateController(const hsPoint3& pos);
|
||||
NxActor* fKinematicActor;
|
||||
NxCapsuleController* fController;
|
||||
void IDeleteController();
|
||||
|
||||
void IDispatchQueuedMsgs();
|
||||
void IProcessDynamicHits();
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
|
||||
void IDrawDebugDisplay();
|
||||
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
|
||||
#endif
|
||||
void IHandleResize();
|
||||
float fPreferedRadius;
|
||||
float fPreferedHeight;
|
||||
// The global position and rotation of the avatar last time we set it (so we
|
||||
// can detect if someone else moves him)
|
||||
|
||||
std::vector<plCollideMsg*> fQueuedCollideMsgs;
|
||||
std::vector<plPXPhysical*> fDynamicHits;
|
||||
|
||||
NxCapsuleController* fController;
|
||||
NxActor* fActor;
|
||||
|
||||
plPhysicalProxy* fProxyGen;
|
||||
bool fBehavingLikeAnimatedPhys;
|
||||
bool fKinematicCCT;
|
||||
bool fHuman;
|
||||
};
|
||||
|
@ -70,139 +70,43 @@ class SensorReport : public NxUserTriggerReport
|
||||
{
|
||||
virtual void onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status)
|
||||
{
|
||||
// Get our trigger physical. This should definitely have a plPXPhysical
|
||||
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
|
||||
plKey otherKey = nil;
|
||||
bool doReport = false;
|
||||
|
||||
// Get the triggerer. This may be an avatar, which doesn't have a
|
||||
// plPXPhysical, so we have to extract the necessary info.
|
||||
plKey otherKey = nil;
|
||||
hsPoint3 otherPos = plPXConvert::Point(otherShape.getGlobalPosition());
|
||||
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("-->%s %s (status=%x) other@(%f,%f,%f)",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit",status,otherPos.fX,otherPos.fY,otherPos.fZ);
|
||||
// Get our trigger physical. This should definitely have a plPXPhysical
|
||||
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
|
||||
|
||||
// Get the triggerer. If it doesn't have a plPXPhyscial, it's an avatar
|
||||
plPXPhysical* otherPhys = (plPXPhysical*)otherShape.getActor().userData;
|
||||
if (otherPhys)
|
||||
{
|
||||
otherKey = otherPhys->GetObjectKey();
|
||||
doReport = triggerPhys->DoReportOn((plSimDefs::Group)otherPhys->GetGroup());
|
||||
if (!doReport)
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s :failed group. US=%x OTHER=(%s)%x",triggerPhys->GetObjectKey()->GetName().c_str(),triggerPhys->GetGroup(),otherPhys->GetObjectKey()->GetName().c_str(),otherPhys->GetGroup());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isController;
|
||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor(),&isController);
|
||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor());
|
||||
if (controller)
|
||||
{
|
||||
if (isController)
|
||||
{
|
||||
#ifdef PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s : ignoring controller events.",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
return;
|
||||
#else // else if trigger on both controller and kinematic
|
||||
// only suppress controller collision 'enters' when disabled but let 'exits' continue
|
||||
// ...this is because there are detector regions that are on the edge on ladders that the exit gets missed.
|
||||
if ( ( !controller->IsEnabled() /*&& (status & NX_TRIGGER_ON_ENTER)*/ ) || controller->IsKinematic() )
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s : controller is not enabled.",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
return;
|
||||
}
|
||||
#endif // PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
|
||||
}
|
||||
#ifndef PHYSX_ONLY_TRIGGER_FROM_KINEMATIC // if triggering only kinematics, then all should trigger
|
||||
else
|
||||
{
|
||||
// only suppress kinematic collision 'enters' when disabled but let 'exits' continue
|
||||
// ...this is because there are detector regions that are on the edge on ladders that the exit gets missed.
|
||||
if ( !controller->IsKinematic() /*&& (status & NX_TRIGGER_ON_ENTER) */ )
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s : kinematic is not enabled.",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
|
||||
otherKey = controller->GetOwner();
|
||||
doReport = triggerPhys->DoReportOn(plSimDefs::kGroupAvatar);
|
||||
if (plSimulationMgr::fExtraProfile )
|
||||
{
|
||||
if (!doReport)
|
||||
{
|
||||
DetectorLogRed("<--Kill collision %s :failed group. US=%x OTHER=(NotAvatar)",triggerPhys->GetObjectKey()->GetName().c_str(),triggerPhys->GetGroup());
|
||||
}
|
||||
else
|
||||
{
|
||||
hsPoint3 avpos;
|
||||
controller->GetPositionSim(avpos);
|
||||
DetectorLogRed("-->Avatar at (%f,%f,%f)",avpos.fX,avpos.fY,avpos.fZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doReport)
|
||||
{
|
||||
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
if ( triggerPhys->DoDetectorHullWorkaround() )
|
||||
{
|
||||
if (status & NX_TRIGGER_ON_ENTER && triggerPhys->Should_I_Trigger(status & NX_TRIGGER_ON_ENTER, otherPos) )
|
||||
if (status & NX_TRIGGER_ON_ENTER)
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("-->Send Collision (CH) %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit");
|
||||
DetectorLogRed("-->Send Collision %s enter",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true);
|
||||
}
|
||||
else if (status & NX_TRIGGER_ON_ENTER)
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s :failed Should I trigger",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
}
|
||||
if (status & NX_TRIGGER_ON_LEAVE && triggerPhys->Should_I_Trigger(status & NX_TRIGGER_ON_ENTER, otherPos) )
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("-->Send Collision (CH) %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit");
|
||||
plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false);
|
||||
}
|
||||
else if (status & NX_TRIGGER_ON_LEAVE)
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s :failed Should I trigger",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
}
|
||||
if (!(status & NX_TRIGGER_ON_ENTER) && !(status & NX_TRIGGER_ON_LEAVE) )
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s :failed event(CH)",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif // USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
if (status & NX_TRIGGER_ON_ENTER)
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("-->Send Collision %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit");
|
||||
plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true);
|
||||
}
|
||||
if (status & NX_TRIGGER_ON_LEAVE)
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("-->Send Collision %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit");
|
||||
DetectorLogRed("-->Send Collision %s exit",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false);
|
||||
}
|
||||
if (!(status & NX_TRIGGER_ON_ENTER) && !(status & NX_TRIGGER_ON_LEAVE) )
|
||||
{
|
||||
if (plSimulationMgr::fExtraProfile)
|
||||
DetectorLogRed("<--Kill collision %s :failed event",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||
}
|
||||
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
}
|
||||
#endif // USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
}
|
||||
}
|
||||
} gSensorReport;
|
||||
@ -289,8 +193,8 @@ class ErrorStream : public NxUserOutputStream
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#define kDefaultMaxDelta 0.1 // if the step is greater than .1 seconds, clamp to that
|
||||
#define kDefaultStepSize 1.f / 60.f // default simulation freqency is 60hz
|
||||
#define kDefaultMaxDelta (0.15) // if the step is greater than .15 seconds, clamp to that
|
||||
#define kDefaultStepSize (1.f / 60.f) // default simulation freqency is 60hz
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -378,6 +282,8 @@ plSimulationMgr* plSimulationMgr::GetInstance()
|
||||
|
||||
plSimulationMgr::plSimulationMgr()
|
||||
: fSuspended(true)
|
||||
, fAccumulator(0.0f)
|
||||
, fStepCount(0)
|
||||
, fLOSDispatch(new plLOSDispatch())
|
||||
, fSoundMgr(new plPhysicsSoundMgr)
|
||||
, fLog(nil)
|
||||
@ -470,6 +376,7 @@ NxScene* plSimulationMgr::GetScene(plKey world)
|
||||
scene->setGroupCollisionFlag(i, plSimDefs::kGroupDynamicBlocker, false);
|
||||
scene->setGroupCollisionFlag(i, plSimDefs::kGroupLOSOnly, false);
|
||||
scene->setGroupCollisionFlag(plSimDefs::kGroupLOSOnly, i, false);
|
||||
scene->setGroupCollisionFlag(i, plSimDefs::kGroupAvatarKinematic, false);
|
||||
}
|
||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatar, false);
|
||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatarBlocker, true);
|
||||
@ -478,6 +385,10 @@ NxScene* plSimulationMgr::GetScene(plKey world)
|
||||
scene->setGroupCollisionFlag( plSimDefs::kGroupStatic, plSimDefs::kGroupAvatar, true);
|
||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupDynamic, true);
|
||||
|
||||
// Kinematically controlled avatars interact with detectors and dynamics
|
||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatarKinematic, plSimDefs::kGroupDetector, true);
|
||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatarKinematic, plSimDefs::kGroupDynamic, true);
|
||||
|
||||
// The dynamics are in actor group 1, everything else is in 0. Request
|
||||
// a callback for whenever a dynamic touches something.
|
||||
scene->setActorGroupPairFlags(0, 1, NX_NOTIFY_ON_TOUCH);
|
||||
@ -507,86 +418,6 @@ void plSimulationMgr::ReleaseScene(plKey world)
|
||||
}
|
||||
}
|
||||
|
||||
void plSimulationMgr::ISendCollisionMsg(plKey receiver, plKey hitter, bool entering)
|
||||
{
|
||||
DetectorLogYellow("Collision: %s is inside %s. Sending an %s msg", hitter ? hitter->GetName().c_str() : "(nil)",
|
||||
receiver->GetName().c_str(), entering ? "'enter'" : "'exit'");
|
||||
plCollideMsg* msg = new plCollideMsg;
|
||||
msg->fOtherKey = hitter;
|
||||
msg->fEntering = entering;
|
||||
msg->AddReceiver(receiver);
|
||||
msg->Send();
|
||||
}
|
||||
|
||||
void plSimulationMgr::UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering)
|
||||
{
|
||||
// search thru the actors in a scene looking for convex hull detectors and see if the avatar is inside it
|
||||
// ... and then send appropiate collision message if needed
|
||||
NxScene* scene = GetScene(world);
|
||||
plSceneObject* avObj = plSceneObject::ConvertNoRef(avatar->ObjectIsLoaded());
|
||||
const plCoordinateInterface* ci = avObj->GetCoordinateInterface();
|
||||
hsPoint3 soPos = ci->GetWorldPos();
|
||||
if (scene)
|
||||
{
|
||||
uint32_t numActors = scene->getNbActors();
|
||||
NxActor** actors = scene->getActors();
|
||||
|
||||
for (int i = 0; i < numActors; i++)
|
||||
{
|
||||
plPXPhysical* physical = (plPXPhysical*)actors[i]->userData;
|
||||
if (physical && physical->DoDetectorHullWorkaround())
|
||||
{
|
||||
if ( physical->IsObjectInsideHull(pos) )
|
||||
{
|
||||
physical->SetInsideConvexHull(entering);
|
||||
// we are entering this world... say we entered this detector
|
||||
ISendCollisionMsg(physical->GetObjectKey(), avatar, entering);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plSimulationMgr::UpdateAvatarInDetector(plKey world, plPXPhysical* detector)
|
||||
{
|
||||
// search thru the actors in a scene looking for avatars that might be in the newly enabled detector region
|
||||
// ... and then send appropiate collision message if needed
|
||||
if ( detector->DoDetectorHullWorkaround() )
|
||||
{
|
||||
NxScene* scene = GetScene(world);
|
||||
if (scene)
|
||||
{
|
||||
uint32_t numActors = scene->getNbActors();
|
||||
NxActor** actors = scene->getActors();
|
||||
|
||||
for (int i = 0; i < numActors; i++)
|
||||
{
|
||||
if ( actors[i]->userData == nil )
|
||||
{
|
||||
// we go a controller
|
||||
bool isController;
|
||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(*actors[i],&isController);
|
||||
if (controller && controller->IsEnabled())
|
||||
{
|
||||
plKey avatar = controller->GetOwner();
|
||||
plSceneObject* avObj = plSceneObject::ConvertNoRef(avatar->ObjectIsLoaded());
|
||||
const plCoordinateInterface* ci;
|
||||
if ( avObj && ( ci = avObj->GetCoordinateInterface() ) )
|
||||
{
|
||||
if ( detector->IsObjectInsideHull(ci->GetWorldPos()) )
|
||||
{
|
||||
detector->SetInsideConvexHull(true);
|
||||
// we are entering this world... say we entered this detector
|
||||
ISendCollisionMsg(detector->GetObjectKey(), avatar, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plSimulationMgr::AddCollisionMsg(plKey hitee, plKey hitter, bool enter)
|
||||
{
|
||||
// First, make sure we have no dupes
|
||||
@ -614,20 +445,41 @@ void plSimulationMgr::AddCollisionMsg(plKey hitee, plKey hitter, bool enter)
|
||||
pMsg->fEntering = enter;
|
||||
fCollideMsgs.push_back(pMsg);
|
||||
}
|
||||
void plSimulationMgr::AddCollisionMsg(plCollideMsg* msg)
|
||||
{
|
||||
fCollideMsgs.push_back(msg);
|
||||
}
|
||||
|
||||
void plSimulationMgr::Advance(float delSecs)
|
||||
{
|
||||
if (fSuspended)
|
||||
return;
|
||||
|
||||
plProfile_IncCount(StepLen, (int)(delSecs*1000));
|
||||
fAccumulator += delSecs;
|
||||
if (fAccumulator < kDefaultStepSize)
|
||||
{
|
||||
// Not enough time has passed to perform a substep.
|
||||
plPXPhysicalControllerCore::UpdateNonPhysical(fAccumulator / kDefaultStepSize);
|
||||
return;
|
||||
}
|
||||
else if (fAccumulator > kDefaultMaxDelta)
|
||||
{
|
||||
if (fExtraProfile)
|
||||
Log("Step clamped from %f to limit of %f", fAccumulator, kDefaultMaxDelta);
|
||||
fAccumulator = kDefaultMaxDelta;
|
||||
}
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELASE
|
||||
uint32_t stepTime = hsTimer::GetPrecTickCount();
|
||||
#endif
|
||||
++fStepCount;
|
||||
|
||||
// Perform as many whole substeps as possible saving the remainder in our accumulator.
|
||||
int numSubSteps = (int)(fAccumulator / kDefaultStepSize + 0.000001f);
|
||||
float delta = numSubSteps * kDefaultStepSize;
|
||||
fAccumulator -= delta;
|
||||
|
||||
plProfile_IncCount(StepLen, (int)(delta*1000));
|
||||
plProfile_BeginTiming(Step);
|
||||
plPXPhysicalControllerCore::UpdatePrestep(delSecs);
|
||||
plPXPhysicalControllerCore::UpdatePoststep( delSecs);
|
||||
|
||||
plPXPhysicalControllerCore::Apply(delta);
|
||||
|
||||
for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
|
||||
{
|
||||
@ -642,12 +494,13 @@ void plSimulationMgr::Advance(float delSecs)
|
||||
}
|
||||
if (do_advance)
|
||||
{
|
||||
scene->simulate(delSecs);
|
||||
scene->simulate(delta);
|
||||
scene->flushStream();
|
||||
scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
|
||||
}
|
||||
}
|
||||
plPXPhysicalControllerCore::UpdatePostSimStep(delSecs);
|
||||
|
||||
plPXPhysicalControllerCore::Update(numSubSteps, fAccumulator / kDefaultStepSize);
|
||||
|
||||
plProfile_EndTiming(Step);
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
@ -730,9 +583,6 @@ void plSimulationMgr::ISendUpdates()
|
||||
plPXPhysical* physical = (plPXPhysical*)actors[i]->userData;
|
||||
if (physical)
|
||||
{
|
||||
// apply any hit forces
|
||||
physical->ApplyHitForce();
|
||||
|
||||
if (physical->GetSceneNode())
|
||||
{
|
||||
physical->SendNewLocation();
|
||||
|
@ -99,12 +99,11 @@ public:
|
||||
|
||||
int GetMaterialIdx(NxScene* scene, float friction, float restitution);
|
||||
|
||||
// PHYSX FIXME - walk thru all the convex hull detector regions to see if we are in any... we're either coming or going
|
||||
void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering);
|
||||
void UpdateAvatarInDetector(plKey world, plPXPhysical* detector);
|
||||
uint32_t GetStepCount() const { return fStepCount; }
|
||||
|
||||
//Fix to Move collision messages and their handling out of the simulation step
|
||||
void AddCollisionMsg(plKey hitee, plKey hitter, bool entering);
|
||||
void AddCollisionMsg(plCollideMsg* msg);
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
static bool fDisplayAwakeActors;
|
||||
@ -121,9 +120,6 @@ protected:
|
||||
// Walk through the synchronization requests and send them as appropriate.
|
||||
void IProcessSynchs();
|
||||
|
||||
// PHYSX FIXME send a collision message - should only be used with UpdateDetectorsInScene
|
||||
void ISendCollisionMsg(plKey receiver, plKey hitter, bool entering);
|
||||
|
||||
NxPhysicsSDK* fSDK;
|
||||
|
||||
plPhysicsSoundMgr* fSoundMgr;
|
||||
@ -144,6 +140,9 @@ protected:
|
||||
// but nothing will move.
|
||||
bool fSuspended;
|
||||
|
||||
float fAccumulator;
|
||||
uint32_t fStepCount;
|
||||
|
||||
// A utility class to keep track of a request for a physical synchronization.
|
||||
// These requests must pass a certain criteria (see the code for the latest)
|
||||
// before they are actually either sent over the network or rejected.
|
||||
|
@ -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,11 +64,15 @@ 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"
|
||||
|
||||
#define USE_PHYSX_MULTIPLE_CAMREGION_ENTER 1
|
||||
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND 1
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
#include "plPhysX/plSimulationMgr.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
plArmatureMod* plCollisionDetector::IGetAvatarModifier(plKey key)
|
||||
{
|
||||
@ -240,57 +243,18 @@ plCameraRegionDetector::~plCameraRegionDetector()
|
||||
hsRefCnt_SafeUnRef(*it);
|
||||
}
|
||||
|
||||
void plCameraRegionDetector::ITrigger(plKey hitter, bool entering, bool immediate)
|
||||
void plCameraRegionDetector::ISendTriggerMsg()
|
||||
{
|
||||
if (fSavingSendMsg)
|
||||
DetectorLogRed("%s: Stale messages on ITrigger. This should never happen!", GetKeyName().c_str());
|
||||
if (fIsInside && entering)
|
||||
DetectorLogRed("%s: Duplicate enter! Did we miss an exit?", GetKeyName().c_str());
|
||||
else if (!fIsInside && !entering)
|
||||
DetectorLogRed("%s: Duplicate exit! Did we miss an enter?", GetKeyName().c_str());
|
||||
|
||||
fSavingSendMsg = true;
|
||||
fSavedMsgEnterFlag = entering;
|
||||
if (entering)
|
||||
for (plCameraMsgVec::iterator it = fMessages.begin(); it != fMessages.end(); ++it)
|
||||
{
|
||||
DetectorLog("%s: Saving camera Entering volume - Evals=%d", GetKeyName().c_str(),fNumEvals);
|
||||
fLastEnterEval = fNumEvals;
|
||||
}
|
||||
plCameraMsg* msg = *it;
|
||||
if (fIsInside)
|
||||
msg->SetCmd(plCameraMsg::kEntering);
|
||||
else
|
||||
{
|
||||
DetectorLog("%s: Saving camera Exiting volume - Evals=%d", GetKeyName().c_str(),fNumEvals);
|
||||
fLastExitEval = fNumEvals;
|
||||
}
|
||||
|
||||
if (immediate)
|
||||
ISendSavedTriggerMsgs();
|
||||
}
|
||||
|
||||
void plCameraRegionDetector::ISendSavedTriggerMsgs()
|
||||
{
|
||||
if (fSavingSendMsg)
|
||||
{
|
||||
for (size_t i = 0; i < fMessages.size(); ++i)
|
||||
{
|
||||
hsRefCnt_SafeRef(fMessages[i]);
|
||||
if (fSavedMsgEnterFlag)
|
||||
{
|
||||
fMessages[i]->SetCmd(plCameraMsg::kEntering);
|
||||
DetectorLog("Entering cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName().c_str(),fNumEvals,i+1,fMessages.size());
|
||||
fIsInside = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fMessages[i]->ClearCmd(plCameraMsg::kEntering);
|
||||
DetectorLog("Exiting cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName().c_str(),fNumEvals,i+1,fMessages.size());
|
||||
fIsInside = false;
|
||||
}
|
||||
plgDispatch::MsgSend(fMessages[i]);
|
||||
msg->ClearCmd(plCameraMsg::kEntering);
|
||||
msg->SendAndKeep();
|
||||
}
|
||||
}
|
||||
fSavingSendMsg = false;
|
||||
}
|
||||
|
||||
|
||||
bool plCameraRegionDetector::MsgReceive(plMessage* msg)
|
||||
{
|
||||
@ -300,8 +264,16 @@ bool plCameraRegionDetector::MsgReceive(plMessage* msg)
|
||||
// camera collisions are only for the local player
|
||||
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey)
|
||||
return true;
|
||||
// Fall through to plObjectInVolumeDetector, which will register us for plEvalMsg
|
||||
// and handle it for us. (Hint: See ISendSavedTriggerMsgs)
|
||||
|
||||
if (!fWaitingForEval)
|
||||
IRegisterForEval();
|
||||
|
||||
fEntering = (pCollMsg->fEntering != 0);
|
||||
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return plObjectInVolumeDetector::MsgReceive(msg);
|
||||
@ -327,56 +299,72 @@ void plCameraRegionDetector::Write(hsStream* stream, hsResMgr* mgr)
|
||||
|
||||
}
|
||||
|
||||
void plCameraRegionDetector::IHandleEval(plEvalMsg*)
|
||||
{
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
if (plSimulationMgr::GetInstance()->GetStepCount() - fLastStep > 1)
|
||||
{
|
||||
#endif
|
||||
if (fIsInside != fEntering)
|
||||
{
|
||||
fIsInside = fEntering;
|
||||
DetectorLog("%s CameraRegion: %s", fIsInside ? "Entering" : "Exiting", GetKeyName().c_str());
|
||||
ISendTriggerMsg();
|
||||
}
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
fWaitingForEval = false;
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
/////////////////////////////////
|
||||
/////////////////////////////////
|
||||
/////////////////////////////////
|
||||
// object-in-volume detector
|
||||
|
||||
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering, bool immediate)
|
||||
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering)
|
||||
{
|
||||
hsRefCnt_SafeUnRef(fSavedActivatorMsg);
|
||||
fSavedActivatorMsg = new plActivatorMsg;
|
||||
fSavedActivatorMsg->AddReceivers(fReceivers);
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
for (bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); ++it)
|
||||
{
|
||||
plCollisionBookKeepingInfo* collisionInfo = *it;
|
||||
if (collisionInfo->fHitter == hitter)
|
||||
{
|
||||
collisionInfo->fEntering = entering;
|
||||
collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fProxyKey)
|
||||
fSavedActivatorMsg->fHiteeObj = fProxyKey;
|
||||
else
|
||||
fSavedActivatorMsg->fHiteeObj = GetTarget()->GetKey();
|
||||
plCollisionBookKeepingInfo* collisionInfo = new plCollisionBookKeepingInfo(hitter, entering);
|
||||
fCollisionList.push_back(collisionInfo);
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
fSavedActivatorMsg->fHitterObj = hitter;
|
||||
fSavedActivatorMsg->SetSender(GetKey());
|
||||
void plObjectInVolumeDetector::IRegisterForEval()
|
||||
{
|
||||
fWaitingForEval = true;
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
}
|
||||
|
||||
void plObjectInVolumeDetector::ISendTriggerMsg(plKey hitter, bool entering)
|
||||
{
|
||||
plActivatorMsg* activatorMsg = new plActivatorMsg();
|
||||
activatorMsg->SetSender(GetKey());
|
||||
activatorMsg->AddReceivers(fReceivers);
|
||||
activatorMsg->fHiteeObj = fProxyKey ? fProxyKey : GetTarget()->GetKey();
|
||||
activatorMsg->fHitterObj = hitter;
|
||||
if (entering)
|
||||
{
|
||||
DetectorLog("%s: Saving Entering volume - Evals=%d", GetKeyName().c_str(), fNumEvals);
|
||||
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
|
||||
fLastEnterEval = fNumEvals;
|
||||
}
|
||||
activatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
|
||||
else
|
||||
{
|
||||
DetectorLog("%s: Saving Exiting volume - Evals=%d", GetKeyName().c_str(), fNumEvals);
|
||||
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
|
||||
fLastExitEval = fNumEvals;
|
||||
}
|
||||
activatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
|
||||
|
||||
if (immediate)
|
||||
ISendSavedTriggerMsgs();
|
||||
}
|
||||
|
||||
void plObjectInVolumeDetector::ISendSavedTriggerMsgs()
|
||||
{
|
||||
if (fSavedActivatorMsg)
|
||||
{
|
||||
if (fSavedActivatorMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
|
||||
DetectorLog("%s: Sending Entering volume - Evals=%d", GetKeyName().c_str(), fNumEvals);
|
||||
else
|
||||
DetectorLog("%s: Sending Exiting volume - Evals=%d", GetKeyName().c_str(), fNumEvals);
|
||||
|
||||
// we're saving the message to be dispatched later...
|
||||
plgDispatch::MsgSend(fSavedActivatorMsg);
|
||||
}
|
||||
fSavedActivatorMsg = nil;
|
||||
plgDispatch::MsgSend(activatorMsg);
|
||||
}
|
||||
|
||||
bool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
|
||||
@ -387,18 +375,17 @@ bool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
|
||||
// If the avatar is disabled (flying around), don't trigger
|
||||
if (IIsDisabledAvatar(pCollMsg->fOtherKey))
|
||||
return false;
|
||||
|
||||
if (!fWaitingForEval)
|
||||
IRegisterForEval();
|
||||
|
||||
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
return true;
|
||||
}
|
||||
|
||||
plEvalMsg* pEvalMsg = plEvalMsg::ConvertNoRef(msg);
|
||||
if (pEvalMsg)
|
||||
{
|
||||
fNumEvals++;
|
||||
ISendSavedTriggerMsgs();
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
}
|
||||
IHandleEval(pEvalMsg);
|
||||
|
||||
plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg);
|
||||
if (pageMsg && pageMsg->fUnload)
|
||||
@ -409,6 +396,48 @@ bool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
|
||||
return plCollisionDetector::MsgReceive(msg);
|
||||
}
|
||||
|
||||
void plObjectInVolumeDetector::IHandleEval(plEvalMsg*)
|
||||
{
|
||||
bookKeepingList::iterator it = fCollisionList.begin();
|
||||
while (it != fCollisionList.end())
|
||||
{
|
||||
plCollisionBookKeepingInfo* collisionInfo = *it;
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
if (plSimulationMgr::GetInstance()->GetStepCount() - collisionInfo->fLastStep > 1)
|
||||
{
|
||||
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
ResidentSet::iterator j = fCurrentResidents.find(collisionInfo->fHitter);
|
||||
bool wasInside = j != fCurrentResidents.end();
|
||||
if (collisionInfo->fEntering != wasInside)
|
||||
{
|
||||
if (collisionInfo->fEntering)
|
||||
{
|
||||
fCurrentResidents.insert(collisionInfo->fHitter);
|
||||
DetectorLog("%s: Sending Volume Enter ActivatorMsg", GetKeyName().c_str());
|
||||
ISendTriggerMsg(collisionInfo->fHitter, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
fCurrentResidents.erase(j);
|
||||
DetectorLog("%s: Sending Volume Exit ActivatorMsg", GetKeyName().c_str());
|
||||
ISendTriggerMsg(collisionInfo->fHitter, false);
|
||||
}
|
||||
}
|
||||
|
||||
delete collisionInfo;
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
it = fCollisionList.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
#else
|
||||
++it;
|
||||
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
}
|
||||
}
|
||||
|
||||
void plObjectInVolumeDetector::SetTarget(plSceneObject* so)
|
||||
{
|
||||
plCollisionDetector::SetTarget(so);
|
||||
@ -475,7 +504,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
|
||||
@ -485,13 +514,13 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
|
||||
{
|
||||
DetectorLog("%s: Trigger InVolume&Facing", GetKeyName().c_str());
|
||||
fTriggered = true;
|
||||
ITrigger(avatar->GetKey(), true, true);
|
||||
ISendTriggerMsg(avatar->GetKey(), true);
|
||||
}
|
||||
else if (!facing && fTriggered)
|
||||
{
|
||||
DetectorLog("%s: Untrigger InVolume&Facing", GetKeyName().c_str());
|
||||
fTriggered = false;
|
||||
ITrigger(avatar->GetKey(), false, true);
|
||||
ISendTriggerMsg(avatar->GetKey(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -525,7 +554,7 @@ bool plObjectInVolumeAndFacingDetector::MsgReceive(plMessage* msg)
|
||||
if (fTriggered)
|
||||
{
|
||||
fTriggered = false;
|
||||
ITrigger(plNetClientApp::GetInstance()->GetLocalPlayerKey(), false, true);
|
||||
ISendTriggerMsg(plNetClientApp::GetInstance()->GetLocalPlayerKey(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -645,11 +674,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
|
||||
|
@ -53,6 +53,8 @@ class plArmatureMod;
|
||||
class plActivatorMsg;
|
||||
class plEvalMsg;
|
||||
|
||||
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
|
||||
class plCollisionDetector : public plDetectorModifier
|
||||
{
|
||||
protected:
|
||||
@ -92,23 +94,37 @@ public:
|
||||
class plObjectInVolumeDetector : public plCollisionDetector
|
||||
{
|
||||
protected:
|
||||
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
|
||||
virtual void ISendSavedTriggerMsgs();
|
||||
class plCollisionBookKeepingInfo
|
||||
{
|
||||
public:
|
||||
plCollisionBookKeepingInfo(const plKey& key, bool entering)
|
||||
: fHitter(key), fEntering(entering) { }
|
||||
|
||||
plActivatorMsg* fSavedActivatorMsg;
|
||||
uint32_t fNumEvals;
|
||||
uint32_t fLastEnterEval;
|
||||
uint32_t fLastExitEval;
|
||||
plKey fHitter;
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
uint32_t fLastStep;
|
||||
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
bool fEntering;
|
||||
};
|
||||
|
||||
void ITrigger(plKey hitter, bool entering);
|
||||
void ISendTriggerMsg(plKey hitter, bool entering);
|
||||
void IRegisterForEval();
|
||||
virtual void IHandleEval(plEvalMsg*);
|
||||
bool fWaitingForEval;
|
||||
|
||||
typedef std::list<plCollisionBookKeepingInfo*> bookKeepingList;
|
||||
bookKeepingList fCollisionList;
|
||||
typedef std::set<plKey> ResidentSet;
|
||||
ResidentSet fCurrentResidents;
|
||||
|
||||
public:
|
||||
|
||||
plObjectInVolumeDetector()
|
||||
: plCollisionDetector(), fSavedActivatorMsg(nil), fNumEvals(0), fLastEnterEval(0), fLastExitEval(0)
|
||||
{ }
|
||||
: plCollisionDetector(), fWaitingForEval(false) { }
|
||||
|
||||
plObjectInVolumeDetector(int8_t type)
|
||||
: plCollisionDetector(type), fSavedActivatorMsg(nil), fNumEvals(0), fLastEnterEval(0), fLastExitEval(0)
|
||||
{ }
|
||||
: plCollisionDetector(type), fWaitingForEval(false) { }
|
||||
|
||||
virtual ~plObjectInVolumeDetector() { }
|
||||
|
||||
@ -159,16 +175,17 @@ protected:
|
||||
typedef std::vector<plCameraMsg*> plCameraMsgVec;
|
||||
|
||||
plCameraMsgVec fMessages;
|
||||
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||
uint32_t fLastStep;
|
||||
#endif
|
||||
bool fIsInside;
|
||||
bool fSavingSendMsg;
|
||||
bool fSavedMsgEnterFlag;
|
||||
bool fEntering;
|
||||
|
||||
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
|
||||
virtual void ISendSavedTriggerMsgs();
|
||||
void ISendTriggerMsg();
|
||||
virtual void IHandleEval(plEvalMsg*);
|
||||
public:
|
||||
plCameraRegionDetector()
|
||||
: plObjectInVolumeDetector(), fIsInside(false), fSavingSendMsg(false)
|
||||
{ }
|
||||
: plObjectInVolumeDetector(), fIsInside(false) { }
|
||||
~plCameraRegionDetector();
|
||||
|
||||
virtual bool MsgReceive(plMessage* msg);
|
||||
|
@ -68,27 +68,10 @@ namespace plSimDefs
|
||||
kGroupLOSOnly,
|
||||
//kExcludeRegion setting up so only blocks avatars and only when not in seek mode
|
||||
kGroupExcludeRegion,
|
||||
// A kinematic avatar only interacts with dynamics and detectors
|
||||
kGroupAvatarKinematic,
|
||||
// Just for error checking
|
||||
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
|
||||
kGroupMax
|
||||
};
|
||||
|
||||
/** Different types of line-of-sight requests. */
|
||||
|
Reference in New Issue
Block a user