2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 14:37:41 +00:00

CWE Directory Reorganization

Rearrange directory structure of CWE to be loosely equivalent to
the H'uru Plasma repository.

Part 1: Movement of directories and files.
This commit is contained in:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View File

@ -0,0 +1,311 @@
/*==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 "plLOSDispatch.h"
#include "plSimulationMgr.h"
#include "plgDispatch.h"
#include "../plMessage/plLOSRequestMsg.h"
#include "../plMessage/plLOSHitMsg.h"
#include "../pnKeyedObject/plFixedKey.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plModifier/plLogicModifier.h"
#include "plPXPhysical.h"
#include "plPXPhysicalControllerCore.h"
#include "plPXConvert.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plArmatureMod.h"
#include "NxPhysics.h"
#include "plProfile.h"
plProfile_Extern(LineOfSight);
class myRaycastReport : public NxUserRaycastReport
{
public:
void InitCast(plSimDefs::plLOSDB db, plLOSRequestMsg::TestType type)
{
fDB = db;
fType = type;
fHitObj = nil;
fNormal.Set(0, 0, 0);
fPoint.Set(0, 0, 0);
fDist = FLT_MAX;
}
bool GotHit() { return fDist != FLT_MAX; }
plKey GetObj() { return fHitObj; }
hsScalar GetDistance() { return fDist; }
const hsVector3& GetNormal() { return fNormal; }
const hsPoint3& GetPoint() { return fPoint; }
void ResetHitObj(){fHitObj=nil;}
private:
virtual bool onHit(const NxRaycastHit& hit)
{
NxActor& hitActor = hit.shape->getActor();
plPXPhysical* phys = (plPXPhysical*)hitActor.userData;
plKey objKey = nil;
UInt16 objDB = plSimDefs::kLOSDBNone;
if (phys)
{
objKey = phys->GetObjectKey();
objDB = phys->GetAllLOSDBs();
}
else
{
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor);
if (controller)
{
objKey = controller->GetOwner();
objDB = controller->GetLOSDB();
}
}
// is the object's physic enabled and is it in the database that we are looking for?
if ( !phys || !phys->GetProperty(plSimulationInterface::kDisable) )
{
if ( (fDB & objDB) != 0)
{
if (fType == plLOSRequestMsg::kTestAny || hit.distance < fDist)
{
// need one more test... if it is a clickable need to see if it is enabled
bool disabled = false;
if ( objKey )
{
plSceneObject* so = plSceneObject::ConvertNoRef( objKey->GetObjectPtr() );
if (so)
{
int i;
for ( i=0; i < so->GetNumModifiers(); i++)
{
plLogicModifier* lo = (plLogicModifier*)plLogicModifier::ConvertNoRef(so->GetModifier(i) );
if (lo)
{
disabled = lo->Disabled();
break;
}
}
}
}
if (!disabled)
{
fHitObj = objKey;
fNormal.Set(hit.worldNormal.x, hit.worldNormal.y, hit.worldNormal.z);
fPoint.Set(hit.worldImpact.x, hit.worldImpact.y, hit.worldImpact.z);
fDist = hit.distance;
if (fType == plLOSRequestMsg::kTestAny)
return false;
}
}
}
}
return true;
}
plSimDefs::plLOSDB fDB;
plLOSRequestMsg::TestType fType;
plKey fHitObj;
hsVector3 fNormal;
hsPoint3 fPoint;
hsScalar fDist;
} gMyReport;
plLOSDispatch::plLOSDispatch()
{
RegisterAs(kLOSObject_KEY);
plgDispatch::Dispatch()->RegisterForExactType(plLOSRequestMsg::Index(), GetKey());
}
plLOSDispatch::~plLOSDispatch()
{
plgDispatch::Dispatch()->UnRegisterForExactType(plLOSRequestMsg::Index(), GetKey());
}
hsBool plLOSDispatch::MsgReceive(plMessage* msg)
{
plLOSRequestMsg* requestMsg = plLOSRequestMsg::ConvertNoRef(msg);
if (requestMsg)
{
plProfile_BeginTiming(LineOfSight);
plSimulationMgr* sim = plSimulationMgr::GetInstance();
plKey worldKey = requestMsg->fWorldKey;
if (!worldKey)
{
plArmatureMod* av = plAvatarMgr::GetInstance()->GetLocalAvatar();
if ( av && av->GetController() )
worldKey = av->GetController()->GetSubworld();
}
hsPoint3 from = requestMsg->fFrom;
hsPoint3 at = requestMsg->fTo;
// requests are always sent in world space, but they might
// need to be converted to subworld space
hsMatrix44 l2w, w2l;
if (worldKey)
{
plSceneObject* so = plSceneObject::ConvertNoRef(worldKey->ObjectIsLoaded());
if (so)
{
l2w = so->GetLocalToWorld();
w2l = so->GetWorldToLocal();
from = w2l * from;
at = w2l * at;
}
}
else
{
l2w.Reset();
w2l.Reset();
}
NxScene* scene = sim->GetScene(worldKey);
gMyReport.InitCast(requestMsg->GetRequestType(), requestMsg->GetTestType());
hsVector3 norm = hsVector3(at - from);
hsScalar dist = norm.Magnitude();
norm.Normalize();
NxRay worldRay;
worldRay.dir = plPXConvert::Vector(norm);
worldRay.orig = plPXConvert::Point(from);
//PhysX will complain to log if ray distance is less than or equal to Zero, besides shouldn't bother throwing
// a point, and if we have negative we have some serious problems
if(dist>0.0f)
{
scene->raycastAllShapes(worldRay, gMyReport, NX_ALL_SHAPES, 0xffffffff, dist, NX_RAYCAST_DISTANCE | NX_RAYCAST_IMPACT | NX_RAYCAST_NORMAL);
}
else{
SimLog("%s sent out a LOS request with a ray length of %d.", requestMsg->GetSender()->GetName(), dist);
}
if (gMyReport.GotHit())
{
// We got a hit, save off the info
plMessage* hitMsg = ICreateHitMsg(requestMsg, l2w);
if (requestMsg->GetCullDB() != plSimDefs::kLOSDBNone)
{
// If we have a cull db, adjust the length of the raycast to be from the
// original point to the object we hit. If we find anything from the cull
// db in there, the cast fails.
hsScalar dist = gMyReport.GetDistance();
if(dist!=0.0)
{
gMyReport.InitCast(requestMsg->GetCullDB(), plLOSRequestMsg::kTestAny);
scene->raycastAllShapes(worldRay, gMyReport, NX_ALL_SHAPES, 0xffffffff, dist, NX_RAYCAST_DISTANCE | NX_RAYCAST_IMPACT | NX_RAYCAST_NORMAL);
if (gMyReport.GotHit())
{
delete hitMsg;
hitMsg = nil;
if (requestMsg->GetReportType() == plLOSRequestMsg::kReportMiss ||
requestMsg->GetReportType() == plLOSRequestMsg::kReportHitOrMiss)
{
ICreateMissMsg(requestMsg)->Send();
}
}
}
else// we are right on top of the object I assume that means we hit it
{// since PhysX would have complained we will log it anyways. Just so we have a better idea, where this
//was happening previously
SimLog("%s sent out a LOS request. The second cast for culling was of length 0. ABORTING and assuming hit.", requestMsg->GetSender()->GetName());
}
}
if (hitMsg &&
(requestMsg->GetReportType() == plLOSRequestMsg::kReportHit ||
requestMsg->GetReportType() == plLOSRequestMsg::kReportHitOrMiss))
hitMsg->Send();
}
else
{
if (requestMsg->GetReportType() == plLOSRequestMsg::kReportMiss ||
requestMsg->GetReportType() == plLOSRequestMsg::kReportHitOrMiss)
{
ICreateMissMsg(requestMsg)->Send();
}
}
plProfile_EndTiming(LineOfSight);
gMyReport.ResetHitObj();
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
plMessage* plLOSDispatch::ICreateHitMsg(plLOSRequestMsg* requestMsg, hsMatrix44& l2w)
{
plKey ourKey = GetKey();
plKey rcvKey = requestMsg->GetSender();
plLOSHitMsg* hitMsg = TRACKED_NEW plLOSHitMsg(ourKey, rcvKey, nil);
hitMsg->fNoHit = false;
hitMsg->fObj = gMyReport.GetObj();
hitMsg->fDistance = gMyReport.GetDistance();
hitMsg->fNormal = l2w * gMyReport.GetNormal();
hitMsg->fHitPoint = l2w * gMyReport.GetPoint();
hitMsg->fRequestID = requestMsg->GetRequestID();
return hitMsg;
}
plMessage* plLOSDispatch::ICreateMissMsg(plLOSRequestMsg* requestMsg)
{
plKey ourKey = GetKey();
plKey rcvKey = requestMsg->GetSender();
plLOSHitMsg* missMsg = TRACKED_NEW plLOSHitMsg(ourKey, rcvKey, nil);
missMsg->fNoHit = true;
missMsg->fObj = nil;
missMsg->fRequestID = requestMsg->GetRequestID();
return missMsg;
}

View File

@ -0,0 +1,67 @@
/*==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 "../pnKeyedObject/hsKeyedObject.h"
class plLOSRequestMsg;
struct hsMatrix44;
/** \class plLOSDispatch
Line-of-sight requests are sent to this guy, who then hands them
to the appropriate solvers, which can vary depending on such
criteria as which subworld the player is currently in.
Eventually we will have more variants of requests, such as
"search all subworlds," etc. */
class plLOSDispatch : public hsKeyedObject
{
public:
plLOSDispatch();
~plLOSDispatch();
CLASSNAME_REGISTER(plLOSDispatch);
GETINTERFACE_ANY(plLOSDispatch, hsKeyedObject);
virtual hsBool MsgReceive(plMessage* msg);
protected:
plMessage* ICreateHitMsg(plLOSRequestMsg* requestMsg, hsMatrix44& l2w);
plMessage* ICreateMissMsg(plLOSRequestMsg* requestMsg);
};

