[Bf-blender-cvs] [1e820898ff4] blender2.8: Depsgraph: add a new operation node for computing B-Bone segments.

Alexander Gavrilov noreply at git.blender.org
Fri Nov 23 21:20:34 CET 2018


Commit: 1e820898ff4dfc734710a6640ca7bafc0bfc69db
Author: Alexander Gavrilov
Date:   Thu Nov 22 13:38:03 2018 +0300
Branches: blender2.8
https://developer.blender.org/rB1e820898ff4dfc734710a6640ca7bafc0bfc69db

Depsgraph: add a new operation node for computing B-Bone segments.

Computing the shape of a B-Bone is a quite expensive operation, and
there are multiple constraints that can access this information in
a variety of useful ways. This means computing the shape once per
bone and saving it is good for performance.

Since the shape may depend on the position of up to two other bones,
often in a "cyclic" manner, this computation has to be a separate
node with its own dependencies.

Reviewers: sergey

Differential Revision: https://developer.blender.org/D3975

===================================================================

M	source/blender/blenkernel/BKE_action.h
M	source/blender/blenkernel/BKE_armature.h
M	source/blender/blenkernel/intern/action.c
M	source/blender/blenkernel/intern/armature.c
M	source/blender/blenkernel/intern/armature_update.c
M	source/blender/blenkernel/intern/constraint.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
M	source/blender/depsgraph/intern/builder/deg_builder_relations.cc
M	source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
M	source/blender/depsgraph/intern/depsgraph_type_defines.cc
M	source/blender/depsgraph/intern/depsgraph_types.h
M	source/blender/draw/intern/draw_armature.c
M	source/blender/makesdna/DNA_action_types.h

===================================================================

diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 79e0860cb98..7f4feb6c2d5 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -137,6 +137,8 @@ void action_groups_clear_tempflags(struct bAction *act);
 void                 BKE_pose_channel_free(struct bPoseChannel *pchan);
 void                 BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user);
 
+void                 BKE_pose_channel_free_bbone_cache(struct bPoseChannel *pchan);
+
 void                 BKE_pose_channels_free(struct bPose *pose);
 void                 BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_user);
 
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index be8bd9557e5..1831e93cccb 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -170,6 +170,9 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, const bool rest, Mat4 resul
 
 int BKE_compute_b_bone_spline(struct BBoneSplineParameters *param, Mat4 result_array[MAX_BBONE_SUBDIV]);
 
+void BKE_pchan_cache_bbone_segments(struct bPoseChannel *pchan);
+void BKE_pchan_copy_bbone_segments_cache(struct bPoseChannel *pchan, struct bPoseChannel *pchan_from);
+
 /* like EBONE_VISIBLE */
 #define PBONE_VISIBLE(arm, bone) ( \
 	CHECK_TYPE_INLINE(arm, bArmature *), \
@@ -241,6 +244,11 @@ void BKE_pose_bone_done(
         struct Object *ob,
         int pchan_index);
 
+void BKE_pose_eval_bbone_segments(
+        struct Depsgraph *depsgraph,
+        struct Object *ob,
+        int pchan_index);
+
 void BKE_pose_iktree_evaluate(
         struct Depsgraph *depsgraph,
         struct Scene *scene,
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 87f821130c7..79230ad9e94 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -594,6 +594,9 @@ void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const
 		}
 
 		pchan->draw_data = NULL;  /* Drawing cache, no need to copy. */
+
+		/* Runtime data, no need to copy. */
+		memset(&pchan->runtime, 0, sizeof(pchan->runtime));
 	}
 
 	/* for now, duplicate Bone Groups too when doing this */
@@ -790,6 +793,21 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
 
 	/* Cached data, for new draw manager rendering code. */
 	MEM_SAFE_FREE(pchan->draw_data);
+
+	/* Cached B-Bone shape data. */
+	BKE_pose_channel_free_bbone_cache(pchan);
+}
+
+/** Deallocates runtime cache of a pose channel's B-Bone shape. */
+void BKE_pose_channel_free_bbone_cache(bPoseChannel *pchan)
+{
+	bPoseChannelRuntime *runtime = &pchan->runtime;
+
+	runtime->bbone_segments = 0;
+	MEM_SAFE_FREE(runtime->bbone_rest_mats);
+	MEM_SAFE_FREE(runtime->bbone_pose_mats);
+	MEM_SAFE_FREE(runtime->bbone_deform_mats);
+	MEM_SAFE_FREE(runtime->bbone_dual_quats);
 }
 
 void BKE_pose_channel_free(bPoseChannel *pchan)
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 967e2ac921c..2004b66c1ef 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -822,26 +822,46 @@ typedef struct ObjectBBoneDeform {
 	int num_pchan;
 } ObjectBBoneDeform;
 
