Branan Purvine-Riley
12 years ago
43 changed files with 1909 additions and 5321 deletions
@ -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 |
|
||||||
|
|
||||||
|
|
@ -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
|
|
File diff suppressed because it is too large
Load Diff
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
Loading…
Reference in new issue