/*==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 .
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);
hsBool MsgReceive(plMessage* msg);
// 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);
// 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 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 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;
// 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 PhysSynchMap;
PhysSynchMap fPendingSynchs;
plStatusLog *fLog;
#ifndef PLASMA_EXTERNAL_RELEASE
void IDrawActiveActorList();
#endif //PLASMA_EXTERNAL_RELEASE
};
#define SIM_VERBOSE
#ifdef SIM_VERBOSE
#include // 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