mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
354 lines
12 KiB
C++
354 lines
12 KiB
C++
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
|
|
|
|
#pragma once
|
|
|
|
#include "V8World/Primitive.h"
|
|
#include "V8World/ContactManager.h"
|
|
|
|
#include "Util/IndexArray.h"
|
|
#include "rbx/rbxTime.h"
|
|
#include "rbx/signal.h"
|
|
#include "Util/SpatialRegion.h"
|
|
#include "Util/HeapValue.h"
|
|
#include "util/PhysicalProperties.h"
|
|
|
|
class btCollisionDispatcher;
|
|
class btCollisionWorld;
|
|
class btDefaultCollisionConfiguration;
|
|
namespace RBX {
|
|
|
|
class JointInstance;
|
|
class Joint;
|
|
class Primitive;
|
|
class Clump;
|
|
class Assembly;
|
|
class Region2;
|
|
class PartInstance;
|
|
|
|
namespace Profiling
|
|
{
|
|
class CodeProfiler;
|
|
}
|
|
|
|
struct RootPrimitiveOwnershipData
|
|
{
|
|
RBX::SystemAddress ownerAddress;
|
|
bool ownershipManual;
|
|
Primitive* prim;
|
|
};
|
|
|
|
class Edge;
|
|
class Contact;
|
|
class MotorJoint;
|
|
|
|
// In Assembly.cpp
|
|
void notifyAssemblyPrimitiveMoved(Primitive* p, bool resetContacts);
|
|
|
|
class EThrottle {
|
|
public:
|
|
typedef enum { ThrottleDefaultAuto, ThrottleDisabled, ThrottleAlways, Skip2, Skip4, Skip8, Skip16} EThrottleType;
|
|
|
|
private:
|
|
int requestedSkip;
|
|
int usedSkip;
|
|
static int const throttleSetting[];
|
|
int throttleIndex;
|
|
|
|
public:
|
|
static EThrottleType globalDebugEThrottle;
|
|
|
|
EThrottle();
|
|
|
|
bool computeThrottle(int step);
|
|
|
|
bool increaseLoad(bool increase);
|
|
|
|
float getEnvironmentSpeed() const;
|
|
|
|
int getThrottleIndex() const { return throttleIndex; }
|
|
|
|
void setThrottleIndex(int index) { throttleIndex = index; }
|
|
|
|
};
|
|
|
|
|
|
class World
|
|
{
|
|
friend class ContactManager;
|
|
public:
|
|
rbx::signal<void(Joint*, Primitive*, std::vector<Primitive*>&)> postInsertJointSignal;
|
|
rbx::signal<void(Joint*, std::vector<Primitive*>&, std::vector<Primitive*>&)> postRemoveJointSignal;
|
|
rbx::signal<void(Joint*)> autoJoinSignal;
|
|
rbx::signal<void(Joint*)> autoDestroySignal;
|
|
rbx::signal<void(std::pair<Primitive*, Primitive*>)> primitiveCollideSignal;
|
|
|
|
struct TouchInfo
|
|
{
|
|
Primitive* p1;
|
|
Primitive* p2;
|
|
shared_ptr<PartInstance> pi1;
|
|
shared_ptr<PartInstance> pi2;
|
|
typedef enum { Touch, Untouch } Type;
|
|
Type type;
|
|
};
|
|
|
|
struct OnPrimitiveMovingVisitor
|
|
{
|
|
ContactManager* ptr;
|
|
OnPrimitiveMovingVisitor(ContactManager* p) : ptr(p) { }
|
|
void operator()(Primitive* p) {
|
|
notifyAssemblyPrimitiveMoved(p, true);
|
|
ptr->onPrimitiveExtentsChanged(p);
|
|
}
|
|
};
|
|
|
|
private:
|
|
|
|
int frmThrottle;
|
|
EThrottle eThrottle;
|
|
|
|
G3D::Array<TouchInfo> touchReporting;
|
|
|
|
bool inStepCode; // debugging
|
|
Joint* inJointNotification;
|
|
|
|
int worldSteps;
|
|
int worldStepId; // two years at 1/30 second dt
|
|
float worldStepAccumulated; // Time unaccounted for in the last step
|
|
|
|
HeapValue<float> fallenPartDestroyHeight;
|
|
|
|
// defining objects
|
|
IndexArray<Primitive, &Primitive::worldIndexFunc> primitives;
|
|
Primitive* groundPrimitive; // for now, only used by kernel joints
|
|
|
|
btCollisionDispatcher* bulletDispatcher;
|
|
btDefaultCollisionConfiguration* bulletCollisionConfiguration;
|
|
|
|
// Generates unique ids for objects registered with this World
|
|
boost::uint64_t UIDGenerator;
|
|
bool usingPGSSolver;
|
|
bool physicsAnalyzerEnabled;
|
|
|
|
// Material Properties
|
|
PhysicalPropertiesMode physicalMaterialsMode;
|
|
|
|
// Networked Interpolation Sync
|
|
Time lastFrameTimeStamp; // Timestamp of current frame beginning
|
|
Time lastSendTimeStamp; // Timestamp of the frame where we last sent physics
|
|
int lastNumWorldSteps;
|
|
double worldStepOffset;
|
|
|
|
public:
|
|
float getUpdateExpectedStepDelta();
|
|
|
|
btCollisionDispatcher* getBulletCollisionDispatcher(void) { return bulletDispatcher; }
|
|
|
|
private:
|
|
|
|
// redundant data
|
|
G3D::Array<Primitive*> movingPrimitives;
|
|
std::set<Joint*> breakableJoints;
|
|
int numJoints;
|
|
int numContacts;
|
|
int numLinkCalls;
|
|
|
|
// motion analytic
|
|
double errorCount;
|
|
double passCount;
|
|
double frameinfosSize;
|
|
double frameinfosTarget;
|
|
double targetDelayTenths;
|
|
double infosSizeTenths;
|
|
double maxDelta;
|
|
double frameinfosCount;
|
|
|
|
|
|
// redundant data - performance - prevent allocation
|
|
G3D::Array<Primitive*> tempPrimitives;
|
|
G3D::Array<boost::shared_ptr<JointInstance> > tempJoints;
|
|
|
|
boost::unordered_map< boost::uint64_t, Primitive* > primitiveIndexation;
|
|
|
|
boost::scoped_ptr<Profiling::CodeProfiler> profilingBreak;
|
|
boost::scoped_ptr<Profiling::CodeProfiler> profilingAssembly;
|
|
boost::scoped_ptr<Profiling::CodeProfiler> profilingFilter;
|
|
boost::scoped_ptr<Profiling::CodeProfiler> profilingWorldStep;
|
|
boost::scoped_ptr<Profiling::CodeProfiler> profilingUiStep;
|
|
|
|
void createAutoJoints(Primitive* p, std::set<Primitive*>* ignoreGroup, std::set<Primitive*>* joinGroup); // if joinGroup, only connect with them
|
|
void destroyAutoJoints(Primitive* p, std::set<Primitive*>* ignoreGroup, bool includeExplicit = true, bool includeAuto = true); // if group, then keep joints between group members
|
|
|
|
void destroyJoint(Joint* j);
|
|
|
|
void removeFromBreakable(Joint* j);
|
|
|
|
// these functions are in the main world->step() loop
|
|
void doBreakJoints(); // goes through the breakableJoints, breaks if necessary;
|
|
|
|
void uiStep(bool longStep, double distributedGameTime);
|
|
void doWorldStep(bool throttling, int uiStepId, int numThreads, boost::uint64_t debugTime);
|
|
|
|
void notifyMovingAssemblies();
|
|
|
|
ContactManager* contactManager;
|
|
class SendPhysics* sendPhysics;
|
|
class CleanStage* cleanStage;
|
|
|
|
class GroundStage* getGroundStage();
|
|
class SleepStage* getSleepStage();
|
|
class TreeStage* getTreeStage();
|
|
const class SpatialFilter* getSpatialFilter() const;
|
|
class AssemblyStage* getAssemblyStage();
|
|
const AssemblyStage* getAssemblyStage() const;
|
|
class MovingAssemblyStage* getMovingAssemblyStage();
|
|
class StepJointsStage* getStepJointsStage();
|
|
const StepJointsStage* getStepJointsStage() const;
|
|
const class SleepStage* getSleepStage() const;
|
|
class SimulateStage* getSimulateStage();
|
|
|
|
public:
|
|
World();
|
|
~World();
|
|
|
|
void assertNotInStep() { RBXASSERT(!inStepCode); }
|
|
void assertInStep() { RBXASSERT(inStepCode); }
|
|
|
|
class SendPhysics* getSendPhysics();
|
|
class SimSendFilter& getSimSendFilter();
|
|
SpatialFilter* getSpatialFilter();
|
|
ContactManager* getContactManager() {return contactManager;}
|
|
const ContactManager* getContactManager() const {return contactManager;}
|
|
class HumanoidStage* getHumanoidStage();
|
|
class Kernel* getKernel();
|
|
const Kernel* getKernel() const;
|
|
|
|
const G3D::Array<TouchInfo>& getTouchInfoFromLastStep() {return touchReporting;}
|
|
void clearTouchInfoFromLastStep() {touchReporting.fastClear();}
|
|
|
|
void computeFallen(G3D::Array<Primitive*>& fallen) const;
|
|
|
|
const G3D::Array<Primitive*>& getPrimitives() const {return primitives.underlyingArray();}
|
|
|
|
// engine interface
|
|
int updateStepsRequiredForCyclicExecutive(float desiredInterval);
|
|
float step(bool longStep, double distributedGameTime, float desiredInterval, int numThreads); // 10-100 frames per second
|
|
void assemble(); // on heartbeat, before collision detection
|
|
bool isAssembled();
|
|
void reset() {RBXASSERT(!inStepCode); worldStepId = 0;}
|
|
int getWorldStepId() {return worldStepId;}
|
|
float getWorldStepsAccumulated() { return worldStepAccumulated; }
|
|
int getUiStepId();
|
|
int getLongUiStepId();
|
|
void sendClumpChangedMessage(Primitive* childPrim);
|
|
|
|
EThrottle& getEThrottle() {return eThrottle;}
|
|
int getFRMThrottle() { return frmThrottle;}
|
|
void setFRMThrottle(int value);
|
|
|
|
Primitive* getGroundPrimitive() {return groundPrimitive;}
|
|
|
|
// PRIMITIVE - Runtime geometry manipulation
|
|
void insertPrimitive(Primitive* p);
|
|
void removePrimitive(Primitive* p, bool isStreamingRemove);
|
|
void ticklePrimitive(Primitive* p, bool recursive); // simulates a touch, wakes up
|
|
Primitive* getPrimitiveFromBodyUID( boost::uint64_t uid ) const;
|
|
|
|
// Auto Joining / Unjoining functions
|
|
void joinAll();
|
|
|
|
void createAutoJoints(Primitive* p);
|
|
void createAutoJointsToWorld(const G3D::Array<Primitive*>& primitives); // ignores joints between them
|
|
void createAutoJointsToPrimitives(const G3D::Array<Primitive*>& primitives); // only join each other in this group
|
|
|
|
void destroyAutoJoints(Primitive* p, bool includeExplicit = true);
|
|
void destroyAutoJointsToWorld(const G3D::Array<Primitive*>& primitives); // ignores joints between them
|
|
|
|
void destroyTerrainWeldJointsWithEmptyCells(Primitive* megaClusterPrim, const SpatialRegion::Id& region, Primitive* touchingPrim);
|
|
void destroyTerrainWeldJointsNoTouch(Primitive* megaClusterPrim, Primitive* touchingPrim);
|
|
|
|
// Joint based insert, remove
|
|
void insertJoint(Joint* j);
|
|
void removeJoint(Joint* j);
|
|
void jointCoordsChanged(Joint* j);
|
|
void notifyMoved(Primitive* p);
|
|
|
|
// Network Ownership API Data Gatherer
|
|
void gatherMechDataPreJoin(Joint *j, Primitive*& unGroundedPrim, std::vector<Primitive*>& combiningRoots);
|
|
void gatherMechDataPreSplit(Joint* j, std::vector<Primitive*>& prim0ChildRoots, std::vector<Primitive*>& prim1Roots);
|
|
|
|
// CONTACT MANAGER - Can only be called by the contact manager;
|
|
void insertContact(Contact* c);
|
|
void destroyContact(Contact* c);
|
|
|
|
// inquiry functions
|
|
int getMetric(IWorldStage::MetricType metricType) const;
|
|
int getNumBodies() const;
|
|
int getNumPoints() const;
|
|
int getNumConstraints() const;
|
|
int getNumHashNodes() const;
|
|
int getMaxBucketSize() const;
|
|
int getNumLinkCalls() const {return numLinkCalls;}
|
|
int getNumContacts() const {return numContacts;}
|
|
int getNumJoints() const {return numJoints;}
|
|
int getNumPrimitives() const {return getPrimitives().size();}
|
|
float getEnvironmentSpeed() const {return eThrottle.getEnvironmentSpeed();}
|
|
float getEnvironmentSpeedPercent() const {return getEnvironmentSpeed() * 100.0f;}
|
|
|
|
void setFallenPartDestroyHeight(float value) {fallenPartDestroyHeight = value;}
|
|
float getFallenPartDestroyHeight() const {return fallenPartDestroyHeight;}
|
|
|
|
RBX::Profiling::CodeProfiler& getProfileWorldStep() { return *profilingWorldStep; }
|
|
const RBX::Profiling::CodeProfiler& getProfileWorldStep() const { return *profilingWorldStep; }
|
|
|
|
void loadProfilers(std::vector<RBX::Profiling::CodeProfiler*>& worldProfilers) const;
|
|
|
|
// PRIMITIVE - notification on edits - only called by Primitive or Clump
|
|
Assembly* onPrimitiveEngineChanging(Primitive* p);
|
|
void onPrimitiveEngineChanged(Assembly* changing);
|
|
|
|
void onPrimitiveFixedChanging(Primitive* p);
|
|
void onPrimitiveFixedChanged(Primitive* p);
|
|
|
|
void onPrimitivePreventCollideChanged(Primitive* p);
|
|
void onPrimitiveExtentsChanged(Primitive* p);
|
|
void onPrimitiveContactParametersChanged(Primitive* p);
|
|
void onPrimitiveGeometryChanged(Primitive* p);
|
|
void reportTouchInfo(const TouchInfo& info);
|
|
void reportTouchInfo(Primitive* p0, Primitive* p1, World::TouchInfo::Type T);
|
|
|
|
void onPrimitiveCollided(Primitive* p0, Primitive* p1);
|
|
|
|
void onAssemblyPhysicsChanged(Assembly* a, bool physics) const;
|
|
void onAssemblyInSimluationStage(Assembly* a);
|
|
|
|
// JOINT - notification on edits - only called by Joint
|
|
void onJointPrimitiveNulling(Joint* j, Primitive* p);
|
|
void onJointPrimitiveSet(Joint* j, Primitive* p);
|
|
|
|
void addAnimatedJointToMovingAssemblyStage(Joint* j);
|
|
void removeAnimatedJointFromMovingAssemblyStage(Joint* j);
|
|
|
|
bool getUsingPGSSolver();
|
|
void setUsingPGSSolver(bool usePGS);
|
|
void setUserId( int id );
|
|
|
|
void setPhysicsAnalyzerEnabled(bool value) { physicsAnalyzerEnabled = value; }
|
|
|
|
bool getUsingNewPhysicalProperties() const;
|
|
|
|
PhysicalPropertiesMode getPhysicalPropertiesMode() const { return physicalMaterialsMode; }
|
|
void setPhysicalPropertiesMode(PhysicalPropertiesMode mode);
|
|
|
|
// motion analytic
|
|
void plusErrorCount(double ec) { errorCount += ec;}
|
|
void plusPassCount(double pc) { passCount += pc; }
|
|
double getPassCount() {return passCount; }
|
|
void sendAnalytics(void);
|
|
void addFrameinfosStat(double fis, double fit, double tdt, double ist, double md, double fic);
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|