[Bf-blender-cvs] [c3ba8910a14] greasepencil-object: WIP: Add basic functions to deform

Antonioya noreply at git.blender.org
Thu Aug 23 10:33:49 CEST 2018


Commit: c3ba8910a142f7ee03a488e42f31b4408be300fb
Author: Antonioya
Date:   Sat Aug 18 18:08:22 2018 +0200
Branches: greasepencil-object
https://developer.blender.org/rBc3ba8910a142f7ee03a488e42f31b4408be300fb

WIP: Add basic functions to deform

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

M	source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c

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

diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 5b28aaf6ef4..275dcdba20f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -30,6 +30,7 @@
 
 #include <stdio.h>
 
+#include "DNA_armature_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
@@ -38,9 +39,12 @@
 #include "DNA_modifier_types.h"
 #include "BLI_math.h"
 
+#include "BLI_listbase.h"
+#include "BLI_task.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_action.h"
+#include "BKE_armature.h"
 #include "BKE_context.h"
 #include "BKE_colortools.h"
 #include "BKE_deform.h"
@@ -61,6 +65,18 @@
 #include "DEG_depsgraph_build.h"
 #include "DEG_depsgraph_query.h"
 
+typedef struct bPoseChanDeform {
+	Mat4     *b_bone_mats;
+	DualQuat *dual_quat;
+	DualQuat *b_bone_dual_quats;
+} bPoseChanDeform;
+
+typedef struct ArmatureBBoneDefmatsData {
+	bPoseChanDeform *pdef_info_array;
+	DualQuat *dualquats;
+	bool use_quaternion;
+} ArmatureBBoneDefmatsData;
+
 static void initData(GpencilModifierData *md)
 {
 	ArmatureGpencilModifierData *gpmd = (ArmatureGpencilModifierData *)md;
@@ -72,6 +88,428 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
 	BKE_gpencil_modifier_copyData_generic(md, target);
 }
 
