11 solver_.setKeepTrace(keep);
18 throw Exception(
"Solver2D.setMaxIterations: iterations must be >= 0");
21 solver_.setMaxIterations(
static_cast<unsigned>(
iterations));
28 throw Exception(
"Solver2D.setTolerance: tolerance must be >= 0");
31 solver_.setTolerance(tol);
38 solver_.setForce(force);
44 if (influence < 0.f || influence > 1.f) {
45 throw Exception(
"Solver2D.setInfluence: influence must be in [0, 1]");
47 influence_ = influence;
56 throw Exception(
"Solver2D.addTarget: boneId must be >= 0");
58 solver_.addTarget(
static_cast<unsigned>(boneId), ::ik::vec2{
x,
y},
weight);
62 return static_cast<int>(solver_.targets().size());
67 throw Exception(
"Solver2D.solve: skeleton is null");
70 std::vector<::ik::vec2> original;
71 if (influence_ < 1.f) {
72 original =
state.position_;
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;
87 throw Exception(
"Solver2D.step: skeleton is null");
90 std::vector<::ik::vec2> original;
91 if (influence_ < 1.f) {
92 original =
state.position_;
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;
107 options.max_iterations =
static_cast<unsigned>(maxIterations_);
109 options.influence = influence_;
110 return solveChainImpl(skeleton, rootBoneId, tipBoneId,
options);
117 options.influence = influence_;
120 f = std::min(1.f, std::max(0.f, dt));
122 f = std::min(1.f,
f * std::max(0.f, dt));
125 solveChainImpl(skeleton, rootBoneId, tipBoneId,
options);
128bool Solver2D::solveChainImpl(
Skeleton2D *skeleton,
int rootBoneId,
int tipBoneId,
131 throw Exception(
"Solver2D.solveChain: skeleton is null");
133 if (rootBoneId < 0 || tipBoneId < 0) {
134 throw Exception(
"Solver2D.solveChain: bone ids must be >= 0");
137 if (rootBoneId >=
count || tipBoneId >=
count) {
138 throw Exception(
"Solver2D.solveChain: bone id out of range");
140 if (rootBoneId == tipBoneId) {
141 throw Exception(
"Solver2D.solveChain: root and tip must differ");
146 if (
b == rootBoneId) {
153 throw Exception(
"Solver2D.solveChain: tipBoneId is not a descendant of rootBoneId");
155 return detail::solveChain<2>(skeleton->
native(), skeleton->
state(),
156 static_cast<unsigned>(rootBoneId),
157 static_cast<unsigned>(tipBoneId), solver_.targets(),
options);
const SquirrelValueOptions & options
EVENGINE_API_FOUNDATION public API.
Script-facing 2D skeleton + pose state (ik::skeleton2d + ik::ecs2d). Bone indices are stable after ea...
::ik::skeleton2d & native()
int getBoneCount() const
Number of bones currently in the skeleton.
int getParent(int boneId) const
Parent bone id, or -1 for the root.
int getMaxIterations() const
Configured maximum FABRIK iterations.
int getTargetCount() const
Number of configured targets.
void setForce(float force)
Soft-IK blend toward the target (0 = hard IK).
bool getKeepTrace() const
Whether solve tracing is enabled.
void setMaxIterations(int iterations)
Maximum FABRIK iterations per solve.
void step(Skeleton2D *skeleton, float dt=1.f)
Runs a time-scaled FABRIK step (dt scales iteration effort).
void setTolerance(float tol)
End-effector distance tolerance for success.
int getTraceSize() const
Number of recorded trace samples.
void clearTargets()
Removes all IK targets.
void setKeepTrace(bool keep)
When true, records intermediate solve samples.
void setInfluence(float influence)
Overall pose blend: 0 = keep the input pose, 1 = full solve (default).
float getForce() const
Configured soft-IK force.
void addTarget(int boneId, float x, float y, float weight=1.f)
Adds an end-effector target for a bone.
bool solve(Skeleton2D *skeleton)
Returns true if every target is within tolerance.
bool solveChain(Skeleton2D *skeleton, int rootBoneId, int tipBoneId)
FABRIK solve restricted to the bone chain rootBoneId..tipBoneId. The chain root stays pinned and bone...
void stepChain(Skeleton2D *skeleton, int rootBoneId, int tipBoneId, float dt=1.f)
Time-scaled chain-scoped FABRIK step.
float getTolerance() const
Configured end-effector tolerance.
void clearTrace()
Clears recorded solve trace samples.
float getInfluence() const
Pose blend weight (0 = keep input, 1 = full solve).
Options shared by the chain-scoped FABRIK solve used by Solver2D / Solver3D. These mirror the knobs o...