载入中...
搜索中...
未找到
Rope3DTopology.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5
6namespace eve::physics {
7namespace {
8Rope3D::Vec3 subtract(Rope3D::Vec3 a, Rope3D::Vec3 b) { return {a.x - b.x, a.y - b.y, a.z - b.z}; }
9Rope3D::Vec3 addScaled(Rope3D::Vec3 a, Rope3D::Vec3 direction, float scale) {
10 return {a.x + direction.x * scale, a.y + direction.y * scale, a.z + direction.z * scale};
11}
12float magnitude(Rope3D::Vec3 value) { return std::sqrt(value.x * value.x + value.y * value.y + value.z * value.z); }
13Rope3D::Vec3 direction(Rope3D::Vec3 from, Rope3D::Vec3 to) {
14 auto delta = subtract(to, from);
15 const float length = magnitude(delta);
16 if (length <= 1e-6f) return {1.f, 0.f, 0.f};
17 return {delta.x / length, delta.y / length, delta.z / length};
18}
19} // namespace
20
21eve::Result<RopeTopologyChange> Rope3D::changeLength(float requested, float spacing, bool fromEnd) {
22 if (!std::isfinite(requested) || requested <= 0.f || !std::isfinite(spacing) || spacing <= 0.f)
24 eve::DiagnosticCode::InvalidArgument, "Length and particle spacing must be finite and positive",
25 "physics.rope3d.changeLength"));
26 if (std::any_of(elements_.begin(), elements_.end(), [](const Element& element) { return !element.active; }))
28 eve::DiagnosticCode::Conflict, "A torn rope must be repaired before cursor topology changes",
29 "physics.rope3d.changeLength"));
30 const float original = getRestLength();
31 if (std::abs(requested - original) <= 1e-6f)
33
34 bool structuralChange = false;
35 if (requested > original) {
36 float remaining = requested - original;
37 while (remaining > 1e-6f) {
38 const float segmentLength = std::min(spacing, remaining);
39 if (particles_.size() >= 100000)
42 "physics.rope3d.changeLength"));
43 if (fromEnd) {
44 const auto heading = direction(particles_[particles_.size() - 2].position, particles_.back().position);
45 Particle particle;
46 particle.position = particle.previous = addScaled(particles_.back().position, heading, segmentLength);
47 const int previous = getParticleCount() - 1;
48 particles_.push_back(particle);
49 Element element;
50 element.a = previous;
51 element.b = previous + 1;
52 element.restLength = segmentLength;
53 elements_.push_back(element);
54 } else {
55 const auto heading = direction(particles_[1].position, particles_[0].position);
56 Particle particle;
57 particle.position = particle.previous = addScaled(particles_[0].position, heading, segmentLength);
58 particles_.insert(particles_.begin(), particle);
59 for (auto& element : elements_) {
60 ++element.a;
61 ++element.b;
62 }
63 Element element;
64 element.a = 0;
65 element.b = 1;
66 element.restLength = segmentLength;
67 elements_.insert(elements_.begin(), element);
68 }
69 remaining -= segmentLength;
70 structuralChange = true;
71 }
72 } else {
73 float remaining = original - requested;
74 while (elements_.size() > 1) {
75 Element& edge = fromEnd ? elements_.back() : elements_.front();
76 if (remaining + 1e-6f < edge.restLength) break;
77 remaining -= edge.restLength;
78 if (fromEnd) {
79 const Particle removed = particles_.back();
80 particles_.pop_back();
81 elements_.pop_back();
82 if (removed.attached) {
83 auto& endpoint = particles_.back();
84 endpoint.attached = true;
85 endpoint.attachment = endpoint.position = endpoint.previous = removed.attachment;
86 }
87 } else {
88 const Particle removed = particles_.front();
89 particles_.erase(particles_.begin());
90 elements_.erase(elements_.begin());
91 for (auto& element : elements_) {
92 --element.a;
93 --element.b;
94 }
95 if (removed.attached) {
96 auto& endpoint = particles_.front();
97 endpoint.attached = true;
98 endpoint.attachment = endpoint.position = endpoint.previous = removed.attachment;
99 }
100 }
101 structuralChange = true;
102 }
103 Element& edge = fromEnd ? elements_.back() : elements_.front();
104 edge.restLength = std::max(1e-6f, edge.restLength - remaining);
105 }
106 if (structuralChange || std::abs(requested - original) > 1e-6f) ++topologyRevision_;
107 syncBendState();
109}
110
111int Rope3D::getLastTornElement(int eventIndex) const {
112 return eventIndex >= 0 && eventIndex < getLastTornElementCount()
113 ? lastTornElements_[static_cast<std::size_t>(eventIndex)]
114 : -1;
115}
116
117} // namespace eve::physics
double value
std::string from
float length
Definition CaveMesh.cpp:94
HexCoordinates to
Cell the unit walks towards on this segment.
Definition HexUnits.cpp:64
std::array< float, 3 > position
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
graphics::Canvas * previous
RoadLaneDirection direction
const RoadEdge * edge
int removed
std::string element
int spacing
V3 heading
Definition TreeMesh.cpp:292
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
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
int getLastTornElement(int eventIndex) const
Returns a torn element index, or -1 for an invalid event index.
int getLastTornElementCount() const
Number of elements automatically torn by the most recent update/step.
Definition Rope3D.h:202
int getParticleCount() const
Definition Rope3D.h:206
float getRestLength() const
Definition Rope3D.cpp:223
eve::Result< RopeTopologyChange > changeLength(float length, float particleSpacing, bool fromEnd=true)
Changes material length at one endpoint by adding/removing particles near the requested spacing.
Optional physics backend for vehicle mobility and body attach.
Definition Climbing.h:36