载入中...
搜索中...
未找到
Solver2D.cpp
浏览该文件的文档.
1#include "ik/Solver2D.h"
2
3#include "common/Exception.h"
4
5#include <algorithm>
6
7namespace eve::ik {
8
9void Solver2D::setKeepTrace(bool keep) {
10 keepTrace_ = keep;
11 solver_.setKeepTrace(keep);
12}
13
14bool Solver2D::getKeepTrace() const { return keepTrace_; }
15
17 if (iterations < 0) {
18 throw Exception("Solver2D.setMaxIterations: iterations must be >= 0");
19 }
20 maxIterations_ = iterations;
21 solver_.setMaxIterations(static_cast<unsigned>(iterations));
22}
23
24int Solver2D::getMaxIterations() const { return maxIterations_; }
25
26void Solver2D::setTolerance(float tol) {
27 if (tol < 0.f) {
28 throw Exception("Solver2D.setTolerance: tolerance must be >= 0");
29 }
30 tolerance_ = tol;
31 solver_.setTolerance(tol);
32}
33
34float Solver2D::getTolerance() const { return tolerance_; }
35
36void Solver2D::setForce(float force) {
37 force_ = force;
38 solver_.setForce(force);
39}
40
41float Solver2D::getForce() const { return force_; }
42
43void Solver2D::setInfluence(float influence) {
44 if (influence < 0.f || influence > 1.f) {
45 throw Exception("Solver2D.setInfluence: influence must be in [0, 1]");
46 }
47 influence_ = influence;
48}
49
50float Solver2D::getInfluence() const { return influence_; }
51
52void Solver2D::clearTargets() { solver_.clearTargets(); }
53
54void Solver2D::addTarget(int boneId, float x, float y, float weight) {
55 if (boneId < 0) {
56 throw Exception("Solver2D.addTarget: boneId must be >= 0");
57 }
58 solver_.addTarget(static_cast<unsigned>(boneId), ::ik::vec2{x, y}, weight);
59}
60
62 return static_cast<int>(solver_.targets().size());
63}
64
65bool Solver2D::solve(Skeleton2D *skeleton) {
66 if (!skeleton) {
67 throw Exception("Solver2D.solve: skeleton is null");
68 }
69 ::ik::ecs2d &state = skeleton->state();
70 std::vector<::ik::vec2> original;
71 if (influence_ < 1.f) {
72 original = state.position_;
73 }
74 const bool reached = solver_.solve(skeleton->native(), state);
75 if (influence_ < 1.f) {
76 const float t = influence_;
77 for (size_t i = 0; i < state.position_.size(); ++i) {
78 state.position_[i] = original[i] + (state.position_[i] - original[i]) * t;
79 }
80 skeleton->native().update_rotations(state);
81 }
82 return reached;
83}
84
85void Solver2D::step(Skeleton2D *skeleton, float dt) {
86 if (!skeleton) {
87 throw Exception("Solver2D.step: skeleton is null");
88 }
89 ::ik::ecs2d &state = skeleton->state();
90 std::vector<::ik::vec2> original;
91 if (influence_ < 1.f) {
92 original = state.position_;
93 }
94 solver_.step(skeleton->native(), skeleton->state(), dt);
95 if (influence_ < 1.f) {
96 const float t = influence_;
97 for (size_t i = 0; i < state.position_.size(); ++i) {
98 state.position_[i] = original[i] + (state.position_[i] - original[i]) * t;
99 }
100 skeleton->native().update_rotations(state);
101 }
102}
103
104bool Solver2D::solveChain(Skeleton2D *skeleton, int rootBoneId, int tipBoneId) {
106 options.tolerance = tolerance_;
107 options.max_iterations = static_cast<unsigned>(maxIterations_);
108 options.force = force_;
109 options.influence = influence_;
110 return solveChainImpl(skeleton, rootBoneId, tipBoneId, options);
111}
112
113void Solver2D::stepChain(Skeleton2D *skeleton, int rootBoneId, int tipBoneId, float dt) {
115 options.tolerance = tolerance_;
116 options.max_iterations = 1;
117 options.influence = influence_;
118 float f = force_;
119 if (f <= 0.f) {
120 f = std::min(1.f, std::max(0.f, dt));
121 } else {
122 f = std::min(1.f, f * std::max(0.f, dt));
123 }
124 options.force = f;
125 solveChainImpl(skeleton, rootBoneId, tipBoneId, options);
126}
127
128bool Solver2D::solveChainImpl(Skeleton2D *skeleton, int rootBoneId, int tipBoneId,
129 const detail::ChainOptions<2> &options) {
130 if (!skeleton) {
131 throw Exception("Solver2D.solveChain: skeleton is null");
132 }
133 if (rootBoneId < 0 || tipBoneId < 0) {
134 throw Exception("Solver2D.solveChain: bone ids must be >= 0");
135 }
136 const int count = skeleton->getBoneCount();
137 if (rootBoneId >= count || tipBoneId >= count) {
138 throw Exception("Solver2D.solveChain: bone id out of range");
139 }
140 if (rootBoneId == tipBoneId) {
141 throw Exception("Solver2D.solveChain: root and tip must differ");
142 }
143 int b = tipBoneId;
144 bool found = false;
145 while (b >= 0) {
146 if (b == rootBoneId) {
147 found = true;
148 break;
149 }
150 b = skeleton->getParent(b);
151 }
152 if (!found) {
153 throw Exception("Solver2D.solveChain: tipBoneId is not a descendant of rootBoneId");
154 }
155 return detail::solveChain<2>(skeleton->native(), skeleton->state(),
156 static_cast<unsigned>(rootBoneId),
157 static_cast<unsigned>(tipBoneId), solver_.targets(), options);
158}
159
160int Solver2D::getTraceSize() const { return static_cast<int>(solver_.traceSize()); }
161
162void Solver2D::clearTrace() { solver_.clearTrace(); }
163
164} // namespace eve::ik
int y
Definition Grass.cpp:135
int x
Definition Grass.cpp:135
JobSystemThreadPool::State * state
uint32_t b
float f
int iterations
Definition TreeMesh.cpp:193
Script-facing 2D skeleton + pose state (ik::skeleton2d + ik::ecs2d). Bone indices are stable after ea...
Definition Skeleton2D.h:12
::ik::skeleton2d & native()
Definition Skeleton2D.h:56
::ik::ecs2d & state()
Definition Skeleton2D.h:57
int getBoneCount() const
int getParent(int boneId) const
int getMaxIterations() const
Definition Solver2D.cpp:24
int getTargetCount() const
Definition Solver2D.cpp:61
void setForce(float force)
Definition Solver2D.cpp:36
bool getKeepTrace() const
Definition Solver2D.cpp:14
void setMaxIterations(int iterations)
Definition Solver2D.cpp:16
void step(Skeleton2D *skeleton, float dt=1.f)
Definition Solver2D.cpp:85
void setTolerance(float tol)
Definition Solver2D.cpp:26
int getTraceSize() const
Definition Solver2D.cpp:160
void setKeepTrace(bool keep)
Definition Solver2D.cpp:9
void setInfluence(float influence)
Overall pose blend: 0 = keep the input pose, 1 = full solve (default).
Definition Solver2D.cpp:43
float getForce() const
Definition Solver2D.cpp:41
void addTarget(int boneId, float x, float y, float weight=1.f)
Definition Solver2D.cpp:54
bool solve(Skeleton2D *skeleton)
Returns true if every target is within tolerance.
Definition Solver2D.cpp:65
bool solveChain(Skeleton2D *skeleton, int rootBoneId, int tipBoneId)
FABRIK solve restricted to the bone chain rootBoneId..tipBoneId. The chain root stays pinned and bone...
Definition Solver2D.cpp:104
void stepChain(Skeleton2D *skeleton, int rootBoneId, int tipBoneId, float dt=1.f)
Definition Solver2D.cpp:113
float getTolerance() const
Definition Solver2D.cpp:34
float getInfluence() const
Definition Solver2D.cpp:50
Options shared by the chain-scoped FABRIK solve used by Solver2D / Solver3D. These mirror the knobs o...
Definition ChainSolver.h:18