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/plAvatarMgr.h"
|
||||||
#include "plAvatar/plArmatureMod.h"
|
#include "plAvatar/plArmatureMod.h"
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
|
|
||||||
bool plListener::fPrintDbgInfo = false;
|
bool plListener::fPrintDbgInfo = false;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "pnSceneObject/plSimulationInterface.h"
|
#include "pnSceneObject/plSimulationInterface.h"
|
||||||
#include "plAvatar/plAvatarMgr.h"
|
#include "plAvatar/plAvatarMgr.h"
|
||||||
#include "plAvatar/plArmatureMod.h"
|
#include "plAvatar/plArmatureMod.h"
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
|
|
||||||
// new stuff
|
// new stuff
|
||||||
|
|
||||||
|
@ -554,7 +554,7 @@ bool pySceneObject::IsAvatar()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
|
|
||||||
PyObject* pySceneObject::GetAvatarVelocity()
|
PyObject* pySceneObject::GetAvatarVelocity()
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,6 @@ set(plAvatar_SOURCES
|
|||||||
plAGMasterSDLModifier.cpp
|
plAGMasterSDLModifier.cpp
|
||||||
plAGModifier.cpp
|
plAGModifier.cpp
|
||||||
plAnimStage.cpp
|
plAnimStage.cpp
|
||||||
plAntiGravAction.cpp
|
|
||||||
plArmatureEffects.cpp
|
plArmatureEffects.cpp
|
||||||
plArmatureMod.cpp
|
plArmatureMod.cpp
|
||||||
plAvatarClothing.cpp
|
plAvatarClothing.cpp
|
||||||
@ -32,7 +31,6 @@ set(plAvatar_SOURCES
|
|||||||
plAvBrainHuman.cpp
|
plAvBrainHuman.cpp
|
||||||
plAvBrainRideAnimatedPhysical.cpp
|
plAvBrainRideAnimatedPhysical.cpp
|
||||||
plAvBrainSwim.cpp
|
plAvBrainSwim.cpp
|
||||||
plAvCallbackAction.cpp
|
|
||||||
plAvLadderModifier.cpp
|
plAvLadderModifier.cpp
|
||||||
plAvTaskBrain.cpp
|
plAvTaskBrain.cpp
|
||||||
plAvTaskSeek.cpp
|
plAvTaskSeek.cpp
|
||||||
@ -60,7 +58,6 @@ set(plAvatar_HEADERS
|
|||||||
plAGMasterSDLModifier.h
|
plAGMasterSDLModifier.h
|
||||||
plAGModifier.h
|
plAGModifier.h
|
||||||
plAnimStage.h
|
plAnimStage.h
|
||||||
plAntiGravAction.h
|
|
||||||
plArmatureEffects.h
|
plArmatureEffects.h
|
||||||
plArmatureMod.h
|
plArmatureMod.h
|
||||||
plAvatarClothing.h
|
plAvatarClothing.h
|
||||||
@ -78,7 +75,6 @@ set(plAvatar_HEADERS
|
|||||||
plAvBrainHuman.h
|
plAvBrainHuman.h
|
||||||
plAvBrainRideAnimatedPhysical.h
|
plAvBrainRideAnimatedPhysical.h
|
||||||
plAvBrainSwim.h
|
plAvBrainSwim.h
|
||||||
plAvCallbackAction.h
|
|
||||||
plAvDefs.h
|
plAvDefs.h
|
||||||
plAvLadderModifier.h
|
plAvLadderModifier.h
|
||||||
plAvTask.h
|
plAvTask.h
|
||||||
|
@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
Mead, WA 99021
|
Mead, WA 99021
|
||||||
|
|
||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
#include "plAvCallbackAction.h" // must be first: references havok new
|
|
||||||
|
|
||||||
// singular
|
// singular
|
||||||
#include "plAnimStage.h"
|
#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
|
Mead, WA 99021
|
||||||
|
|
||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
#include "plAvCallbackAction.h"
|
|
||||||
|
|
||||||
#include "plStatusLog/plStatusLog.h"
|
#include "plStatusLog/plStatusLog.h"
|
||||||
#include "plArmatureEffects.h"
|
#include "plArmatureEffects.h"
|
||||||
|
@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "plAvBrainHuman.h"
|
#include "plAvBrainHuman.h"
|
||||||
#include "plMatrixChannel.h"
|
#include "plMatrixChannel.h"
|
||||||
#include "plAvatarTasks.h"
|
#include "plAvatarTasks.h"
|
||||||
#include "plAvCallbackAction.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
#include "plAvBrainCritter.h"
|
#include "plAvBrainCritter.h"
|
||||||
|
|
||||||
// global
|
// global
|
||||||
@ -534,8 +534,7 @@ void plArmatureModBase::EnablePhysics(bool status, uint16_t reason /* = kDisable
|
|||||||
// i.e. normal enabled physical
|
// i.e. normal enabled physical
|
||||||
void plArmatureModBase::EnablePhysicsKinematic(bool status)
|
void plArmatureModBase::EnablePhysicsKinematic(bool status)
|
||||||
{
|
{
|
||||||
if (fController)
|
EnablePhysics(!status, kDisableReasonKinematic);
|
||||||
fController->Kinematic(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plArmatureModBase::EnableDrawing(bool status, uint16_t reason /* = kDisableReasonUnknown */)
|
void plArmatureModBase::EnableDrawing(bool status, uint16_t reason /* = kDisableReasonUnknown */)
|
||||||
@ -1994,7 +1993,11 @@ bool plArmatureMod::ValidatePhysics()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!fController)
|
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)
|
if (fController)
|
||||||
{
|
{
|
||||||
@ -2670,19 +2673,7 @@ void plArmatureMod::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
|
|||||||
debugTxt.DrawString(x, y, strBuf);
|
debugTxt.DrawString(x, y, strBuf);
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
hsPoint3 kPos;
|
|
||||||
const char *kinematic = "n.a.";
|
|
||||||
const char* frozen = "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)
|
if (fController)
|
||||||
frozen = fController->IsEnabled() ? "no" : "yes";
|
frozen = fController->IsEnabled() ? "no" : "yes";
|
||||||
|
|
||||||
|
@ -146,6 +146,7 @@ public:
|
|||||||
kDisableReasonCCR = 0x0008,
|
kDisableReasonCCR = 0x0008,
|
||||||
kDisableReasonVehicle = 0x0010,
|
kDisableReasonVehicle = 0x0010,
|
||||||
kDisableReasonGenericBrain = 0x0020,
|
kDisableReasonGenericBrain = 0x0020,
|
||||||
|
kDisableReasonKinematic = 0x0040
|
||||||
};
|
};
|
||||||
void EnablePhysics(bool status, uint16_t reason = kDisableReasonUnknown);
|
void EnablePhysics(bool status, uint16_t reason = kDisableReasonUnknown);
|
||||||
void EnablePhysicsKinematic(bool status);
|
void EnablePhysicsKinematic(bool status);
|
||||||
|
@ -40,7 +40,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
|
|
||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
|
|
||||||
#include "plAvCallbackAction.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
#include "plAvBrainCritter.h"
|
#include "plAvBrainCritter.h"
|
||||||
#include "plAvBrainHuman.h"
|
#include "plAvBrainHuman.h"
|
||||||
#include "plArmatureMod.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),
|
fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0),
|
||||||
fAngRight(0)
|
fAngRight(0)
|
||||||
{
|
{
|
||||||
@ -143,8 +143,8 @@ plAvBrainCritter::~plAvBrainCritter()
|
|||||||
fBehaviors[i] = nil;
|
fBehaviors[i] = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete fCallbackAction;
|
delete fWalkingStrategy;
|
||||||
fCallbackAction = nil;
|
fWalkingStrategy = nil;
|
||||||
|
|
||||||
fUserBehaviors.clear();
|
fUserBehaviors.clear();
|
||||||
fReceivers.clear();
|
fReceivers.clear();
|
||||||
@ -167,8 +167,8 @@ bool plAvBrainCritter::Apply(double time, float elapsed)
|
|||||||
IProcessBehavior(time, elapsed); // just continue with the currently running one
|
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
|
// update our controller to keep us turned and moving to where we want to go
|
||||||
fCallbackAction->RecalcVelocity(time, time - elapsed);
|
fWalkingStrategy->SetTurnStrength(IGetTurnStrength(time));
|
||||||
fCallbackAction->SetTurnStrength(IGetTurnStrength(time));
|
fWalkingStrategy->RecalcVelocity(time, elapsed);
|
||||||
|
|
||||||
return plArmatureBrain::Apply(time, elapsed);
|
return plArmatureBrain::Apply(time, elapsed);
|
||||||
}
|
}
|
||||||
@ -188,13 +188,13 @@ void plAvBrainCritter::Activate(plArmatureModBase* avMod)
|
|||||||
IInitBaseAnimations();
|
IInitBaseAnimations();
|
||||||
|
|
||||||
// create the controller if we haven't done so already
|
// create the controller if we haven't done so already
|
||||||
if (!fCallbackAction)
|
if (!fWalkingStrategy)
|
||||||
{
|
{
|
||||||
plSceneObject* avObj = fArmature->GetTarget(0);
|
plSceneObject* avObj = fArmature->GetTarget(0);
|
||||||
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
||||||
plPhysicalControllerCore* controller = avMod->GetController();
|
plPhysicalControllerCore* controller = avMod->GetController();
|
||||||
fCallbackAction = new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
|
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
|
||||||
fCallbackAction->ActivateController();
|
controller->SetMovementStrategy(fWalkingStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell people that care that we are good to go
|
// tell people that care that we are good to go
|
||||||
@ -224,7 +224,7 @@ void plAvBrainCritter::Resume()
|
|||||||
// fade in the idle
|
// fade in the idle
|
||||||
fNextMode = kIdle;
|
fNextMode = kIdle;
|
||||||
|
|
||||||
fCallbackAction->Reset(false);
|
fWalkingStrategy->Reset(false);
|
||||||
|
|
||||||
plArmatureBrain::Resume();
|
plArmatureBrain::Resume();
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "pnKeyedObject/plKey.h"
|
#include "pnKeyedObject/plKey.h"
|
||||||
|
|
||||||
class plArmatureMod;
|
class plArmatureMod;
|
||||||
class plWalkingController;
|
class plWalkingStrategy;
|
||||||
class plAIMsg;
|
class plAIMsg;
|
||||||
|
|
||||||
class plAvBrainCritter : public plArmatureBrain
|
class plAvBrainCritter : public plArmatureBrain
|
||||||
@ -134,8 +134,6 @@ public:
|
|||||||
|
|
||||||
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
|
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
|
||||||
|
|
||||||
plWalkingController* GetCallbackAction() {return fCallbackAction;}
|
|
||||||
|
|
||||||
// For the console
|
// For the console
|
||||||
static bool fDrawDebug;
|
static bool fDrawDebug;
|
||||||
|
|
||||||
@ -159,7 +157,7 @@ protected:
|
|||||||
std::vector<plArmatureMod*> IAvatarsICanSee() const;
|
std::vector<plArmatureMod*> IAvatarsICanSee() const;
|
||||||
std::vector<plArmatureMod*> IAvatarsICanHear() const;
|
std::vector<plArmatureMod*> IAvatarsICanHear() const;
|
||||||
|
|
||||||
plWalkingController* fCallbackAction;
|
plWalkingStrategy* fWalkingStrategy;
|
||||||
int fCurMode; // current behavior we are running
|
int fCurMode; // current behavior we are running
|
||||||
int fNextMode; // the next behavior to run (-1 if we aren't switching on next eval)
|
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?
|
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
|
// local includes
|
||||||
#include "plAvBrainDrive.h"
|
#include "plAvBrainDrive.h"
|
||||||
#include "plArmatureMod.h"
|
#include "plArmatureMod.h"
|
||||||
#include "plAvCallbackAction.h"
|
|
||||||
|
|
||||||
// global includes
|
// global includes
|
||||||
#include "hsTimer.h"
|
#include "hsTimer.h"
|
||||||
|
@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
Mead, WA 99021
|
Mead, WA 99021
|
||||||
|
|
||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
#include "plAvCallbackAction.h" // havok-contaminated file: must go first
|
|
||||||
|
|
||||||
// singular
|
// singular
|
||||||
#include "plAvBrainGeneric.h"
|
#include "plAvBrainGeneric.h"
|
||||||
@ -94,7 +93,6 @@ plAvBrainGeneric::plAvBrainGeneric()
|
|||||||
fFadeIn(0.0f),
|
fFadeIn(0.0f),
|
||||||
fFadeOut(0.0f),
|
fFadeOut(0.0f),
|
||||||
fMoveMode(kMoveRelative),
|
fMoveMode(kMoveRelative),
|
||||||
fCallbackAction(nil),
|
|
||||||
fBodyUsage(plAGAnim::kBodyUnknown)
|
fBodyUsage(plAGAnim::kBodyUnknown)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -122,7 +120,6 @@ plAvBrainGeneric::plAvBrainGeneric(plAnimStageVec *stages,
|
|||||||
fFadeIn(fadeIn),
|
fFadeIn(fadeIn),
|
||||||
fFadeOut(fadeOut),
|
fFadeOut(fadeOut),
|
||||||
fMoveMode(moveMode),
|
fMoveMode(moveMode),
|
||||||
fCallbackAction(nil),
|
|
||||||
fBodyUsage(plAGAnim::kBodyUnknown)
|
fBodyUsage(plAGAnim::kBodyUnknown)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -141,7 +138,6 @@ plAvBrainGeneric::plAvBrainGeneric(uint32_t exitFlags, float fadeIn, float fadeO
|
|||||||
fFadeIn(fadeIn),
|
fFadeIn(fadeIn),
|
||||||
fFadeOut(fadeOut),
|
fFadeOut(fadeOut),
|
||||||
fMoveMode(moveMode),
|
fMoveMode(moveMode),
|
||||||
fCallbackAction(nil),
|
|
||||||
fBodyUsage(plAGAnim::kBodyUnknown)
|
fBodyUsage(plAGAnim::kBodyUnknown)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
class plAnimStage;
|
class plAnimStage;
|
||||||
class plAnimStageVec;
|
class plAnimStageVec;
|
||||||
class plAvBrainGenericMsg;
|
class plAvBrainGenericMsg;
|
||||||
class plHorizontalFreezeAction;
|
|
||||||
class plNotifyMsg;
|
class plNotifyMsg;
|
||||||
|
|
||||||
/** \class plAvBrainGeneric
|
/** \class plAvBrainGeneric
|
||||||
@ -300,7 +299,6 @@ protected:
|
|||||||
int fCurStage; // which stage are we playing? (zero-based)
|
int fCurStage; // which stage are we playing? (zero-based)
|
||||||
BrainType fType; // what type of brain are we?
|
BrainType fType; // what type of brain are we?
|
||||||
uint32_t fExitFlags; // what will cause us to exit?
|
uint32_t fExitFlags; // what will cause us to exit?
|
||||||
plHorizontalFreezeAction *fCallbackAction;
|
|
||||||
|
|
||||||
bool fForward; // are we currently moving forward or backward through the stages?
|
bool fForward; // are we currently moving forward or backward through the stages?
|
||||||
// this is used by the "auto-" movement types in 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==*/
|
*==LICENSE==*/
|
||||||
|
|
||||||
#include "plAvCallbackAction.h" // subclasses a havok object; must be in first include section
|
|
||||||
#include "HeadSpin.h"
|
#include "HeadSpin.h"
|
||||||
|
|
||||||
|
#include "plPhysicalControllerCore.h"
|
||||||
#include "plAvBrainHuman.h"
|
#include "plAvBrainHuman.h"
|
||||||
#include "plAvBrainClimb.h"
|
#include "plAvBrainClimb.h"
|
||||||
#include "plAvBrainDrive.h"
|
#include "plAvBrainDrive.h"
|
||||||
@ -140,7 +140,7 @@ plAvBrainHuman::TurnCurve plAvBrainHuman::GetTurnCurve(bool walk)
|
|||||||
plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) :
|
plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) :
|
||||||
fHandleAGMod(nil),
|
fHandleAGMod(nil),
|
||||||
fStartedTurning(-1.0f),
|
fStartedTurning(-1.0f),
|
||||||
fCallbackAction(nil),
|
fWalkingStrategy(nil),
|
||||||
fPreconditions(0),
|
fPreconditions(0),
|
||||||
fIsActor(isActor)
|
fIsActor(isActor)
|
||||||
{
|
{
|
||||||
@ -154,9 +154,9 @@ bool plAvBrainHuman::Apply(double timeNow, float elapsed)
|
|||||||
#endif
|
#endif
|
||||||
// SetTurnStrength runs first to make sure it's set to a sane value
|
// SetTurnStrength runs first to make sure it's set to a sane value
|
||||||
// (or cleared). RunStandardBehaviors may overwrite it.
|
// (or cleared). RunStandardBehaviors may overwrite it.
|
||||||
fCallbackAction->SetTurnStrength(IGetTurnStrength(timeNow));
|
fWalkingStrategy->SetTurnStrength(IGetTurnStrength(timeNow));
|
||||||
RunStandardBehaviors(timeNow, elapsed);
|
RunStandardBehaviors(timeNow, elapsed);
|
||||||
fCallbackAction->RecalcVelocity(timeNow, timeNow - elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
|
fWalkingStrategy->RecalcVelocity(timeNow, elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
|
||||||
|
|
||||||
plArmatureBrain::Apply(timeNow, elapsed);
|
plArmatureBrain::Apply(timeNow, elapsed);
|
||||||
#ifndef _DEBUG
|
#ifndef _DEBUG
|
||||||
@ -177,13 +177,13 @@ void plAvBrainHuman::Activate(plArmatureModBase *avMod)
|
|||||||
|
|
||||||
IInitBoneMap();
|
IInitBoneMap();
|
||||||
IInitAnimations();
|
IInitAnimations();
|
||||||
if (!fCallbackAction)
|
if (!fWalkingStrategy)
|
||||||
{
|
{
|
||||||
plSceneObject* avObj = fArmature->GetTarget(0);
|
plSceneObject* avObj = fArmature->GetTarget(0);
|
||||||
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
||||||
plPhysicalControllerCore* controller = avMod->GetController();
|
plPhysicalControllerCore* controller = avMod->GetController();
|
||||||
fCallbackAction = new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
|
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
|
||||||
fCallbackAction->ActivateController();
|
controller->SetMovementStrategy(fWalkingStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -328,8 +328,8 @@ plAvBrainHuman::~plAvBrainHuman()
|
|||||||
delete fBehaviors[i];
|
delete fBehaviors[i];
|
||||||
fBehaviors.Reset();
|
fBehaviors.Reset();
|
||||||
|
|
||||||
delete fCallbackAction;
|
delete fWalkingStrategy;
|
||||||
fCallbackAction = nil;
|
fWalkingStrategy = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void plAvBrainHuman::Deactivate()
|
void plAvBrainHuman::Deactivate()
|
||||||
@ -361,7 +361,7 @@ void plAvBrainHuman::Resume()
|
|||||||
if (fAvMod->GetInputFlag(S_PUSH_TO_TALK))
|
if (fAvMod->GetInputFlag(S_PUSH_TO_TALK))
|
||||||
IChatOn();
|
IChatOn();
|
||||||
|
|
||||||
fCallbackAction->Reset(false);
|
fWalkingStrategy->Reset(false);
|
||||||
|
|
||||||
plArmatureBrain::Resume();
|
plArmatureBrain::Resume();
|
||||||
}
|
}
|
||||||
@ -465,25 +465,23 @@ bool plAvBrainHuman::MsgReceive(plMessage * msg)
|
|||||||
{
|
{
|
||||||
if(ride->Entering())
|
if(ride->Entering())
|
||||||
{
|
{
|
||||||
//plAvBrainRideAnimatedPhysical *rideBrain = new plAvBrainRideAnimatedPhysical();
|
// Switch to dynamic walking strategy
|
||||||
//fAvMod->PushBrain(rideBrain);
|
delete fWalkingStrategy;
|
||||||
delete fCallbackAction;
|
|
||||||
plSceneObject* avObj = fArmature->GetTarget(0);
|
plSceneObject* avObj = fArmature->GetTarget(0);
|
||||||
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
||||||
plPhysicalControllerCore* controller = fAvMod->GetController();
|
plPhysicalControllerCore* controller = fAvMod->GetController();
|
||||||
fCallbackAction= new plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
|
fWalkingStrategy = new plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
|
||||||
fCallbackAction->ActivateController();
|
controller->SetMovementStrategy(fWalkingStrategy);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete fCallbackAction;
|
// Restore default walking strategy
|
||||||
|
delete fWalkingStrategy;
|
||||||
plSceneObject* avObj = fArmature->GetTarget(0);
|
plSceneObject* avObj = fArmature->GetTarget(0);
|
||||||
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
||||||
plPhysicalControllerCore* controller = fAvMod->GetController();
|
plPhysicalControllerCore* controller = fAvMod->GetController();
|
||||||
fCallbackAction= new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
|
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
|
||||||
fCallbackAction->ActivateController();
|
controller->SetMovementStrategy(fWalkingStrategy);
|
||||||
//hsStatusMessage("Got an exiting ride animated physical message");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,8 +555,8 @@ float plAvBrainHuman::IGetTurnStrength(double timeNow)
|
|||||||
// Turning based on keypress
|
// Turning based on keypress
|
||||||
if ((turnLeftStrength > 0.f)
|
if ((turnLeftStrength > 0.f)
|
||||||
|| (turnRightStrength > 0.f)
|
|| (turnRightStrength > 0.f)
|
||||||
|| (!fCallbackAction->IsOnGround()
|
|| (!fWalkingStrategy->IsOnGround()
|
||||||
&& !fCallbackAction->IsControlledFlight())
|
&& !fWalkingStrategy->IsControlledFlight())
|
||||||
) {
|
) {
|
||||||
float t = (float)(timeNow - fStartedTurning);
|
float t = (float)(timeNow - fStartedTurning);
|
||||||
float turnSpeed;
|
float turnSpeed;
|
||||||
@ -590,7 +588,7 @@ float plAvBrainHuman::IGetTurnStrength(double timeNow)
|
|||||||
result += fAvMod->GetKeyTurnStrength() * turnSpeed;
|
result += fAvMod->GetKeyTurnStrength() * turnSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fCallbackAction->IsControlledFlight())
|
if (!fWalkingStrategy->IsControlledFlight())
|
||||||
result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed;
|
result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -647,7 +645,7 @@ void plAvBrainHuman::ResetIdle()
|
|||||||
|
|
||||||
void plAvBrainHuman::IdleOnly(bool instantOff)
|
void plAvBrainHuman::IdleOnly(bool instantOff)
|
||||||
{
|
{
|
||||||
if (!fCallbackAction)
|
if (!fWalkingStrategy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float rate = instantOff ? 0.f : 1.f;
|
float rate = instantOff ? 0.f : 1.f;
|
||||||
@ -673,7 +671,7 @@ bool plAvBrainHuman::IsMovementZeroBlend()
|
|||||||
|
|
||||||
void plAvBrainHuman::TurnToPoint(hsPoint3 point)
|
void plAvBrainHuman::TurnToPoint(hsPoint3 point)
|
||||||
{
|
{
|
||||||
if (!fCallbackAction->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
|
if (!fWalkingStrategy->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hsPoint3 avPos;
|
hsPoint3 avPos;
|
||||||
@ -869,23 +867,23 @@ void plAvBrainHuman::Spawn(double timeNow)
|
|||||||
bool plAvBrainHuman::LeaveAge()
|
bool plAvBrainHuman::LeaveAge()
|
||||||
{
|
{
|
||||||
plPhysicalControllerCore* controller = fAvMod->GetController();
|
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 fWalkingStrategy;
|
||||||
delete fCallbackAction;
|
|
||||||
plSceneObject* avObj = fArmature->GetTarget(0);
|
plSceneObject* avObj = fArmature->GetTarget(0);
|
||||||
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
||||||
fCallbackAction= new plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
|
fWalkingStrategy = new plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
|
||||||
fCallbackAction->ActivateController();
|
|
||||||
}
|
}
|
||||||
plArmatureBrain::LeaveAge();
|
|
||||||
|
|
||||||
|
|
||||||
|
fWalkingStrategy->Reset(true);
|
||||||
|
|
||||||
|
plArmatureBrain::LeaveAge();
|
||||||
|
|
||||||
// pin the physical so it doesn't fall when the world is deleted
|
// pin the physical so it doesn't fall when the world is deleted
|
||||||
fAvMod->EnablePhysics(false);
|
fAvMod->EnablePhysics(false);
|
||||||
// this will get set to true when we hit ground
|
|
||||||
fCallbackAction->Reset(true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,11 +893,10 @@ void plAvBrainHuman::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *st
|
|||||||
debugTxt.DrawString(x, y, strBuf);
|
debugTxt.DrawString(x, y, strBuf);
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
const char *grounded = fCallbackAction->IsOnGround() ? "yes" : "no";
|
const char *grounded = fWalkingStrategy->IsOnGround() ? "yes" : "no";
|
||||||
const char *falseGrounded = fCallbackAction->IsOnFalseGround() ? "yes" : "no";
|
const char *pushing = (fWalkingStrategy->GetPushingPhysical() ? (fWalkingStrategy->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
|
||||||
const char *pushing = (fCallbackAction->GetPushingPhysical() ? (fCallbackAction->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
|
sprintf(strBuf, "Ground: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
|
||||||
sprintf(strBuf, "Ground: %3s, FalseGround: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
|
grounded, fWalkingStrategy->GetAirTime(), fWalkingStrategy->GetImpactTime(), pushing);
|
||||||
grounded, falseGrounded, fCallbackAction->GetAirTime(), fCallbackAction->GetImpactTime(), pushing);
|
|
||||||
debugTxt.DrawString(x, y, strBuf);
|
debugTxt.DrawString(x, y, strBuf);
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
@ -1012,8 +1009,8 @@ bool Run::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (fAnim)
|
if (fAnim)
|
||||||
{
|
{
|
||||||
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
|
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1023,8 +1020,8 @@ bool Walk::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (fAnim)
|
if (fAnim)
|
||||||
{
|
{
|
||||||
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
|
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1034,8 +1031,8 @@ bool WalkBack::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (fAnim)
|
if (fAnim)
|
||||||
{
|
{
|
||||||
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
|
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1048,7 +1045,7 @@ bool StepLeft::PreCondition(double time, float elapsed)
|
|||||||
return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
|
return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
|
||||||
!(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
|
!(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
|
||||||
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
||||||
fHuBrain->fCallbackAction->IsOnGround());
|
fHuBrain->fWalkingStrategy->IsOnGround());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1060,7 +1057,7 @@ bool StepRight::PreCondition(double time, float elapsed)
|
|||||||
return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
|
return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
|
||||||
!(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
|
!(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
|
||||||
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
||||||
fHuBrain->fCallbackAction->IsOnGround());
|
fHuBrain->fWalkingStrategy->IsOnGround());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1101,8 +1098,8 @@ bool MovingTurnLeft::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (fAvMod->GetTurnStrength() > 0)
|
if (fAvMod->GetTurnStrength() > 0)
|
||||||
{
|
{
|
||||||
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1112,8 +1109,8 @@ bool MovingTurnRight::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (fAvMod->GetTurnStrength() < 0)
|
if (fAvMod->GetTurnStrength() < 0)
|
||||||
{
|
{
|
||||||
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,14 +1119,14 @@ bool MovingTurnRight::PreCondition(double time, float elapsed)
|
|||||||
|
|
||||||
void Jump::IStart()
|
void Jump::IStart()
|
||||||
{
|
{
|
||||||
fHuBrain->fCallbackAction->EnableControlledFlight(true);
|
fHuBrain->fWalkingStrategy->EnableControlledFlight(true);
|
||||||
|
|
||||||
plHBehavior::IStart();
|
plHBehavior::IStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jump::IStop()
|
void Jump::IStop()
|
||||||
{
|
{
|
||||||
fHuBrain->fCallbackAction->EnableControlledFlight(false);
|
fHuBrain->fWalkingStrategy->EnableControlledFlight(false);
|
||||||
|
|
||||||
plHBehavior::IStop();
|
plHBehavior::IStop();
|
||||||
}
|
}
|
||||||
@ -1140,7 +1137,7 @@ bool StandingJump::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (GetStrength() > 0.f)
|
if (GetStrength() > 0.f)
|
||||||
{
|
{
|
||||||
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
|
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
|
||||||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
|
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1152,7 +1149,7 @@ bool StandingJump::PreCondition(double time, float elapsed)
|
|||||||
if (fAvMod->JumpKeyDown() &&
|
if (fAvMod->JumpKeyDown() &&
|
||||||
!fAvMod->ForwardKeyDown() &&
|
!fAvMod->ForwardKeyDown() &&
|
||||||
fAnim->GetBlend() == 0.0f &&
|
fAnim->GetBlend() == 0.0f &&
|
||||||
fHuBrain->fCallbackAction->IsOnGround())
|
fHuBrain->fWalkingStrategy->IsOnGround())
|
||||||
{
|
{
|
||||||
if (fAvMod->ConsumeJump())
|
if (fAvMod->ConsumeJump())
|
||||||
return true;
|
return true;
|
||||||
@ -1168,7 +1165,7 @@ bool WalkingJump::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (GetStrength() > 0.f)
|
if (GetStrength() > 0.f)
|
||||||
{
|
{
|
||||||
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
|
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
|
||||||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
|
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1181,8 +1178,8 @@ bool WalkingJump::PreCondition(double time, float elapsed)
|
|||||||
!fAvMod->FastKeyDown() &&
|
!fAvMod->FastKeyDown() &&
|
||||||
fAvMod->ForwardKeyDown() &&
|
fAvMod->ForwardKeyDown() &&
|
||||||
fAnim->GetBlend() == 0.0f &&
|
fAnim->GetBlend() == 0.0f &&
|
||||||
fHuBrain->fCallbackAction->IsOnGround() &&
|
fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
{
|
{
|
||||||
if (fAvMod->ConsumeJump())
|
if (fAvMod->ConsumeJump())
|
||||||
return true;
|
return true;
|
||||||
@ -1198,7 +1195,7 @@ bool RunningJump::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (GetStrength() > 0.f)
|
if (GetStrength() > 0.f)
|
||||||
{
|
{
|
||||||
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
|
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
|
||||||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
|
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1211,8 +1208,8 @@ bool RunningJump::PreCondition(double time, float elapsed)
|
|||||||
fAvMod->ForwardKeyDown() &&
|
fAvMod->ForwardKeyDown() &&
|
||||||
fAvMod->FastKeyDown() &&
|
fAvMod->FastKeyDown() &&
|
||||||
fAnim->GetBlend() == 0.0f &&
|
fAnim->GetBlend() == 0.0f &&
|
||||||
fHuBrain->fCallbackAction->IsOnGround() &&
|
fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
|
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
|
||||||
{
|
{
|
||||||
if (fAvMod->ConsumeJump())
|
if (fAvMod->ConsumeJump())
|
||||||
return true;
|
return true;
|
||||||
@ -1237,13 +1234,13 @@ bool RunningImpact::PreCondition(double time, float elapsed)
|
|||||||
{
|
{
|
||||||
if (fDuration > 0.0f)
|
if (fDuration > 0.0f)
|
||||||
fDuration = fDuration - elapsed;
|
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)
|
if (fMaxBlend > 1)
|
||||||
fMaxBlend = 1;
|
fMaxBlend = 1;
|
||||||
fDuration = 1.0f / fFadeIn;
|
fDuration = 1.0f / fFadeIn;
|
||||||
@ -1267,13 +1264,13 @@ bool GroundImpact::PreCondition(double time, float elapsed)
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
if (fDuration > 0.0f)
|
if (fDuration > 0.0f)
|
||||||
fDuration = fDuration - elapsed;
|
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)
|
if (fMaxBlend > 1)
|
||||||
fMaxBlend = 1;
|
fMaxBlend = 1;
|
||||||
fDuration = 1.0f / fFadeIn;
|
fDuration = 1.0f / fFadeIn;
|
||||||
@ -1292,7 +1289,7 @@ void GroundImpact::IStop()
|
|||||||
|
|
||||||
bool Fall::PreCondition(double time, float elapsed)
|
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)
|
void Fall::Process(double time, float elapsed)
|
||||||
@ -1304,7 +1301,7 @@ void Fall::Process(double time, float elapsed)
|
|||||||
if (fAnim && fAnim->GetBlend() > 0.8)
|
if (fAnim && fAnim->GetBlend() > 0.8)
|
||||||
{
|
{
|
||||||
float panicThresh = plAvBrainHuman::kAirTimePanicThreshold;
|
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
|
fHuBrain->IdleOnly(); // clear the fall state; we're going somewhere new
|
||||||
fAvMod->PanicLink();
|
fAvMod->PanicLink();
|
||||||
@ -1321,7 +1318,7 @@ void Push::Process(double time, float elapsed)
|
|||||||
fAvMod->GetPositionAndRotationSim(&pos, &rot);
|
fAvMod->GetPositionAndRotationSim(&pos, &rot);
|
||||||
|
|
||||||
hsPoint3 lookAt;
|
hsPoint3 lookAt;
|
||||||
fHuBrain->fCallbackAction->GetPushingPhysical()->GetPositionSim(lookAt);
|
fHuBrain->fWalkingStrategy->GetPushingPhysical()->GetPositionSim(lookAt);
|
||||||
hsVector3 up(0.f, 0.f, 1.f);
|
hsVector3 up(0.f, 0.f, 1.f);
|
||||||
float angle = atan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + M_PI / 2;
|
float angle = atan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + M_PI / 2;
|
||||||
hsQuat targRot(angle, &up);
|
hsQuat targRot(angle, &up);
|
||||||
@ -1335,23 +1332,23 @@ void Push::Process(double time, float elapsed)
|
|||||||
globFwd = rot.Rotate(&globFwd);
|
globFwd = rot.Rotate(&globFwd);
|
||||||
|
|
||||||
if (globFwd.fX < 0)
|
if (globFwd.fX < 0)
|
||||||
fHuBrain->fCallbackAction->SetTurnStrength(-turnSpeed);
|
fHuBrain->fWalkingStrategy->SetTurnStrength(-turnSpeed);
|
||||||
else
|
else
|
||||||
fHuBrain->fCallbackAction->SetTurnStrength(turnSpeed);
|
fHuBrain->fWalkingStrategy->SetTurnStrength(turnSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool PushIdle::PreCondition(double time, float elapsed)
|
//bool PushIdle::PreCondition(double time, float elapsed)
|
||||||
//{
|
//{
|
||||||
// return (fHuBrain->fCallbackAction->GetPushingPhysical() &&
|
// return (fHuBrain->fWalkingStrategy->GetPushingPhysical() &&
|
||||||
// fHuBrain->fCallbackAction->IsOnGround() &&
|
// fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
// !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown()
|
// !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown()
|
||||||
// && fAvMod->GetTurnStrength() == 0);
|
// && fAvMod->GetTurnStrength() == 0);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
bool PushWalk::PreCondition(double time, float elapsed)
|
bool PushWalk::PreCondition(double time, float elapsed)
|
||||||
{
|
{
|
||||||
return (fHuBrain->fCallbackAction->GetPushingPhysical() && fHuBrain->fCallbackAction->GetFacingPushingPhysical() &&
|
return (fHuBrain->fWalkingStrategy->GetPushingPhysical() && fHuBrain->fWalkingStrategy->GetFacingPushingPhysical() &&
|
||||||
fHuBrain->fCallbackAction->IsOnGround() &&
|
fHuBrain->fWalkingStrategy->IsOnGround() &&
|
||||||
fAvMod->ForwardKeyDown());
|
fAvMod->ForwardKeyDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1366,7 +1363,7 @@ bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const ch
|
|||||||
{
|
{
|
||||||
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index()));
|
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index()));
|
||||||
const char *names[3] = {enterAnim, idleAnim, exitAnim};
|
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))
|
!avatar->IsPhysicsEnabled() || avatar->FindMatchingGenericBrain(names, 3))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1429,7 +1426,7 @@ bool AvatarEmote(plArmatureMod *avatar, const char *emoteName)
|
|||||||
if (swimBrain && swimBrain->IsSwimming())
|
if (swimBrain && swimBrain->IsSwimming())
|
||||||
return false;
|
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())
|
emote && !alreadyActive && avatar->IsPhysicsEnabled())
|
||||||
{
|
{
|
||||||
plKey avKey = avatar->GetKey();
|
plKey avKey = avatar->GetKey();
|
||||||
|
@ -58,7 +58,7 @@ class plAGAnimInstance;
|
|||||||
class plAvTask;
|
class plAvTask;
|
||||||
class plAvTaskMsg;
|
class plAvTaskMsg;
|
||||||
class plAvBrainHuman;
|
class plAvBrainHuman;
|
||||||
class plWalkingController;
|
class plWalkingStrategy;
|
||||||
class plArmatureUpdateMsg;
|
class plArmatureUpdateMsg;
|
||||||
class plClimbMsg;
|
class plClimbMsg;
|
||||||
class plControlEventMsg;
|
class plControlEventMsg;
|
||||||
@ -164,7 +164,7 @@ public:
|
|||||||
static const float kControlledFlightThreshold;
|
static const float kControlledFlightThreshold;
|
||||||
static const float kAirTimeThreshold;
|
static const float kAirTimeThreshold;
|
||||||
static const float kAirTimePanicThreshold;
|
static const float kAirTimePanicThreshold;
|
||||||
plWalkingController* fCallbackAction;
|
plWalkingStrategy* fWalkingStrategy;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
plAGAnim *FindCustomAnim(const char *baseName);
|
plAGAnim *FindCustomAnim(const char *baseName);
|
||||||
|
@ -44,7 +44,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
|
|
||||||
#include "plAvBrainHuman.h"
|
#include "plAvBrainHuman.h"
|
||||||
#include "plAvBrain.h"
|
#include "plAvBrain.h"
|
||||||
#include "plAvCallbackAction.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
#include "plMessage/plRideAnimatedPhysMsg.h"
|
#include "plMessage/plRideAnimatedPhysMsg.h"
|
||||||
|
|
||||||
|
|
||||||
@ -52,20 +52,19 @@ void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod)
|
|||||||
{
|
{
|
||||||
plArmatureBrain::Activate(avMod);
|
plArmatureBrain::Activate(avMod);
|
||||||
IInitAnimations();
|
IInitAnimations();
|
||||||
if (!fCallbackAction)
|
if (!fWalkingStrategy)
|
||||||
{
|
{
|
||||||
plSceneObject* avObj = fArmature->GetTarget(0);
|
plSceneObject* avObj = fArmature->GetTarget(0);
|
||||||
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
|
||||||
plPhysicalControllerCore* controller = avMod->GetController();
|
plPhysicalControllerCore* controller = avMod->GetController();
|
||||||
fCallbackAction = new plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
|
fWalkingStrategy = new plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
|
||||||
fCallbackAction->ActivateController();
|
controller->SetMovementStrategy(fWalkingStrategy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
|
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
|
||||||
{
|
{
|
||||||
delete fCallbackAction;
|
delete fWalkingStrategy;
|
||||||
fCallbackAction=nil;
|
fWalkingStrategy = nil;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plAvBrainRideAnimatedPhysical::Deactivate()
|
void plAvBrainRideAnimatedPhysical::Deactivate()
|
||||||
|
@ -41,8 +41,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
#include "plAvBrainHuman.h"
|
#include "plAvBrainHuman.h"
|
||||||
|
|
||||||
class plRidingAnimatedPhysicalController;
|
|
||||||
|
|
||||||
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
|
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
|
||||||
{
|
{
|
||||||
public:
|
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
|
// singular
|
||||||
#include "plAvBrainSwim.h"
|
#include "plAvBrainSwim.h"
|
||||||
|
|
||||||
@ -69,7 +65,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "hsTimer.h"
|
#include "hsTimer.h"
|
||||||
#include "plPhysical.h"
|
#include "plPhysical.h"
|
||||||
#include "plPhysicalControllerCore.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
#include "plAvCallbackAction.h"
|
|
||||||
// other
|
// other
|
||||||
#include "plPhysical/plCollisionDetector.h"
|
#include "plPhysical/plCollisionDetector.h"
|
||||||
#include "plPipeline/plDebugText.h"
|
#include "plPipeline/plDebugText.h"
|
||||||
@ -180,18 +175,16 @@ public:
|
|||||||
static const float timeToMaxTurn = 0.5f;
|
static const float timeToMaxTurn = 0.5f;
|
||||||
static const float incPerSec = maxTurnSpeed / timeToMaxTurn;
|
static const float incPerSec = maxTurnSpeed / timeToMaxTurn;
|
||||||
|
|
||||||
// hsAssert(0, "fixme physx");
|
float oldSpeed = fabs(fSwimBrain->fSwimStrategy->GetTurnStrength());
|
||||||
float oldSpeed = fabs(fSwimBrain->fCallbackAction->GetTurnStrength());
|
|
||||||
float thisInc = elapsed * incPerSec;
|
float thisInc = elapsed * incPerSec;
|
||||||
float newSpeed = min(oldSpeed + thisInc, maxTurnSpeed);
|
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
|
// the turn is actually applied during PhysicsUpdate
|
||||||
}
|
}
|
||||||
virtual void IStop()
|
virtual void IStop()
|
||||||
{
|
{
|
||||||
// hsAssert(0, "fixme physx");
|
if (fSwimBrain->fSwimStrategy)
|
||||||
if (fSwimBrain->fCallbackAction)
|
fSwimBrain->fSwimStrategy->SetTurnStrength(0.0f);
|
||||||
fSwimBrain->fCallbackAction->SetTurnStrength(0.0f);
|
|
||||||
plSwimBehavior::IStop();
|
plSwimBehavior::IStop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -237,7 +230,7 @@ public:
|
|||||||
const float plAvBrainSwim::kMinSwimDepth = 4.0f;
|
const float plAvBrainSwim::kMinSwimDepth = 4.0f;
|
||||||
|
|
||||||
plAvBrainSwim::plAvBrainSwim() :
|
plAvBrainSwim::plAvBrainSwim() :
|
||||||
fCallbackAction(nil),
|
fSwimStrategy(nil),
|
||||||
fMode(kWalking),
|
fMode(kWalking),
|
||||||
fSurfaceDistance(0.f)
|
fSurfaceDistance(0.f)
|
||||||
{
|
{
|
||||||
@ -250,12 +243,9 @@ plAvBrainSwim::plAvBrainSwim() :
|
|||||||
|
|
||||||
plAvBrainSwim::~plAvBrainSwim()
|
plAvBrainSwim::~plAvBrainSwim()
|
||||||
{
|
{
|
||||||
if(fCallbackAction)
|
delete fSwimStrategy;
|
||||||
{
|
fSwimStrategy = nil;
|
||||||
IDetachAction();
|
|
||||||
delete fCallbackAction;
|
|
||||||
fCallbackAction=nil;
|
|
||||||
}
|
|
||||||
fSurfaceProbeMsg->UnRef();
|
fSurfaceProbeMsg->UnRef();
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -273,8 +263,7 @@ bool plAvBrainSwim::Apply(double time, float elapsed)
|
|||||||
fMode = kWading;
|
fMode = kWading;
|
||||||
|
|
||||||
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this));
|
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this));
|
||||||
// hsAssert(0, "fixme physx");
|
if (huBrain && !huBrain->fWalkingStrategy->IsOnGround())
|
||||||
if (huBrain && !huBrain->fCallbackAction->IsOnGround())
|
|
||||||
{
|
{
|
||||||
// We're jumping in! Trigger splash effect (sound)
|
// We're jumping in! Trigger splash effect (sound)
|
||||||
plArmatureEffectMsg *msg = new plArmatureEffectMsg(fAvMod->GetArmatureEffects()->GetKey(), kTime);
|
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
|
// The contact check is so that if buoyancy bobs us a little too high, we don't
|
||||||
// switch to wading only to fall again.
|
// switch to wading only to fall again.
|
||||||
// hsAssert(0, "fixme physx");
|
if (fSurfaceDistance < kMinSwimDepth-.5 && fSwimStrategy->HadContacts())
|
||||||
if (fSurfaceDistance < kMinSwimDepth-.5 && fCallbackAction->HadContacts())
|
|
||||||
IStartWading();
|
IStartWading();
|
||||||
}
|
}
|
||||||
else if (fMode == kSwimming3D)
|
else if (fMode == kSwimming3D)
|
||||||
@ -346,13 +334,12 @@ bool plAvBrainSwim::MsgReceive(plMessage *msg)
|
|||||||
else
|
else
|
||||||
fSurfaceDistance = -100.f;
|
fSurfaceDistance = -100.f;
|
||||||
|
|
||||||
// hsAssert(0, "fixme physx");
|
if (fSwimStrategy)
|
||||||
if (fCallbackAction)
|
|
||||||
{
|
{
|
||||||
if (region)
|
if (region)
|
||||||
fCallbackAction->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
|
fSwimStrategy->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
|
||||||
else
|
else
|
||||||
fCallbackAction->SetSurface(nil, 0.f);
|
fSwimStrategy->SetSurface(nil, 0.f);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -419,20 +406,16 @@ void plAvBrainSwim::Activate(plArmatureModBase* avMod)
|
|||||||
void plAvBrainSwim::Deactivate()
|
void plAvBrainSwim::Deactivate()
|
||||||
{
|
{
|
||||||
plArmatureBrain::Deactivate();
|
plArmatureBrain::Deactivate();
|
||||||
|
|
||||||
IDetachAction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plAvBrainSwim::Suspend()
|
void plAvBrainSwim::Suspend()
|
||||||
{
|
{
|
||||||
if (fMode == kSwimming2D)
|
|
||||||
IDetachAction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plAvBrainSwim::Resume()
|
void plAvBrainSwim::Resume()
|
||||||
{
|
{
|
||||||
if (fMode == kSwimming2D)
|
if (fMode == kSwimming2D)
|
||||||
IAttachAction();
|
fSwimStrategy->Reset(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool plAvBrainSwim::IsWalking()
|
bool plAvBrainSwim::IsWalking()
|
||||||
@ -460,8 +443,6 @@ void plAvBrainSwim::IStartWading()
|
|||||||
for (i = 0; i < fBehaviors.GetCount(); i++)
|
for (i = 0; i < fBehaviors.GetCount(); i++)
|
||||||
fBehaviors[i]->SetStrength(0.f, 2.f);
|
fBehaviors[i]->SetStrength(0.f, 2.f);
|
||||||
|
|
||||||
IDetachAction();
|
|
||||||
|
|
||||||
if (fAvMod->IsLocalAvatar())
|
if (fAvMod->IsLocalAvatar())
|
||||||
{
|
{
|
||||||
plCameraMsg* pMsg = new plCameraMsg;
|
plCameraMsg* pMsg = new plCameraMsg;
|
||||||
@ -479,7 +460,16 @@ void plAvBrainSwim::IStartSwimming(bool is2D)
|
|||||||
plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this);
|
plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this);
|
||||||
nextBrain->Suspend();
|
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)
|
if (is2D)
|
||||||
fMode = kSwimming2D;
|
fMode = kSwimming2D;
|
||||||
else
|
else
|
||||||
@ -509,8 +499,8 @@ bool plAvBrainSwim::IProcessSwimming2D(double time, float elapsed)
|
|||||||
else
|
else
|
||||||
behavior->SetStrength(0.f, 2.f);
|
behavior->SetStrength(0.f, 2.f);
|
||||||
}
|
}
|
||||||
// hsAssert(0, "fixme physx");
|
|
||||||
fCallbackAction->RecalcVelocity(time, time - elapsed);
|
fSwimStrategy->RecalcVelocity(time, elapsed);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -568,59 +558,6 @@ bool plAvBrainSwim::IInitAnimations()
|
|||||||
return true;
|
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()
|
void plAvBrainSwim::IProbeSurface()
|
||||||
{
|
{
|
||||||
hsPoint3 ourPos = fAvMod->GetTarget(0)->GetLocalToWorld().GetTranslate();
|
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);
|
debugTxt.DrawString(x, y, strBuf);
|
||||||
y += lineHeight;
|
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");
|
hsVector3 linV = fAvMod->GetController()->GetAchievedLinearVelocity();
|
||||||
// float buoy = fCallbackAction? fCallbackAction->GetBuoyancy() : 0.0f;
|
sprintf(strBuf, "Linear Velocity: (%5.2f, %5.2f, %5.2f)", linV.fX, linV.fY, linV.fZ);
|
||||||
// sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy);
|
debugTxt.DrawString(x, y, strBuf);
|
||||||
// debugTxt.DrawString(x, y, strBuf);
|
y += lineHeight;
|
||||||
// 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;
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < fBehaviors.GetCount(); i++)
|
for (i = 0; i < fBehaviors.GetCount(); i++)
|
||||||
|
@ -51,7 +51,7 @@ class plAntiGravAction;
|
|||||||
class plControlEventMsg;
|
class plControlEventMsg;
|
||||||
class plLOSRequestMsg;
|
class plLOSRequestMsg;
|
||||||
class plSwimRegionInterface;
|
class plSwimRegionInterface;
|
||||||
class plSwimmingController;
|
class plSwimStrategy;
|
||||||
class plAvBrainSwim : public plArmatureBrain
|
class plAvBrainSwim : public plArmatureBrain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -73,7 +73,7 @@ public:
|
|||||||
bool IsSwimming();
|
bool IsSwimming();
|
||||||
float GetSurfaceDistance() { return fSurfaceDistance; }
|
float GetSurfaceDistance() { return fSurfaceDistance; }
|
||||||
|
|
||||||
plSwimmingController *fCallbackAction;
|
plSwimStrategy *fSwimStrategy;
|
||||||
static const float kMinSwimDepth;
|
static const float kMinSwimDepth;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -86,8 +86,6 @@ protected:
|
|||||||
bool IProcessBehaviors(double time, float elapsed);
|
bool IProcessBehaviors(double time, float elapsed);
|
||||||
|
|
||||||
virtual bool IInitAnimations();
|
virtual bool IInitAnimations();
|
||||||
bool IAttachAction();
|
|
||||||
bool IDetachAction();
|
|
||||||
void IProbeSurface();
|
void IProbeSurface();
|
||||||
bool IHandleControlMsg(plControlEventMsg* msg);
|
bool IHandleControlMsg(plControlEventMsg* msg);
|
||||||
float IGetTargetZ();
|
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
|
Mead, WA 99021
|
||||||
|
|
||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
|
|
||||||
#include "HeadSpin.h"
|
#include "HeadSpin.h"
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ bool plAvLadderMod::IIsReadyToClimb()
|
|||||||
if (armMod)
|
if (armMod)
|
||||||
{
|
{
|
||||||
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
|
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
|
||||||
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
|
if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
|
||||||
movingForward = true;
|
movingForward = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "plAGAnim.h"
|
#include "plAGAnim.h"
|
||||||
#include "plArmatureMod.h"
|
#include "plArmatureMod.h"
|
||||||
#include "plAvatarMgr.h"
|
#include "plAvatarMgr.h"
|
||||||
#include "plAvCallbackAction.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
|
|
||||||
// other
|
// other
|
||||||
#include "plMessage/plAvatarMsg.h"
|
#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
|
// While warping, we might be hovering just above the ground. Don't want that to
|
||||||
// trigger any falling behavior.
|
// 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?
|
// how far will we translate this frame?
|
||||||
float thisDist = kFloatSpeed * elapsed;
|
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/plAvBrainClimb.h"
|
||||||
#include "plAvatar/plAvBrainDrive.h"
|
#include "plAvatar/plAvBrainDrive.h"
|
||||||
#include "plAvatar/plAnimStage.h"
|
#include "plAvatar/plAnimStage.h"
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
#include "pnSceneObject/plSceneObject.h"
|
#include "pnSceneObject/plSceneObject.h"
|
||||||
#include "pnMessage/plSDLModifierMsg.h"
|
#include "pnMessage/plSDLModifierMsg.h"
|
||||||
#include "plSDL/plSDL.h"
|
#include "plSDL/plSDL.h"
|
||||||
|
@ -52,7 +52,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "plAGAnimInstance.h"
|
#include "plAGAnimInstance.h"
|
||||||
#include "plAGModifier.h"
|
#include "plAGModifier.h"
|
||||||
#include "plMatrixChannel.h"
|
#include "plMatrixChannel.h"
|
||||||
#include "plAvCallbackAction.h"
|
#include "plPhysicalControllerCore.h"
|
||||||
#include "plAvatarMgr.h"
|
#include "plAvatarMgr.h"
|
||||||
|
|
||||||
// global
|
// global
|
||||||
@ -671,7 +671,7 @@ bool plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, dou
|
|||||||
if(fEnablePhysicsAtEnd)
|
if(fEnablePhysicsAtEnd)
|
||||||
{
|
{
|
||||||
#if 0//ndef PLASMA_EXTERNAL_RELEASE
|
#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
|
// For some reason, calling CheckValidPosition at the beginning of
|
||||||
// an age can cause detectors to incorrectly report collisions. So
|
// 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==*/
|
*==LICENSE==*/
|
||||||
#ifndef PLPHYSICALCONTROLLERCORE_H
|
#ifndef PLPHYSICALCONTROLLERCORE_H
|
||||||
#define PLPHYSICALCONTROLLERCORE_H
|
#define PLPHYSICALCONTROLLERCORE_H
|
||||||
|
|
||||||
#include "hsGeometry3.h"
|
#include "hsGeometry3.h"
|
||||||
#include "hsMatrix44.h"
|
#include "hsMatrix44.h"
|
||||||
|
#include "hsQuat.h"
|
||||||
#include "hsTemplates.h"
|
#include "hsTemplates.h"
|
||||||
#include "pnKeyedObject/plKey.h"
|
#include "pnKeyedObject/plKey.h"
|
||||||
#include "plPhysical/plSimDefs.h"
|
#include "plPhysical/plSimDefs.h"
|
||||||
#include "pnMessage/plMessage.h"
|
#include <vector>
|
||||||
|
|
||||||
#include "hsQuat.h"
|
|
||||||
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
|
|
||||||
#define kSLOPELIMIT (cosf(hsDegreesToRadians(45.f)))
|
|
||||||
|
|
||||||
class plCoordinateInterface;
|
class plCoordinateInterface;
|
||||||
class plPhysical;
|
class plPhysical;
|
||||||
class plPXPhysical;
|
class plMovementStrategy;
|
||||||
|
class plAGApplicator;
|
||||||
class plSwimRegionInterface;
|
class plSwimRegionInterface;
|
||||||
//Replacement for for plPhysicalController stripped out some walk specific code
|
|
||||||
//plPhysicalControllerCore needs to have movement strategies registered to it these will then
|
#define kSlopeLimit (cosf(hsDegreesToRadians(55.f)))
|
||||||
//be called by the controller during the simulation steps. The Strategies need to at least have an
|
|
||||||
// Apply and Update definition. Everything else should be movement specific. I hope to come back and
|
|
||||||
//and refactor when I have time this in the future.
|
|
||||||
enum plControllerCollisionFlags
|
enum plControllerCollisionFlags
|
||||||
{
|
{
|
||||||
kSides=1,
|
kSides = 1,
|
||||||
kTop= (1<<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;
|
plPhysical *ObjHit;
|
||||||
hsPoint3 locHit;//World space
|
hsPoint3 Point;
|
||||||
float TimeHit;//Normalized between 0 and 1
|
hsVector3 Normal;
|
||||||
hsVector3 Norm;
|
|
||||||
};
|
};
|
||||||
bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right);
|
|
||||||
class plPhysicalControllerCore
|
class plPhysicalControllerCore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~plPhysicalControllerCore();
|
plPhysicalControllerCore(plKey ownerSceneObject, float height, float radius);
|
||||||
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)=0;
|
virtual ~plPhysicalControllerCore() { }
|
||||||
virtual void SetMovementSimulationInterface(plMovementStrategySimulationInterface* strat){fMovementInterface=strat;}
|
|
||||||
virtual void Apply(float delSecs);
|
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
|
||||||
virtual void Update(float delSecs);
|
// Use plArmatureModBase::EnablePhysics() instead.
|
||||||
virtual void PostStep(float delSecs);
|
|
||||||
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
|
|
||||||
virtual void Enable(bool enable) = 0;
|
virtual void Enable(bool enable) = 0;
|
||||||
virtual bool IsEnabled() {return fEnabled;}
|
virtual bool IsEnabled() { return fEnabled; }
|
||||||
virtual plKey GetSubworld() {return fWorldKey;}
|
|
||||||
|
// Subworld
|
||||||
|
virtual plKey GetSubworld() { return fWorldKey; }
|
||||||
virtual void SetSubworld(plKey world) = 0;
|
virtual void SetSubworld(plKey world) = 0;
|
||||||
virtual const plCoordinateInterface* GetSubworldCI() const = 0;
|
virtual const plCoordinateInterface* GetSubworldCI();
|
||||||
|
|
||||||
// For the avatar SDL only
|
// For the avatar SDL only
|
||||||
virtual void GetState(hsPoint3& pos, float& zRot) = 0;
|
virtual void GetState(hsPoint3& pos, float& zRot) = 0;
|
||||||
virtual void SetState(const 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;
|
// The LOS DB this avatar is in (only one)
|
||||||
virtual bool IsKinematic() = 0;
|
virtual plSimDefs::plLOSDB GetLOSDB() { return fLOSDB; }
|
||||||
virtual void GetKinematicPosition(hsPoint3& pos) = 0;
|
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
|
||||||
virtual const hsMatrix44& GetPrevSubworldW2L() = 0;
|
|
||||||
//when seeking no longer want to interact with exclusion regions
|
// Movement strategy
|
||||||
virtual void SetSeek(bool seek){fSeeking=seek;}
|
virtual void SetMovementStrategy(plMovementStrategy* strategy) = 0;
|
||||||
virtual bool IsSeeking(){return fSeeking;}
|
|
||||||
static plPhysicalControllerCore* Create(plKey ownerSO, float height, float radius);
|
// Global location
|
||||||
virtual plMovementStrategySimulationInterface* GetMovementInterface(){return fMovementInterface;}
|
virtual const hsMatrix44& GetLastGlobalLoc() { return fLastGlobalLoc; }
|
||||||
plPhysicalControllerCore(plKey ownerSceneObject, float height, float radius);
|
virtual void SetGlobalLoc(const hsMatrix44& l2w) = 0;
|
||||||
virtual plKey GetOwner(){return fOwner;};
|
|
||||||
// Set the LOS DB this avatar will be in (only one)
|
// Local sim position
|
||||||
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; } ;
|
virtual void GetPositionSim(hsPoint3& pos) = 0;
|
||||||
virtual plSimDefs::plLOSDB GetLOSDB() {return fLOSDB ; }
|
|
||||||
virtual const hsMatrix44& GetLastGlobalLoc()=0;
|
// Move kinematic controller
|
||||||
virtual void SetKinematicLoc(const hsMatrix44& l2w)=0;
|
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults) = 0;
|
||||||
virtual void SetGlobalLoc(const hsMatrix44& l2w)=0;
|
|
||||||
virtual bool IsEnabledChanged(){return fEnableChanged;}
|
// Set linear velocity on dynamic controller
|
||||||
virtual void HandleEnableChanged()=0;
|
virtual void SetLinearVelocitySim(const hsVector3& linearVel) = 0;
|
||||||
virtual bool IsKinematicChanged(){return fKinematicChanged;}
|
|
||||||
virtual void GetPositionSim(hsPoint3& pos)=0;
|
// Sweep the controller path from startPos through endPos
|
||||||
virtual void HandleKinematicChanged()=0;
|
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, bool vsDynamics, bool vsStatics,
|
||||||
virtual bool IsKinematicEnableNextUpdate(){return fKinematicEnableNextUpdate;}
|
uint32_t& vsSimGroups, std::vector<plControllerSweepRecord>& hits) = 0;
|
||||||
virtual void HandleKinematicEnableNextUpdate()=0;
|
|
||||||
virtual void MoveKinematicToController(hsPoint3& pos)=0;
|
// any clean up for the controller should go here
|
||||||
virtual void UpdateControllerAndPhysicalRep()=0;
|
virtual void LeaveAge() = 0;
|
||||||
virtual void CheckAndHandleAnyStateChanges();
|
|
||||||
virtual void UpdateSubstepNonPhysical();
|
// Local rotation
|
||||||
virtual const hsPoint3& GetLocalPosition()=0;
|
const hsQuat& GetLocalRotation() const { return fLocalRotation; }
|
||||||
const hsQuat& GetLocalRotation() { return fLocalRotation; }
|
|
||||||
virtual void MoveActorToSim();
|
|
||||||
|
|
||||||
virtual void OverrideAchievedVelocity(hsVector3 newAchievedVel)
|
|
||||||
{//because of things like superjumps this is needed I'd rather not, but can't help it
|
|
||||||
fAchievedLinearVelocity=newAchievedVel;
|
|
||||||
}
|
|
||||||
//any clean up for the controller should go here
|
|
||||||
virtual void LeaveAge()=0;
|
|
||||||
hsVector3 DisplacementLastStep(){return fDisplacementThisStep;}
|
|
||||||
hsVector3 MeanVelocityForLastStep()
|
|
||||||
{
|
|
||||||
hsVector3 vel=fDisplacementThisStep;
|
|
||||||
return vel/fSimLength;
|
|
||||||
}
|
|
||||||
void SendCorrectionMessages();
|
|
||||||
void IncrementAngle(float deltaAngle);
|
void IncrementAngle(float deltaAngle);
|
||||||
void UpdateWorldRelativePos();
|
|
||||||
virtual void SetLinearVelocity(const hsVector3& linearVel){fLinearVelocity=linearVel;}
|
// Linear velocity
|
||||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
void SetLinearVelocity(const hsVector3& linearVel) { fLinearVelocity = linearVel; }
|
||||||
virtual void SetAngularVelocity(const float angvel){ fAngularVelocity=angvel;}
|
const hsVector3& GetLinearVelocity() const { return fLinearVelocity; }
|
||||||
virtual void SetVelocities(const hsVector3& linearVel, float angVel)
|
|
||||||
{
|
// Acheived linear velocity
|
||||||
fLinearVelocity=linearVel;
|
const hsVector3& GetAchievedLinearVelocity() const { return fAchievedLinearVelocity; }
|
||||||
fAngularVelocity=angVel;
|
void OverrideAchievedLinearVelocity(const hsVector3& linearVel) { fAchievedLinearVelocity = linearVel; }
|
||||||
}
|
void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
|
||||||
|
|
||||||
virtual const hsVector3& GetLinearVelocity() ;
|
// SceneObject
|
||||||
virtual float GetAngularVelocity(){return fAngularVelocity;}
|
plKey GetOwner() { return fOwner; }
|
||||||
virtual const hsVector3& GetAchievedLinearVelocity()const {return fAchievedLinearVelocity;}
|
|
||||||
plPhysical* GetPushingPhysical();
|
// When seeking no longer want to interact with exclude regions
|
||||||
bool GetFacingPushingPhysical();
|
void SetSeek(bool seek) { fSeeking = seek; }
|
||||||
virtual void SetPushingPhysical(plPhysical* pl){fPushingPhysical=pl;}
|
bool IsSeeking() const { return fSeeking; }
|
||||||
virtual void SetFacingPushingPhysical(bool ans){fFacingPushingPhysical=ans;}
|
|
||||||
//To be Used during runtime conversions, say to switch a tall controller to a ball for swimming
|
// Pushing physical
|
||||||
virtual void SetControllerDimensions(float radius, float height)=0;
|
plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
|
||||||
virtual float GetControllerWidth(){return fRadius;}
|
void SetPushingPhysical(plPhysical* phys) { fPushingPhysical = phys; }
|
||||||
virtual float GetControllerHeight(){return fHeight;}
|
bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
|
||||||
virtual void ResetAchievedLinearVelocity()
|
void SetFacingPushingPhysical(bool facing) { fFacingPushingPhysical = facing; }
|
||||||
{
|
|
||||||
fAchievedLinearVelocity.Set(0.f,0.f,0.f);
|
// Controller dimensions
|
||||||
}
|
float GetRadius() const { return fRadius; }
|
||||||
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, bool vsDynamics, bool vsStatics, uint32_t& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut)=0;
|
float GetHeight() const { return fHeight; }
|
||||||
//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;}
|
// Create a new controller instance - Implemented in the physics system
|
||||||
virtual float GetRadius() {return fRadius;}
|
static plPhysicalControllerCore* Create(plKey ownerSO, float height, float radius, bool human);
|
||||||
//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;
|
|
||||||
protected:
|
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 fOwner;
|
||||||
|
plKey fWorldKey;
|
||||||
|
|
||||||
float fHeight;
|
float fHeight;
|
||||||
float fRadius;
|
float fRadius;
|
||||||
plKey fWorldKey;
|
|
||||||
plSimDefs::plLOSDB fLOSDB;
|
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 fSeeking;
|
||||||
bool fEnabled;
|
bool fEnabled;
|
||||||
bool fEnableChanged;
|
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:
|
public:
|
||||||
virtual void SetControllerCore(plPhysicalControllerCore* core)
|
plMovementStrategy(plPhysicalControllerCore* controller);
|
||||||
{
|
virtual ~plMovementStrategy() { }
|
||||||
fCore=core;
|
|
||||||
fCore->SetMovementSimulationInterface(this);
|
virtual void Apply(float delSecs) = 0;
|
||||||
}
|
virtual void Update(float delSecs) { }
|
||||||
virtual void RefreshConnectionToControllerCore()
|
|
||||||
{
|
virtual void AddContactNormals(hsVector3& vec) { }
|
||||||
fCore->SetMovementSimulationInterface(this);
|
virtual void Reset(bool newAge);
|
||||||
//fCore->SetControllerDimensions(fPreferedControllerWidth,fPreferedControllerHeight);
|
virtual bool IsKinematic() { return true; }
|
||||||
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; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical()=0;
|
plPhysicalControllerCore* fController;
|
||||||
virtual void IApplyKinematic();
|
|
||||||
plPhysicalControllerCore* fCore;
|
|
||||||
hsVector3 fLinearAcceleration;
|
|
||||||
float fAngularAcceleration;
|
|
||||||
plKey fOwner;
|
|
||||||
static const float kAirTimeThreshold;
|
|
||||||
float fTimeInAir;
|
|
||||||
float fPreferedControllerWidth;
|
|
||||||
float fPreferedControllerHeight;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class plWalkingStrategy: public plMovementStrategy
|
class plAnimatedMovementStrategy : public plMovementStrategy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
plWalkingStrategy(plPhysicalControllerCore* core):plMovementStrategy(core)
|
plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||||
{
|
virtual ~plAnimatedMovementStrategy() { }
|
||||||
fGroundHit=false;
|
|
||||||
fFalseGround=false;
|
virtual void RecalcVelocity(double timeNow, float elapsed, bool useAnim = true);
|
||||||
fHitHead=false;
|
void SetTurnStrength(float val) { fTurnStr = val; }
|
||||||
fCore->SetMovementSimulationInterface(this);
|
float GetTurnStrength() const { return fTurnStr; }
|
||||||
fPreferedControllerWidth=core->GetControllerWidth();
|
|
||||||
fPreferedControllerHeight=core->GetControllerHeight();
|
private:
|
||||||
fOnTopOfAnimatedPhysLastFrame=false;
|
void IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
|
||||||
}
|
void IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
|
||||||
virtual ~plWalkingStrategy(){};
|
|
||||||
|
plAGApplicator* fRootApp;
|
||||||
|
hsVector3 fAnimLinearVel;
|
||||||
|
float fAnimAngularVel;
|
||||||
|
float fTurnStr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class plWalkingStrategy : public plAnimatedMovementStrategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||||
|
virtual ~plWalkingStrategy() { }
|
||||||
|
|
||||||
virtual void Apply(float delSecs);
|
virtual void Apply(float delSecs);
|
||||||
virtual void Update(float delSecs);
|
virtual void Update(float delSecs);
|
||||||
|
|
||||||
|
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; }
|
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
|
||||||
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
|
|
||||||
void GroundHit() { fGroundHit = true; }
|
float GetAirTime() const { return fTimeInAir; }
|
||||||
virtual void IAddContactNormals(hsVector3& vec);
|
void ResetAirTime() { fTimeInAir = 0.0f; }
|
||||||
virtual void StartJump(){};
|
|
||||||
|
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:
|
protected:
|
||||||
|
static const float kAirTimeThreshold;
|
||||||
void ICheckForFalseGround();
|
static const float kControlledFlightThreshold;
|
||||||
|
|
||||||
|
hsTArray<hsVector3> fSlidingNormals;
|
||||||
|
|
||||||
|
hsVector3 fImpactVelocity;
|
||||||
|
float fImpactTime;
|
||||||
|
|
||||||
|
float fTimeInAir;
|
||||||
|
|
||||||
|
float fControlledFlightTime;
|
||||||
|
int fControlledFlight;
|
||||||
|
|
||||||
bool fGroundHit;
|
bool fGroundHit;
|
||||||
bool fFalseGround;
|
bool fFalseGround;
|
||||||
bool fHitHead;
|
bool fHeadHit;
|
||||||
bool fOnTopOfAnimatedPhysLastFrame;
|
bool fSliding;
|
||||||
hsTArray<hsVector3> fPrevSlidingNormals;
|
|
||||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
|
|
||||||
|
|
||||||
|
bool fClearImpact;
|
||||||
|
bool fHitGroundInThisAge;
|
||||||
};
|
};
|
||||||
class plSwimStrategy: public plMovementStrategy
|
|
||||||
|
class plSwimStrategy : public plAnimatedMovementStrategy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
plSwimStrategy(plPhysicalControllerCore *core);
|
plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||||
virtual ~plSwimStrategy(){};
|
virtual ~plSwimStrategy() { }
|
||||||
void SetSurface(plSwimRegionInterface *region, float surfaceHeight);
|
|
||||||
virtual void Apply(float delSecs);
|
virtual void Apply(float delSecs);
|
||||||
virtual void Update(float delSecs);
|
|
||||||
float GetBuoyancy() { return fBuoyancy; }
|
virtual void AddContactNormals(hsVector3& vec);
|
||||||
bool IsOnGround() { return fOnGround; }
|
|
||||||
bool HadContacts() { return fHadContacts; }
|
void SetSurface(plSwimRegionInterface* region, float surfaceHeight);
|
||||||
virtual void IAddContactNormals(hsVector3& vec);
|
|
||||||
|
float GetBuoyancy() const { return fBuoyancy; }
|
||||||
|
bool IsOnGround() const { return fOnGround; }
|
||||||
|
bool HadContacts() const { return fHadContacts; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
|
|
||||||
private:
|
|
||||||
void IAdjustBuoyancy();
|
void IAdjustBuoyancy();
|
||||||
|
|
||||||
float fBuoyancy;
|
float fBuoyancy;
|
||||||
|
float fSurfaceHeight;
|
||||||
|
|
||||||
|
plSwimRegionInterface *fCurrentRegion;
|
||||||
|
|
||||||
bool fOnGround;
|
bool fOnGround;
|
||||||
bool fHadContacts;
|
bool fHadContacts;
|
||||||
float fSurfaceHeight;
|
|
||||||
plSwimRegionInterface *fCurrentRegion;
|
|
||||||
};
|
};
|
||||||
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
|
|
||||||
|
class plDynamicWalkingStrategy : public plWalkingStrategy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) :
|
plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
|
||||||
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){};
|
virtual ~plDynamicWalkingStrategy() { }
|
||||||
virtual ~plRidingAnimatedPhysicalStrategy(){};
|
|
||||||
virtual void Apply(float delSecs);
|
virtual void Apply(float delSecs);
|
||||||
virtual void Update(float delSecs);
|
|
||||||
virtual void PostStep(float delSecs);
|
virtual bool IsKinematic() { return false; }
|
||||||
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
|
|
||||||
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
|
|
||||||
void GroundHit() { fGroundHit = true; }
|
|
||||||
virtual void StartJump(){fStartJump = true;}
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool IRequireBehaviourLikeAnAnimatedPhysical(){return false;}
|
bool ICheckForGround(float& zVelocity);
|
||||||
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
|
|
||||||
bool fNeedVelocityOverride;
|
|
||||||
hsVector3 fOverrideVelocity;
|
|
||||||
bool fStartJump;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif// PLPHYSICALCONTROLLERCORE_H
|
#endif// PLPHYSICALCONTROLLERCORE_H
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
#include "plAvatar/plArmatureMod.h"
|
#include "plAvatar/plArmatureMod.h"
|
||||||
#include "plAvatar/plAvBrain.h"
|
#include "plAvatar/plAvBrain.h"
|
||||||
#include "plAvatar/plAvatarMgr.h"
|
#include "plAvatar/plAvatarMgr.h"
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
#include "plModifier/plInterfaceInfoModifier.h"
|
#include "plModifier/plInterfaceInfoModifier.h"
|
||||||
#include "pnModifier/plLogicModBase.h"
|
#include "pnModifier/plLogicModBase.h"
|
||||||
#include "plVault/plVault.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 "plMessage/plAvatarMsg.h"
|
||||||
#include "plPhysical.h"
|
#include "plPhysical.h"
|
||||||
#include "plPhysical/plSimDefs.h"
|
#include "plPhysical/plSimDefs.h"
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
|
||||||
|
|
||||||
#include "plAvatar/plAvBrainGeneric.h"
|
#include "plAvatar/plAvBrainGeneric.h"
|
||||||
|
|
||||||
|
@ -94,8 +94,7 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isController;
|
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor);
|
||||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor,&isController);
|
|
||||||
if (controller)
|
if (controller)
|
||||||
{
|
{
|
||||||
objKey = controller->GetOwner();
|
objKey = controller->GetOwner();
|
||||||
|
@ -138,14 +138,10 @@ plPXPhysical::plPXPhysical()
|
|||||||
, fSceneNode(nil)
|
, fSceneNode(nil)
|
||||||
, fWorldKey(nil)
|
, fWorldKey(nil)
|
||||||
, fSndGroup(nil)
|
, fSndGroup(nil)
|
||||||
, fWorldHull(nil)
|
|
||||||
, fSaveTriangles(nil)
|
|
||||||
, fHullNumberPlanes(0)
|
|
||||||
, fMass(0.f)
|
, fMass(0.f)
|
||||||
, fWeWereHit(false)
|
, fWeWereHit(false)
|
||||||
, fHitForce(0,0,0)
|
, fHitForce(0,0,0)
|
||||||
, fHitPos(0,0,0)
|
, fHitPos(0,0,0)
|
||||||
, fInsideConvexHull(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +186,6 @@ plPXPhysical::~plPXPhysical()
|
|||||||
plSimulationMgr::GetInstance()->ReleaseScene(fWorldKey);
|
plSimulationMgr::GetInstance()->ReleaseScene(fWorldKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fWorldHull)
|
|
||||||
delete [] fWorldHull;
|
|
||||||
if (fSaveTriangles)
|
|
||||||
delete [] fSaveTriangles;
|
|
||||||
|
|
||||||
delete fProxyGen;
|
delete fProxyGen;
|
||||||
|
|
||||||
// remove sdl modifier
|
// remove sdl modifier
|
||||||
@ -206,155 +197,6 @@ plPXPhysical::~plPXPhysical()
|
|||||||
delete fSDLMod;
|
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 plPXPhysical::Init(PhysRecipe& recipe)
|
||||||
{
|
{
|
||||||
bool startAsleep = false;
|
bool startAsleep = false;
|
||||||
@ -388,29 +230,6 @@ bool plPXPhysical::Init(PhysRecipe& recipe)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case plSimDefs::kHullBounds:
|
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.meshData = recipe.convexMesh;
|
||||||
convexShapeDesc.userData = recipe.meshStream;
|
convexShapeDesc.userData = recipe.meshStream;
|
||||||
@ -669,9 +488,6 @@ void plPXPhysical::IEnable(bool enable)
|
|||||||
{
|
{
|
||||||
fActor->clearActorFlag(NX_AF_DISABLE_COLLISION);
|
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())
|
if (fActor->isDynamic())
|
||||||
fActor->clearBodyFlag(NX_BF_FROZEN);
|
fActor->clearBodyFlag(NX_BF_FROZEN);
|
||||||
else
|
else
|
||||||
|
@ -156,11 +156,6 @@ public:
|
|||||||
virtual uint16_t GetAllLOSDBs() { return fLOSDBs; }
|
virtual uint16_t GetAllLOSDBs() { return fLOSDBs; }
|
||||||
virtual bool IsInLOSDB(uint16_t flag) { return hsCheckBits(fLOSDBs, flag); }
|
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 plKey GetWorldKey() const { return fWorldKey; }
|
||||||
|
|
||||||
virtual plPhysicalSndGroup* GetSoundGroup() const { return fSndGroup; }
|
virtual plPhysicalSndGroup* GetSoundGroup() const { return fSndGroup; }
|
||||||
@ -201,14 +196,6 @@ protected:
|
|||||||
/** Handle messages about our references. */
|
/** Handle messages about our references. */
|
||||||
bool HandleRefMsg(plGenRefMsg * refM);
|
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.
|
/** See if the object is in a valid, non-overlapping position.
|
||||||
A valid overlap is one which is approved by the collision
|
A valid overlap is one which is approved by the collision
|
||||||
masking code, i.e. my memberOf has no intersection with your
|
masking code, i.e. my memberOf has no intersection with your
|
||||||
@ -236,8 +223,6 @@ protected:
|
|||||||
// Enable/disable collisions and dynamic movement
|
// Enable/disable collisions and dynamic movement
|
||||||
void IEnable(bool enable);
|
void IEnable(bool enable);
|
||||||
|
|
||||||
void IMakeHull(NxConvexMesh* convexMesh, hsMatrix44 l2w);
|
|
||||||
|
|
||||||
NxActor* fActor;
|
NxActor* fActor;
|
||||||
plKey fWorldKey; // either a subworld or nil
|
plKey fWorldKey; // either a subworld or nil
|
||||||
|
|
||||||
@ -251,24 +236,6 @@ protected:
|
|||||||
plKey fObjectKey; // the key to our scene object
|
plKey fObjectKey; // the key to our scene object
|
||||||
plKey fSceneNode; // the room we're in
|
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
|
// 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,
|
// so that we can recognize them when we send them back and not reapply them,
|
||||||
// which would reactivate our body. inelegant but effective
|
// 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==*/
|
*==LICENSE==*/
|
||||||
#include "plAvatar/plPhysicalControllerCore.h"
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
#include "hsQuat.h"
|
|
||||||
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
|
|
||||||
|
|
||||||
class NxController;
|
|
||||||
class NxCapsuleController;
|
class NxCapsuleController;
|
||||||
class NxActor;
|
class NxActor;
|
||||||
class plCoordinateInterface;
|
class NxCapsule;
|
||||||
|
class PXControllerHitReport;
|
||||||
class plPhysicalProxy;
|
class plPhysicalProxy;
|
||||||
class plDrawableSpans;
|
class plDrawableSpans;
|
||||||
class hsGMaterial;
|
class hsGMaterial;
|
||||||
class NxCapsule;
|
|
||||||
class plSceneObject;
|
class plSceneObject;
|
||||||
class PXControllerHitReportWalk;
|
class plPXPhysical;
|
||||||
class plCollideMsg;
|
class plCollideMsg;
|
||||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
|
||||||
|
|
||||||
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||||
class plDbgCollisionInfo
|
class plDbgCollisionInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -64,97 +61,113 @@ public:
|
|||||||
bool fOverlap;
|
bool fOverlap;
|
||||||
};
|
};
|
||||||
#endif // PLASMA_EXTERNAL_RELEASE
|
#endif // PLASMA_EXTERNAL_RELEASE
|
||||||
|
|
||||||
class plPXPhysicalControllerCore: public plPhysicalControllerCore
|
class plPXPhysicalControllerCore: public plPhysicalControllerCore
|
||||||
{
|
{
|
||||||
friend class PXControllerHitReportWalk;
|
|
||||||
public:
|
public:
|
||||||
plPXPhysicalControllerCore(plKey ownerSO, float height, float radius);
|
plPXPhysicalControllerCore(plKey ownerSO, float height, float radius, bool human);
|
||||||
~plPXPhysicalControllerCore();
|
~plPXPhysicalControllerCore();
|
||||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
|
||||||
|
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
|
||||||
inline virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
|
// Use plArmatureModBase::EnablePhysics() instead.
|
||||||
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
|
|
||||||
virtual void Enable(bool enable);
|
virtual void Enable(bool enable);
|
||||||
|
|
||||||
virtual void SetSubworld(plKey world) ;
|
// Subworld
|
||||||
virtual const plCoordinateInterface* GetSubworldCI() const ;
|
virtual void SetSubworld(plKey world);
|
||||||
|
|
||||||
// For the avatar SDL only
|
// For the avatar SDL only
|
||||||
virtual void GetState(hsPoint3& pos, float& zRot);
|
virtual void GetState(hsPoint3& pos, float& zRot);
|
||||||
virtual void SetState(const 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);
|
// Movement strategy
|
||||||
virtual bool IsKinematic();
|
virtual void SetMovementStrategy(plMovementStrategy* strategy);
|
||||||
virtual void GetKinematicPosition(hsPoint3& pos);
|
|
||||||
virtual const hsMatrix44& GetPrevSubworldW2L(){ return fPrevSubworldW2L; }
|
// Global location
|
||||||
//when seeking no longer want to interact with exclusion regions
|
virtual void SetGlobalLoc(const hsMatrix44& l2w);
|
||||||
virtual void GetWorldSpaceCapsule(NxCapsule& cap) const;
|
|
||||||
static void RebuildCache();
|
// Local Sim Position
|
||||||
virtual const hsMatrix44& GetLastGlobalLoc(){return fLastGlobalLoc;}
|
virtual void GetPositionSim(hsPoint3& pos);
|
||||||
virtual void SetKinematicLoc(const hsMatrix44& l2w){ISetKinematicLoc(l2w);}
|
|
||||||
virtual void SetGlobalLoc(const hsMatrix44& l2w){ISetGlobalLoc(l2w);}
|
// Move kinematic controller
|
||||||
virtual void HandleEnableChanged();
|
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
|
||||||
virtual void HandleKinematicChanged();
|
|
||||||
virtual void HandleKinematicEnableNextUpdate();
|
// Set linear velocity on dynamic controller
|
||||||
virtual void GetPositionSim(hsPoint3& pos){IGetPositionSim(pos);}
|
virtual void SetLinearVelocitySim(const hsVector3& linearVel);
|
||||||
virtual void MoveKinematicToController(hsPoint3& pos);
|
|
||||||
virtual const hsPoint3& GetLocalPosition(){return fLocalPosition;}
|
// Sweep the controller path from startPos through endPos
|
||||||
virtual void SetControllerDimensions(float radius, float height);
|
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 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
|
//Static Helper Functions
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
// Used by the LOS mgr to find the controller for an actor it hit
|
|
||||||
static plPXPhysicalControllerCore* GetController(NxActor& actor, bool* isController);
|
// Call pre-sim to apply movement to controllers
|
||||||
// test to see if there are any controllers (i.e. avatars) in this subworld
|
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 bool AnyControllersInThisWorld(plKey world);
|
||||||
static int NumControllers();
|
|
||||||
static int GetControllersInThisSubWorld(plKey world, int maxToReturn,
|
|
||||||
plPXPhysicalControllerCore** bufferout);
|
|
||||||
static int GetNumberOfControllersInThisSubWorld(plKey world);
|
static int GetNumberOfControllersInThisSubWorld(plKey world);
|
||||||
static void UpdatePrestep(float delSecs);
|
static int GetControllersInThisSubWorld(plKey world, int maxToReturn, plPXPhysicalControllerCore** bufferout);
|
||||||
static void UpdatePoststep(float delSecs);
|
|
||||||
static void UpdatePostSimStep(float delSecs);
|
// Controller count
|
||||||
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<uint32_t>& idx, plDrawableSpans* addTo);
|
static int NumControllers();
|
||||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
|
||||||
static bool fDebugDisplay;
|
|
||||||
#endif // PLASMA_EXTERNAL_RELEASE
|
|
||||||
static void SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
|
static void SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
|
||||||
static int fPXControllersMax;
|
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);
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||||
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
|
static bool fDebugDisplay;
|
||||||
virtual void SetAngularVelocity(const float angvel);
|
#endif
|
||||||
virtual void SetVelocities(const hsVector3& linearVel, float angVel);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class PXControllerHitReport;
|
friend class PXControllerHitReport;
|
||||||
static plPXPhysicalControllerCore* FindController(NxController* controller);
|
|
||||||
void ISetGlobalLoc(const hsMatrix44& l2w);
|
virtual void IHandleEnableChanged();
|
||||||
void IMatchKinematicToController();
|
|
||||||
void IMatchControllerToKinematic();
|
void IInformDetectors(bool entering);
|
||||||
void ISetKinematicLoc(const hsMatrix44& l2w);
|
|
||||||
void IGetPositionSim(hsPoint3& pos) const;
|
|
||||||
void ICreateController();
|
|
||||||
void IDeleteController();
|
|
||||||
void IInformDetectors(bool entering,bool deferUntilNextSim);
|
|
||||||
void ICreateController(const hsPoint3& pos);
|
void ICreateController(const hsPoint3& pos);
|
||||||
NxActor* fKinematicActor;
|
void IDeleteController();
|
||||||
NxCapsuleController* fController;
|
|
||||||
|
void IDispatchQueuedMsgs();
|
||||||
|
void IProcessDynamicHits();
|
||||||
|
|
||||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||||
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
|
|
||||||
void IDrawDebugDisplay();
|
void IDrawDebugDisplay();
|
||||||
|
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
|
||||||
#endif
|
#endif
|
||||||
void IHandleResize();
|
|
||||||
float fPreferedRadius;
|
std::vector<plCollideMsg*> fQueuedCollideMsgs;
|
||||||
float fPreferedHeight;
|
std::vector<plPXPhysical*> fDynamicHits;
|
||||||
// The global position and rotation of the avatar last time we set it (so we
|
|
||||||
// can detect if someone else moves him)
|
NxCapsuleController* fController;
|
||||||
plPhysicalProxy* fProxyGen;
|
NxActor* fActor;
|
||||||
bool fBehavingLikeAnimatedPhys;
|
|
||||||
|
plPhysicalProxy* fProxyGen;
|
||||||
|
bool fKinematicCCT;
|
||||||
|
bool fHuman;
|
||||||
};
|
};
|
||||||
|
@ -70,139 +70,43 @@ class SensorReport : public NxUserTriggerReport
|
|||||||
{
|
{
|
||||||
virtual void onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status)
|
virtual void onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status)
|
||||||
{
|
{
|
||||||
// Get our trigger physical. This should definitely have a plPXPhysical
|
plKey otherKey = nil;
|
||||||
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
|
|
||||||
bool doReport = false;
|
bool doReport = false;
|
||||||
|
|
||||||
// Get the triggerer. This may be an avatar, which doesn't have a
|
// Get our trigger physical. This should definitely have a plPXPhysical
|
||||||
// plPXPhysical, so we have to extract the necessary info.
|
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
|
||||||
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 the triggerer. If it doesn't have a plPXPhyscial, it's an avatar
|
||||||
plPXPhysical* otherPhys = (plPXPhysical*)otherShape.getActor().userData;
|
plPXPhysical* otherPhys = (plPXPhysical*)otherShape.getActor().userData;
|
||||||
if (otherPhys)
|
if (otherPhys)
|
||||||
{
|
{
|
||||||
otherKey = otherPhys->GetObjectKey();
|
otherKey = otherPhys->GetObjectKey();
|
||||||
doReport = triggerPhys->DoReportOn((plSimDefs::Group)otherPhys->GetGroup());
|
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
|
else
|
||||||
{
|
{
|
||||||
bool isController;
|
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor());
|
||||||
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor(),&isController);
|
|
||||||
if (controller)
|
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();
|
otherKey = controller->GetOwner();
|
||||||
doReport = triggerPhys->DoReportOn(plSimDefs::kGroupAvatar);
|
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)
|
if (doReport)
|
||||||
{
|
{
|
||||||
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
|
if (status & NX_TRIGGER_ON_ENTER)
|
||||||
if ( triggerPhys->DoDetectorHullWorkaround() )
|
|
||||||
{
|
{
|
||||||
if (status & NX_TRIGGER_ON_ENTER && triggerPhys->Should_I_Trigger(status & NX_TRIGGER_ON_ENTER, otherPos) )
|
if (plSimulationMgr::fExtraProfile)
|
||||||
{
|
DetectorLogRed("-->Send Collision %s enter",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||||
if (plSimulationMgr::fExtraProfile)
|
plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, true);
|
||||||
DetectorLogRed("-->Send Collision (CH) %s %s",triggerPhys->GetObjectKey()->GetName().c_str(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit");
|
|
||||||
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
|
else if (status & NX_TRIGGER_ON_LEAVE)
|
||||||
{
|
{
|
||||||
#endif // USE_PHYSX_CONVEXHULL_WORKAROUND
|
if (plSimulationMgr::fExtraProfile)
|
||||||
if (status & NX_TRIGGER_ON_ENTER)
|
DetectorLogRed("-->Send Collision %s exit",triggerPhys->GetObjectKey()->GetName().c_str());
|
||||||
{
|
plSimulationMgr::GetInstance()->AddCollisionMsg(triggerPhys->GetObjectKey(), otherKey, false);
|
||||||
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");
|
|
||||||
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;
|
} 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 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
|
#define kDefaultStepSize (1.f / 60.f) // default simulation freqency is 60hz
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@ -378,6 +282,8 @@ plSimulationMgr* plSimulationMgr::GetInstance()
|
|||||||
|
|
||||||
plSimulationMgr::plSimulationMgr()
|
plSimulationMgr::plSimulationMgr()
|
||||||
: fSuspended(true)
|
: fSuspended(true)
|
||||||
|
, fAccumulator(0.0f)
|
||||||
|
, fStepCount(0)
|
||||||
, fLOSDispatch(new plLOSDispatch())
|
, fLOSDispatch(new plLOSDispatch())
|
||||||
, fSoundMgr(new plPhysicsSoundMgr)
|
, fSoundMgr(new plPhysicsSoundMgr)
|
||||||
, fLog(nil)
|
, fLog(nil)
|
||||||
@ -470,6 +376,7 @@ NxScene* plSimulationMgr::GetScene(plKey world)
|
|||||||
scene->setGroupCollisionFlag(i, plSimDefs::kGroupDynamicBlocker, false);
|
scene->setGroupCollisionFlag(i, plSimDefs::kGroupDynamicBlocker, false);
|
||||||
scene->setGroupCollisionFlag(i, plSimDefs::kGroupLOSOnly, false);
|
scene->setGroupCollisionFlag(i, plSimDefs::kGroupLOSOnly, false);
|
||||||
scene->setGroupCollisionFlag(plSimDefs::kGroupLOSOnly, i, 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::kGroupAvatar, false);
|
||||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatarBlocker, true);
|
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatarBlocker, true);
|
||||||
@ -477,7 +384,11 @@ NxScene* plSimulationMgr::GetScene(plKey world)
|
|||||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupStatic, true);
|
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupStatic, true);
|
||||||
scene->setGroupCollisionFlag( plSimDefs::kGroupStatic, plSimDefs::kGroupAvatar, true);
|
scene->setGroupCollisionFlag( plSimDefs::kGroupStatic, plSimDefs::kGroupAvatar, true);
|
||||||
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupDynamic, 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
|
// The dynamics are in actor group 1, everything else is in 0. Request
|
||||||
// a callback for whenever a dynamic touches something.
|
// a callback for whenever a dynamic touches something.
|
||||||
scene->setActorGroupPairFlags(0, 1, NX_NOTIFY_ON_TOUCH);
|
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)
|
void plSimulationMgr::AddCollisionMsg(plKey hitee, plKey hitter, bool enter)
|
||||||
{
|
{
|
||||||
// First, make sure we have no dupes
|
// First, make sure we have no dupes
|
||||||
@ -614,20 +445,41 @@ void plSimulationMgr::AddCollisionMsg(plKey hitee, plKey hitter, bool enter)
|
|||||||
pMsg->fEntering = enter;
|
pMsg->fEntering = enter;
|
||||||
fCollideMsgs.push_back(pMsg);
|
fCollideMsgs.push_back(pMsg);
|
||||||
}
|
}
|
||||||
|
void plSimulationMgr::AddCollisionMsg(plCollideMsg* msg)
|
||||||
|
{
|
||||||
|
fCollideMsgs.push_back(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void plSimulationMgr::Advance(float delSecs)
|
void plSimulationMgr::Advance(float delSecs)
|
||||||
{
|
{
|
||||||
if (fSuspended)
|
if (fSuspended)
|
||||||
return;
|
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
|
++fStepCount;
|
||||||
uint32_t stepTime = hsTimer::GetPrecTickCount();
|
|
||||||
#endif
|
// 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);
|
plProfile_BeginTiming(Step);
|
||||||
plPXPhysicalControllerCore::UpdatePrestep(delSecs);
|
|
||||||
plPXPhysicalControllerCore::UpdatePoststep( delSecs);
|
plPXPhysicalControllerCore::Apply(delta);
|
||||||
|
|
||||||
for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
|
for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
|
||||||
{
|
{
|
||||||
@ -642,12 +494,13 @@ void plSimulationMgr::Advance(float delSecs)
|
|||||||
}
|
}
|
||||||
if (do_advance)
|
if (do_advance)
|
||||||
{
|
{
|
||||||
scene->simulate(delSecs);
|
scene->simulate(delta);
|
||||||
scene->flushStream();
|
scene->flushStream();
|
||||||
scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
|
scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plPXPhysicalControllerCore::UpdatePostSimStep(delSecs);
|
|
||||||
|
plPXPhysicalControllerCore::Update(numSubSteps, fAccumulator / kDefaultStepSize);
|
||||||
|
|
||||||
plProfile_EndTiming(Step);
|
plProfile_EndTiming(Step);
|
||||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||||
@ -730,9 +583,6 @@ void plSimulationMgr::ISendUpdates()
|
|||||||
plPXPhysical* physical = (plPXPhysical*)actors[i]->userData;
|
plPXPhysical* physical = (plPXPhysical*)actors[i]->userData;
|
||||||
if (physical)
|
if (physical)
|
||||||
{
|
{
|
||||||
// apply any hit forces
|
|
||||||
physical->ApplyHitForce();
|
|
||||||
|
|
||||||
if (physical->GetSceneNode())
|
if (physical->GetSceneNode())
|
||||||
{
|
{
|
||||||
physical->SendNewLocation();
|
physical->SendNewLocation();
|
||||||
|
@ -99,12 +99,11 @@ public:
|
|||||||
|
|
||||||
int GetMaterialIdx(NxScene* scene, float friction, float restitution);
|
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
|
uint32_t GetStepCount() const { return fStepCount; }
|
||||||
void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering);
|
|
||||||
void UpdateAvatarInDetector(plKey world, plPXPhysical* detector);
|
|
||||||
|
|
||||||
//Fix to Move collision messages and their handling out of the simulation step
|
//Fix to Move collision messages and their handling out of the simulation step
|
||||||
void AddCollisionMsg(plKey hitee, plKey hitter, bool entering);
|
void AddCollisionMsg(plKey hitee, plKey hitter, bool entering);
|
||||||
|
void AddCollisionMsg(plCollideMsg* msg);
|
||||||
|
|
||||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||||
static bool fDisplayAwakeActors;
|
static bool fDisplayAwakeActors;
|
||||||
@ -121,9 +120,6 @@ protected:
|
|||||||
// Walk through the synchronization requests and send them as appropriate.
|
// Walk through the synchronization requests and send them as appropriate.
|
||||||
void IProcessSynchs();
|
void IProcessSynchs();
|
||||||
|
|
||||||
// PHYSX FIXME send a collision message - should only be used with UpdateDetectorsInScene
|
|
||||||
void ISendCollisionMsg(plKey receiver, plKey hitter, bool entering);
|
|
||||||
|
|
||||||
NxPhysicsSDK* fSDK;
|
NxPhysicsSDK* fSDK;
|
||||||
|
|
||||||
plPhysicsSoundMgr* fSoundMgr;
|
plPhysicsSoundMgr* fSoundMgr;
|
||||||
@ -144,6 +140,9 @@ protected:
|
|||||||
// but nothing will move.
|
// but nothing will move.
|
||||||
bool fSuspended;
|
bool fSuspended;
|
||||||
|
|
||||||
|
float fAccumulator;
|
||||||
|
uint32_t fStepCount;
|
||||||
|
|
||||||
// A utility class to keep track of a request for a physical synchronization.
|
// 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)
|
// These requests must pass a certain criteria (see the code for the latest)
|
||||||
// before they are actually either sent over the network or rejected.
|
// 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
|
Mead, WA 99021
|
||||||
|
|
||||||
*==LICENSE==*/
|
*==LICENSE==*/
|
||||||
#include "plAvatar/plAvCallbackAction.h"
|
|
||||||
|
|
||||||
#include "HeadSpin.h"
|
#include "HeadSpin.h"
|
||||||
#include "plCollisionDetector.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/plAvatarMgr.h"
|
||||||
#include "plAvatar/plAvBrainHuman.h"
|
#include "plAvatar/plAvBrainHuman.h"
|
||||||
#include "plAvatar/plAvBrainDrive.h"
|
#include "plAvatar/plAvBrainDrive.h"
|
||||||
|
#include "plAvatar/plPhysicalControllerCore.h"
|
||||||
|
|
||||||
#include "plModifier/plDetectorLog.h"
|
#include "plModifier/plDetectorLog.h"
|
||||||
|
|
||||||
#define USE_PHYSX_MULTIPLE_CAMREGION_ENTER 1
|
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||||
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND 1
|
#include "plPhysX/plSimulationMgr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plArmatureMod* plCollisionDetector::IGetAvatarModifier(plKey key)
|
plArmatureMod* plCollisionDetector::IGetAvatarModifier(plKey key)
|
||||||
{
|
{
|
||||||
@ -240,58 +243,19 @@ plCameraRegionDetector::~plCameraRegionDetector()
|
|||||||
hsRefCnt_SafeUnRef(*it);
|
hsRefCnt_SafeUnRef(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void plCameraRegionDetector::ITrigger(plKey hitter, bool entering, bool immediate)
|
void plCameraRegionDetector::ISendTriggerMsg()
|
||||||
{
|
{
|
||||||
if (fSavingSendMsg)
|
for (plCameraMsgVec::iterator it = fMessages.begin(); it != fMessages.end(); ++it)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
DetectorLog("%s: Saving camera Entering volume - Evals=%d", GetKeyName().c_str(),fNumEvals);
|
plCameraMsg* msg = *it;
|
||||||
fLastEnterEval = fNumEvals;
|
if (fIsInside)
|
||||||
|
msg->SetCmd(plCameraMsg::kEntering);
|
||||||
|
else
|
||||||
|
msg->ClearCmd(plCameraMsg::kEntering);
|
||||||
|
msg->SendAndKeep();
|
||||||
}
|
}
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fSavingSendMsg = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool plCameraRegionDetector::MsgReceive(plMessage* msg)
|
bool plCameraRegionDetector::MsgReceive(plMessage* msg)
|
||||||
{
|
{
|
||||||
plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg);
|
plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg);
|
||||||
@ -300,8 +264,16 @@ bool plCameraRegionDetector::MsgReceive(plMessage* msg)
|
|||||||
// camera collisions are only for the local player
|
// camera collisions are only for the local player
|
||||||
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey)
|
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey)
|
||||||
return true;
|
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);
|
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
|
// object-in-volume detector
|
||||||
|
|
||||||
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering, bool immediate)
|
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering)
|
||||||
{
|
{
|
||||||
hsRefCnt_SafeUnRef(fSavedActivatorMsg);
|
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||||
fSavedActivatorMsg = new plActivatorMsg;
|
for (bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); ++it)
|
||||||
fSavedActivatorMsg->AddReceivers(fReceivers);
|
|
||||||
|
|
||||||
if (fProxyKey)
|
|
||||||
fSavedActivatorMsg->fHiteeObj = fProxyKey;
|
|
||||||
else
|
|
||||||
fSavedActivatorMsg->fHiteeObj = GetTarget()->GetKey();
|
|
||||||
|
|
||||||
fSavedActivatorMsg->fHitterObj = hitter;
|
|
||||||
fSavedActivatorMsg->SetSender(GetKey());
|
|
||||||
|
|
||||||
if (entering)
|
|
||||||
{
|
{
|
||||||
DetectorLog("%s: Saving Entering volume - Evals=%d", GetKeyName().c_str(), fNumEvals);
|
plCollisionBookKeepingInfo* collisionInfo = *it;
|
||||||
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
|
if (collisionInfo->fHitter == hitter)
|
||||||
fLastEnterEval = fNumEvals;
|
{
|
||||||
}
|
collisionInfo->fEntering = entering;
|
||||||
else
|
collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
|
||||||
{
|
return;
|
||||||
DetectorLog("%s: Saving Exiting volume - Evals=%d", GetKeyName().c_str(), fNumEvals);
|
}
|
||||||
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
|
|
||||||
fLastExitEval = fNumEvals;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (immediate)
|
plCollisionBookKeepingInfo* collisionInfo = new plCollisionBookKeepingInfo(hitter, entering);
|
||||||
ISendSavedTriggerMsgs();
|
fCollisionList.push_back(collisionInfo);
|
||||||
|
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||||
|
collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void plObjectInVolumeDetector::ISendSavedTriggerMsgs()
|
void plObjectInVolumeDetector::IRegisterForEval()
|
||||||
{
|
{
|
||||||
if (fSavedActivatorMsg)
|
fWaitingForEval = true;
|
||||||
{
|
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||||
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...
|
void plObjectInVolumeDetector::ISendTriggerMsg(plKey hitter, bool entering)
|
||||||
plgDispatch::MsgSend(fSavedActivatorMsg);
|
{
|
||||||
}
|
plActivatorMsg* activatorMsg = new plActivatorMsg();
|
||||||
fSavedActivatorMsg = nil;
|
activatorMsg->SetSender(GetKey());
|
||||||
|
activatorMsg->AddReceivers(fReceivers);
|
||||||
|
activatorMsg->fHiteeObj = fProxyKey ? fProxyKey : GetTarget()->GetKey();
|
||||||
|
activatorMsg->fHitterObj = hitter;
|
||||||
|
if (entering)
|
||||||
|
activatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
|
||||||
|
else
|
||||||
|
activatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
|
||||||
|
|
||||||
|
plgDispatch::MsgSend(activatorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
|
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 the avatar is disabled (flying around), don't trigger
|
||||||
if (IIsDisabledAvatar(pCollMsg->fOtherKey))
|
if (IIsDisabledAvatar(pCollMsg->fOtherKey))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!fWaitingForEval)
|
||||||
|
IRegisterForEval();
|
||||||
|
|
||||||
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
|
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
|
||||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
plEvalMsg* pEvalMsg = plEvalMsg::ConvertNoRef(msg);
|
plEvalMsg* pEvalMsg = plEvalMsg::ConvertNoRef(msg);
|
||||||
if (pEvalMsg)
|
if (pEvalMsg)
|
||||||
{
|
IHandleEval(pEvalMsg);
|
||||||
fNumEvals++;
|
|
||||||
ISendSavedTriggerMsgs();
|
|
||||||
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg);
|
plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg);
|
||||||
if (pageMsg && pageMsg->fUnload)
|
if (pageMsg && pageMsg->fUnload)
|
||||||
@ -409,6 +396,48 @@ bool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
|
|||||||
return plCollisionDetector::MsgReceive(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)
|
void plObjectInVolumeDetector::SetTarget(plSceneObject* so)
|
||||||
{
|
{
|
||||||
plCollisionDetector::SetTarget(so);
|
plCollisionDetector::SetTarget(so);
|
||||||
@ -475,7 +504,7 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
|
|||||||
// And are we walking towards it?
|
// And are we walking towards it?
|
||||||
plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain();
|
plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain();
|
||||||
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain);
|
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain);
|
||||||
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
|
if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
|
||||||
movingForward = true;
|
movingForward = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -485,13 +514,13 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
|
|||||||
{
|
{
|
||||||
DetectorLog("%s: Trigger InVolume&Facing", GetKeyName().c_str());
|
DetectorLog("%s: Trigger InVolume&Facing", GetKeyName().c_str());
|
||||||
fTriggered = true;
|
fTriggered = true;
|
||||||
ITrigger(avatar->GetKey(), true, true);
|
ISendTriggerMsg(avatar->GetKey(), true);
|
||||||
}
|
}
|
||||||
else if (!facing && fTriggered)
|
else if (!facing && fTriggered)
|
||||||
{
|
{
|
||||||
DetectorLog("%s: Untrigger InVolume&Facing", GetKeyName().c_str());
|
DetectorLog("%s: Untrigger InVolume&Facing", GetKeyName().c_str());
|
||||||
fTriggered = false;
|
fTriggered = false;
|
||||||
ITrigger(avatar->GetKey(), false, true);
|
ISendTriggerMsg(avatar->GetKey(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,7 +554,7 @@ bool plObjectInVolumeAndFacingDetector::MsgReceive(plMessage* msg)
|
|||||||
if (fTriggered)
|
if (fTriggered)
|
||||||
{
|
{
|
||||||
fTriggered = false;
|
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())
|
if (avMod->IsLinkedIn())
|
||||||
{
|
{
|
||||||
hsPoint3 kinPos;
|
hsPoint3 pos;
|
||||||
if (avMod->GetController())
|
if (avMod->GetController())
|
||||||
{
|
{
|
||||||
avMod->GetController()->GetKinematicPosition(kinPos);
|
avMod->GetController()->GetPositionSim(pos);
|
||||||
DetectorLogSpecial("Avatar is panic linking. KinPos at %f,%f,%f and is %s",kinPos.fX,kinPos.fY,kinPos.fZ,avMod->GetController()->IsEnabled() ? "enabled" : "disabled");
|
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);
|
avMod->PanicLink(fPlayLinkOutAnim);
|
||||||
} else
|
} else
|
||||||
|
@ -53,6 +53,8 @@ class plArmatureMod;
|
|||||||
class plActivatorMsg;
|
class plActivatorMsg;
|
||||||
class plEvalMsg;
|
class plEvalMsg;
|
||||||
|
|
||||||
|
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||||
|
|
||||||
class plCollisionDetector : public plDetectorModifier
|
class plCollisionDetector : public plDetectorModifier
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -92,23 +94,37 @@ public:
|
|||||||
class plObjectInVolumeDetector : public plCollisionDetector
|
class plObjectInVolumeDetector : public plCollisionDetector
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
|
class plCollisionBookKeepingInfo
|
||||||
virtual void ISendSavedTriggerMsgs();
|
{
|
||||||
|
public:
|
||||||
plActivatorMsg* fSavedActivatorMsg;
|
plCollisionBookKeepingInfo(const plKey& key, bool entering)
|
||||||
uint32_t fNumEvals;
|
: fHitter(key), fEntering(entering) { }
|
||||||
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:
|
public:
|
||||||
|
|
||||||
plObjectInVolumeDetector()
|
plObjectInVolumeDetector()
|
||||||
: plCollisionDetector(), fSavedActivatorMsg(nil), fNumEvals(0), fLastEnterEval(0), fLastExitEval(0)
|
: plCollisionDetector(), fWaitingForEval(false) { }
|
||||||
{ }
|
|
||||||
|
|
||||||
plObjectInVolumeDetector(int8_t type)
|
plObjectInVolumeDetector(int8_t type)
|
||||||
: plCollisionDetector(type), fSavedActivatorMsg(nil), fNumEvals(0), fLastEnterEval(0), fLastExitEval(0)
|
: plCollisionDetector(type), fWaitingForEval(false) { }
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual ~plObjectInVolumeDetector() { }
|
virtual ~plObjectInVolumeDetector() { }
|
||||||
|
|
||||||
@ -159,16 +175,17 @@ protected:
|
|||||||
typedef std::vector<plCameraMsg*> plCameraMsgVec;
|
typedef std::vector<plCameraMsg*> plCameraMsgVec;
|
||||||
|
|
||||||
plCameraMsgVec fMessages;
|
plCameraMsgVec fMessages;
|
||||||
bool fIsInside;
|
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
|
||||||
bool fSavingSendMsg;
|
uint32_t fLastStep;
|
||||||
bool fSavedMsgEnterFlag;
|
#endif
|
||||||
|
bool fIsInside;
|
||||||
|
bool fEntering;
|
||||||
|
|
||||||
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
|
void ISendTriggerMsg();
|
||||||
virtual void ISendSavedTriggerMsgs();
|
virtual void IHandleEval(plEvalMsg*);
|
||||||
public:
|
public:
|
||||||
plCameraRegionDetector()
|
plCameraRegionDetector()
|
||||||
: plObjectInVolumeDetector(), fIsInside(false), fSavingSendMsg(false)
|
: plObjectInVolumeDetector(), fIsInside(false) { }
|
||||||
{ }
|
|
||||||
~plCameraRegionDetector();
|
~plCameraRegionDetector();
|
||||||
|
|
||||||
virtual bool MsgReceive(plMessage* msg);
|
virtual bool MsgReceive(plMessage* msg);
|
||||||
|
@ -68,27 +68,10 @@ namespace plSimDefs
|
|||||||
kGroupLOSOnly,
|
kGroupLOSOnly,
|
||||||
//kExcludeRegion setting up so only blocks avatars and only when not in seek mode
|
//kExcludeRegion setting up so only blocks avatars and only when not in seek mode
|
||||||
kGroupExcludeRegion,
|
kGroupExcludeRegion,
|
||||||
|
// A kinematic avatar only interacts with dynamics and detectors
|
||||||
|
kGroupAvatarKinematic,
|
||||||
// Just for error checking
|
// Just for error checking
|
||||||
kGroupMax,
|
kGroupMax
|
||||||
};
|
|
||||||
|
|
||||||
/** A taxonomy of action types. Crucial for doing things like making sure you don't
|
|
||||||
do things like attach duplicate actions. */
|
|
||||||
enum ActionType
|
|
||||||
{
|
|
||||||
kUnknownAction = 0x01, // don't know the type (probably forgot to override GetType())
|
|
||||||
kUnknownZAction = 0x02, // unknown type of z-order action
|
|
||||||
kAntiGravityAction = 0x03, // an action that counters gravity exactly
|
|
||||||
kUprightAction = 0x04, // an action that keeps an object upright by apply force
|
|
||||||
kPhysAnimAction = 0x05, // an action that parses keyframed animation into physical information
|
|
||||||
kConstraint = 0x06, // a general constraint.
|
|
||||||
kCallbackAction = 0x07, // an action that just hands us the physics "tick"
|
|
||||||
kPseudoPhysAction = 0x08, // replacement for the physAnim
|
|
||||||
kAntiGravAction = 0x09, // makes things float in the air
|
|
||||||
kBasicGroundAction = 0x0a, // for your basic walkAroundOnGround corrections
|
|
||||||
kHorizontalFreeze = 0x0b, // Let's you fall vertically, but otherwise keeps you in place (generic brains)
|
|
||||||
|
|
||||||
kMaxAction = 0xffff // force 16-bit
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Different types of line-of-sight requests. */
|
/** Different types of line-of-sight requests. */
|
||||||
|
Reference in New Issue
Block a user