I’m currently trying to create a class that can keep track of when objects enter and exit an overlap.
Currently my class to track this is:
class OverlapDetector {
public:
OverlapDetector(const ci::vec3& center, float OverlapDistance) : mCurrentResults(),
mPreviousResults(),
mQueryFilter(),
mTransform(sitara::ecs::physics::to(ci::quat(), center)) {
mOverlapShape = new physx::PxSphereGeometry(OverlapDistance);
mCurrentResults.reserve(4096);
mPreviousResults.reserve(4096);
}
~OverlapDetector() {
delete mOverlapShape;
}
protected:
physx::PxGeometry& getGeometry() {
return *mOverlapShape;
}
physx::PxTransform& getTransform() {
return mTransform;
}
physx::PxOverlapHit* getWriteBuffer() {
return mCurrentResults.data();
}
int getBufferSize() {
return mBufferSize;
}
void resizeBuffer(size_t size) {
mCurrentResults.resize(size);
}
void swapBuffers() {
mCurrentResults.swap(mPreviousResults);
mCurrentResults.clear();
}
std::vector<physx::PxOverlapHit>& getResults() {
return mCurrentResults;
}
std::vector<physx::PxOverlapHit>& getPreviousResults() {
return mPreviousResults;
}
physx::PxQueryFilterData& getFilter() {
return mQueryFilter;
}
static const int mBufferSize = 4096;
physx::PxGeometry* mOverlapShape;
physx::PxTransform mTransform;
physx::PxQueryFilterData mQueryFilter;
std::vector<physx::PxOverlapHit> mCurrentResults;
std::vector<physx::PxOverlapHit> mPreviousResults;
The idea is that the class uses two std::vector
s to hold this query’s results, and the previous query’s results. My main loop is:
proximityDetector->swapBuffers();
size_t num = physx::PxSceneQueryExt::overlapMultiple(*mScene,
proximityDetector->getGeometry(),
proximityDetector->getTransform(),
proximityDetector->getWriteBuffer(),
proximityDetector->getBufferSize(),
proximityDetector->getFilter());
proximityDetector->resizeBuffer(num);
std::cout << "Detected " << num << " overlaps." << std::endl;
for (auto& hit : proximityDetector->getResults()) {
std::cout << "Starting collision detection" << std::endl;
if (hit.actor != nullptr) {
std::cout << "Test " << std::endl;
auto prev = proximityDetector->getPreviousResults();
auto it = std::find_if(prev.begin(), prev.end(), [&](const physx::PxOverlapHit& h) {return h.actor->userData == hit.actor->userData; });
if (it != prev.end()) {
// in current collision + previous collision, still colliding
std::cout << "Still Colliding..." << std::endl;
}
}
}
for (auto& hit : proximityDetector->getPreviousResults()) {
if (hit.actor != nullptr) {
auto res = proximityDetector->getResults();
auto it = std::find_if(res.begin(), res.end(), [&](const physx::PxOverlapHit& h) {return h.actor->userData == hit.actor->userData; });
if (it != res.end()) {
// in previous collision but NOT in current collision, ending collision
std::cout << "Ending Collision." << std::endl;
}
}
}
For the purposes of checking if a hit in both lists is the same, I check whether the userData is pointing to the same user application object.
Using this code, I am finding that my buffers consistently have the correct number of hits, but when I check the hit.actor
attribute, they are always nullptr
. Am I doing something incorrect here? I want to know which actor each hit is associated with.