载入中...
搜索中...
未找到
Cloth3DTearing.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4
5#include <algorithm>
6#include <cmath>
7#include <map>
8#include <utility>
9#include <vector>
10
11namespace eve::physics {
12
13float Cloth3D::getTearThreshold() const { return tearThreshold_; }
14int Cloth3D::getMaxTearsPerStep() const { return maxTearsPerStep_; }
15int Cloth3D::getTornConstraintCount() const { return tornConstraintCount_; }
16
17void Cloth3D::setTearThreshold(float strain) {
18 tearThreshold_ = std::isfinite(strain) && strain > 1.f ? strain : 0.f;
19}
20
21void Cloth3D::setMaxTearsPerStep(int count) { maxTearsPerStep_ = std::max(0, count); }
22
23void Cloth3D::tearConstraint(int particleA, int particleB) {
24 if (!validIndex(particleA) || !validIndex(particleB))
25 throw Exception("Cloth3D.tearConstraint: particle index out of range");
26 const auto found = std::find_if(links_.begin(), links_.end(), [particleA, particleB](const Link& link) {
27 return link.kind == ClothConstraintKind::Structural &&
28 ((link.a == particleA && link.b == particleB) || (link.a == particleB && link.b == particleA));
29 });
30 if (found == links_.end()) throw Exception("Cloth3D.tearConstraint: structural edge not found");
31 tearLink(static_cast<size_t>(std::distance(links_.begin(), found)));
32}
33
34void Cloth3D::applyAutomaticTearing() {
35 if (tearThreshold_ <= 1.f || maxTearsPerStep_ <= 0) return;
36 int torn = 0;
37 for (size_t index = 0; index < links_.size() && torn < maxTearsPerStep_;) {
38 const Link& link = links_[index];
39 if (link.kind != ClothConstraintKind::Structural || link.rest <= 1e-7f) {
40 ++index;
41 continue;
42 }
43 const Particle& a = particles_[static_cast<size_t>(link.a)];
44 const Particle& b = particles_[static_cast<size_t>(link.b)];
45 const float dx = b.x - a.x;
46 const float dy = b.y - a.y;
47 const float dz = b.z - a.z;
48 if (std::sqrt(dx * dx + dy * dy + dz * dz) <= link.rest * tearThreshold_) {
49 ++index;
50 continue;
51 }
52 tearLink(index);
53 ++torn;
54 }
55}
56
57void Cloth3D::tearLink(size_t linkIndex) {
58 const int a = links_[linkIndex].a;
59 const int b = links_[linkIndex].b;
60 links_.erase(links_.begin() + static_cast<std::ptrdiff_t>(linkIndex));
61 std::erase_if(triangles_, [a, b](const Tri& triangle) {
62 bool hasA = false;
63 bool hasB = false;
64 for (int vertex : triangle.v) {
65 hasA = hasA || vertex == a;
66 hasB = hasB || vertex == b;
67 }
68 return hasA && hasB;
69 });
70 ++tornConstraintCount_;
71 buildLinkKeys();
72 rebuildFoldPairsFromTriangles();
73}
74
75void Cloth3D::rebuildFoldPairsFromTriangles() {
76 struct EdgeUse {
77 int a = 0;
78 int b = 0;
79 std::vector<int> opposites;
80 };
81 std::map<std::pair<int, int>, EdgeUse> edges;
82 for (const Tri& triangle : triangles_) {
83 for (int edge = 0; edge < 3; ++edge) {
84 const int first = triangle.v[edge];
85 const int second = triangle.v[(edge + 1) % 3];
86 const int opposite = triangle.v[(edge + 2) % 3];
87 const auto key = std::minmax(first, second);
88 EdgeUse& use = edges[{key.first, key.second}];
89 use.a = key.first;
90 use.b = key.second;
91 use.opposites.push_back(opposite);
92 }
93 }
94 foldPairs_.clear();
95 for (const auto& [key, use] : edges)
96 if (use.opposites.size() == 2)
97 foldPairs_.push_back({use.a, use.b, use.opposites[0], use.opposites[1]});
98}
99
100} // namespace eve::physics
int triangle
std::uint32_t key
float v
std::int32_t second
std::int32_t first
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
const RoadEdge * edge
bool found
float dz
float dy
float dx
std::uint32_t count
float size
Definition TreeMesh.cpp:156
uint32_t index
std::vector< int > edges
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
int getMaxTearsPerStep() const
Return the automatic tear budget per substep.
void setMaxTearsPerStep(int count)
Limit automatic structural tears per simulation substep.
int getTornConstraintCount() const
Return the cumulative number of torn structural constraints.
void tearConstraint(int particleA, int particleB)
Tear an existing structural edge.
float getTearThreshold() const
Return the automatic tear strain threshold, or zero when disabled.
void setTearThreshold(float strain)
Set automatic structural-edge tear strain; zero disables, values must exceed one.
constexpr HexDirection opposite(HexDirection d) noexcept
The direction opposite to d.
Definition HexMetrics.h:65
Optional physics backend for vehicle mobility and body attach.
Definition Climbing.h:36