mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 13:43:49 +02:00
build StaticMeshShapes outside of mainloop
This commit is contained in:
parent
7fb7e503f9
commit
fbd4db5505
4 changed files with 94 additions and 11 deletions
|
@ -481,3 +481,8 @@ void ShapeFactory::deleteShape(const btCollisionShape* shape) {
|
|||
}
|
||||
delete nonConstShape;
|
||||
}
|
||||
|
||||
void ShapeFactory::Worker::run() {
|
||||
shape = ShapeFactory::createShapeFromInfo(shapeInfo);
|
||||
emit submitWork(this);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <QObject>
|
||||
#include <QtCore/QRunnable>
|
||||
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
|
@ -22,6 +24,17 @@
|
|||
namespace ShapeFactory {
|
||||
const btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
|
||||
void deleteShape(const btCollisionShape* shape);
|
||||
|
||||
class Worker : public QObject, public QRunnable {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Worker(const ShapeInfo& info) : shapeInfo(info), shape(nullptr) {}
|
||||
void run() override;
|
||||
ShapeInfo shapeInfo;
|
||||
const btCollisionShape* shape;
|
||||
signals:
|
||||
void submitWork(Worker*);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // hifi_ShapeFactory_h
|
||||
|
|
|
@ -12,10 +12,8 @@
|
|||
#include "ShapeManager.h"
|
||||
|
||||
#include <glm/gtx/norm.hpp>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "ShapeFactory.h"
|
||||
|
||||
const int MAX_RING_SIZE = 256;
|
||||
|
||||
|
@ -42,13 +40,36 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
|
|||
shapeRef->refCount++;
|
||||
return shapeRef->shape;
|
||||
}
|
||||
const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
|
||||
if (shape) {
|
||||
ShapeReference newRef;
|
||||
newRef.refCount = 1;
|
||||
newRef.shape = shape;
|
||||
newRef.key = info.getHash();
|
||||
_shapeMap.insert(hashKey, newRef);
|
||||
const btCollisionShape* shape = nullptr;
|
||||
if (info.getType() == SHAPE_TYPE_STATIC_MESH) {
|
||||
uint64_t hash = info.getHash();
|
||||
const auto itr = std::find(_pendingMeshShapes.begin(), _pendingMeshShapes.end(), hash);
|
||||
if (itr == _pendingMeshShapes.end()) {
|
||||
// start a worker
|
||||
_pendingMeshShapes.push_back(hash);
|
||||
// try to recycle old deadWorker
|
||||
ShapeFactory::Worker* worker = _deadWorker;
|
||||
if (!worker) {
|
||||
worker = new ShapeFactory::Worker(info);
|
||||
} else {
|
||||
worker->shapeInfo = info;
|
||||
_deadWorker = nullptr;
|
||||
}
|
||||
// we will delete worker manually later
|
||||
worker->setAutoDelete(false);
|
||||
QObject::connect(worker, &ShapeFactory::Worker::submitWork, this, &ShapeManager::acceptWork);
|
||||
QThreadPool::globalInstance()->start(worker);
|
||||
}
|
||||
// else we're still waiting for the shape to be created on another thread
|
||||
} else {
|
||||
shape = ShapeFactory::createShapeFromInfo(info);
|
||||
if (shape) {
|
||||
ShapeReference newRef;
|
||||
newRef.refCount = 1;
|
||||
newRef.shape = shape;
|
||||
newRef.key = info.getHash();
|
||||
_shapeMap.insert(hashKey, newRef);
|
||||
}
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
@ -153,3 +174,39 @@ bool ShapeManager::hasShape(const btCollisionShape* shape) const {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// slot: called when ShapeFactory::Worker is done building shape
|
||||
void ShapeManager::acceptWork(ShapeFactory::Worker* worker) {
|
||||
auto itr = std::find(_pendingMeshShapes.begin(), _pendingMeshShapes.end(), worker->shapeInfo.getHash());
|
||||
if (itr == _pendingMeshShapes.end()) {
|
||||
// we've received a shape but don't remember asking for it
|
||||
// (should not fall in here, but if we do: delete the unwanted shape)
|
||||
if (worker->shape) {
|
||||
ShapeFactory::deleteShape(worker->shape);
|
||||
}
|
||||
} else {
|
||||
// clear pending status
|
||||
*itr = _pendingMeshShapes.back();
|
||||
_pendingMeshShapes.pop_back();
|
||||
|
||||
// cache the new shape
|
||||
if (worker->shape) {
|
||||
ShapeReference newRef;
|
||||
newRef.refCount = 1;
|
||||
newRef.shape = worker->shape;
|
||||
newRef.key = worker->shapeInfo.getHash();
|
||||
HashKey hashKey(newRef.key);
|
||||
_shapeMap.insert(hashKey, newRef);
|
||||
}
|
||||
}
|
||||
disconnect(worker, &ShapeFactory::Worker::submitWork, this, &ShapeManager::acceptWork);
|
||||
|
||||
if (_deadWorker) {
|
||||
// delete the previous deadWorker manually
|
||||
delete _deadWorker;
|
||||
}
|
||||
// save this dead worker for later
|
||||
worker->shapeInfo.clear();
|
||||
worker->shape = nullptr;
|
||||
_deadWorker = worker;
|
||||
}
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <LinearMath/btHashMap.h>
|
||||
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "ShapeFactory.h"
|
||||
#include "HashKey.h"
|
||||
|
||||
// The ShapeManager handles the ref-counting on shared shapes:
|
||||
|
@ -44,7 +46,8 @@
|
|||
// entries that still have zero ref-count.
|
||||
|
||||
|
||||
class ShapeManager {
|
||||
class ShapeManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
ShapeManager();
|
||||
|
@ -65,6 +68,9 @@ public:
|
|||
int getNumReferences(const btCollisionShape* shape) const;
|
||||
bool hasShape(const btCollisionShape* shape) const;
|
||||
|
||||
protected slots:
|
||||
void acceptWork(ShapeFactory::Worker* worker);
|
||||
|
||||
private:
|
||||
bool releaseShapeByKey(uint64_t key);
|
||||
|
||||
|
@ -79,6 +85,8 @@ private:
|
|||
// btHashMap is required because it supports memory alignment of the btCollisionShapes
|
||||
btHashMap<HashKey, ShapeReference> _shapeMap;
|
||||
std::vector<uint64_t> _garbageRing;
|
||||
std::vector<uint64_t> _pendingMeshShapes;
|
||||
ShapeFactory::Worker* _deadWorker { nullptr };
|
||||
uint32_t _ringIndex { 0 };
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue