2#include <hpp/utility/overload.hpp>
18 result.
set_translation(base.get_translation() + weight * (additive.get_translation() - ref.get_translation()));
21 math::quat additive_delta = additive.get_rotation() * glm::inverse(ref.get_rotation());
23 math::quat weighted_delta = math::slerp(math::identity<math::quat>(), additive_delta, weight);
25 result.
set_rotation(math::normalize(weighted_delta * base.get_rotation()));
28 result.
set_scale(base.get_scale() + weight * (additive.get_scale() - ref.get_scale()));
74 for(
const auto& ref_node : ref_pose.
nodes)
77 blended_node.
desc = ref_node.desc;
84 while(i_base < base.
nodes.size() && base.
nodes[i_base].desc.index < ref_node.desc.index)
89 if(i_base < base.
nodes.size() && base.
nodes[i_base].desc.index == ref_node.desc.index)
91 base_transform = base.
nodes[i_base].transform;
95 while(i_add < additive.
nodes.size() && additive.
nodes[i_add].desc.index < ref_node.desc.index)
99 if(i_add < additive.
nodes.size() && additive.
nodes[i_add].desc.index == ref_node.desc.index)
101 additive_transform = additive.
nodes[i_add].transform;
109 result.
nodes.push_back(blended_node);
125 result.
set_translation(math::lerp(lhs.get_translation(), rhs.get_translation(), factor));
126 result.
set_rotation(math::slerp(lhs.get_rotation(), rhs.get_rotation(), factor));
127 result.
set_scale(math::lerp(lhs.get_scale(), rhs.get_scale(), factor));
142 if(r1.root_position_node_index == -1)
146 else if(r2.root_position_node_index == -1)
155 if(r1.root_rotation_node_index == -1)
159 else if(r2.root_rotation_node_index == -1)
180 result.
nodes.clear();
188 while(i1 < pose1.
nodes.size() && i2 < pose2.
nodes.size())
190 const auto& node1 = pose1.
nodes[i1];
191 const auto& node2 = pose2.
nodes[i2];
193 if(node1.desc.index < node2.desc.index)
196 result.
nodes.push_back(node1);
199 else if(node1.desc.index > node2.desc.index)
202 result.
nodes.push_back(node2);
207 auto& node = result.
nodes.emplace_back();
209 node.desc = node1.desc;
210 node.transform =
blend(node1.transform, node2.transform, factor);
218 while(i1 < pose1.
nodes.size())
225 while(i2 < pose2.
nodes.size())
238 const std::vector<float>& weights,
242 if(poses.size() == 1)
250 size_t k = poses.size();
251 std::vector<size_t> idx(k, 0);
253 result.
nodes.clear();
259 size_t min_index = (size_t)-1;
260 bool all_finished =
true;
265 for(
size_t p = 0; p < k; ++p)
267 if(idx[p] < poses[p].nodes.size())
269 all_finished =
false;
270 size_t node_index = poses[p].nodes[idx[p]].desc.index;
271 if(min_index == (
size_t)-1 || node_index < min_index)
273 min_index = node_index;
285 float total_weight{0.0f};
287 bool first_transform_set{
false};
289 for(
size_t p = 0; p < k; ++p)
291 if(idx[p] < poses[p].nodes.size())
293 const auto& node = poses[p].nodes[idx[p]];
294 if(node.desc.index == min_index)
297 float w = weights[p];
298 if(!first_transform_set)
300 accum_transform = node.transform;
302 first_transform_set =
true;
309 float factor = w / (total_weight + w);
310 accum_transform =
blend(accum_transform, node.transform, factor);
322 auto& out = result.
nodes.emplace_back();
323 out.desc.index = min_index;
324 out.transform = accum_transform;
333 const std::vector<float>& weights,
342 parameter_count_ = params.size();
351 if(parameter_count_ == 1)
355 compute_blend_1d(current_params, out_clips);
358 if(parameter_count_ == 2)
360 compute_blend_2d(current_params, out_clips);
367void blend_space_def::compute_blend_1d(
const parameters_t& current_params,
371 float param = current_params[0];
374 std::set<float> unique_values;
375 for(
const auto&
point : points_)
377 unique_values.insert(
point.parameters[0]);
381 std::vector<float> sorted_values(unique_values.begin(), unique_values.end());
384 if(sorted_values.size() <= 1)
389 out_clips.emplace_back(points_.front().clip, 1.0f);
397 auto find_index_1d = [&](
float p)
399 for(
size_t i = 0;
i < sorted_values.size() - 1; ++
i)
401 if(p >= sorted_values[i] && p <= sorted_values[i + 1])
405 return sorted_values.size() - 2;
408 size_t idx = find_index_1d(param);
409 float v0 = sorted_values[idx];
410 float v1 = sorted_values[idx + 1];
414 if(fabs(v1 - v0) > 1e-5f)
415 t = (param - v0) / (v1 - v0);
417 t = math::clamp(t, 0.0f, 1.0f);
420 const blend_space_point* p0 =
nullptr;
421 const blend_space_point* p1 =
nullptr;
425 for(
const auto&
point : points_)
427 if(fabs(
point.parameters[0] - v0) < 1e-5f)
429 if(fabs(
point.parameters[0] - v1) < 1e-5f)
436 if(p0 && p1 && p0 != p1)
441 out_clips.emplace_back(p0->clip, w0);
442 out_clips.emplace_back(p1->clip, w1);
447 out_clips.emplace_back(p0->clip, 1.0f);
452 out_clips.emplace_back(p1->clip, 1.0f);
456void blend_space_def::compute_blend_2d(
const parameters_t& current_params,
463 if(parameter_count_ != 2)
473 std::set<float> param0_values;
474 std::set<float> param1_values;
475 for(
const auto&
point : points_)
477 param0_values.insert(
point.parameters[0]);
478 param1_values.insert(
point.parameters[1]);
482 std::vector<float> param0_vector(param0_values.begin(), param0_values.end());
483 std::vector<float> param1_vector(param1_values.begin(), param1_values.end());
486 auto find_index = [](
const std::vector<float>& values,
float param) ->
size_t
488 for(
size_t i = 0;
i < values.size() - 1; ++
i)
490 if(param >= values[i] && param <= values[i + 1])
495 return values.size() - 2;
498 size_t index0 = find_index(param0_vector, current_params[0]);
499 size_t index1 = find_index(param1_vector, current_params[1]);
502 float p00 = param0_vector[index0];
503 float p01 = param0_vector[index0 + 1];
504 float p10 = param1_vector[index1];
505 float p11 = param1_vector[index1 + 1];
508 std::array<const blend_space_point*, 4> corner_points = {
nullptr,
nullptr,
nullptr,
nullptr};
510 for(
const auto&
point : points_)
512 const auto& params =
point.parameters;
513 if(params[0] == p00 && params[1] == p10)
514 corner_points[0] = &
point;
515 if(params[0] == p01 && params[1] == p10)
516 corner_points[1] = &
point;
517 if(params[0] == p00 && params[1] == p11)
518 corner_points[2] = &
point;
519 if(params[0] == p01 && params[1] == p11)
520 corner_points[3] = &
point;
524 for(
const auto* cp : corner_points)
531 float tx = (current_params[0] - p00) / (p01 - p00);
532 float ty = (current_params[1] - p10) / (p11 - p10);
535 float w_bl = (1 - tx) * (1 - ty);
536 float w_br = tx * (1 - ty);
537 float w_tl = (1 - tx) * ty;
538 float w_tr = tx * ty;
541 out_clips.emplace_back(corner_points[0]->clip, w_bl);
542 out_clips.emplace_back(corner_points[1]->clip, w_br);
543 out_clips.emplace_back(corner_points[2]->clip, w_tl);
544 out_clips.emplace_back(corner_points[3]->clip, w_tr);
549 return parameter_count_;
void add_clip(const parameters_t ¶ms, const asset_handle< animation_clip > &clip)
void compute_blend(const parameters_t ¤t_params, std::vector< std::pair< asset_handle< animation_clip >, float > > &out_clips) const
std::vector< parameter_t > parameters_t
auto get_parameter_count() const -> size_t
void blend_poses_by_node_index_sorted_additive(const animation_pose &base, const animation_pose &additive, const animation_pose &ref_pose, float weight, animation_pose &result)
void blend_poses_by_node_index_sorted_multiway(const std::vector< animation_pose > &poses, const std::vector< float > &weights, animation_pose &result)
void blend_poses(const animation_pose &pose1, const animation_pose &pose2, float factor, animation_pose &result_pose)
void blend_poses_by_node_index_sorted(const animation_pose &pose1, const animation_pose &pose2, float factor, animation_pose &result)
void blend_poses_additive(const animation_pose &base, const animation_pose &additive, const animation_pose &ref_pose, float weight, animation_pose &result)
auto blend_additive(const math::transform &base, const math::transform &additive, const math::transform &ref, float weight) -> math::transform
auto blend(const math::transform &lhs, const math::transform &rhs, float factor) -> math::transform
Represents a handle to an asset, providing access and management functions.
math::transform transform
float bone_rotation_weight
float root_rotation_weight
math::vec3 bone_position_weights
math::vec3 root_position_weights
math::transform root_transform_delta
int root_position_node_index
int root_rotation_node_index
std::vector< node > nodes
root_motion_result motion_result