载入中...
搜索中...
未找到
VolumeFluidContactTracker.cpp
浏览该文件的文档.
1#include <algorithm>
2#include <cmath>
4
5namespace eve::fluids {
6namespace {
7bool keyLess(const VolumeFluidContact& a, const VolumeFluidContact& b) {
8 return a.colliderLabel < b.colliderLabel || (a.colliderLabel == b.colliderLabel && a.actorGroup < b.actorGroup);
9}
10bool sameKey(const VolumeFluidContact& a, const VolumeFluidContact& b) {
11 return a.colliderLabel == b.colliderLabel && a.actorGroup == b.actorGroup;
12}
13bool finiteContact(const VolumeFluidContact& contact) {
14 const auto finite3 = [](glm::vec3 value) {
15 return std::isfinite(value.x) && std::isfinite(value.y) && std::isfinite(value.z);
16 };
17 return finite3(contact.point) && finite3(contact.normal) && finite3(contact.impulse) &&
18 std::isfinite(contact.distance);
19}
20} // namespace
21
23 std::span<const VolumeFluidContact> contacts, float distanceThreshold) {
25 if (contacts.size() > 65536 || !std::isfinite(distanceThreshold) || distanceThreshold < 0.f ||
26 distanceThreshold > 1.f ||
27 std::any_of(contacts.begin(), contacts.end(), [](const auto& contact) { return !finiteContact(contact); }))
28 return Output::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid contact event batch",
29 "fluids.volume.contacts"));
30
31 scratch_.clear();
32 scratch_.reserve(std::max(scratch_.capacity(), contacts.size()));
33 for (const auto& contact : contacts)
34 if (contact.distance <= distanceThreshold) scratch_.push_back(contact);
35 std::stable_sort(scratch_.begin(), scratch_.end(), keyLess);
36 scratch_.erase(std::unique(scratch_.begin(), scratch_.end(), sameKey), scratch_.end());
37
38 std::vector<VolumeFluidContactEvent> events;
39 events.reserve(scratch_.size() + previous_.size());
40 size_t current = 0, previous = 0;
41 while (current < scratch_.size() && previous < previous_.size()) {
42 if (keyLess(scratch_[current], previous_[previous]))
43 events.push_back({VolumeFluidContactEventType::Enter, scratch_[current++]});
44 else if (keyLess(previous_[previous], scratch_[current]))
45 events.push_back({VolumeFluidContactEventType::Exit, previous_[previous++]});
46 else {
47 events.push_back({VolumeFluidContactEventType::Stay, scratch_[current++]});
48 ++previous;
49 }
50 }
51 while (current < scratch_.size()) events.push_back({VolumeFluidContactEventType::Enter, scratch_[current++]});
52 while (previous < previous_.size()) events.push_back({VolumeFluidContactEventType::Exit, previous_[previous++]});
53 previous_ = scratch_;
54 return Output::success(std::move(events));
55}
56
58 previous_.clear();
59 scratch_.clear();
60}
61} // namespace eve::fluids
double value
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
graphics::Canvas * previous
double current
Battle::Events events
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
void reset()
Clears prior keys so the next contacts enter again.
Result< std::vector< VolumeFluidContactEvent > > advance(std::span< const VolumeFluidContact > contacts, float distanceThreshold=.01f)
Diffs latest contacts against the preceding successful call.
GLSL compute kernels for the GPU surface-flow solver.
Definition FluidTarget.h:12