View File

@ -0,0 +1,82 @@
/*==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 "plPXConvert.h"
bool plPXConvert::Validate()
{
NxVec3 nxVec;
hsVector3 plVec;
int nxVecXOffset = ((char*)&nxVec.x) - ((char*)&nxVec);
int nxVecYOffset = ((char*)&nxVec.y) - ((char*)&nxVec);
int nxVecZOffset = ((char*)&nxVec.z) - ((char*)&nxVec);
int plVecXOffset = ((char*)&plVec.fX) - ((char*)&plVec);
int plVecYOffset = ((char*)&plVec.fY) - ((char*)&plVec);
int plVecZOffset = ((char*)&plVec.fZ) - ((char*)&plVec);
NxQuat nxQuat;
hsQuat plQuat;
int nxQuatXOffset = ((char*)&nxQuat.x) - ((char*)&nxQuat);
int nxQuatYOffset = ((char*)&nxQuat.y) - ((char*)&nxQuat);
int nxQuatZOffset = ((char*)&nxQuat.z) - ((char*)&nxQuat);
int nxQuatWOffset = ((char*)&nxQuat.w) - ((char*)&nxQuat);
int plQuatXOffset = ((char*)&plQuat.fX) - ((char*)&plQuat);
int plQuatYOffset = ((char*)&plQuat.fY) - ((char*)&plQuat);
int plQuatZOffset = ((char*)&plQuat.fZ) - ((char*)&plQuat);
int plQuatWOffset = ((char*)&plQuat.fW) - ((char*)&plQuat);
bool offsetsOK =
nxVecXOffset == plVecXOffset &&
nxVecYOffset == plVecYOffset &&
nxVecZOffset == plVecZOffset &&
nxQuatXOffset == plQuatXOffset &&
nxQuatYOffset == plQuatYOffset &&
nxQuatZOffset == plQuatZOffset &&
nxQuatWOffset == plQuatWOffset;
hsAssert(offsetsOK, "PhysX or Plasma offsets have changed, need to rewrite conversion code");
return offsetsOK;
}

View File

@ -0,0 +1,79 @@
/*==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 plPXConvert_h_inc
#define plPXConvert_h_inc
#include "hsGeometry3.h"
#include "hsQuat.h"
#include "hsMatrix44.h"
#include "NxVec3.h"
#include "NxQuat.h"
#include "NxMat34.h"
// Converts to and from the PhysX types
namespace plPXConvert
{
// The following conversions are just casts, due to the fact that the Plasma
// and PhysX vector and quat classes don't have any virtual fuctions and have
// all their data in the same offsets.
inline NxVec3& Point(hsPoint3& vec) { return *((NxVec3*)&vec); }
inline const NxVec3& Point(const hsPoint3& vec) { return *((NxVec3*)&vec); }
inline hsPoint3& Point(NxVec3& vec) { return *((hsPoint3*)&vec); }
inline const hsPoint3& Point(const NxVec3& vec) { return *((hsPoint3*)&vec); }
inline NxVec3& Vector(hsVector3& vel) { return *((NxVec3*)&vel); }
inline const NxVec3& Vector(const hsVector3& vel){ return *((NxVec3*)&vel); }
inline hsVector3& Vector(NxVec3& vec) { return *((hsVector3*)&vec); }
inline const hsVector3& Vector(const NxVec3& vec) { return *((hsVector3*)&vec); }
inline const NxQuat& Quat(const hsQuat& quat) { return *((NxQuat*)&quat); }
inline const hsQuat& Quat(const NxQuat& quat) { return *((hsQuat*)&quat); }
// The matrix data doesn't match up, so we have to convert it
inline void Matrix(const hsMatrix44& fromMat, NxMat34& toMat) { toMat.setRowMajor44(&fromMat.fMap[0][0]); }
inline void Matrix(const NxMat34& fromMat, hsMatrix44& toMat) { toMat.NotIdentity(); fromMat.getRowMajor44(&toMat.fMap[0][0]); }
bool Validate();
};
#endif // plPXConvert_h_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
/*==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 plPXPhysical_h_inc
#define plPXPhysical_h_inc
#include "plPhysical.h"
#include "hsMatrix44.h"
#include "../plPhysical/plSimDefs.h"
#include "hsBitVector.h"
#include "hsUtils.h"
class NxActor;
class NxConvexMesh;
class NxTriangleMesh;
struct hsPoint3;
class hsQuat;
class plPhysicalProxy;
class plDrawableSpans;
class hsGMaterial;
struct hsPlane3;
class plMessage;
class plLOSHit;
class plSimulationMsg;
class plSDLModifier;
class plPhysicalSndGroup;
class plGenRefMsg;
class plSceneObject;
class hsVectorStream;
class NxCapsule;
class PhysRecipe
{
public:
PhysRecipe();
hsScalar mass;
hsScalar friction;
hsScalar restitution;
plSimDefs::Bounds bounds;
plSimDefs::Group group;
UInt32 reportsOn;
plKey objectKey;
plKey sceneNode;
plKey worldKey;
// The local to subworld matrix (or local to world if worldKey is nil)
hsMatrix44 l2s;
NxConvexMesh* convexMesh;
NxTriangleMesh* triMesh;
// For spheres only
hsScalar radius;
hsPoint3 offset;
// For Boxes
hsPoint3 bDimensions;
hsPoint3 bOffset;
// For export time only. The original data used to create the mesh
hsVectorStream* meshStream;
};
class plPXPhysical : public plPhysical
{
public:
friend class plSimulationMgr;
enum PhysRefType
{
kPhysRefWorld,
kPhysRefSndGroup
};
plPXPhysical();
virtual ~plPXPhysical();
CLASSNAME_REGISTER(plPXPhysical);
GETINTERFACE_ANY(plPXPhysical, plPhysical);
// Export time and internal use only
hsBool Init(PhysRecipe& recipe);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
//
// From plPhysical
//
virtual plPhysical& SetProperty(int prop, hsBool b);
virtual hsBool GetProperty(int prop) const { return fProps.IsBitSet(prop) != 0; }
virtual void SetObjectKey(plKey key) { fObjectKey = key; }
virtual plKey GetObjectKey() const { return fObjectKey; }
virtual void SetSceneNode(plKey node);
virtual plKey GetSceneNode() const;
virtual hsBool GetLinearVelocitySim(hsVector3& vel) const;
virtual void SetLinearVelocitySim(const hsVector3& vel);
virtual void ClearLinearVelocity();
virtual hsBool GetAngularVelocitySim(hsVector3& vel) const;
virtual void SetAngularVelocitySim(const hsVector3& vel);
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l, hsBool force=false);
virtual void GetTransform(hsMatrix44& l2w, hsMatrix44& w2l);
virtual int GetGroup() const { return fGroup; }
virtual void AddLOSDB(UInt16 flag) { hsSetBits(fLOSDBs, flag); }
virtual void RemoveLOSDB(UInt16 flag) { hsClearBits(fLOSDBs, flag); }
virtual UInt16 GetAllLOSDBs() { return fLOSDBs; }
virtual hsBool IsInLOSDB(UInt16 flag) { return hsCheckBits(fLOSDBs, flag); }
virtual hsBool DoDetectorHullWorkaround() { return fSaveTriangles ? true : false; }
virtual hsBool Should_I_Trigger(hsBool enter, hsPoint3& pos);
virtual hsBool IsObjectInsideHull(const hsPoint3& pos);
virtual void SetInsideConvexHull(hsBool inside) { fInsideConvexHull = inside; }
virtual plKey GetWorldKey() const { return fWorldKey; }
virtual plPhysicalSndGroup* GetSoundGroup() const { return fSndGroup; }
virtual void GetPositionSim(hsPoint3& pos) const { IGetPositionSim(pos); }
virtual void SendNewLocation(hsBool synchTransform = false, hsBool isSynchUpdate = false);
virtual void SetHitForce(const hsVector3& force, const hsPoint3& pos) { fWeWereHit=true; fHitForce = force; fHitPos = pos; }
virtual void ApplyHitForce();
virtual void ResetHitForce() { fWeWereHit=false; fHitForce.Set(0,0,0); fHitPos.Set(0,0,0); }
virtual void GetSyncState(hsPoint3& pos, hsQuat& rot, hsVector3& linV, hsVector3& angV);
virtual void SetSyncState(hsPoint3* pos, hsQuat* rot, hsVector3* linV, hsVector3* angV);
virtual void ExcludeRegionHack(hsBool cleared);
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
hsBool DoReportOn(plSimDefs::Group group) const { return hsCheckBits(fReportsOn, 1<<group); }
// Returns true if this object is *really* dynamic. We can have physicals
// that are in the dynamic group but are actually animated or something.
// This weeds those out.
hsBool IsDynamic() const;
//Hack to check if there is an overlap with the capsule
//this partially for exclude regions vs avatar capsule
virtual hsBool OverlapWithCapsule(NxCapsule& cap);
virtual hsScalar GetMass() {return fMass;}
protected:
class NxConvexMesh* IReadHull(hsStream* s);
class NxTriangleMesh* IReadTriMesh(hsStream* s);
void IGetPositionSim(hsPoint3& pos) const;
void IGetRotationSim(hsQuat& rot) const;
void ISetPositionSim(const hsPoint3& pos);
void ISetRotationSim(const hsQuat& rot);
/** Handle messages about our references. */
hsBool HandleRefMsg(plGenRefMsg * refM);
/////////////////////////////////////////////////////////////
//
// WORLDS, SUBWORLDS && CONTEXTS
//
/////////////////////////////////////////////////////////////
void IConvertGroups(UInt32 memberOf, UInt32 reportsOn, UInt32 collideWith);
/** See if the object is in a valid, non-overlapping position.
A valid overlap is one which is approved by the collision
masking code, i.e. my memberOf has no intersection with your
bounceOff and vice-versa
*/
// Set overlapText to get a string naming all the overlapping physicals (that you must delete)
hsBool CheckValidPosition(char** overlapText=nil);
/////////////////////////////////////////////////////////////
//
// NETWORK SYNCHRONIZATION
//
/////////////////////////////////////////////////////////////
/** Remember that we need to do a synch soon. */
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags );
double GetLastSyncTime() { return fLastSyncTime; }
/** Get the simulation transform of the physical, in world
coordinates (factoring in the subworld if necessary */
void IGetTransformGlobal(hsMatrix44 &l2w) const;
void ISetTransformGlobal(const hsMatrix44& l2w);
// Enable/disable collisions and dynamic movement
void IEnable(hsBool enable);
void IMakeHull(NxConvexMesh* convexMesh, hsMatrix44 l2w);
NxActor* fActor;
plKey fWorldKey; // either a subworld or nil
plSimDefs::Bounds fBoundsType;
plSimDefs::Group fGroup;
UInt32 fReportsOn; // bit vector for groups we report interactions with
UInt16 fLOSDBs; // Which LOS databases we get put into
hsBitVector fProps; // plSimulationInterface::plSimulationProperties kept here
float fMass;
plKey fObjectKey; // the key to our scene object
plKey fSceneNode; // the room we're in
// PHYSX FIXME - need to create a plasma hull so that we can determine if inside
hsPlane3* fWorldHull;
UInt32 fHullNumberPlanes;
hsPoint3* fSaveTriangles;
hsBool fInsideConvexHull;
void ISetHullToWorldWTriangles();
inline hsBool ITestPlane(const hsPoint3 &pos, const hsPlane3 &plane)
{
hsScalar dis = plane.fN.InnerProduct(pos);
dis += plane.fD;
if (dis == 0.f)
return false;
if( dis >= 0.f )
return false;
return true;
}
// we need to remember the last matrices we sent to the coordinate interface
// so that we can recognize them when we send them back and not reapply them,
// which would reactivate our body. inelegant but effective
hsMatrix44 fCachedLocal2World;
// Syncronization
double fLastSyncTime;
plSDLModifier* fSDLMod;
plPhysicalSndGroup* fSndGroup;
hsBool fWeWereHit;
hsVector3 fHitForce;
hsPoint3 fHitPos;
plPhysicalProxy* fProxyGen; // visual proxy for debugging
static int fNumberAnimatedPhysicals;
static int fNumberAnimatedActivators;
};
#endif

