// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #pragma once #include #include JPH_NAMESPACE_BEGIN /// Simple implementation that collects all hits and optionally sorts them on distance template class AllHitCollisionCollector : public CollectorType { public: /// Redeclare ResultType using ResultType = typename CollectorType::ResultType; // See: CollectorType::Reset virtual void Reset() override { CollectorType::Reset(); mHits.clear(); } // See: CollectorType::AddHit virtual void AddHit(const ResultType &inResult) override { mHits.push_back(inResult); } /// Order hits on closest first void Sort() { QuickSort(mHits.begin(), mHits.end(), [](const ResultType &inLHS, const ResultType &inRHS) { return inLHS.GetEarlyOutFraction() < inRHS.GetEarlyOutFraction(); }); } /// Check if any hits were collected inline bool HadHit() const { return !mHits.empty(); } Array mHits; }; /// Simple implementation that collects the closest / deepest hit template class ClosestHitCollisionCollector : public CollectorType { public: /// Redeclare ResultType using ResultType = typename CollectorType::ResultType; // See: CollectorType::Reset virtual void Reset() override { CollectorType::Reset(); mHadHit = false; } // See: CollectorType::AddHit virtual void AddHit(const ResultType &inResult) override { float early_out = inResult.GetEarlyOutFraction(); if (!mHadHit || early_out < mHit.GetEarlyOutFraction()) { // Update early out fraction CollectorType::UpdateEarlyOutFraction(early_out); // Store hit mHit = inResult; mHadHit = true; } } /// Check if this collector has had a hit inline bool HadHit() const { return mHadHit; } ResultType mHit; private: bool mHadHit = false; }; /// Implementation that collects the closest / deepest hit for each body and optionally sorts them on distance template class ClosestHitPerBodyCollisionCollector : public CollectorType { public: /// Redeclare ResultType using ResultType = typename CollectorType::ResultType; // See: CollectorType::Reset virtual void Reset() override { CollectorType::Reset(); mHits.clear(); mHadHit = false; } // See: CollectorType::OnBody virtual void OnBody(const Body &inBody) override { // Store the early out fraction so we can restore it after we've collected all hits for this body mPreviousEarlyOutFraction = CollectorType::GetEarlyOutFraction(); } // See: CollectorType::AddHit virtual void AddHit(const ResultType &inResult) override { float early_out = inResult.GetEarlyOutFraction(); if (!mHadHit || early_out < CollectorType::GetEarlyOutFraction()) { // Update early out fraction to avoid spending work on collecting further hits for this body CollectorType::UpdateEarlyOutFraction(early_out); if (!mHadHit) { // First time we have a hit we append it to the array mHits.push_back(inResult); mHadHit = true; } else { // Closer hits will override the previous one mHits.back() = inResult; } } } // See: CollectorType::OnBodyEnd virtual void OnBodyEnd() override { if (mHadHit) { // Reset the early out fraction to the configured value so that we will continue // to collect hits at any distance for other bodies JPH_ASSERT(mPreviousEarlyOutFraction != -FLT_MAX); // Check that we got a call to OnBody CollectorType::ResetEarlyOutFraction(mPreviousEarlyOutFraction); mHadHit = false; } // For asserting purposes we reset the stored early out fraction so we can detect that OnBody was called JPH_IF_ENABLE_ASSERTS(mPreviousEarlyOutFraction = -FLT_MAX;) } /// Order hits on closest first void Sort() { QuickSort(mHits.begin(), mHits.end(), [](const ResultType &inLHS, const ResultType &inRHS) { return inLHS.GetEarlyOutFraction() < inRHS.GetEarlyOutFraction(); }); } /// Check if any hits were collected inline bool HadHit() const { return !mHits.empty(); } Array mHits; private: // Store early out fraction that was initially configured for the collector float mPreviousEarlyOutFraction = -FLT_MAX; // Flag to indicate if we have a hit for the current body bool mHadHit = false; }; /// Simple implementation that collects any hit template class AnyHitCollisionCollector : public CollectorType { public: /// Redeclare ResultType using ResultType = typename CollectorType::ResultType; // See: CollectorType::Reset virtual void Reset() override { CollectorType::Reset(); mHadHit = false; } // See: CollectorType::AddHit virtual void AddHit(const ResultType &inResult) override { // Test that the collector is not collecting more hits after forcing an early out JPH_ASSERT(!mHadHit); // Abort any further testing CollectorType::ForceEarlyOut(); // Store hit mHit = inResult; mHadHit = true; } /// Check if this collector has had a hit inline bool HadHit() const { return mHadHit; } ResultType mHit; private: bool mHadHit = false; }; JPH_NAMESPACE_END