mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 09:16:14 +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) {
|
bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) {
|
||||||
FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData);
|
FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData);
|
||||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
|
||||||
|
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position,
|
bool sphereIntersection = element->getAABox().findSpherePenetration(args->position,
|
||||||
args->targetRadius, penetration);
|
args->targetRadius, penetration);
|
||||||
|
|
||||||
// If this particleTreeElement contains the point, then search it...
|
// If this element contains the point, then search it...
|
||||||
if (sphereIntersection) {
|
if (sphereIntersection) {
|
||||||
QVector<const Particle*> moreParticles = particleTreeElement->getParticles(args->position, args->targetRadius);
|
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||||
args->particles << moreParticles;
|
particleTreeElement->getParticles(args->position, args->targetRadius, args->particles);
|
||||||
return true; // keep searching in case children have closer particles
|
return true; // keep searching in case children have closer particles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,13 +185,43 @@ bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<const Particle*> ParticleTree::findParticles(const glm::vec3& center, float radius) {
|
void ParticleTree::findParticles(const glm::vec3& center, float radius, QVector<const Particle*>& foundParticles) {
|
||||||
QVector<Particle*> result;
|
|
||||||
FindAllNearPointArgs args = { center, radius };
|
FindAllNearPointArgs args = { center, radius };
|
||||||
lockForRead();
|
lockForRead();
|
||||||
recurseTreeWithOperation(findInSphereOperation, &args);
|
recurseTreeWithOperation(findInSphereOperation, &args);
|
||||||
unlock();
|
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 {
|
class FindByIDArgs {
|
||||||
|
@ -495,31 +523,3 @@ void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const Hi
|
||||||
recurseTreeWithOperation(findAndDeleteOperation, &args);
|
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);
|
void storeParticle(const Particle& particle, Node* senderNode = NULL);
|
||||||
const Particle* findClosestParticle(glm::vec3 position, float targetRadius);
|
const Particle* findClosestParticle(glm::vec3 position, float targetRadius);
|
||||||
const Particle* findParticleByID(uint32_t id, bool alreadyLocked = false);
|
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 addNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
||||||
void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook);
|
||||||
|
@ -54,12 +66,6 @@ public:
|
||||||
|
|
||||||
void processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode);
|
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:
|
private:
|
||||||
|
|
||||||
static bool updateOperation(OctreeElement* element, void* extraData);
|
static bool updateOperation(OctreeElement* element, void* extraData);
|
||||||
|
|
|
@ -185,21 +185,34 @@ const Particle* ParticleTreeElement::getClosestParticle(glm::vec3 position) cons
|
||||||
return closestParticle;
|
return closestParticle;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<const Particle*> ParticleTreeElement::getParticles(glm::vec3 searchPosition, float searchRadius) const {
|
void ParticleTreeElement::getParticles(const glm::vec3& searchPosition, float searchRadius, QVector<const Particle*>& foundParticles) const {
|
||||||
QVector<const Particle*> results;
|
|
||||||
uint16_t numberOfParticles = _particles->size();
|
uint16_t numberOfParticles = _particles->size();
|
||||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||||
const Particle* particle = &(*_particles)[i];
|
const Particle* particle = &(*_particles)[i];
|
||||||
glm::vec3 particlePosition = particle->getPosition();
|
glm::vec3 particlePosition = particle->getPosition();
|
||||||
float particleRadius = particle->getRadius();
|
float distance = glm::length(particle->getPosition() - searchPosition);
|
||||||
glm::vec3 penetration;
|
if (distance < searchRadius + particle->getRadius()) {
|
||||||
|
foundParticles.push_back(particle);
|
||||||
// check to see that the particle (penetrator) penetrates the search area
|
|
||||||
if (findSphereSpherePenetration(particlePosition, particleRadius, searchPosition, searchRadius, penetration)) {
|
|
||||||
results << 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 {
|
const Particle* ParticleTreeElement::getParticleWithID(uint32_t id) const {
|
||||||
|
@ -228,22 +241,6 @@ bool ParticleTreeElement::removeParticleWithID(uint32_t id) {
|
||||||
return foundParticle;
|
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,
|
int ParticleTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||||
ReadBitstreamToTreeParams& args) {
|
ReadBitstreamToTreeParams& args) {
|
||||||
|
|
||||||
|
|
|
@ -89,15 +89,21 @@ public:
|
||||||
bool containsParticle(const Particle& particle) const;
|
bool containsParticle(const Particle& particle) const;
|
||||||
bool updateParticle(const Particle& particle);
|
bool updateParticle(const Particle& particle);
|
||||||
const Particle* getClosestParticle(glm::vec3 position) const;
|
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
|
/// finds all particles that touch a box
|
||||||
/// \param box the query box
|
/// \param box the query box
|
||||||
/// \param particles[out] vector of Particle pointers
|
/// \param particles[out] vector of non-const Particle*
|
||||||
void findParticles(const AABox& box, QVector<Particle*>& foundParticles);
|
void getParticlesForUpdate(const AABox& box, QVector<Particle*>& foundParticles);
|
||||||
|
|
||||||
|
const Particle* getParticleWithID(uint32_t id) const;
|
||||||
|
|
||||||
|
bool removeParticleWithID(uint32_t id);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void init(unsigned char * octalCode);
|
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> ParticlesScriptingInterface::findParticles(const glm::vec3& center, float radius) const {
|
||||||
QVector<ParticleID> result;
|
QVector<ParticleID> result;
|
||||||
if (_particleTree) {
|
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) {
|
foreach (const Particle* particle, particles) {
|
||||||
ParticleID thisParticleID(particle->getID(), UNKNOWN_TOKEN, true);
|
ParticleID thisParticleID(particle->getID(), UNKNOWN_TOKEN, true);
|
||||||
|
|
Loading…
Reference in a new issue