View File

@ -0,0 +1,882 @@
/*==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 "plPXPhysicalControllerCore.h"
#include "plSimulationMgr.h"
#include "plPXPhysical.h"
#include "plPXConvert.h"
#include "../pnSceneObject/plSimulationInterface.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plAvatar/plArmatureMod.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../plDrawable/plDrawableGenerator.h"
#include "../plPhysical/plPhysicalProxy.h"
#include "../pnMessage/plSetNetGroupIDMsg.h"
#include "../plMessage/plCollideMsg.h"
#include "../plModifier/plDetectorLog.h"
#include "../plSurface/hsGMaterial.h" // For our proxy
#include "../plSurface/plLayerInterface.h" // For our proxy
#include "NxPhysics.h"
#include "NxCapsuleController.h"
#include "NxCapsuleShape.h"
#include "ControllerManager.h"
static ControllerManager gControllerMgr;
static std::vector<plPXPhysicalControllerCore*> gControllers;
static bool gRebuildCache = false;
#ifndef PLASMA_EXTERNAL_RELEASE
hsBool plPXPhysicalControllerCore::fDebugDisplay = false;
#endif // PLASMA_EXTERNAL_RELEASE
int plPXPhysicalControllerCore::fPXControllersMax = 0;
#define kCCTSkinWidth 0.1f
#define kCCTStepOffset 0.7f
#define kCCTZOffset ((fRadius + (fHeight / 2)) + kCCTSkinWidth)
#define kPhysHeightCorrection 0.8f
#define kPhysZOffset ((kCCTZOffset + (kPhysHeightCorrection / 2)) - 0.05f)
#define kAvatarMass 200.0f
static class PXControllerHitReport : public NxUserControllerHitReport
{
public:
virtual NxControllerAction onShapeHit(const NxControllerShapeHit& hit)
{
plPXPhysicalControllerCore* controller = (plPXPhysicalControllerCore*)hit.controller->getUserData();
NxActor& actor = hit.shape->getActor();
plPXPhysical* phys = (plPXPhysical*)actor.userData;
hsVector3 normal = plPXConvert::Vector(hit.worldNormal);
#ifndef PLASMA_EXTERNAL_RELEASE
plDbgCollisionInfo info;
info.fNormal = normal;
info.fSO = plSceneObject::ConvertNoRef(phys->GetObjectKey()->ObjectIsLoaded());
NxCapsule capsule;
controller->GetWorldSpaceCapsule(capsule);
info.fOverlap = hit.shape->checkOverlapCapsule(capsule);
controller->fDbgCollisionInfo.Append(info);
#endif PLASMA_EXTERNAL_RELEASE
// If the avatar hit a movable physical, apply some force to it.
if (actor.isDynamic())
{
if (!actor.readBodyFlag(NX_BF_KINEMATIC) && !actor.readBodyFlag(NX_BF_FROZEN))
{
// Don't apply force when standing on top of an object.
if (normal.fZ < 0.85f)
{
hsVector3 velocity = controller->GetLinearVelocity();
velocity.fZ = 0.0f;
float length = velocity.Magnitude();
if (length > 0)
{
// Only allow horizontal pushes for now
NxVec3 hitDir = hit.worldPos - hit.controller->getPosition();
hitDir.z = 0.0f;
hitDir.normalize();
// Get controller speed along the hitDir
float cctProj = velocity.fX * hitDir.x + velocity.fY * hitDir.y;
length = length + cctProj / 2.0f;
// Get hit actors speed along the hitDir
float hitProj = actor.getLinearVelocity().dot(hitDir);
if (hitProj > 0)
length -= hitProj;
length *= kAvatarMass;
hsPoint3 pos((float)hit.worldPos.x, (float)hit.worldPos.y, (float)hit.worldPos.z);
phys->SetHitForce(plPXConvert::Vector(hitDir * length), pos);
controller->AddDynamicHit(phys);
}
}
}
}
else // else if the avatar hit a static
{
controller->fMovementStrategy->AddContactNormals(normal);
return NX_ACTION_NONE;
}
if (phys && phys->GetProperty(plSimulationInterface::kAvAnimPushable))
{
hsQuat inverseRotation = controller->fLocalRotation.Inverse();
hsVector3 normal = plPXConvert::Vector(hit.worldNormal);
controller->SetPushingPhysical(phys);
controller->SetFacingPushingPhysical((inverseRotation.Rotate(&kAvatarForward).InnerProduct(normal) < 0 ? true : false));
}
return NX_ACTION_NONE;
}
virtual NxControllerAction onControllerHit(const NxControllersHit& hit)
{
return NX_ACTION_NONE;
}
} gControllerHitReport;
plPhysicalControllerCore* plPhysicalControllerCore::Create(plKey ownerSO, hsScalar height, hsScalar width, bool human)
{
if (!plPXPhysicalControllerCore::fPXControllersMax || gControllers.size() < plPXPhysicalControllerCore::fPXControllersMax)
{
hsScalar radius = width / 2.0f;
hsScalar realHeight = height - width;
return TRACKED_NEW plPXPhysicalControllerCore(ownerSO, realHeight, radius, human);
}
return nil;
}
plPXPhysicalControllerCore::plPXPhysicalControllerCore(plKey ownerSO, hsScalar height, hsScalar radius, bool human)
: plPhysicalControllerCore(ownerSO, height, radius),
fController(nil),
fActor(nil),
fProxyGen(nil),
fKinematicCCT(true),
fHuman(human)
{
ICreateController(fLocalPosition);
fActor->raiseActorFlag(NX_AF_DISABLE_COLLISION);
gControllers.push_back(this);
}
plPXPhysicalControllerCore::~plPXPhysicalControllerCore()
{
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
if (gControllers[i] == this)
{
gControllers.erase(gControllers.begin()+i);
break;
}
}
IDeleteController();
// Release any queued messages we may have
int numMsgs = fQueuedCollideMsgs.size();
if (numMsgs)
{
for (int i = 0; i < numMsgs; ++i)
delete fQueuedCollideMsgs[i];
fQueuedCollideMsgs.clear();
}
delete fProxyGen;
}
void plPXPhysicalControllerCore::Enable(bool enable)
{
if (fEnabled != enable)
{
fEnabled = enable;
if (fEnabled)
{
// Defer until the next physics update.
fEnableChanged = true;
}
else
{
if (!fKinematicCCT)
{
// Dynamic controllers are forced kinematic
fActor->raiseBodyFlag(NX_BF_KINEMATIC);
NxShape* shape = fActor->getShapes()[0];
shape->setGroup(plSimDefs::kGroupAvatarKinematic);
}
}
}
}
void plPXPhysicalControllerCore::SetSubworld(plKey world)
{
if (fWorldKey != world)
{
SimLog("Changing subworlds!");
// Inform detectors in the old world that we are leaving
IInformDetectors(false);
IDeleteController();
// We need our real global location here, not the interpolated location
fLocalRotation.MakeMatrix(&fLastGlobalLoc);
fLastGlobalLoc.SetTranslate(&fLocalPosition);
if (fWorldKey)
{
hsMatrix44 prevSubL2W;
fPrevSubworldW2L.GetInverse(&prevSubL2W);
fLastGlobalLoc = prevSubL2W * fLastGlobalLoc;
}
// Update our scene object so the change isn't wiped out
plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
if (so)
{
hsMatrix44 globalLocInv;
fLastGlobalLoc.GetInverse(&globalLocInv);
so->SetTransform(fLastGlobalLoc, globalLocInv);
so->FlushTransform();
}
// Update Local Position and rotation
fWorldKey = world;
const plCoordinateInterface* subworldCI = GetSubworldCI();
if (subworldCI)
{
fPrevSubworldW2L = subworldCI->GetWorldToLocal();
hsMatrix44 l2s = fPrevSubworldW2L * fLastGlobalLoc;
l2s.GetTranslate(&fLocalPosition);
fLocalRotation.SetFromMatrix44(l2s);
}
else
{
fPrevSubworldW2L.Reset();
fLastGlobalLoc.GetTranslate(&fLocalPosition);
fLocalRotation.SetFromMatrix44(fLastGlobalLoc);
}
fLastLocalPosition = fLocalPosition;
// Create new controller
ICreateController(fLocalPosition);
RebuildCache();
}
}
void plPXPhysicalControllerCore::GetState(hsPoint3& pos, float& zRot)
{
// Temporarily use the position point while we get the z rotation
fLocalRotation.NormalizeIfNeeded();
fLocalRotation.GetAngleAxis(&zRot, (hsVector3*)&pos);
if (pos.fZ < 0)
zRot = (2 * hsScalarPI) - zRot; // axis is backwards, so reverse the angle too
pos = fLocalPosition;
}
void plPXPhysicalControllerCore::SetState(const hsPoint3& pos, float zRot)
{
plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
if (so)
{
hsQuat worldRot;
hsVector3 zAxis(0.f, 0.f, 1.f);
worldRot.SetAngleAxis(zRot, zAxis);
hsMatrix44 l2w, w2l;
worldRot.MakeMatrix(&l2w);
l2w.SetTranslate(&pos);
// Localize new position and rotation to global coords if we're in a subworld
const plCoordinateInterface* ci = GetSubworldCI();
if (ci)
{
const hsMatrix44& subworldL2W = ci->GetLocalToWorld();
l2w = subworldL2W * l2w;
}
l2w.GetInverse(&w2l);
so->SetTransform(l2w, w2l);
so->FlushTransform();
}
}
void plPXPhysicalControllerCore::SetMovementStrategy(plMovementStrategy* strategy)
{
if (fKinematicCCT != strategy->IsKinematic())
{
IDeleteController();
fKinematicCCT = !fKinematicCCT;
ICreateController(fLocalPosition);
}
fMovementStrategy = strategy;
}
void plPXPhysicalControllerCore::SetGlobalLoc(const hsMatrix44& l2w)
{
fLastGlobalLoc = l2w;
// Update our local position and rotation
hsPoint3 prevPosition = fLocalPosition;
const plCoordinateInterface* subworldCI = GetSubworldCI();
if (subworldCI)
{
hsMatrix44 l2s = fPrevSubworldW2L * l2w;
l2s.GetTranslate(&fLocalPosition);
fLocalRotation.SetFromMatrix44(l2s);
}
else
{
l2w.GetTranslate(&fLocalPosition);
fLocalRotation.SetFromMatrix44(l2w);
}
fLastLocalPosition = fLocalPosition;
if (fProxyGen)
{
hsMatrix44 w2l;
l2w.GetInverse(&w2l);
fProxyGen->SetTransform(l2w, w2l);
}
// Update the physical position
if (fKinematicCCT)
{
hsVector3 disp(&fLocalPosition, &prevPosition);
if (disp.Magnitude() > 2.f)
{
// Teleport the underlying actor most of the way
disp.Normalize();
disp *= 0.001f;
hsPoint3 teleportPos = fLocalPosition - disp;
NxVec3 pos(teleportPos.fX, teleportPos.fY, teleportPos.fZ + kPhysZOffset);
fActor->setGlobalPosition(pos);
}
NxExtendedVec3 extPos(fLocalPosition.fX, fLocalPosition.fY, fLocalPosition.fZ + kCCTZOffset);
fController->setPosition(extPos);
}
else
{
NxVec3 pos(fLocalPosition.fX, fLocalPosition.fY, fLocalPosition.fZ + kPhysZOffset);
if (fActor->readBodyFlag(NX_BF_KINEMATIC))
fActor->moveGlobalPosition(pos);
else
fActor->setGlobalPosition(pos);
}
}
void plPXPhysicalControllerCore::GetPositionSim(hsPoint3& pos)
{
if (fKinematicCCT)
{
const NxExtendedVec3& extPos = fController->getPosition();
pos.Set((hsScalar)extPos.x, (hsScalar)extPos.y, (hsScalar)extPos.z - kCCTZOffset);
}
else
{
NxVec3 nxPos = fActor->getGlobalPosition();
pos.Set(nxPos.x, nxPos.y, nxPos.z - kPhysZOffset);
}
}
void plPXPhysicalControllerCore::Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)
{
NxU32 colFlags = 0;
fController->move(plPXConvert::Vector(displacement), collideWith, 0.00001f, colFlags);
collisionResults = 0;
if (colFlags & NXCC_COLLISION_DOWN)
collisionResults |= kBottom;
if (colFlags & NXCC_COLLISION_UP)
collisionResults |= kTop;
if (colFlags & NXCC_COLLISION_SIDES)
collisionResults |= kSides;
}
void plPXPhysicalControllerCore::SetLinearVelocitySim(const hsVector3& linearVel)
{
if (!fKinematicCCT)
{
NxVec3 vel = plPXConvert::Vector(linearVel);
fActor->setLinearVelocity(vel);
}
}
int plPXPhysicalControllerCore::SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics,
UInt32& vsSimGroups, std::vector<plControllerSweepRecord>& hits)
{
NxSweepQueryHit queryHit[10];
unsigned int flags = NX_SF_ALL_HITS;
if (vsDynamics)
flags |= NX_SF_DYNAMICS;
if (vsStatics)
flags |= NX_SF_STATICS;
NxVec3 vec;
vec.x = endPos.fX - startPos.fX;
vec.y = endPos.fY - startPos.fY;
vec.z = endPos.fZ - startPos.fZ;
NxShape* shape = fActor->getShapes()[0];
NxCapsuleShape* capShape = shape->isCapsule();
float radius = capShape->getRadius();
float height = capShape->getHeight();
NxCapsule capsule;
capsule.p0 = plPXConvert::Point(startPos);
capsule.p0.z = capsule.p0.z + radius;
capsule.radius = radius;
capsule.p1 = capsule.p0;
capsule.p1.z = capsule.p1.z + height;
NxScene *scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
int numHits = scene->linearCapsuleSweep(capsule, vec, flags, nil, 10, queryHit, nil, vsSimGroups);
if (numHits)
{
for (int i = 0; i < numHits; ++i)
{
plControllerSweepRecord currentHit;
currentHit.ObjHit = (plPhysical*)queryHit[i].hitShape->getActor().userData;
if (currentHit.ObjHit)
{
currentHit.Point = plPXConvert::Point(queryHit[i].point);
currentHit.Normal = plPXConvert::Vector(queryHit[i].normal);
hits.push_back(currentHit);
}
}
}
return hits.size();
}
void plPXPhysicalControllerCore::LeaveAge()
{
SetPushingPhysical(nil);
if (fWorldKey)
SetSubworld(nil);
// Disable all collisions
fActor->raiseActorFlag(NX_AF_DISABLE_COLLISION);
}
void plPXPhysicalControllerCore::GetWorldSpaceCapsule(NxCapsule& cap) const
{
NxShape* shape = fActor->getShapes()[0];
NxCapsuleShape* capShape = shape->isCapsule();
capShape->getWorldCapsule(cap);
}
plDrawableSpans* plPXPhysicalControllerCore::CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo)
{
// FIXME
plDrawableSpans* myDraw = addTo;
hsBool blended = ((mat->GetLayer(0)->GetBlendFlags() & hsGMatState::kBlendMask));
float radius = fRadius;
myDraw = plDrawableGenerator::GenerateSphericalDrawable(fLocalPosition, radius,
mat, fLastGlobalLoc, blended,
nil, &idx, myDraw);
/*
plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
if (so)
{
hsBool blended = ((mat->GetLayer(0)->GetBlendFlags() & hsGMatState::kBlendMask));
myDraw = plDrawableGenerator::GenerateConicalDrawable(fRadius*10, fHeight*10,
mat, so->GetLocalToWorld(), blended,
nil, &idx, myDraw);
}
*/
return myDraw;
}
void plPXPhysicalControllerCore::AddDynamicHit(plPXPhysical* phys)
{
int numHits = fDynamicHits.size();
for (int i = 0; i < numHits; ++i)
{
if (fDynamicHits[i] == phys)
return;
}
fDynamicHits.push_back(phys);
}
void plPXPhysicalControllerCore::Apply(hsScalar delSecs)
{
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
if (gRebuildCache && controller->fController)
controller->fController->reportSceneChanged();
#ifndef PLASMA_EXTERNAL_RELEASE
controller->fDbgCollisionInfo.SetCount(0);
#endif
controller->IDispatchQueuedMsgs();
controller->IApply(delSecs);
controller->IProcessDynamicHits();
}
gRebuildCache = false;
}
void plPXPhysicalControllerCore::Update(int numSubSteps, hsScalar alpha)
{
gControllerMgr.updateControllers();
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
controller->IUpdate(numSubSteps, alpha);
#ifndef PLASMA_EXTERNAL_RELEASE
if (fDebugDisplay)
controller->IDrawDebugDisplay();
#endif
}
}
void plPXPhysicalControllerCore::UpdateNonPhysical(hsScalar alpha)
{
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
controller->IUpdateNonPhysical(alpha);
}
}
void plPXPhysicalControllerCore::RebuildCache() { gRebuildCache = true; }
plPXPhysicalControllerCore* plPXPhysicalControllerCore::GetController(NxActor& actor)
{
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
if (controller->fActor == &actor)
return controller;
}
return nil;
}
bool plPXPhysicalControllerCore::AnyControllersInThisWorld(plKey world)
{
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
if (controller->GetSubworld() == world)
return true;
}
return false;
}
int plPXPhysicalControllerCore::GetNumberOfControllersInThisSubWorld(plKey world)
{
int count = 0;
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
if (controller->GetSubworld() == world)
++count;
}
return count;
}
int plPXPhysicalControllerCore::GetControllersInThisSubWorld(plKey world, int maxToReturn, plPXPhysicalControllerCore** bufferout)
{
int count = 0;
plPXPhysicalControllerCore* controller;
int numControllers = gControllers.size();
for (int i = 0; i < numControllers; ++i)
{
controller = gControllers[i];
if (controller->GetSubworld() == world)
{
if (count < maxToReturn)
{
bufferout[count] = controller;
++count;
}
}
}
return count;
}
int plPXPhysicalControllerCore::NumControllers() { return gControllers.size(); }
void plPXPhysicalControllerCore::IHandleEnableChanged()
{
// Defered enable
fEnableChanged = false;
if (!fKinematicCCT)
{
// Restore dynamic controller
fActor->clearBodyFlag(NX_BF_KINEMATIC);
NxShape* shape = fActor->getShapes()[0];
shape->setGroup(plSimDefs::kGroupAvatar);
}
// Enable actor collisions
if (fActor->readActorFlag(NX_AF_DISABLE_COLLISION))
fActor->clearActorFlag(NX_AF_DISABLE_COLLISION);
}
void plPXPhysicalControllerCore::IInformDetectors(bool entering)
{
static const NxU32 kDetectorFlag = 1<<plSimDefs::kGroupDetector;
static const int kNumShapes = 30;
DetectorLog("Informing from plPXPhysicalControllerCore::IInformDetectors");
NxShape* shapes[kNumShapes];
NxCapsule capsule;
GetWorldSpaceCapsule(capsule);
NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
int numCollided = scene->overlapCapsuleShapes(capsule, NX_ALL_SHAPES, kNumShapes, shapes, NULL, kDetectorFlag, NULL, true);
for (int i = 0; i < numCollided; ++i)
{
plPXPhysical* physical = (plPXPhysical*)shapes[i]->getActor().userData;
if (physical && physical->DoReportOn(plSimDefs::kGroupAvatar))
{
plCollideMsg* msg = TRACKED_NEW plCollideMsg();
msg->fOtherKey = fOwner;
msg->fEntering = entering;
msg->AddReceiver(physical->GetObjectKey());
// Queue until the next sim step
fQueuedCollideMsgs.push_back(msg);
}
}
DetectorLog("Done informing from plPXPhysicalControllerCore::IInformDetectors");
}
void plPXPhysicalControllerCore::ICreateController(const hsPoint3& pos)
{
NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
if (fKinematicCCT)
{
// Use PhysX character controller
NxCapsuleControllerDesc desc;
desc.position.x = pos.fX;
desc.position.y = pos.fY;
desc.position.z = pos.fZ + kCCTZOffset;
desc.upDirection = NX_Z;
desc.slopeLimit = kSlopeLimit;
desc.skinWidth = kCCTSkinWidth;
desc.stepOffset = kCCTStepOffset;
desc.callback = &gControllerHitReport;
desc.userData = this;
desc.radius = fRadius;
desc.height = fHeight;
desc.interactionFlag = NXIF_INTERACTION_EXCLUDE;
fController = (NxCapsuleController*)gControllerMgr.createController(scene, desc);
fActor = fController->getActor();
// Set the actor group - Dynamics are in group 1 and will report on everything in group 0.
// We don't want notifications
fActor->setGroup(2);
// Set the shape group. Not used by the NxController itself,
// But required for correct group interactions in the simulation.
NxShape* shape = fActor->getShapes()[0];
shape->setGroup(plSimDefs::kGroupAvatarKinematic);
// In PhysX 2, the kinematic actors scale factor isn't exposed.
// It is hardcoded at 0.8 which doesn't suit, so we have to manually adjust its dimensions.
float kineRadius = fRadius + kCCTSkinWidth;
float kineHeight = fHeight;
NxCapsuleShape* capShape = shape->isCapsule();
if (fHuman)
{
kineHeight += kPhysHeightCorrection;
capShape->setLocalPosition(NxVec3(0.0f, (kPhysHeightCorrection / 2.0f), 0.0f));
}
capShape->setDimensions(kineRadius, kineHeight);
}
else
{
// Use dynamic actor for the character controller
NxCapsuleShapeDesc capDesc;
capDesc.materialIndex = plSimulationMgr::GetInstance()->GetMaterialIdx(scene, 0.0f, 0.0f);
capDesc.radius = fRadius + kCCTSkinWidth;
capDesc.height = fHeight + kPhysHeightCorrection;
NxBodyDesc bodyDesc;
bodyDesc.mass = kAvatarMass;
bodyDesc.flags = NX_BF_DISABLE_GRAVITY;
bodyDesc.flags |= NX_BF_FROZEN_ROT;
if (fEnabled)
capDesc.group = plSimDefs::kGroupAvatar;
else
{
bodyDesc.flags |= NX_BF_KINEMATIC;
capDesc.group = plSimDefs::kGroupAvatarKinematic;
}
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&capDesc);
actorDesc.body = &bodyDesc;
actorDesc.group = 2;
actorDesc.globalPose.M.rotX(NxHalfPiF32);
actorDesc.globalPose.t.x = pos.fX;
actorDesc.globalPose.t.y = pos.fY;
actorDesc.globalPose.t.z = pos.fZ + kPhysZOffset;
fActor = scene->createActor(actorDesc);
}
fSeeking = false;
// Create proxy for the debug display
/* FIXME
// the avatar proxy doesn't seem to work... not sure why?
hsColorRGBA physColor;
hsScalar opac = 1.0f;
// local avatar is light purple and transparent
physColor.Set(.2f, .1f, .2f, 1.f);
opac = 0.8f;
fProxyGen = TRACKED_NEW plPhysicalProxy(hsColorRGBA().Set(0,0,0,1.f), physColor, opac);
fProxyGen->Init(this);
*/
}
void plPXPhysicalControllerCore::IDeleteController()
{
if (fKinematicCCT)
{
gControllerMgr.releaseController(*fController);
fController = nil;
}
else
{
NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
scene->releaseActor(*fActor);
}
fActor = nil;
plSimulationMgr::GetInstance()->ReleaseScene(fWorldKey);
}
void plPXPhysicalControllerCore::IDispatchQueuedMsgs()
{
int numMsgs = fQueuedCollideMsgs.size();
if (numMsgs)
{
plSimulationMgr* simMgr = plSimulationMgr::GetInstance();
for (int i = 0; i < numMsgs; ++i)
simMgr->AddCollisionMsg(fQueuedCollideMsgs[i]);
fQueuedCollideMsgs.clear();
}
}
void plPXPhysicalControllerCore::IProcessDynamicHits()
{
int numHits = fDynamicHits.size();
if (numHits)
{
plPXPhysical* phys;
plSimulationMgr* simMgr = plSimulationMgr::GetInstance();
for (int i = 0; i < numHits; ++i)
{
phys = fDynamicHits[i];
// If this is the local avatar, we need to take ownership of this dynamic if we haven't already
if (fLOSDB == plSimDefs::kLOSDBLocalAvatar && !phys->IsLocallyOwned() && !phys->GetProperty(plSimulationInterface::kNoOwnershipChange))
{
plSynchedObject* obj = plSynchedObject::ConvertNoRef(phys->GetObjectKey()->ObjectIsLoaded());
obj->SetNetGroupConstant(plNetGroup::kNetGroupLocalPhysicals);
plSetNetGroupIDMsg* setNetGroupID = TRACKED_NEW plSetNetGroupIDMsg;
setNetGroupID->fId = plNetGroup::kNetGroupRemotePhysicals;
setNetGroupID->SetBCastFlag(plMessage::kNetPropagate | plMessage::kNetForce);
setNetGroupID->SetBCastFlag(plMessage::kLocalPropagate, false);
setNetGroupID->Send(obj->GetKey());
}
phys->ApplyHitForce();
simMgr->ConsiderSynch(phys, nil);
}
fDynamicHits.clear();
}
}
#ifndef PLASMA_EXTERNAL_RELEASE
#include "../plPipeline/plDebugText.h"
void plPXPhysicalControllerCore::IDrawDebugDisplay()
{
plDebugText &debugTxt = plDebugText::Instance();
char strBuf[ 2048 ];
int lineHeight = debugTxt.GetFontSize() + 4;
UInt32 scrnWidth, scrnHeight;
debugTxt.GetScreenSize( &scrnWidth, &scrnHeight );
int y = 10;
int x = 10;
sprintf(strBuf, "Controller Count: %d", gControllers.size());
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
debugTxt.DrawString(x, y, "Avatar Collisions:");
y += lineHeight;
int i;
for (i = 0; i < fDbgCollisionInfo.GetCount(); i++)
{
hsVector3 normal = fDbgCollisionInfo[i].fNormal;
char *overlapStr = fDbgCollisionInfo[i].fOverlap ? "yes" : "no";
hsScalar angle = hsScalarRadToDeg(hsACosine(normal * hsVector3(0, 0, 1)));
sprintf(strBuf, " Obj: %s, Normal: (%.2f, %.2f, %.2f), Angle(%.1f), Overlap(%3s)",
fDbgCollisionInfo[i].fSO->GetKeyName(),
normal.fX, normal.fY, normal.fZ, angle, overlapStr);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
}
}
#endif PLASMA_EXTERNAL_RELEASE