-static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, const bool use_quaternion)
+static void allocate_bbone_cache(bPoseChannel *pchan, int segments)
 {
+	bPoseChannelRuntime *runtime = &pchan->runtime;
+
+	if (runtime->bbone_segments != segments) {
+		if (runtime->bbone_segments != 0) {
+			BKE_pose_channel_free_bbone_cache(pchan);
+		}
+
+		runtime->bbone_segments = segments;
+		runtime->bbone_rest_mats = MEM_malloc_arrayN(sizeof(Mat4), (uint)segments, "bPoseChannelRuntime::bbone_rest_mats");
+		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 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;
-	Mat4 b_bone[MAX_BBONE_SUBDIV], b_bone_rest[MAX_BBONE_SUBDIV];
-	Mat4 *b_bone_mats;
-	DualQuat *b_bone_dual_quats = NULL;
+	int segments = bone->segments;
+
+	BLI_assert(segments > 1);
+
+	/* Allocate the cache if needed. */
+	allocate_bbone_cache(pchan, segments);
+
+	/* 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);
 
-	/* allocate b_bone matrices and dual quats */
-	b_bone_mats = MEM_mallocN((1 + bone->segments) * sizeof(Mat4), "BBone defmats");
-	pdef_info->b_bone_mats = b_bone_mats;
-
-	if (use_quaternion) {
-		b_bone_dual_quats = MEM_mallocN((bone->segments) * sizeof(DualQuat), "BBone dqs");
-		pdef_info->b_bone_dual_quats = b_bone_dual_quats;
-	}
-
+	/* Compute deform matrices. */
 	/* first matrix is the inverse arm_mat, to bring points in local bone space
 	 * for finding out which segment it belongs to */
 	invert_m4_m4(b_bone_mats[0].mat, bone->arm_mat);
@@ -858,8 +878,27 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info
 		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);
 
-		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);
+	}
+}
+
+/** Copy cached B-Bone segments from one channel to another */
+void BKE_pchan_copy_bbone_segments_cache(bPoseChannel *pchan, bPoseChannel *pchan_from)
+{
+	bPoseChannelRuntime *runtime = &pchan->runtime;
+	bPoseChannelRuntime *runtime_from = &pchan_from->runtime;
+	int segments = runtime_from->bbone_segments;
+
+	if (segments <= 1) {
+		BKE_pose_channel_free_bbone_cache(pchan);
+	}
+	else {
+		allocate_bbone_cache(pchan, segments);
+
+		memcpy(runtime->bbone_rest_mats, runtime_from->bbone_rest_mats, sizeof(Mat4) * segments);
+		memcpy(runtime->bbone_pose_mats, runtime_from->bbone_pose_mats, sizeof(Mat4) * segments);
+		memcpy(runtime->bbone_deform_mats, runtime_from->bbone_deform_mats, sizeof(Mat4) * (1 + segments));
+		memcpy(runtime->bbone_dual_quats, runtime_from->bbone_dual_quats, sizeof(DualQuat) * segments);
 	}
 }
 
@@ -978,7 +1017,7 @@ static float dist_bone_deform(bPoseChannel *pchan, const bPoseChanDeform *pdef_i
 		contrib = fac;
 		if (contrib > 0.0f) {
 			if (vec) {
-				if (bone->segments > 1)
+				if (bone->segments > 1 && pdef_info->b_bone_mats != NULL)
 					/* applies on cop and bbonemat */
 					b_bone_deform(pdef_info, bone, cop, NULL, (mat) ? bbonemat : NULL);
 				else
@@ -992,7 +1031,7 @@ static float dist_bone_deform(bPoseChannel *pchan, const bPoseChanDeform *pdef_i
 					pchan_deform_mat_add(pchan, fac, bbonemat, mat);
 			}
 			else {
-				if (bone->segments > 1) {
+				if (bone->segments > 1 && pdef_info->b_bone_mats != NULL) {
 					b_bone_deform(pdef_info, bone, cop, &bbonedq, NULL);
 					add_weighted_dq_dq(dq, &bbonedq, fac);
 				}
@@ -1059,7 +1098,10 @@ static void armature_bbone_defmats_cb(void *userdata, Link *iter, int index)
 		const bool use_quaternion = data->use_quaternion;
 
 		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) {
@@ -2498,16 +2540,6 @@ void BKE_armature_cached_bbone_deformation_free_data(Object *object)
 	if (bbone_deform == NULL) {
 		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. */
 	MEM_SAFE_FREE(bbone_deform->pdef_info_array);
 	MEM_SAFE_FREE(bbone_deform->dualquats);
@@ -2560,7 +2592,7 @@ void BKE_armature_cached_bbone_deformation_update(Object *object)
 	BLI_task_parallel_listbase(&pose->chanbase,
 	                           &data,
 	                           armature_bbone_defmats_cb,
-	                           totchan > 512);
+	                           totchan > 1024);
 	/* Store pointers. */
 	bbone_deform->dualquats = dualquats;
 	atomic_cas_ptr((void **)&bbone_deform->pdef_info_array,
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 0fba7677479..b917aae08de 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -605,6 +605,11 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph,
 	/* clear flags */
 	for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
 		pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
+
+		/* Free B-Bone shape data cache if it's not a B-Bone. */
+		if (pchan->bone == NULL || pchan->bone->segments <= 1) {
+			BKE_pose_channel_free_bbone_cache(pchan);
+		}
 	}
 
 	pose_pchan_index_create(pose);
@@ -713,6 +718,17 @@ void BKE_pose_bone_done(struct Depsgraph *depsgraph,
 	}
 }
 
+void BKE_pose_eval_bbone_segments(struct Depsgraph *depsgraph,
+                               struct Object *ob,
+                               int pchan_index)
+{
+	bPoseChannel *pchan = pose_pch

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list