+static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float co[3], DualQuat *dq, float defmat[3][3])
+{
+	Mat4 *b_bone = pdef_info->b_bone_mats;
+	float(*mat)[4] = b_bone[0].mat;
+	float segment, y;
+	int a;
+
+	/* need to transform co back to bonespace, only need y */
+	y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
+
+	/* now calculate which of the b_bones are deforming this */
+	segment = bone->length / ((float)bone->segments);
+	a = (int)(y / segment);
+
+	/* note; by clamping it extends deform at endpoints, goes best with
+	 * straight joints in restpos. */
+	CLAMP(a, 0, bone->segments - 1);
+
+	if (dq) {
+		copy_dq_dq(dq, &(pdef_info->b_bone_dual_quats)[a]);
+	}
+	else {
+		mul_m4_v3(b_bone[a + 1].mat, co);
+
+		if (defmat) {
+			copy_m3_m4(defmat, b_bone[a + 1].mat);
+		}
+	}
+}
+
+static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonemat[3][3], float mat[3][3])
+{
+	float wmat[3][3];
+
+	if (pchan->bone->segments > 1)
+		copy_m3_m3(wmat, bbonemat);
+	else
+		copy_m3_m4(wmat, pchan->chan_mat);
+
+	mul_m3_fl(wmat, weight);
+	add_m3_m3m3(mat, mat, wmat);
+}
+
+static void pchan_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float weight, float vec[3], DualQuat *dq,
+	float mat[3][3], const float co[3], float *contrib)
+{
+	float cop[3], bbonemat[3][3];
+	DualQuat bbonedq;
+
+	if (!weight)
+		return;
+
+	copy_v3_v3(cop, co);
+
+	if (vec) {
+		if (pchan->bone->segments > 1)
+			/* applies on cop and bbonemat */
+			b_bone_deform(pdef_info, pchan->bone, cop, NULL, (mat) ? bbonemat : NULL);
+		else
+			mul_m4_v3(pchan->chan_mat, cop);
+
+		vec[0] += (cop[0] - co[0]) * weight;
+		vec[1] += (cop[1] - co[1]) * weight;
+		vec[2] += (cop[2] - co[2]) * weight;
+
+		if (mat)
+			pchan_deform_mat_add(pchan, weight, bbonemat, mat);
+	}
+	else {
+		if (pchan->bone->segments > 1) {
+			b_bone_deform(pdef_info, pchan->bone, cop, &bbonedq, NULL);
+			add_weighted_dq_dq(dq, &bbonedq, weight);
+		}
+		else
+			add_weighted_dq_dq(dq, pdef_info->dual_quat, weight);
+	}
+
+	(*contrib) += weight;
+}
+
+static float dist_bone_deform(bPoseChannel *pchan, bPoseChanDeform *pdef_info, float vec[3], DualQuat *dq,
+	float mat[3][3], const float co[3])
+{
+	Bone *bone = pchan->bone;
+	float fac, contrib = 0.0;
+	float cop[3], bbonemat[3][3];
+	DualQuat bbonedq;
+
+	if (bone == NULL)
+		return 0.0f;
+
+	copy_v3_v3(cop, co);
+
+	fac = distfactor_to_bone(cop, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
+
+	if (fac > 0.0f) {
+		fac *= bone->weight;
+		contrib = fac;
+		if (contrib > 0.0f) {
+			if (vec) {
+				if (bone->segments > 1)
+					/* applies on cop and bbonemat */
+					b_bone_deform(pdef_info, bone, cop, NULL, (mat) ? bbonemat : NULL);
+				else
+					mul_m4_v3(pchan->chan_mat, cop);
+
+				/* Make this a delta from the base position */
+				sub_v3_v3(cop, co);
+				madd_v3_v3fl(vec, cop, fac);
+
+				if (mat)
+					pchan_deform_mat_add(pchan, fac, bbonemat, mat);
+			}
+			else {
+				if (bone->segments > 1) {
+					b_bone_deform(pdef_info, bone, cop, &bbonedq, NULL);
+					add_weighted_dq_dq(dq, &bbonedq, fac);
+				}
+				else
+					add_weighted_dq_dq(dq, pdef_info->dual_quat, fac);
+			}
+		}
+	}
+
+	return contrib;
+}
+
+static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, const bool use_quaternion)
+{
+	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 a;
+
+	b_bone_spline_setup(pchan, 0, b_bone);
+	b_bone_spline_setup(pchan, 1, 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;
+	}
+
+	/* 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);
+
+	/* then we make the b_bone_mats:
+	 * - first transform to local bone space
+	 * - translate over the curve to the bbone mat space
+	 * - transform with b_bone matrix
+	 * - transform back into global space */
+
+	for (a = 0; a < bone->segments; a++) {
+		float tmat[4][4];
+
+		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);
+	}
+}
+
+static void gpencil_armature_bbone_defmats_cb(void *userdata, Link *iter, int index)
+{
+	ArmatureBBoneDefmatsData *data = userdata;
+	bPoseChannel *pchan = (bPoseChannel *)iter;
+
+	if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+		bPoseChanDeform *pdef_info = &data->pdef_info_array[index];
+		const bool use_quaternion = data->use_quaternion;
+
+		if (pchan->bone->segments > 1) {
+			pchan_b_bone_defmats(pchan, pdef_info, use_quaternion);
+		}
+
+		if (use_quaternion) {
+			pdef_info->dual_quat = &data->dualquats[index];
+			mat4_to_dquat(pdef_info->dual_quat, pchan->bone->arm_mat, pchan->chan_mat);
+		}
+	}
+}
+
+static void gpencil_armature_deform_verts(Object *armOb, Object *target, bGPDstroke *gps, float(*vertexCos)[3],
+	float(*defMats)[3][3], int numVerts, int deformflag,
+	float(*prevCos)[3], const char *defgrp_name)
+{
+	bPoseChanDeform *pdef_info_array;
+	bPoseChanDeform *pdef_info = NULL;
+	bArmature *arm = armOb->data;
+	bPoseChannel *pchan, **defnrToPC = NULL;
+	int *defnrToPCIndex = NULL;
+	MDeformVert *dverts = NULL;
+	bDeformGroup *dg;
+	DualQuat *dualquats = NULL;
+	float obinv[4][4], premat[4][4], postmat[4][4];
+	const bool use_envelope = (deformflag & ARM_DEF_ENVELOPE) != 0;
+	const bool use_quaternion = (deformflag & ARM_DEF_QUATERNION) != 0;
+	const bool invert_vgroup = (deformflag & ARM_DEF_INVERT_VGROUP) != 0;
+	int defbase_tot = 0;       /* safety for vertexgroup index overflow */
+	int i, target_totvert = 0; /* safety for vertexgroup overflow */
+	int armature_def_nr;
+	int totchan;
+
+	/* in editmode, or not an armature */
+	if (arm->edbo || (armOb->pose == NULL)) {
+		return;
+	}
+
+	if ((armOb->pose->flag & POSE_RECALC) != 0) {
+		printf("ERROR! Trying to evaluate influence of armature '%s' which needs Pose recalc!", armOb->id.name);
+		BLI_assert(0);
+	}
+
+	invert_m4_m4(obinv, target->obmat);
+	copy_m4_m4(premat, target->obmat);
+	mul_m4_m4m4(postmat, obinv, armOb->obmat);
+	invert_m4_m4(premat, postmat);
+
+	/* initialize B_bone matrices and dual quaternions */
+	totchan = BLI_listbase_count(&armOb->pose->chanbase);
+
+	if (use_quaternion) {
+		dualquats = MEM_callocN(sizeof(DualQuat) * totchan, "dualquats");
+	}
+
+	pdef_info_array = MEM_callocN(sizeof(bPoseChanDeform) * totchan, "bPoseChanDeform");
+
+	ArmatureBBoneDefmatsData data = {
+		.pdef_info_array = pdef_info_array,.dualquats = dualquats,.use_quaternion = use_quaternion
+	};
+	BLI_task_parallel_listbase(&armOb->pose->chanbase, &data,
+		gpencil_armature_bbone_defmats_cb, totchan > 512);
+
+	/* get the def_nr for the overall armature vertex group if present */
+	//creo que esto sobra
+	armature_def_nr = defgroup_name_index(target, defgrp_name);
+
+	defbase_tot = BLI_listbase_count(&target->defbase);
+	dverts = gps->dvert;
+	if (dverts)
+		target_totvert = gps->totpoints;
+
+	/* get a vertex-deform-index to posechannel array */
+	defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone");
+	defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * defbase_tot, "defnrToIndex");
+
+	GHash *idx_hash = BLI_ghash_ptr_new("pose channel index by name");
+	int pchan_index = 0;
+	for (pchan = armOb->pose->chanbase.first; pchan != NULL; pchan = pchan->next, ++pchan_index) {
+		BLI_ghash_insert(idx_hash, pchan, SET_INT_IN_POINTER(pchan_index));
+	}
+	for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) {
+		defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name);
+		/* exclude non-deforming bones */
+		if (defnrToPC[i]) {
+			if (defnrToPC[i]->bone->flag & BONE_NO_DEFORM) {
+				defnrToPC[i] = NULL;
+			}
+			else {
+				defnrToPCIndex[i] = GET_INT_FROM_POINTER(BLI_ghash_lookup(idx_hash, defnrToPC[i]));
+			}
+		}
+	}
+	BLI_ghash_free(idx_hash, NULL, NULL);
+
+	for (i = 0; i < numVerts; i++) {
+		MDeformVert *dvert;
+		DualQuat sumdq, *dq = NULL;
+		float *co, dco[3];
+		float sumvec[3], summat[3][3];
+		float *vec = NULL, (*smat)[3] = NULL;
+		float contrib = 0.0f;
+		float armature_weight = 1.0f; /* default to 1 if no overall def group */
+		float prevco_weight = 1.0f;   /* weight for optional cached ver

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list