View File

@ -0,0 +1,173 @@
/*==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 "../plAvatar/plPhysicalControllerCore.h"
class NxCapsuleController;
class NxActor;
class NxCapsule;
class PXControllerHitReport;
class plPhysicalProxy;
class plDrawableSpans;
class hsGMaterial;
class plSceneObject;
class plPXPhysical;
class plCollideMsg;
#ifndef PLASMA_EXTERNAL_RELEASE
class plDbgCollisionInfo
{
public:
plSceneObject *fSO;
hsVector3 fNormal;
hsBool fOverlap;
};
#endif // PLASMA_EXTERNAL_RELEASE
class plPXPhysicalControllerCore: public plPhysicalControllerCore
{
public:
plPXPhysicalControllerCore(plKey ownerSO, hsScalar height, hsScalar radius, bool human);
~plPXPhysicalControllerCore();
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
// Use plArmatureModBase::EnablePhysics() instead.
virtual void Enable(bool enable);
// Subworld
virtual void SetSubworld(plKey world);
// For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot);
virtual void SetState(const hsPoint3& pos, float zRot);
// Movement strategy
virtual void SetMovementStrategy(plMovementStrategy* strategy);
// Global location
virtual void SetGlobalLoc(const hsMatrix44& l2w);
// Local Sim Position
virtual void GetPositionSim(hsPoint3& pos);
// Move kinematic controller
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
// Set linear velocity on dynamic controller
virtual void SetLinearVelocitySim(const hsVector3& linearVel);
// Sweep the controller path from startPos through endPos
virtual int SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, hsBool vsDynamics,
hsBool vsStatics, UInt32& vsSimGroups, std::vector<plControllerSweepRecord>& hits);
// any clean up for the controller should go here
virtual void LeaveAge();
// Capsule
void GetWorldSpaceCapsule(NxCapsule& cap) const;
// Create Proxy for debug rendering
plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
// Dynamic hits
void AddDynamicHit(plPXPhysical* phys);
//////////////////////////////////////////
//Static Helper Functions
////////////////////////////////////////
// Call pre-sim to apply movement to controllers
static void Apply(hsScalar delSecs);
// Call post-sim to update controllers
static void Update(int numSubSteps, hsScalar alpha);
// Update controllers when not performing a physics step
static void UpdateNonPhysical(hsScalar alpha);
// Rebuild the controller cache, required when a static actor in the scene has changed.
static void RebuildCache();
// Returns the plPXPhysicalControllerCore associated with the given NxActor
static plPXPhysicalControllerCore* GetController(NxActor& actor);
// Subworld controller queries
static bool AnyControllersInThisWorld(plKey world);
static int GetNumberOfControllersInThisSubWorld(plKey world);
static int GetControllersInThisSubWorld(plKey world, int maxToReturn, plPXPhysicalControllerCore** bufferout);
// Controller count
static int NumControllers();
static void SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
static int fPXControllersMax;
#ifndef PLASMA_EXTERNAL_RELEASE
static hsBool fDebugDisplay;
#endif
protected:
friend class PXControllerHitReport;
virtual void IHandleEnableChanged();
void IInformDetectors(bool entering);
void ICreateController(const hsPoint3& pos);
void IDeleteController();
void IDispatchQueuedMsgs();
void IProcessDynamicHits();
#ifndef PLASMA_EXTERNAL_RELEASE
void IDrawDebugDisplay();
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
#endif
std::vector<plCollideMsg*> fQueuedCollideMsgs;
std::vector<plPXPhysical*> fDynamicHits;
NxCapsuleController* fController;
NxActor* fActor;
plPhysicalProxy* fProxyGen;
bool fKinematicCCT;
bool fHuman;
};

View File

@ -0,0 +1,73 @@
/*==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 plPXStream_h_inc
#define plPXStream_h_inc
#include "hsStream.h"
#include "NxPhysics.h"
#include "NxStream.h"
// A super simple wrapper to convert a Plasma stream into a PhysX one
class plPXStream : public NxStream
{
public:
plPXStream(hsStream* s) : fStream(s) {}
virtual NxU8 readByte() const { return fStream->ReadByte(); }
virtual NxU16 readWord() const { return fStream->ReadSwap16(); }
virtual NxU32 readDword() const { return fStream->ReadSwap32(); }
virtual float readFloat() const { return fStream->ReadSwapScalar(); }
virtual double readDouble() const { return fStream->ReadSwapDouble(); }
virtual void readBuffer(void* buffer, NxU32 size) const { fStream->Read(size, buffer); }
virtual NxStream& storeByte(NxU8 b) { fStream->WriteByte(b); return *this; }
virtual NxStream& storeWord(NxU16 w) { fStream->WriteSwap16(w); return *this; }
virtual NxStream& storeDword(NxU32 d) { fStream->WriteSwap32(d); return *this; }
virtual NxStream& storeFloat(NxReal f) { fStream->WriteSwapScalar(f); return *this; }
virtual NxStream& storeDouble(NxF64 f) { fStream->WriteSwapDouble(f); return *this; }
virtual NxStream& storeBuffer(const void* buffer, NxU32 size) { fStream->Write(size, buffer); return *this; }
protected:
hsStream* fStream;
};
#endif // plPXStream_h_inc

View File

@ -0,0 +1,71 @@
/*==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 plPhysXCreatable_inc
#define plPhysXCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plPXPhysical.h"
REGISTER_CREATABLE(plPXPhysical);
//#include "plHKSimulationSynchMsg.h"
//REGISTER_CREATABLE(plHKSimulationSynchMsg);
//#include "plHavokConstraintTools.h"
//REGISTER_NONCREATABLE(plHavokConstraintsMod);
//REGISTER_CREATABLE(plHingeConstraintMod);
//REGISTER_CREATABLE(plStrongSpringConstraintMod);
//REGISTER_CREATABLE(plWheelConstraintMod);
#include "plLOSDispatch.h"
REGISTER_CREATABLE( plLOSDispatch );
#include "plSimulationMgr.h"
REGISTER_CREATABLE( plSimulationMgr );
//#include "plVehicleModifier.h"
//REGISTER_CREATABLE(plVehicleModifier);
#endif // plPhysXCreatable_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
/*==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 plSimulationMgr_H
#define plSimulationMgr_H
#include "hsStlUtils.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsTemplates.h"
class plPXPhysical;
class plLOSDispatch;
class plStatusLog;
class plPhysicsSoundMgr;
class NxPhysicsSDK;
class NxScene;
class plCollideMsg;
struct hsPoint3;
class plSimulationMgr : public hsKeyedObject
{
public:
CLASSNAME_REGISTER(plSimulationMgr);
GETINTERFACE_ANY(plSimulationMgr, hsKeyedObject);
static plSimulationMgr* GetInstance();
static void Init();
static void Shutdown();
static bool fExtraProfile;
static bool fSubworldOptimization;
static bool fDoClampingOnStep;
// initialiation of the PhysX simulation
virtual bool InitSimulation();
// Advance the simulation by the given number of seconds
void Advance(float delSecs);
// The simulation won't run at all if it is suspended
void Suspend() { fSuspended = true; }
void Resume() { fSuspended = false; }
bool IsSuspended() { return fSuspended; }
// Output the given debug text to the simulation log.
static void Log(const char* formatStr, ...);
static void LogV(const char* formatStr, va_list args);
static void ClearLog();
// We've detected a collision, which may be grounds for synchronizing the involved
// physicals over the network.
void ConsiderSynch(plPXPhysical *physical, plPXPhysical *other);
NxPhysicsSDK* GetSDK() const { return fSDK; }
NxScene* GetScene(plKey world);
// Called when an actor is removed from a scene, checks if it's time to delete
// the scene
void ReleaseScene(plKey world);
int GetMaterialIdx(NxScene* scene, hsScalar friction, hsScalar restitution);
UInt32 GetStepCount() { return fStepCount; }
// PHYSX FIXME - walk thru all the convex hull detector regions to see if we are in any... we're either coming or going
void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering);
void UpdateAvatarInDetector(plKey world, plPXPhysical* detector);
//Fix to Move collision messages and their handling out of the simulation step
void AddCollisionMsg(plCollideMsg* msg);
#ifndef PLASMA_EXTERNAL_RELEASE
static bool fDisplayAwakeActors;
#endif //PLASMA_EXTERNAL_RELEASE
protected:
friend class ContactReport;
void ISendUpdates();
plSimulationMgr();
virtual ~plSimulationMgr();
// Set the maximum amount of time (in seconds) that the physics will advance
// between frames. If a frame-to-frame delta is bigger than this, we'll
// clamp it to this value.
// WARNING: animation doesn't do this, so if we clamp the time animated
// physicals and the avatar may move at a faster rate than usual.
void SetMaxDelta(float maxDelta);
float GetMaxDelta() const;
// Set the number of steps per second that physics will advance.
// The more steps per second, the less fallthough and more accurate
// simulation response.
void SetStepsPerSecond(int stepsPerSecond);
int GetStepsPerSecond();
// Walk through the synchronization requests and send them as appropriate.
void IProcessSynchs();
// PHYSX FIXME send a collision message - should only be used with UpdateDetectorsInScene
void ISendCollisionMsg(plKey receiver, plKey hitter, hsBool entering);
NxPhysicsSDK* fSDK;
plPhysicsSoundMgr* fSoundMgr;
//a list of collision messages generated by the simulation steps. Added to by AddCollisionMsg(plCollideMsg* msg)
//cleared by IDispatchCollisionMessages when done
hsTArray<plCollideMsg*> fCollisionMessages;
void IDispatchCollisionMessages();
// A mapping from a key to a PhysX scene. The key is either the
// SimulationMgr key, for the main world, or a SceneObject key if it's a
// subworld.
typedef std::map<plKey, NxScene*> SceneMap;
SceneMap fScenes;
plLOSDispatch* fLOSDispatch;
// Is the entire physics world suspended? If so, the clock can still advance
// but nothing will move.
bool fSuspended;
float fMaxDelta;
float fStepSize;
float fAccumulator;
UInt32 fStepCount;
// A utility class to keep track of a request for a physical synchronization.
// These requests must pass a certain criteria (see the code for the latest)
// before they are actually either sent over the network or rejected.
class SynchRequest
{
public:
double fTime; // when to synch
plKey fKey; // key of the object to be synched, so we can make sure it still lives
static const double kDefaultTime;
SynchRequest() : fTime(kDefaultTime) {};
};
// All currently pending synch requests. Keyed by the physical in question
// so we can quickly eliminate redundant requests, which are very common.
typedef std::map<plPXPhysical*, SynchRequest> PhysSynchMap;
PhysSynchMap fPendingSynchs;
plStatusLog *fLog;
#ifndef PLASMA_EXTERNAL_RELEASE
void IDrawActiveActorList();
#endif //PLASMA_EXTERNAL_RELEASE
};
#define SIM_VERBOSE
#ifdef SIM_VERBOSE
#include <stdarg.h> // only include when we need to call plSimulationMgr::Log
inline void SimLog(const char *str, ...)
{
va_list args;
va_start(args, str);
plSimulationMgr::LogV(str, args);
va_end(args);
}
#else
inline void SimLog(const char *str, ...)
{
// will get stripped out
}
#endif
#endif