52 const float closest_radius,
53 const float falloff_distance)
57 if (distance_squared < closest_radius * closest_radius) {
62 if (falloff_distance == 0.0f ||
63 distance_squared >=
math::square(closest_radius + falloff_distance))
69 const float dist_envelope =
sqrtf(distance_squared) - closest_radius;
70 return 1.0f - (dist_envelope * dist_envelope) / (falloff_distance * falloff_distance);
76 const float radius_head,
77 const float radius_tail,
78 const float falloff_distance)
85 const float height =
math::dot(position - head, bone_axis);
92 else if (height > bone_length) {
100 const float closest_radius = bone_length != 0.0f ?
math::interpolate(radius_head,
102 height / bone_length) :
124 if constexpr (full_deform) {
137 const float4x4 &pose_mat = pose_mats[index + 1];
140 if constexpr (full_deform) {
141 deform += weight * pose_mat.view<3, 3>();
147 float armature_weight,
151 const float scale_factor = armature_weight / total;
153 r_deform_mat =
deform * scale_factor;
178 const DualQuat &deform_quat = quats[index];
185 float armature_weight,
193 r_delta_co = (dco - co) * armature_weight;
200template<
typename MixerT>
211 mixer.accumulate_bbone(pchan, co, weight * (1.0f -
blend), index);
212 mixer.accumulate_bbone(pchan, co, weight *
blend, index + 1);
216template<
typename MixerT>
220 if (bone ==
nullptr || bone->
weight == 0.0f) {
234 const float weight = fac * bone->
weight;
239 mixer.accumulate(pchan, co, weight);
246template<
typename MixerT>
262 mixer.accumulate(pchan, co, weight);
309 const int deformflag,
311 const bool try_use_dverts)
351 deform_params.
target_to_armature = ob_arm.world_to_object() * ob_target.object_to_world();
352 deform_params.
armature_to_target = ob_target.world_to_object() * ob_arm.object_to_world();
354 deform_params.
armature_to_target = ob_target.world_to_object() * ob_arm.object_to_world();
358 return deform_params;
362template<
typename MixerT>
368 const bool full_deform =
params.vert_deform_mats.has_value();
371 float armature_weight = 1.0f;
372 float prevco_weight = 0.0f;
373 if (
params.armature_def_nr != -1 && dvert) {
376 if (
params.vert_coords_prev) {
377 prevco_weight =
params.invert_vgroup ? mask_weight : 1.0f - mask_weight;
378 if (prevco_weight == 1.0f) {
383 armature_weight =
params.invert_vgroup ? 1.0f - mask_weight : mask_weight;
384 if (armature_weight == 0.0f) {
395 float contrib = 0.0f;
396 bool deformed =
false;
398 if (
params.use_dverts && dvert) {
400 const IndexRange def_nr_range =
params.pose_channel_by_vertex_group.index_range();
402 for (
const auto &dw : dweights) {
404 params.pose_channel_by_vertex_group[dw.def_nr] :
406 if (pchan ==
nullptr) {
410 float weight = dw.weight;
428 if (!deformed &&
params.use_envelope) {
437 constexpr float contrib_threshold = 0.0001f;
438 if (contrib > contrib_threshold) {
441 mixer.finalize(co, contrib, armature_weight, delta_co, local_deform_mat);
446 const float3x3 armature_to_target =
params.armature_to_target.view<3, 3>();
447 const float3x3 target_to_armature =
params.target_to_armature.view<3, 3>();
448 deform_mat = armature_to_target * local_deform_mat * target_to_armature * deform_mat;
456 if (
params.vert_coords_prev) {
468 const bool use_quaternion)
471 if (use_quaternion) {
498 const int deformflag,
502 const Mesh *me_target)
515 constexpr int grain_size = 32;
517 for (const int i : range) {
518 const MDeformVert *dvert = nullptr;
519 if (deform_params.use_dverts || deform_params.armature_def_nr >= 0) {
521 BLI_assert(i < me_target->verts_num);
523 dvert = &(*dverts)[i];
526 else if (dverts && i < dverts->size()) {
527 dvert = &(*dverts)[i];
531 armature_vert_task_with_dvert(deform_params, i, dvert, use_quaternion);
543template<
bool use_dvert>
562 const int deformflag,
566 const int cd_dvert_offset)
576 cd_dvert_offset >= 0);
580 data.cd_dvert_offset = cd_dvert_offset;
581 data.deform_params = std::move(deform_params);
590 if (
data.deform_params.use_dverts) {
604 if (arm->
edbo || (ob_arm.
pose ==
nullptr)) {
609 "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
659 const Mesh *me_target)
669 const ID *id_target =
static_cast<const ID *
>(ob_target.
data);
682 if (me_target ==
nullptr) {
683 me_target =
static_cast<const Mesh *
>(ob_target.
data);
685 dverts = me_target->deform_verts();
689 if (lt->
dvert !=
nullptr) {
694 std::optional<Span<MDeformVert>> dverts_opt;
695 if ((me_target && !me_target->deform_verts().is_empty()) || dverts.
size() == vert_coords.
size())
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan, const float *co, int *r_index, float *r_blend_next)
float distfactor_to_bone(const blender::float3 &position, const blender::float3 &head, const blender::float3 &tail, float radius_head, float radius_tail, float falloff_distance)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq)
void add_weighted_dq_dq_pivot(DualQuat *dq_sum, const DualQuat *dq, const float pivot[3], float weight, bool compute_scale_matrix)
void normalize_dq(DualQuat *dq, float totweight)
MINLINE void copy_v3_v3(float r[3], const float a[3])
struct MempoolIterData MempoolIterData
void BLI_task_parallel_mempool(struct BLI_mempool *mempool, void *userdata, TaskParallelMempoolFunc func, const TaskParallelSettings *settings)
BLI_INLINE void BLI_parallel_mempool_settings_defaults(TaskParallelSettings *settings)
#define CLOG_ERROR(clg_ref,...)
These structs are the foundation for all linked lists in the library system.
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_index_get(ele)
BMesh const char void * data
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
ATTR_WARN_UNUSED_RESULT const BMVert * v
void reinitialize(const int64_t new_size)
constexpr bool contains(int64_t value) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
Span< NewT > constexpr cast() const
constexpr int64_t size() const
static void armature_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter, const TaskParallelTLS *__restrict)
static void armature_vert_task_with_mixer(const ArmatureDeformParams ¶ms, const int i, const MDeformVert *dvert, MixerT &mixer)
static void armature_vert_task_with_dvert(const ArmatureDeformParams &deform_params, const int i, const MDeformVert *dvert, const bool use_quaternion)
static float dist_bone_deform(const bPoseChannel &pchan, const float3 &co, MixerT &mixer)
static void b_bone_deform(const bPoseChannel &pchan, const float3 &co, const float weight, MixerT &mixer)
static void armature_deform_editmesh(const Object &ob_arm, const Object &ob_target, const ListBase *defbase, const MutableSpan< float3 > vert_coords, const std::optional< MutableSpan< float3x3 > > vert_deform_mats, const int deformflag, const std::optional< Span< float3 > > vert_coords_prev, blender::StringRefNull defgrp_name, const BMEditMesh &em_target, const int cd_dvert_offset)
static float pchan_bone_deform(const bPoseChannel &pchan, const float weight, const float3 &co, MixerT &mixer)
static bool verify_armature_deform_valid(const Object &ob_arm)
static ArmatureDeformParams get_armature_deform_params(const Object &ob_arm, const Object &ob_target, const ListBase *defbase, MutableSpan< float3 > vert_coords, std::optional< Span< float3 > > vert_coords_prev, std::optional< MutableSpan< float3x3 > > vert_deform_mats, const int deformflag, blender::StringRefNull defgrp_name, const bool try_use_dverts)
static void armature_deform_coords(const Object &ob_arm, const Object &ob_target, const ListBase *defbase, const MutableSpan< float3 > vert_coords, const std::optional< MutableSpan< float3x3 > > vert_deform_mats, const int deformflag, const std::optional< Span< float3 > > vert_coords_prev, blender::StringRefNull defgrp_name, const std::optional< Span< MDeformVert > > dverts, const Mesh *me_target)
QuaternionBase< T > normalize_and_get_length(const QuaternionBase< T > &q, T &out_length)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
T interpolate(const T &a, const T &b, const FactorT &t)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
MatBase< float, 4, 4 > float4x4
ListBaseWrapperTemplate< const ListBase, const T > ConstListBaseWrapper
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
struct BLI_mempool * vpool
struct MDeformVert * dvert
struct Mat4 * bbone_deform_mats
struct DualQuat deform_dual_quat
struct DualQuat * bbone_dual_quats
struct bPoseChannel_Runtime runtime
const c_style_mat & ptr() const
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const
ArmatureDeformParams deform_params
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)