mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 12:33:27 +02:00
more efficient ParticleTree::getParticles() and adding ParticleTree::getParticlesForUpdate()
This commit is contained in:
parent
daf11692d8
commit
31a2e467f4
5 changed files with 85 additions and 75 deletions
|
@ -170,16 +170,14 @@ public:
|
|||
|
||||
bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) {
|
||||
FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData);
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
|
||||
glm::vec3 penetration;
|
||||
bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position,
|
||||
bool sphereIntersection = element->getAABox().findSpherePenetration(args->position,
|
||||
args->targetRadius, penetration);
|
||||
|
||||
// If this particleTreeElement contains the point, then search it...
|
||||
// If this element contains the point, then search it...
|
||||
if (sphereIntersection) {
|
||||
QVector<const Particle*> moreParticles = particleTreeElement->getParticles(args->position, args->targetRadius);
|
||||
args->particles << moreParticles;
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
particleTreeElement->getParticles(args->position, args->targetRadius, args->particles);
|
||||
return true; // keep searching in case children have closer particles
|
||||
}
|
||||
|
||||
|
@ -187,13 +185,43 @@ bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData
|
|||
return false;
|
||||
}
|
||||
|
||||
QVector<const Particle*> ParticleTree::findParticles(const glm::vec3& center, float radius) {
|
||||
QVector<Particle*> result;
|
||||
void ParticleTree::findParticles(const glm::vec3& center, float radius, QVector<const Particle*>& foundParticles) {
|
||||
FindAllNearPointArgs args = { center, radius };
|
||||
lockForRead();
|
||||
recurseTreeWithOperation(findInSphereOperation, &args);
|
||||
unlock();
|
||||
return args.particles;
|
||||
// swap the two lists of particle pointers instead of copy
|
||||
foundParticles.swap(args.particles);
|
||||
}
|
||||
|
||||
class FindParticlesInBoxArgs {
|
||||
public:
|
||||
FindParticlesInBoxArgs(const AABox& box)
|
||||
: _box(box), _foundParticles() {
|
||||
}
|
||||
|
||||
AABox _box;
|
||||
QVector<Particle*> _foundParticles;
|
||||
};
|
||||
|
||||
bool findInBoxForUpdateOperation(OctreeElement* element, void* extraData) {
|
||||
FindParticlesInBoxArgs* args = static_cast< FindParticlesInBoxArgs*>(extraData);
|
||||
const AABox& elementBox = element->getAABox();
|
||||
if (elementBox.touches(args->_box)) {
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
particleTreeElement->getParticlesForUpdate(args->_box, args->_foundParticles);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ParticleTree::findParticlesForUpdate(const AABox& box, QVector<Particle*> foundParticles) {
|
||||
FindParticlesInBoxArgs args(box);
|
||||
lockForRead();
|
||||
recurseTreeWithOperation(findInBoxForUpdateOperation, &args);
|
||||
unlock();
|
||||
// swap the two lists of particle pointers instead of copy
|
||||
foundParticles.swap(args._foundParticles);
|
||||
}
|
||||
|
||||
class FindByIDArgs {
|
||||
|
@ -495,31 +523,3 @@ void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const Hi
|
|||
recurseTreeWithOperation(findAndDeleteOperation, &args);
|
||||
}
|
||||
}
|
||||
|
||||
class FindParticlesArgs {
|
||||
public:
|
||||
FindParticlesArgs(const AABox& box)
|
||||
: _box(box), _foundParticles() {
|
||||
}
|
||||
|
||||
AABox _box;
|
||||
QVector<Particle*> _foundParticles;
|
||||
};
|
||||
|
||||
bool findOperation(OctreeElement* element, void* extraData) {
|
||||
FindParticlesArgs* args = static_cast< FindParticlesArgs*>(extraData);
|
||||
const AABox& elementBox = element->getAABox();
|
||||
if (elementBox.touches(args->_box)) {
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
particleTreeElement->findParticles(args->_box, args->_foundParticles);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ParticleTree::findParticles(const AABox& box, QVector<Particle*> foundParticles) {
|
||||
FindParticlesArgs args(box);
|
||||
recurseTreeWithOperation(findOperation, &args);
|
||||
// swap the two lists of particle pointers instead of copy
|
||||
foundParticles.swap(args._foundParticles);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,19 @@ public:
|
|||
void storeParticle(const Particle& particle, Node* senderNode = NULL);
|
||||
const Particle* findClosestParticle(glm::vec3 position, float targetRadius);
|
||||
const Particle* findParticleByID(uint32_t id, bool alreadyLocked = false);
|
||||
QVector<const Particle*> findParticles(const glm::vec3& center, float radius);
|
||||
|
||||
/// finds all particles that touch a sphere
|
||||
/// \param center the center of the sphere
|
||||
/// \param radius the radius of the sphere
|
||||
/// \param foundParticles[out] vector of const Particle*
|
||||
/// \remark Side effect: any initial contents in foundParticles will be lost
|
||||
void findParticles(const glm::vec3& center, float radius, QVector<const Particle*>& foundParticles);
|
||||
|
||||
/// finds all particles that touch a box
|
||||
/// \param box the query box
|
||||
/// \param foundParticles[out] vector of non-const Particle*
|
||||
/// \remark Side effect: any initial contents in particles will be lost
|
||||
void findParticlesForUpdate(const AABox& box, QVector<Particle*> foundParticles);
|
||||
|
||||
void addNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
||||
void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
||||
|
@ -54,12 +66,6 @@ public:
|
|||
|
||||
void processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode);
|
||||
|
||||
/// finds all particles that touch a box
|
||||
/// \param box the query box
|
||||
/// \param particles[out] vector of Particle pointer
|
||||
/// \remark Side effect: any initial contents in particles will be lost
|
||||
void findParticles(const AABox& box, QVector<Particle*> particles);
|
||||
|
||||
private:
|
||||
|
||||
static bool updateOperation(OctreeElement* element, void* extraData);
|
||||
|
|
|
@ -185,21 +185,34 @@ const Particle* ParticleTreeElement::getClosestParticle(glm::vec3 position) cons
|
|||
return closestParticle;
|
||||
}
|
||||
|
||||
QVector<const Particle*> ParticleTreeElement::getParticles(glm::vec3 searchPosition, float searchRadius) const {
|
||||
QVector<const Particle*> results;
|
||||
void ParticleTreeElement::getParticles(const glm::vec3& searchPosition, float searchRadius, QVector<const Particle*>& foundParticles) const {
|
||||
uint16_t numberOfParticles = _particles->size();
|
||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||
const Particle* particle = &(*_particles)[i];
|
||||
glm::vec3 particlePosition = particle->getPosition();
|
||||
float particleRadius = particle->getRadius();
|
||||
glm::vec3 penetration;
|
||||
|
||||
// check to see that the particle (penetrator) penetrates the search area
|
||||
if (findSphereSpherePenetration(particlePosition, particleRadius, searchPosition, searchRadius, penetration)) {
|
||||
results << particle;
|
||||
float distance = glm::length(particle->getPosition() - searchPosition);
|
||||
if (distance < searchRadius + particle->getRadius()) {
|
||||
foundParticles.push_back(particle);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void ParticleTreeElement::getParticlesForUpdate(const AABox& box, QVector<Particle*>& foundParticles) {
|
||||
QList<Particle>::iterator particleItr = _particles->begin();
|
||||
QList<Particle>::iterator particleEnd = _particles->end();
|
||||
AABox particleBox;
|
||||
while(particleItr != particleEnd) {
|
||||
Particle* particle = &(*particleItr);
|
||||
float radius = particle->getRadius();
|
||||
// NOTE: we actually do box-box collision queries here, which is sloppy but good enough for now
|
||||
// TODO: decide whether to replace particleBox-box query with sphere-box (requires a square root
|
||||
// but will be slightly more accurate).
|
||||
particleBox.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius);
|
||||
if (particleBox.touches(_box)) {
|
||||
foundParticles.push_back(particle);
|
||||
}
|
||||
++particleItr;
|
||||
}
|
||||
}
|
||||
|
||||
const Particle* ParticleTreeElement::getParticleWithID(uint32_t id) const {
|
||||
|
@ -228,22 +241,6 @@ bool ParticleTreeElement::removeParticleWithID(uint32_t id) {
|
|||
return foundParticle;
|
||||
}
|
||||
|
||||
void ParticleTreeElement::findParticles(const AABox& box, QVector<Particle*>& foundParticles) {
|
||||
QList<Particle>::iterator particleItr = _particles->begin();
|
||||
QList<Particle>::iterator particleEnd = _particles->end();
|
||||
AABox particleBox;
|
||||
while(particleItr != particleEnd) {
|
||||
Particle* particle = &(*particleItr);
|
||||
float radius = particle->getRadius();
|
||||
particleBox.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius);
|
||||
// TODO: replace particleBox-box query with sphere-box
|
||||
if (particleBox.touches(_box)) {
|
||||
foundParticles.push_back(particle);
|
||||
}
|
||||
++particleItr;
|
||||
}
|
||||
}
|
||||
|
||||
int ParticleTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args) {
|
||||
|
||||
|
|
|
@ -89,15 +89,21 @@ public:
|
|||
bool containsParticle(const Particle& particle) const;
|
||||
bool updateParticle(const Particle& particle);
|
||||
const Particle* getClosestParticle(glm::vec3 position) const;
|
||||
QVector<const Particle*> getParticles(glm::vec3 position, float radius) const;
|
||||
const Particle* getParticleWithID(uint32_t id) const;
|
||||
|
||||
bool removeParticleWithID(uint32_t id);
|
||||
/// finds all particles that touch a sphere
|
||||
/// \param position the center of the query sphere
|
||||
/// \param radius the radius of the query sphere
|
||||
/// \param particles[out] vector of const Particle*
|
||||
void getParticles(const glm::vec3& position, float radius, QVector<const Particle*>& foundParticles) const;
|
||||
|
||||
/// finds all particles that touch a box
|
||||
/// \param box the query box
|
||||
/// \param particles[out] vector of Particle pointers
|
||||
void findParticles(const AABox& box, QVector<Particle*>& foundParticles);
|
||||
/// \param particles[out] vector of non-const Particle*
|
||||
void getParticlesForUpdate(const AABox& box, QVector<Particle*>& foundParticles);
|
||||
|
||||
const Particle* getParticleWithID(uint32_t id) const;
|
||||
|
||||
bool removeParticleWithID(uint32_t id);
|
||||
|
||||
protected:
|
||||
virtual void init(unsigned char * octalCode);
|
||||
|
|
|
@ -150,7 +150,8 @@ ParticleID ParticlesScriptingInterface::findClosestParticle(const glm::vec3& cen
|
|||
QVector<ParticleID> ParticlesScriptingInterface::findParticles(const glm::vec3& center, float radius) const {
|
||||
QVector<ParticleID> result;
|
||||
if (_particleTree) {
|
||||
QVector<const Particle*> particles = _particleTree->findParticles(center/(float)TREE_SCALE, radius/(float)TREE_SCALE);
|
||||
QVector<const Particle*> particles;
|
||||
_particleTree->findParticles(center/(float)TREE_SCALE, radius/(float)TREE_SCALE, particles);
|
||||
|
||||
foreach (const Particle* particle, particles) {
|
||||
ParticleID thisParticleID(particle->getID(), UNKNOWN_TOKEN, true);
|
||||
|
|
Loading…
Reference in a new issue