[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