multithreaded physics
This commit is contained in:
parent
417ccb5edb
commit
c71abf207b
|
|
@ -127,6 +127,8 @@ namespace RNR
|
||||||
this->render_time += ogreRoot->getTimer()->getMilliseconds() / 1000.0;
|
this->render_time += ogreRoot->getTimer()->getMilliseconds() / 1000.0;
|
||||||
ogreRoot->getTimer()->reset();
|
ogreRoot->getTimer()->reset();
|
||||||
|
|
||||||
|
world->preRender(this->delta);
|
||||||
|
|
||||||
if(world->getWorkspace()->getCurrentCamera())
|
if(world->getWorkspace()->getCurrentCamera())
|
||||||
{
|
{
|
||||||
Camera* cam = world->getWorkspace()->getCurrentCamera();
|
Camera* cam = world->getWorkspace()->getCurrentCamera();
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@ int main(int argc, char** argv)
|
||||||
window.statusBar()->showMessage(QString::asprintf("Dt=%f, Rt=%f, FPS=%f", window.ogreWidget->delta, window.ogreWidget->render_time, 1 / window.ogreWidget->delta));
|
window.statusBar()->showMessage(QString::asprintf("Dt=%f, Rt=%f, FPS=%f", window.ogreWidget->delta, window.ogreWidget->render_time, 1 / window.ogreWidget->delta));
|
||||||
app.processEvents();
|
app.processEvents();
|
||||||
window.ogreWidget->render();
|
window.ogreWidget->render();
|
||||||
world->preStep();
|
|
||||||
world->step(window.ogreWidget->delta);
|
|
||||||
world->update();
|
world->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ add_library(Engine STATIC
|
||||||
Header/Helpers/XML.hpp
|
Header/Helpers/XML.hpp
|
||||||
Header/Helpers/NormalId.hpp
|
Header/Helpers/NormalId.hpp
|
||||||
Header/Helpers/Bullet.hpp
|
Header/Helpers/Bullet.hpp
|
||||||
|
Header/Helpers/Lock.hpp
|
||||||
Header/App/Script/ReflectionProperty.hpp
|
Header/App/Script/ReflectionProperty.hpp
|
||||||
Header/App/Script/Script.hpp
|
Header/App/Script/Script.hpp
|
||||||
Header/App/Script/ScriptContext.hpp
|
Header/App/Script/ScriptContext.hpp
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <Helpers/Name.hpp>
|
#include <Helpers/Name.hpp>
|
||||||
|
#include <Helpers/Lock.hpp>
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
|
|
||||||
#include <App/Script/ReflectionProperty.hpp>
|
#include <App/Script/ReflectionProperty.hpp>
|
||||||
|
|
@ -78,5 +79,7 @@ namespace RNR
|
||||||
virtual void onChildRemoved(RNR::Instance* childRemoved);
|
virtual void onChildRemoved(RNR::Instance* childRemoved);
|
||||||
virtual void onDescendantRemoved(RNR::Instance* descendantRemoved); // make sure this is called in any derived versions of this
|
virtual void onDescendantRemoved(RNR::Instance* descendantRemoved); // make sure this is called in any derived versions of this
|
||||||
virtual void onSetParent(RNR::Instance* newParent);
|
virtual void onSetParent(RNR::Instance* newParent);
|
||||||
|
|
||||||
|
Lock instanceLock;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -30,6 +30,10 @@ namespace RNR
|
||||||
class World
|
class World
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
std::thread m_physicsThread;
|
||||||
|
Ogre::Timer* m_physicsTimer;
|
||||||
|
|
||||||
|
bool m_runPhysics;
|
||||||
std::map<std::string, Instance*> m_refs;
|
std::map<std::string, Instance*> m_refs;
|
||||||
std::stack<WorldUndeserialized> m_undeserialized;
|
std::stack<WorldUndeserialized> m_undeserialized;
|
||||||
btDiscreteDynamicsWorld* m_dynamicsWorld;
|
btDiscreteDynamicsWorld* m_dynamicsWorld;
|
||||||
|
|
@ -43,6 +47,8 @@ namespace RNR
|
||||||
InstanceFactory* m_instanceFactory;
|
InstanceFactory* m_instanceFactory;
|
||||||
IInputManager* m_inputManager;
|
IInputManager* m_inputManager;
|
||||||
float m_lastDelta;
|
float m_lastDelta;
|
||||||
|
float m_lastPhysicsDelta;
|
||||||
|
float m_physicsTime;
|
||||||
|
|
||||||
void xmlAddItem(pugi::xml_node node, Instance* parent);
|
void xmlAddItem(pugi::xml_node node, Instance* parent);
|
||||||
public:
|
public:
|
||||||
|
|
@ -53,12 +59,14 @@ namespace RNR
|
||||||
|
|
||||||
void load(char* path);
|
void load(char* path);
|
||||||
|
|
||||||
|
void preRender(float timestep);
|
||||||
void preStep();
|
void preStep();
|
||||||
double step(float timestep);
|
double step(float timestep);
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
btDiscreteDynamicsWorld* getDynamicsWorld() { return m_dynamicsWorld; }
|
btDiscreteDynamicsWorld* getDynamicsWorld() { return m_dynamicsWorld; }
|
||||||
float getLastDelta() { return m_lastDelta; }
|
float getLastDelta() { return m_lastDelta; }
|
||||||
|
float getLastPhysicsDelta() { return m_lastPhysicsDelta; }
|
||||||
DataModel* getDatamodel() { return m_datamodel; }
|
DataModel* getDatamodel() { return m_datamodel; }
|
||||||
void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; }
|
void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; }
|
||||||
IInputManager* getInputManager() { return m_inputManager; }
|
IInputManager* getInputManager() { return m_inputManager; }
|
||||||
|
|
@ -69,8 +77,14 @@ namespace RNR
|
||||||
void setRunService(RunService* runService) { m_runService = runService; }
|
void setRunService(RunService* runService) { m_runService = runService; }
|
||||||
Ogre::Root* getOgreRoot() { return m_ogreRoot; }
|
Ogre::Root* getOgreRoot() { return m_ogreRoot; }
|
||||||
Ogre::SceneManager* getOgreSceneManager() { return m_ogreSceneManager; }
|
Ogre::SceneManager* getOgreSceneManager() { return m_ogreSceneManager; }
|
||||||
|
Ogre::Timer* getPhysicsTimer() { return m_physicsTimer; }
|
||||||
|
float getPhysicsTime() { return m_physicsTime; }
|
||||||
|
void setPhysicsTime(float newTime) { m_physicsTime = newTime; } // should only be used by physicsThread
|
||||||
|
bool getPhysicsShouldBeRunningPleaseStopIfItIsStillRunning() { return m_runPhysics; }
|
||||||
|
|
||||||
void registerPhysicsPart(PartInstance* partRegistered);
|
void registerPhysicsPart(PartInstance* partRegistered);
|
||||||
void deletePhysicsPart(PartInstance* partDelete);
|
void deletePhysicsPart(PartInstance* partDelete);
|
||||||
|
|
||||||
|
Lock physicsIterateLock;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace RNR
|
||||||
|
{
|
||||||
|
struct Lock {
|
||||||
|
std::atomic<bool> lock_ = {false};
|
||||||
|
|
||||||
|
void lock() { while(lock_.exchange(true, std::memory_order_acquire)); }
|
||||||
|
|
||||||
|
void unlock() { lock_.store(false, std::memory_order_release); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -128,9 +128,10 @@ namespace RNR
|
||||||
snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size());
|
snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n\nPhysics\n%i objects, %i constraints\nRunService: running = %s, paused = %s",
|
snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n\nPhysics\nDT = %f\n%i objects, %i constraints\nRunService: running = %s, paused = %s",
|
||||||
m_world->getLastDelta(),
|
m_world->getLastDelta(),
|
||||||
render_debugtext,
|
render_debugtext,
|
||||||
|
m_world->getLastPhysicsDelta(),
|
||||||
dynamicsWorld->getNumCollisionObjects(), dynamicsWorld->getNumConstraints(),
|
dynamicsWorld->getNumCollisionObjects(), dynamicsWorld->getNumConstraints(),
|
||||||
m_world->getRunService()->getRunning() ? "true" : "false",
|
m_world->getRunService()->getRunning() ? "true" : "false",
|
||||||
m_world->getRunService()->getPaused() ? "true" : "false");
|
m_world->getRunService()->getPaused() ? "true" : "false");
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,21 @@
|
||||||
|
|
||||||
namespace RNR
|
namespace RNR
|
||||||
{
|
{
|
||||||
|
void physicsThread(World* world)
|
||||||
|
{
|
||||||
|
float delta;
|
||||||
|
float time;
|
||||||
|
while(world->getPhysicsShouldBeRunningPleaseStopIfItIsStillRunning())
|
||||||
|
{
|
||||||
|
delta = world->getPhysicsTimer()->getMicroseconds() / 1000000.0;
|
||||||
|
time += world->getPhysicsTimer()->getMilliseconds() / 1000.0;
|
||||||
|
world->setPhysicsTime(time);
|
||||||
|
world->getPhysicsTimer()->reset();
|
||||||
|
world->preStep();
|
||||||
|
world->step(delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
World::World(Ogre::Root* ogre, Ogre::SceneManager* ogreSceneManager)
|
World::World(Ogre::Root* ogre, Ogre::SceneManager* ogreSceneManager)
|
||||||
{
|
{
|
||||||
Instance::setWorld(this);
|
Instance::setWorld(this);
|
||||||
|
|
@ -46,6 +61,10 @@ namespace RNR
|
||||||
m_runService = (RunService*)m_datamodel->getService("RunService");
|
m_runService = (RunService*)m_datamodel->getService("RunService");
|
||||||
m_players = (Players*)m_datamodel->getService("Players");
|
m_players = (Players*)m_datamodel->getService("Players");
|
||||||
|
|
||||||
|
m_runPhysics = true;
|
||||||
|
m_physicsTimer = new Ogre::Timer();
|
||||||
|
m_physicsThread = std::thread(physicsThread, this);
|
||||||
|
|
||||||
m_tmb = new TopMenuBar(this);
|
m_tmb = new TopMenuBar(this);
|
||||||
|
|
||||||
Camera* start_cam = new Camera();
|
Camera* start_cam = new Camera();
|
||||||
|
|
@ -55,7 +74,8 @@ namespace RNR
|
||||||
|
|
||||||
World::~World()
|
World::~World()
|
||||||
{
|
{
|
||||||
//
|
m_runPhysics = false;
|
||||||
|
m_physicsThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::xmlAddItem(pugi::xml_node node, Instance* parent)
|
void World::xmlAddItem(pugi::xml_node node, Instance* parent)
|
||||||
|
|
@ -142,11 +162,27 @@ namespace RNR
|
||||||
m_workspace->build();
|
m_workspace->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::preStep()
|
void World::preRender(float timestep)
|
||||||
{
|
{
|
||||||
if(m_inputManager)
|
if(m_inputManager)
|
||||||
m_inputManager->frame();
|
m_inputManager->frame();
|
||||||
m_tmb->frame();
|
m_tmb->frame();
|
||||||
|
m_lastDelta = timestep;
|
||||||
|
physicsIterateLock.lock();
|
||||||
|
for(int j = m_dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[j];
|
||||||
|
if(!obj->isActive())
|
||||||
|
continue;
|
||||||
|
PartInstance* part = (PartInstance*)obj->getUserPointer();
|
||||||
|
part->updateMatrix();
|
||||||
|
}
|
||||||
|
physicsIterateLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::preStep()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double World::step(float timestep)
|
double World::step(float timestep)
|
||||||
|
|
@ -154,8 +190,9 @@ namespace RNR
|
||||||
if(m_runService && m_runService->getRunning() && !m_runService->getPaused())
|
if(m_runService && m_runService->getRunning() && !m_runService->getPaused())
|
||||||
{
|
{
|
||||||
m_runService->step(timestep);
|
m_runService->step(timestep);
|
||||||
m_dynamicsWorld->stepSimulation(timestep, 4, 1.0/60.0);
|
m_dynamicsWorld->stepSimulation(timestep, 2);
|
||||||
|
|
||||||
|
physicsIterateLock.lock();
|
||||||
for(int j = m_dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
|
for(int j = m_dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
|
||||||
{
|
{
|
||||||
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[j];
|
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[j];
|
||||||
|
|
@ -177,10 +214,10 @@ namespace RNR
|
||||||
Ogre::Quaternion transOgre = Bullet::qtToOgre(trans.getRotation());
|
Ogre::Quaternion transOgre = Bullet::qtToOgre(trans.getRotation());
|
||||||
transOgre.ToRotationMatrix(partRot);
|
transOgre.ToRotationMatrix(partRot);
|
||||||
part->getCFrame().setRotation(partRot);
|
part->getCFrame().setRotation(partRot);
|
||||||
part->updateMatrix();
|
|
||||||
}
|
}
|
||||||
|
physicsIterateLock.unlock();
|
||||||
}
|
}
|
||||||
m_lastDelta = timestep;
|
m_lastPhysicsDelta = timestep;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,6 +243,7 @@ namespace RNR
|
||||||
btVector3 localInertia = btVector3(0,0,0);
|
btVector3 localInertia = btVector3(0,0,0);
|
||||||
if(mass)
|
if(mass)
|
||||||
partShape->calculateLocalInertia(mass, localInertia);
|
partShape->calculateLocalInertia(mass, localInertia);
|
||||||
|
|
||||||
btDefaultMotionState* partMotionState = new btDefaultMotionState(partTransform);
|
btDefaultMotionState* partMotionState = new btDefaultMotionState(partTransform);
|
||||||
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, partMotionState, partShape, localInertia);
|
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, partMotionState, partShape, localInertia);
|
||||||
btRigidBody* body = new btRigidBody(rbInfo);
|
btRigidBody* body = new btRigidBody(rbInfo);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue