multithreaded physics

This commit is contained in:
floralrainfall 2023-07-20 03:49:39 -04:00
parent 417ccb5edb
commit c71abf207b
8 changed files with 77 additions and 8 deletions

View File

@ -127,6 +127,8 @@ namespace RNR
this->render_time += ogreRoot->getTimer()->getMilliseconds() / 1000.0;
ogreRoot->getTimer()->reset();
world->preRender(this->delta);
if(world->getWorkspace()->getCurrentCamera())
{
Camera* cam = world->getWorkspace()->getCurrentCamera();

View File

@ -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));
app.processEvents();
window.ogreWidget->render();
world->preStep();
world->step(window.ogreWidget->delta);
world->update();
}
}

View File

@ -4,6 +4,7 @@ add_library(Engine STATIC
Header/Helpers/XML.hpp
Header/Helpers/NormalId.hpp
Header/Helpers/Bullet.hpp
Header/Helpers/Lock.hpp
Header/App/Script/ReflectionProperty.hpp
Header/App/Script/Script.hpp
Header/App/Script/ScriptContext.hpp

View File

@ -8,6 +8,7 @@
#include <boost/shared_ptr.hpp>
#include <Helpers/Name.hpp>
#include <Helpers/Lock.hpp>
#include <pugixml.hpp>
#include <App/Script/ReflectionProperty.hpp>
@ -78,5 +79,7 @@ namespace RNR
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 onSetParent(RNR::Instance* newParent);
Lock instanceLock;
};
}

View File

@ -30,6 +30,10 @@ namespace RNR
class World
{
private:
std::thread m_physicsThread;
Ogre::Timer* m_physicsTimer;
bool m_runPhysics;
std::map<std::string, Instance*> m_refs;
std::stack<WorldUndeserialized> m_undeserialized;
btDiscreteDynamicsWorld* m_dynamicsWorld;
@ -43,6 +47,8 @@ namespace RNR
InstanceFactory* m_instanceFactory;
IInputManager* m_inputManager;
float m_lastDelta;
float m_lastPhysicsDelta;
float m_physicsTime;
void xmlAddItem(pugi::xml_node node, Instance* parent);
public:
@ -53,12 +59,14 @@ namespace RNR
void load(char* path);
void preRender(float timestep);
void preStep();
double step(float timestep);
void update();
btDiscreteDynamicsWorld* getDynamicsWorld() { return m_dynamicsWorld; }
float getLastDelta() { return m_lastDelta; }
float getLastPhysicsDelta() { return m_lastPhysicsDelta; }
DataModel* getDatamodel() { return m_datamodel; }
void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; }
IInputManager* getInputManager() { return m_inputManager; }
@ -69,8 +77,14 @@ namespace RNR
void setRunService(RunService* runService) { m_runService = runService; }
Ogre::Root* getOgreRoot() { return m_ogreRoot; }
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 deletePhysicsPart(PartInstance* partDelete);
Lock physicsIterateLock;
};
}

View File

@ -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); }
};
}

View File

@ -128,9 +128,10 @@ namespace RNR
snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size());
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(),
render_debugtext,
m_world->getLastPhysicsDelta(),
dynamicsWorld->getNumCollisionObjects(), dynamicsWorld->getNumConstraints(),
m_world->getRunService()->getRunning() ? "true" : "false",
m_world->getRunService()->getPaused() ? "true" : "false");

View File

@ -12,6 +12,21 @@
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)
{
Instance::setWorld(this);
@ -46,6 +61,10 @@ namespace RNR
m_runService = (RunService*)m_datamodel->getService("RunService");
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);
Camera* start_cam = new Camera();
@ -55,7 +74,8 @@ namespace RNR
World::~World()
{
//
m_runPhysics = false;
m_physicsThread.join();
}
void World::xmlAddItem(pugi::xml_node node, Instance* parent)
@ -142,11 +162,27 @@ namespace RNR
m_workspace->build();
}
void World::preStep()
void World::preRender(float timestep)
{
if(m_inputManager)
m_inputManager->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)
@ -154,8 +190,9 @@ namespace RNR
if(m_runService && m_runService->getRunning() && !m_runService->getPaused())
{
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--)
{
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[j];
@ -177,10 +214,10 @@ namespace RNR
Ogre::Quaternion transOgre = Bullet::qtToOgre(trans.getRotation());
transOgre.ToRotationMatrix(partRot);
part->getCFrame().setRotation(partRot);
part->updateMatrix();
}
physicsIterateLock.unlock();
}
m_lastDelta = timestep;
m_lastPhysicsDelta = timestep;
return 0.0;
}
@ -206,6 +243,7 @@ namespace RNR
btVector3 localInertia = btVector3(0,0,0);
if(mass)
partShape->calculateLocalInertia(mass, localInertia);
btDefaultMotionState* partMotionState = new btDefaultMotionState(partTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, partMotionState, partShape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);