Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/armature.c
| Show First 20 Lines • Show All 816 Lines • ▼ Show 20 Lines | |||||
| /* Definition of cached object bbone deformations. */ | /* Definition of cached object bbone deformations. */ | ||||
| typedef struct ObjectBBoneDeform { | typedef struct ObjectBBoneDeform { | ||||
| DualQuat *dualquats; | DualQuat *dualquats; | ||||
| bPoseChanDeform *pdef_info_array; | bPoseChanDeform *pdef_info_array; | ||||
| int num_pchan; | int num_pchan; | ||||
| } ObjectBBoneDeform; | } ObjectBBoneDeform; | ||||
| static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, const bool use_quaternion) | /** Compute and cache the B-Bone shape in the channel runtime struct. */ | ||||
| void BKE_pchan_cache_bbone_segments(bPoseChannel *pchan) | |||||
| { | { | ||||
| bPoseChannelRuntime *runtime = &pchan->runtime; | |||||
| Bone *bone = pchan->bone; | Bone *bone = pchan->bone; | ||||
| Mat4 b_bone[MAX_BBONE_SUBDIV], b_bone_rest[MAX_BBONE_SUBDIV]; | int segments = bone->segments; | ||||
| Mat4 *b_bone_mats; | |||||
| DualQuat *b_bone_dual_quats = NULL; | |||||
| int a; | |||||
| b_bone_spline_setup(pchan, false, b_bone); | BLI_assert(segments > 1); | ||||
| b_bone_spline_setup(pchan, true, b_bone_rest); | |||||
| /* allocate b_bone matrices and dual quats */ | /* Allocate the cache if needed. */ | ||||
| b_bone_mats = MEM_mallocN((1 + bone->segments) * sizeof(Mat4), "BBone defmats"); | if (runtime->bbone_segments != segments) { | ||||
| pdef_info->b_bone_mats = b_bone_mats; | if (runtime->bbone_segments != 0) { | ||||
| BKE_pose_channel_free_bbone_cache(pchan); | |||||
| } | |||||
| if (use_quaternion) { | runtime->bbone_segments = segments; | ||||
| b_bone_dual_quats = MEM_mallocN((bone->segments) * sizeof(DualQuat), "BBone dqs"); | runtime->bbone_rest_mats = MEM_malloc_arrayN(sizeof(Mat4), (uint)segments, "bPoseChannelRuntime::bbone_rest_mats"); | ||||
| pdef_info->b_bone_dual_quats = b_bone_dual_quats; | runtime->bbone_pose_mats = MEM_malloc_arrayN(sizeof(Mat4), (uint)segments, "bPoseChannelRuntime::bbone_pose_mats"); | ||||
| runtime->bbone_deform_mats = MEM_malloc_arrayN(sizeof(Mat4), 1 + (uint)segments, "bPoseChannelRuntime::bbone_deform_mats"); | |||||
| runtime->bbone_dual_quats = MEM_malloc_arrayN(sizeof(DualQuat), (uint)segments, "bPoseChannelRuntime::bbone_dual_quats"); | |||||
| } | } | ||||
| /* Compute the shape. */ | |||||
| Mat4 *b_bone = runtime->bbone_pose_mats; | |||||
| Mat4 *b_bone_rest = runtime->bbone_rest_mats; | |||||
| Mat4 *b_bone_mats = runtime->bbone_deform_mats; | |||||
| DualQuat *b_bone_dual_quats = runtime->bbone_dual_quats; | |||||
| int a; | |||||
| b_bone_spline_setup(pchan, false, b_bone); | |||||
| b_bone_spline_setup(pchan, true, b_bone_rest); | |||||
| /* Compute deform matrices. */ | |||||
| /* first matrix is the inverse arm_mat, to bring points in local bone space | /* first matrix is the inverse arm_mat, to bring points in local bone space | ||||
| * for finding out which segment it belongs to */ | * for finding out which segment it belongs to */ | ||||
| invert_m4_m4(b_bone_mats[0].mat, bone->arm_mat); | invert_m4_m4(b_bone_mats[0].mat, bone->arm_mat); | ||||
| /* then we make the b_bone_mats: | /* then we make the b_bone_mats: | ||||
| * - first transform to local bone space | * - first transform to local bone space | ||||
| * - translate over the curve to the bbone mat space | * - translate over the curve to the bbone mat space | ||||
| * - transform with b_bone matrix | * - transform with b_bone matrix | ||||
| * - transform back into global space */ | * - transform back into global space */ | ||||
| for (a = 0; a < bone->segments; a++) { | for (a = 0; a < bone->segments; a++) { | ||||
| float tmat[4][4]; | float tmat[4][4]; | ||||
| invert_m4_m4(tmat, b_bone_rest[a].mat); | invert_m4_m4(tmat, b_bone_rest[a].mat); | ||||
| mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat); | mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat); | ||||
| if (use_quaternion) | |||||
| mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat); | mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat); | ||||
| } | } | ||||
| } | } | ||||
| static void b_bone_deform(const bPoseChanDeform *pdef_info, Bone *bone, float co[3], DualQuat *dq, float defmat[3][3]) | static void b_bone_deform(const bPoseChanDeform *pdef_info, Bone *bone, float co[3], DualQuat *dq, float defmat[3][3]) | ||||
| { | { | ||||
| const Mat4 *b_bone = pdef_info->b_bone_mats; | const Mat4 *b_bone = pdef_info->b_bone_mats; | ||||
| const float (*mat)[4] = b_bone[0].mat; | const float (*mat)[4] = b_bone[0].mat; | ||||
| float segment, y; | float segment, y; | ||||
| ▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | static void armature_bbone_defmats_cb(void *userdata, Link *iter, int index) | ||||
| ArmatureBBoneDefmatsData *data = userdata; | ArmatureBBoneDefmatsData *data = userdata; | ||||
| bPoseChannel *pchan = (bPoseChannel *)iter; | bPoseChannel *pchan = (bPoseChannel *)iter; | ||||
| if (!(pchan->bone->flag & BONE_NO_DEFORM)) { | if (!(pchan->bone->flag & BONE_NO_DEFORM)) { | ||||
| bPoseChanDeform *pdef_info = &data->pdef_info_array[index]; | bPoseChanDeform *pdef_info = &data->pdef_info_array[index]; | ||||
| const bool use_quaternion = data->use_quaternion; | const bool use_quaternion = data->use_quaternion; | ||||
| if (pchan->bone->segments > 1) { | if (pchan->bone->segments > 1) { | ||||
| pchan_b_bone_defmats(pchan, pdef_info, use_quaternion); | BLI_assert(pchan->runtime.bbone_segments == pchan->bone->segments); | ||||
| pdef_info->b_bone_mats = pchan->runtime.bbone_deform_mats; | |||||
| pdef_info->b_bone_dual_quats = pchan->runtime.bbone_dual_quats; | |||||
| } | } | ||||
| if (use_quaternion) { | if (use_quaternion) { | ||||
| pdef_info->dual_quat = &data->dualquats[index]; | pdef_info->dual_quat = &data->dualquats[index]; | ||||
| mat4_to_dquat(pdef_info->dual_quat, pchan->bone->arm_mat, pchan->chan_mat); | mat4_to_dquat(pdef_info->dual_quat, pchan->bone->arm_mat, pchan->chan_mat); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,422 Lines • ▼ Show 20 Lines | |||||
| void BKE_armature_cached_bbone_deformation_free_data(Object *object) | void BKE_armature_cached_bbone_deformation_free_data(Object *object) | ||||
| { | { | ||||
| ObjectBBoneDeform *bbone_deform = | ObjectBBoneDeform *bbone_deform = | ||||
| BKE_armature_cached_bbone_deformation_get(object); | BKE_armature_cached_bbone_deformation_get(object); | ||||
| if (bbone_deform == NULL) { | if (bbone_deform == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* free B_bone matrices */ | |||||
| for (int i = 0; i < bbone_deform->num_pchan; i++) { | |||||
| bPoseChanDeform *pdef_info = &bbone_deform->pdef_info_array[i]; | |||||
| if (pdef_info->b_bone_mats != NULL) { | |||||
| MEM_freeN(pdef_info->b_bone_mats); | |||||
| } | |||||
| if (pdef_info->b_bone_dual_quats != NULL) { | |||||
| MEM_freeN(pdef_info->b_bone_dual_quats); | |||||
| } | |||||
| } | |||||
| /* Free arrays. */ | /* Free arrays. */ | ||||
| MEM_SAFE_FREE(bbone_deform->pdef_info_array); | MEM_SAFE_FREE(bbone_deform->pdef_info_array); | ||||
| MEM_SAFE_FREE(bbone_deform->dualquats); | MEM_SAFE_FREE(bbone_deform->dualquats); | ||||
| /* Tag that we've got no data, so we are safe for sequential calls to | /* Tag that we've got no data, so we are safe for sequential calls to | ||||
| * data free. */ | * data free. */ | ||||
| bbone_deform->num_pchan = 0; | bbone_deform->num_pchan = 0; | ||||
| } | } | ||||
| Show All 36 Lines | void BKE_armature_cached_bbone_deformation_update(Object *object) | ||||
| ArmatureBBoneDefmatsData data = { | ArmatureBBoneDefmatsData data = { | ||||
| .pdef_info_array = pdef_info_array, | .pdef_info_array = pdef_info_array, | ||||
| .dualquats = dualquats, | .dualquats = dualquats, | ||||
| .use_quaternion = use_quaternion | .use_quaternion = use_quaternion | ||||
| }; | }; | ||||
| BLI_task_parallel_listbase(&pose->chanbase, | BLI_task_parallel_listbase(&pose->chanbase, | ||||
| &data, | &data, | ||||
| armature_bbone_defmats_cb, | armature_bbone_defmats_cb, | ||||
| totchan > 512); | totchan > 1024); | ||||
| /* Store pointers. */ | /* Store pointers. */ | ||||
| bbone_deform->dualquats = dualquats; | bbone_deform->dualquats = dualquats; | ||||
| atomic_cas_ptr((void **)&bbone_deform->pdef_info_array, | atomic_cas_ptr((void **)&bbone_deform->pdef_info_array, | ||||
| bbone_deform->pdef_info_array, | bbone_deform->pdef_info_array, | ||||
| pdef_info_array); | pdef_info_array); | ||||
| bbone_deform->num_pchan = totchan; | bbone_deform->num_pchan = totchan; | ||||
| } | } | ||||