Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_armature.h31
-rw-r--r--source/blender/blenkernel/BKE_curve.h35
-rw-r--r--source/blender/blenkernel/BKE_lattice.h95
-rw-r--r--source/blender/blenkernel/CMakeLists.txt3
-rw-r--r--source/blender/blenkernel/intern/armature.c562
-rw-r--r--source/blender/blenkernel/intern/armature_deform.c608
-rw-r--r--source/blender/blenkernel/intern/curve.c3
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c398
-rw-r--r--source/blender/blenkernel/intern/lattice.c693
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c389
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c2
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c2
13 files changed, 1491 insertions, 1332 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index c22e7a24afe..30a1644af39 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -32,11 +32,13 @@ struct Bone;
struct Depsgraph;
struct ListBase;
struct Main;
+struct Mesh;
struct Object;
struct PoseTree;
struct Scene;
struct bArmature;
struct bConstraint;
+struct bGPDstroke;
struct bPose;
struct bPoseChannel;
@@ -342,6 +344,35 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
struct Object *object,
int pchan_index);
+/* -------------------------------------------------------------------- */
+/** \name Deform 3D Coordinates by Armature (armature_deform.c)
+ * \{ */
+
+/* Note that we could have a 'BKE_armature_deform_coords' that doesn't take object data
+ * currently there are no callers for this though. */
+
+void BKE_armature_deform_coords_with_gpencil_stroke(struct Object *ob_arm,
+ struct Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ struct bGPDstroke *gps_target);
+
+void BKE_armature_deform_coords_with_mesh(struct Object *ob_arm,
+ struct Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ const struct Mesh *me_target);
+
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 40f73ccfe84..417dbd49855 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -34,6 +34,7 @@ struct Curve;
struct Depsgraph;
struct GHash;
struct ListBase;
+struct MDeformVert;
struct Main;
struct Nurb;
struct Object;
@@ -278,7 +279,15 @@ enum {
void BKE_curve_batch_cache_dirty_tag(struct Curve *cu, int mode);
void BKE_curve_batch_cache_free(struct Curve *cu);
-/* curve_decimate.c */
+extern void (*BKE_curve_batch_cache_dirty_tag_cb)(struct Curve *cu, int mode);
+extern void (*BKE_curve_batch_cache_free_cb)(struct Curve *cu);
+
+/* -------------------------------------------------------------------- */
+/** \name Decimate Curve (curve_decimate.c)
+ *
+ * Simplify curve data.
+ * \{ */
+
unsigned int BKE_curve_decimate_bezt_array(struct BezTriple *bezt_array,
const unsigned int bezt_array_len,
const unsigned int resolu,
@@ -293,8 +302,28 @@ void BKE_curve_decimate_nurb(struct Nurb *nu,
const float error_sq_max,
const unsigned int error_target_len);
-extern void (*BKE_curve_batch_cache_dirty_tag_cb)(struct Curve *cu, int mode);
-extern void (*BKE_curve_batch_cache_free_cb)(struct Curve *cu);
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Deform 3D Coordinates by Curve (curve_deform.c)
+ * \{ */
+
+void BKE_curve_deform_coords(struct Object *ob_curve,
+ struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const struct MDeformVert *dvert,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis);
+void BKE_curve_deform_co(struct Object *ob_curve,
+ struct Object *ob_target,
+ const float orco[3],
+ float vec[3],
+ float mat[3][3],
+ const int no_rot_axis);
+
+/** \} */
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 19cb4f5c4e1..922f7278034 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -45,77 +45,9 @@ struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Main *bmain, const struct Lattice *lt);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
-struct LatticeDeformData *init_latt_deform(struct Object *oblatt,
- struct Object *ob) ATTR_WARN_UNUSED_RESULT;
-void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
-void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
-
bool object_deform_mball(struct Object *ob, struct ListBase *dispbase);
void outside_lattice(struct Lattice *lt);
-/* -------------------------------------------------------------------- */
-/** \name Deform 3D Coordinates by Object Data
- *
- * Used by modifiers (odd location for this API, for now keep these related functions together).
- * \{ */
-
-void BKE_curve_deform_coords(struct Object *ob_curve,
- struct Object *ob_target,
- float (*vert_coords)[3],
- const int vert_coords_len,
- const struct MDeformVert *dvert,
- const int defgrp_index,
- const short flag,
- const short defaxis);
-void BKE_curve_deform_co(struct Object *ob_curve,
- struct Object *ob_target,
- const float orco[3],
- float vec[3],
- float mat[3][3],
- const int no_rot_axis);
-
-void BKE_lattice_deform_coords(struct Object *ob_lattice,
- struct Object *ob_target,
- float (*vert_coords)[3],
- const int vert_coords_len,
- const short flag,
- const char *defgrp_name,
- float influence);
-
-void BKE_lattice_deform_coords_with_mesh(struct Object *ob_lattice,
- struct Object *ob_target,
- float (*vert_coords)[3],
- const int vert_coords_len,
- const short flag,
- const char *defgrp_name,
- const float influence,
- const struct Mesh *me_target);
-
-/* Note that we could have a 'BKE_armature_deform_coords' that doesn't take object data
- * currently there are no callers for this though. */
-
-void BKE_armature_deform_coords_with_gpencil_stroke(struct Object *ob_arm,
- struct Object *ob_target,
- float (*vert_coords)[3],
- float (*vert_deform_mats)[3][3],
- int vert_coords_len,
- int deformflag,
- float (*vert_coords_prev)[3],
- const char *defgrp_name,
- struct bGPDstroke *gps_target);
-
-void BKE_armature_deform_coords_with_mesh(struct Object *ob_arm,
- struct Object *ob_target,
- float (*vert_coords)[3],
- float (*vert_deform_mats)[3][3],
- int vert_coords_len,
- int deformflag,
- float (*vert_coords_prev)[3],
- const char *defgrp_name,
- const struct Mesh *me_target);
-
-/** \} */
-
float (*BKE_lattice_vert_coords_alloc(const struct Lattice *lt, int *r_vert_len))[3];
void BKE_lattice_vert_coords_get(const struct Lattice *lt, float (*vert_coords)[3]);
void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt,
@@ -166,6 +98,33 @@ void BKE_lattice_batch_cache_free(struct Lattice *lt);
extern void (*BKE_lattice_batch_cache_dirty_tag_cb)(struct Lattice *lt, int mode);
extern void (*BKE_lattice_batch_cache_free_cb)(struct Lattice *lt);
+/* -------------------------------------------------------------------- */
+/** \name Deform 3D Coordinates by Lattice (lattice_deform.c)
+ * \{ */
+
+struct LatticeDeformData *init_latt_deform(struct Object *oblatt,
+ struct Object *ob) ATTR_WARN_UNUSED_RESULT;
+void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
+void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
+
+void BKE_lattice_deform_coords(struct Object *ob_lattice,
+ struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ float influence);
+
+void BKE_lattice_deform_coords_with_mesh(struct Object *ob_lattice,
+ struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float influence,
+ const struct Mesh *me_target);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index c1a548360af..b9054d29752 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRC
intern/anim_visualization.c
intern/appdir.c
intern/armature.c
+ intern/armature_deform.c
intern/armature_update.c
intern/autoexec.c
intern/blender.c
@@ -99,6 +100,7 @@ set(SRC
intern/crazyspace.c
intern/curve.c
intern/curve_decimate.c
+ intern/curve_deform.c
intern/curveprofile.c
intern/customdata.c
intern/customdata_file.c
@@ -138,6 +140,7 @@ set(SRC
intern/key.c
intern/keyconfig.c
intern/lattice.c
+ intern/lattice_deform.c
intern/layer.c
intern/layer_utils.c
intern/lib_id.c
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index d2ba3434f2a..007062abb5b 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -35,18 +35,12 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
-#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_lattice_types.h"
#include "DNA_listBase.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -55,11 +49,8 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
-#include "BKE_deform.h"
-#include "BKE_displist.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
@@ -71,8 +62,6 @@
#include "BIK_api.h"
-#include "atomic_ops.h"
-
#include "CLG_log.h"
static CLG_LogRef LOG = {"bke.armature"};
@@ -1386,557 +1375,6 @@ void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Armature Deform Internal Utilities
- * \{ */
-
-/* Add the effect of one bone or B-Bone segment to the accumulated result. */
-static void pchan_deform_accumulate(const DualQuat *deform_dq,
- const float deform_mat[4][4],
- const float co_in[3],
- float weight,
- float co_accum[3],
- DualQuat *dq_accum,
- float mat_accum[3][3])
-{
- if (weight == 0.0f) {
- return;
- }
-
- if (dq_accum) {
- BLI_assert(!co_accum);
-
- add_weighted_dq_dq(dq_accum, deform_dq, weight);
- }
- else {
- float tmp[3];
- mul_v3_m4v3(tmp, deform_mat, co_in);
-
- sub_v3_v3(tmp, co_in);
- madd_v3_v3fl(co_accum, tmp, weight);
-
- if (mat_accum) {
- float tmpmat[3][3];
- copy_m3_m4(tmpmat, deform_mat);
-
- madd_m3_m3m3fl(mat_accum, mat_accum, tmpmat, weight);
- }
- }
-}
-
-static void b_bone_deform(const bPoseChannel *pchan,
- const float co[3],
- float weight,
- float vec[3],
- DualQuat *dq,
- float defmat[3][3])
-{
- const DualQuat *quats = pchan->runtime.bbone_dual_quats;
- const Mat4 *mats = pchan->runtime.bbone_deform_mats;
- const float(*mat)[4] = mats[0].mat;
- float blend, y;
- int index;
-
- /* Transform co to bone space and get its y component. */
- y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
-
- /* Calculate the indices of the 2 affecting b_bone segments. */
- BKE_pchan_bbone_deform_segment_index(pchan, y / pchan->bone->length, &index, &blend);
-
- pchan_deform_accumulate(
- &quats[index], mats[index + 1].mat, co, weight * (1.0f - blend), vec, dq, defmat);
- pchan_deform_accumulate(
- &quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat);
-}
-
-/* using vec with dist to bone b1 - b2 */
-float distfactor_to_bone(
- const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
-{
- float dist_sq;
- float bdelta[3];
- float pdelta[3];
- float hsqr, a, l, rad;
-
- sub_v3_v3v3(bdelta, b2, b1);
- l = normalize_v3(bdelta);
-
- sub_v3_v3v3(pdelta, vec, b1);
-
- a = dot_v3v3(bdelta, pdelta);
- hsqr = len_squared_v3(pdelta);
-
- if (a < 0.0f) {
- /* If we're past the end of the bone, do a spherical field attenuation thing */
- dist_sq = len_squared_v3v3(b1, vec);
- rad = rad1;
- }
- else if (a > l) {
- /* If we're past the end of the bone, do a spherical field attenuation thing */
- dist_sq = len_squared_v3v3(b2, vec);
- rad = rad2;
- }
- else {
- dist_sq = (hsqr - (a * a));
-
- if (l != 0.0f) {
- rad = a / l;
- rad = rad * rad2 + (1.0f - rad) * rad1;
- }
- else {
- rad = rad1;
- }
- }
-
- a = rad * rad;
- if (dist_sq < a) {
- return 1.0f;
- }
- else {
- l = rad + rdist;
- l *= l;
- if (rdist == 0.0f || dist_sq >= l) {
- return 0.0f;
- }
- else {
- a = sqrtf(dist_sq) - rad;
- return 1.0f - (a * a) / (rdist * rdist);
- }
- }
-}
-
-static float dist_bone_deform(
- bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
-{
- Bone *bone = pchan->bone;
- float fac, contrib = 0.0;
-
- if (bone == NULL) {
- return 0.0f;
- }
-
- fac = distfactor_to_bone(
- co, 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 (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
- b_bone_deform(pchan, co, fac, vec, dq, mat);
- }
- else {
- pchan_deform_accumulate(
- &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
- }
- }
- }
-
- return contrib;
-}
-
-static void pchan_bone_deform(bPoseChannel *pchan,
- float weight,
- float vec[3],
- DualQuat *dq,
- float mat[3][3],
- const float co[3],
- float *contrib)
-{
- Bone *bone = pchan->bone;
-
- if (!weight) {
- return;
- }
-
- if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
- b_bone_deform(pchan, co, weight, vec, dq, mat);
- }
- else {
- pchan_deform_accumulate(
- &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
- }
-
- (*contrib) += weight;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Armature Deform #BKE_armature_deform_coords API
- *
- * #BKE_armature_deform_coords and related functions.
- * \{ */
-
-typedef struct ArmatureUserdata {
- Object *ob_arm;
- Object *ob_target;
- const Mesh *me_target;
- float (*vert_coords)[3];
- float (*vert_deform_mats)[3][3];
- float (*vert_coords_prev)[3];
-
- bool use_envelope;
- bool use_quaternion;
- bool invert_vgroup;
- bool use_dverts;
-
- int armature_def_nr;
-
- const MDeformVert *dverts;
- int dverts_len;
-
- bPoseChannel **pchan_from_defbase;
- int defbase_len;
-
- float premat[4][4];
- float postmat[4][4];
-} ArmatureUserdata;
-
-static void armature_vert_task(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- const ArmatureUserdata *data = userdata;
- float(*const vert_coords)[3] = data->vert_coords;
- float(*const vert_deform_mats)[3][3] = data->vert_deform_mats;
- float(*const vert_coords_prev)[3] = data->vert_coords_prev;
- const bool use_envelope = data->use_envelope;
- const bool use_quaternion = data->use_quaternion;
- const bool use_dverts = data->use_dverts;
- const int armature_def_nr = data->armature_def_nr;
-
- const MDeformVert *dvert;
- DualQuat sumdq, *dq = NULL;
- bPoseChannel *pchan;
- 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 vertexcos */
-
- if (use_quaternion) {
- memset(&sumdq, 0, sizeof(DualQuat));
- dq = &sumdq;
- }
- else {
- zero_v3(sumvec);
- vec = sumvec;
-
- if (vert_deform_mats) {
- zero_m3(summat);
- smat = summat;
- }
- }
-
- if (use_dverts || armature_def_nr != -1) {
- if (data->me_target) {
- BLI_assert(i < data->me_target->totvert);
- if (data->me_target->dvert != NULL) {
- dvert = data->me_target->dvert + i;
- }
- else {
- dvert = NULL;
- }
- }
- else if (data->dverts && i < data->dverts_len) {
- dvert = data->dverts + i;
- }
- else {
- dvert = NULL;
- }
- }
- else {
- dvert = NULL;
- }
-
- if (armature_def_nr != -1 && dvert) {
- armature_weight = BKE_defvert_find_weight(dvert, armature_def_nr);
-
- if (data->invert_vgroup) {
- armature_weight = 1.0f - armature_weight;
- }
-
- /* hackish: the blending factor can be used for blending with vert_coords_prev too */
- if (vert_coords_prev) {
- prevco_weight = armature_weight;
- armature_weight = 1.0f;
- }
- }
-
- /* check if there's any point in calculating for this vert */
- if (armature_weight == 0.0f) {
- return;
- }
-
- /* get the coord we work on */
- co = vert_coords_prev ? vert_coords_prev[i] : vert_coords[i];
-
- /* Apply the object's matrix */
- mul_m4_v3(data->premat, co);
-
- if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
- const MDeformWeight *dw = dvert->dw;
- int deformed = 0;
- unsigned int j;
- for (j = dvert->totweight; j != 0; j--, dw++) {
- const uint index = dw->def_nr;
- if (index < data->defbase_len && (pchan = data->pchan_from_defbase[index])) {
- float weight = dw->weight;
- Bone *bone = pchan->bone;
-
- deformed = 1;
-
- if (bone && bone->flag & BONE_MULT_VG_ENV) {
- weight *= distfactor_to_bone(
- co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
- }
-
- pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
- }
- }
- /* if there are vertexgroups but not groups with bones
- * (like for softbody groups) */
- if (deformed == 0 && use_envelope) {
- for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
- contrib += dist_bone_deform(pchan, vec, dq, smat, co);
- }
- }
- }
- }
- else if (use_envelope) {
- for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
- contrib += dist_bone_deform(pchan, vec, dq, smat, co);
- }
- }
- }
-
- /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
- if (contrib > 0.0001f) {
- if (use_quaternion) {
- normalize_dq(dq, contrib);
-
- if (armature_weight != 1.0f) {
- copy_v3_v3(dco, co);
- mul_v3m3_dq(dco, (vert_deform_mats) ? summat : NULL, dq);
- sub_v3_v3(dco, co);
- mul_v3_fl(dco, armature_weight);
- add_v3_v3(co, dco);
- }
- else {
- mul_v3m3_dq(co, (vert_deform_mats) ? summat : NULL, dq);
- }
-
- smat = summat;
- }
- else {
- mul_v3_fl(vec, armature_weight / contrib);
- add_v3_v3v3(co, vec, co);
- }
-
- if (vert_deform_mats) {
- float pre[3][3], post[3][3], tmpmat[3][3];
-
- copy_m3_m4(pre, data->premat);
- copy_m3_m4(post, data->postmat);
- copy_m3_m3(tmpmat, vert_deform_mats[i]);
-
- if (!use_quaternion) { /* quaternion already is scale corrected */
- mul_m3_fl(smat, armature_weight / contrib);
- }
-
- mul_m3_series(vert_deform_mats[i], post, smat, pre, tmpmat);
- }
- }
-
- /* always, check above code */
- mul_m4_v3(data->postmat, co);
-
- /* interpolate with previous modifier position using weight group */
- if (vert_coords_prev) {
- float mw = 1.0f - prevco_weight;
- vert_coords[i][0] = prevco_weight * vert_coords[i][0] + mw * co[0];
- vert_coords[i][1] = prevco_weight * vert_coords[i][1] + mw * co[1];
- vert_coords[i][2] = prevco_weight * vert_coords[i][2] + mw * co[2];
- }
-}
-
-static void armature_deform_coords_impl(Object *ob_arm,
- Object *ob_target,
- float (*vert_coords)[3],
- float (*vert_deform_mats)[3][3],
- const int vert_coords_len,
- const int deformflag,
- float (*vert_coords_prev)[3],
- const char *defgrp_name,
- const Mesh *me_target,
- bGPDstroke *gps_target)
-{
- bArmature *arm = ob_arm->data;
- bPoseChannel **pchan_from_defbase = NULL;
- const MDeformVert *dverts = NULL;
- bDeformGroup *dg;
- 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_len = 0; /* safety for vertexgroup index overflow */
- int i, dverts_len = 0; /* safety for vertexgroup overflow */
- bool use_dverts = false;
- int armature_def_nr;
-
- /* in editmode, or not an armature */
- if (arm->edbo || (ob_arm->pose == NULL)) {
- return;
- }
-
- if ((ob_arm->pose->flag & POSE_RECALC) != 0) {
- CLOG_ERROR(&LOG,
- "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
- ob_arm->id.name);
- BLI_assert(0);
- }
-
- /* get the def_nr for the overall armature vertex group if present */
- armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name);
-
- if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- defbase_len = BLI_listbase_count(&ob_target->defbase);
-
- if (ob_target->type == OB_MESH) {
- Mesh *me = ob_target->data;
- dverts = me->dvert;
- if (dverts) {
- dverts_len = me->totvert;
- }
- }
- else if (ob_target->type == OB_LATTICE) {
- Lattice *lt = ob_target->data;
- dverts = lt->dvert;
- if (dverts) {
- dverts_len = lt->pntsu * lt->pntsv * lt->pntsw;
- }
- }
- else if (ob_target->type == OB_GPENCIL) {
- dverts = gps_target->dvert;
- if (dverts) {
- dverts_len = gps_target->totpoints;
- }
- }
- }
-
- /* get a vertex-deform-index to posechannel array */
- if (deformflag & ARM_DEF_VGROUP) {
- if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- /* if we have a Mesh, only use dverts if it has them */
- if (me_target) {
- use_dverts = (me_target->dvert != NULL);
- }
- else if (dverts) {
- use_dverts = true;
- }
-
- if (use_dverts) {
- pchan_from_defbase = MEM_callocN(sizeof(*pchan_from_defbase) * defbase_len, "defnrToBone");
- /* TODO(sergey): Some considerations here:
- *
- * - Check whether keeping this consistent across frames gives speedup.
- */
- for (i = 0, dg = ob_target->defbase.first; dg; i++, dg = dg->next) {
- pchan_from_defbase[i] = BKE_pose_channel_find_name(ob_arm->pose, dg->name);
- /* exclude non-deforming bones */
- if (pchan_from_defbase[i]) {
- if (pchan_from_defbase[i]->bone->flag & BONE_NO_DEFORM) {
- pchan_from_defbase[i] = NULL;
- }
- }
- }
- }
- }
- }
-
- ArmatureUserdata data = {
- .ob_arm = ob_arm,
- .ob_target = ob_target,
- .me_target = me_target,
- .vert_coords = vert_coords,
- .vert_deform_mats = vert_deform_mats,
- .vert_coords_prev = vert_coords_prev,
- .use_envelope = use_envelope,
- .use_quaternion = use_quaternion,
- .invert_vgroup = invert_vgroup,
- .use_dverts = use_dverts,
- .armature_def_nr = armature_def_nr,
- .dverts = dverts,
- .dverts_len = dverts_len,
- .pchan_from_defbase = pchan_from_defbase,
- .defbase_len = defbase_len,
- };
-
- float obinv[4][4];
- invert_m4_m4(obinv, ob_target->obmat);
-
- mul_m4_m4m4(data.postmat, obinv, ob_arm->obmat);
- invert_m4_m4(data.premat, data.postmat);
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 32;
- BLI_task_parallel_range(0, vert_coords_len, &data, armature_vert_task, &settings);
-
- if (pchan_from_defbase) {
- MEM_freeN(pchan_from_defbase);
- }
-}
-
-void BKE_armature_deform_coords_with_gpencil_stroke(Object *ob_arm,
- Object *ob_target,
- float (*vert_coords)[3],
- float (*vert_deform_mats)[3][3],
- int vert_coords_len,
- int deformflag,
- float (*vert_coords_prev)[3],
- const char *defgrp_name,
- bGPDstroke *gps_target)
-{
- armature_deform_coords_impl(ob_arm,
- ob_target,
- vert_coords,
- vert_deform_mats,
- vert_coords_len,
- deformflag,
- vert_coords_prev,
- defgrp_name,
- NULL,
- gps_target);
-}
-
-void BKE_armature_deform_coords_with_mesh(Object *ob_arm,
- Object *ob_target,
- float (*vert_coords)[3],
- float (*vert_deform_mats)[3][3],
- int vert_coords_len,
- int deformflag,
- float (*vert_coords_prev)[3],
- const char *defgrp_name,
- const Mesh *me_target)
-{
- armature_deform_coords_impl(ob_arm,
- ob_target,
- vert_coords,
- vert_deform_mats,
- vert_coords_len,
- deformflag,
- vert_coords_prev,
- defgrp_name,
- me_target,
- NULL);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Bone Space to Space Conversion API
* \{ */
diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c
new file mode 100644
index 00000000000..cee487e2244
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature_deform.c
@@ -0,0 +1,608 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Deform coordinates by a armature object (used by modifier).
+ */
+
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_deform.h"
+#include "BKE_lattice.h"
+
+#include "DEG_depsgraph_build.h"
+
+#include "CLG_log.h"
+
+static CLG_LogRef LOG = {"bke.armature_deform"};
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Deform Internal Utilities
+ * \{ */
+
+/* Add the effect of one bone or B-Bone segment to the accumulated result. */
+static void pchan_deform_accumulate(const DualQuat *deform_dq,
+ const float deform_mat[4][4],
+ const float co_in[3],
+ float weight,
+ float co_accum[3],
+ DualQuat *dq_accum,
+ float mat_accum[3][3])
+{
+ if (weight == 0.0f) {
+ return;
+ }
+
+ if (dq_accum) {
+ BLI_assert(!co_accum);
+
+ add_weighted_dq_dq(dq_accum, deform_dq, weight);
+ }
+ else {
+ float tmp[3];
+ mul_v3_m4v3(tmp, deform_mat, co_in);
+
+ sub_v3_v3(tmp, co_in);
+ madd_v3_v3fl(co_accum, tmp, weight);
+
+ if (mat_accum) {
+ float tmpmat[3][3];
+ copy_m3_m4(tmpmat, deform_mat);
+
+ madd_m3_m3m3fl(mat_accum, mat_accum, tmpmat, weight);
+ }
+ }
+}
+
+static void b_bone_deform(const bPoseChannel *pchan,
+ const float co[3],
+ float weight,
+ float vec[3],
+ DualQuat *dq,
+ float defmat[3][3])
+{
+ const DualQuat *quats = pchan->runtime.bbone_dual_quats;
+ const Mat4 *mats = pchan->runtime.bbone_deform_mats;
+ const float(*mat)[4] = mats[0].mat;
+ float blend, y;
+ int index;
+
+ /* Transform co to bone space and get its y component. */
+ y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
+
+ /* Calculate the indices of the 2 affecting b_bone segments. */
+ BKE_pchan_bbone_deform_segment_index(pchan, y / pchan->bone->length, &index, &blend);
+
+ pchan_deform_accumulate(
+ &quats[index], mats[index + 1].mat, co, weight * (1.0f - blend), vec, dq, defmat);
+ pchan_deform_accumulate(
+ &quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat);
+}
+
+/* using vec with dist to bone b1 - b2 */
+float distfactor_to_bone(
+ const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
+{
+ float dist_sq;
+ float bdelta[3];
+ float pdelta[3];
+ float hsqr, a, l, rad;
+
+ sub_v3_v3v3(bdelta, b2, b1);
+ l = normalize_v3(bdelta);
+
+ sub_v3_v3v3(pdelta, vec, b1);
+
+ a = dot_v3v3(bdelta, pdelta);
+ hsqr = len_squared_v3(pdelta);
+
+ if (a < 0.0f) {
+ /* If we're past the end of the bone, do a spherical field attenuation thing */
+ dist_sq = len_squared_v3v3(b1, vec);
+ rad = rad1;
+ }
+ else if (a > l) {
+ /* If we're past the end of the bone, do a spherical field attenuation thing */
+ dist_sq = len_squared_v3v3(b2, vec);
+ rad = rad2;
+ }
+ else {
+ dist_sq = (hsqr - (a * a));
+
+ if (l != 0.0f) {
+ rad = a / l;
+ rad = rad * rad2 + (1.0f - rad) * rad1;
+ }
+ else {
+ rad = rad1;
+ }
+ }
+
+ a = rad * rad;
+ if (dist_sq < a) {
+ return 1.0f;
+ }
+ else {
+ l = rad + rdist;
+ l *= l;
+ if (rdist == 0.0f || dist_sq >= l) {
+ return 0.0f;
+ }
+ else {
+ a = sqrtf(dist_sq) - rad;
+ return 1.0f - (a * a) / (rdist * rdist);
+ }
+ }
+}
+
+static float dist_bone_deform(
+ bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
+{
+ Bone *bone = pchan->bone;
+ float fac, contrib = 0.0;
+
+ if (bone == NULL) {
+ return 0.0f;
+ }
+
+ fac = distfactor_to_bone(
+ co, 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 (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
+ b_bone_deform(pchan, co, fac, vec, dq, mat);
+ }
+ else {
+ pchan_deform_accumulate(
+ &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
+ }
+ }
+ }
+
+ return contrib;
+}
+
+static void pchan_bone_deform(bPoseChannel *pchan,
+ float weight,
+ float vec[3],
+ DualQuat *dq,
+ float mat[3][3],
+ const float co[3],
+ float *contrib)
+{
+ Bone *bone = pchan->bone;
+
+ if (!weight) {
+ return;
+ }
+
+ if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
+ b_bone_deform(pchan, co, weight, vec, dq, mat);
+ }
+ else {
+ pchan_deform_accumulate(
+ &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
+ }
+
+ (*contrib) += weight;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Deform #BKE_armature_deform_coords API
+ *
+ * #BKE_armature_deform_coords and related functions.
+ * \{ */
+
+typedef struct ArmatureUserdata {
+ Object *ob_arm;
+ Object *ob_target;
+ const Mesh *me_target;
+ float (*vert_coords)[3];
+ float (*vert_deform_mats)[3][3];
+ float (*vert_coords_prev)[3];
+
+ bool use_envelope;
+ bool use_quaternion;
+ bool invert_vgroup;
+ bool use_dverts;
+
+ int armature_def_nr;
+
+ const MDeformVert *dverts;
+ int dverts_len;
+
+ bPoseChannel **pchan_from_defbase;
+ int defbase_len;
+
+ float premat[4][4];
+ float postmat[4][4];
+} ArmatureUserdata;
+
+static void armature_vert_task(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ const ArmatureUserdata *data = userdata;
+ float(*const vert_coords)[3] = data->vert_coords;
+ float(*const vert_deform_mats)[3][3] = data->vert_deform_mats;
+ float(*const vert_coords_prev)[3] = data->vert_coords_prev;
+ const bool use_envelope = data->use_envelope;
+ const bool use_quaternion = data->use_quaternion;
+ const bool use_dverts = data->use_dverts;
+ const int armature_def_nr = data->armature_def_nr;
+
+ const MDeformVert *dvert;
+ DualQuat sumdq, *dq = NULL;
+ bPoseChannel *pchan;
+ 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 vertexcos */
+
+ if (use_quaternion) {
+ memset(&sumdq, 0, sizeof(DualQuat));
+ dq = &sumdq;
+ }
+ else {
+ zero_v3(sumvec);
+ vec = sumvec;
+
+ if (vert_deform_mats) {
+ zero_m3(summat);
+ smat = summat;
+ }
+ }
+
+ if (use_dverts || armature_def_nr != -1) {
+ if (data->me_target) {
+ BLI_assert(i < data->me_target->totvert);
+ if (data->me_target->dvert != NULL) {
+ dvert = data->me_target->dvert + i;
+ }
+ else {
+ dvert = NULL;
+ }
+ }
+ else if (data->dverts && i < data->dverts_len) {
+ dvert = data->dverts + i;
+ }
+ else {
+ dvert = NULL;
+ }
+ }
+ else {
+ dvert = NULL;
+ }
+
+ if (armature_def_nr != -1 && dvert) {
+ armature_weight = BKE_defvert_find_weight(dvert, armature_def_nr);
+
+ if (data->invert_vgroup) {
+ armature_weight = 1.0f - armature_weight;
+ }
+
+ /* hackish: the blending factor can be used for blending with vert_coords_prev too */
+ if (vert_coords_prev) {
+ prevco_weight = armature_weight;
+ armature_weight = 1.0f;
+ }
+ }
+
+ /* check if there's any point in calculating for this vert */
+ if (armature_weight == 0.0f) {
+ return;
+ }
+
+ /* get the coord we work on */
+ co = vert_coords_prev ? vert_coords_prev[i] : vert_coords[i];
+
+ /* Apply the object's matrix */
+ mul_m4_v3(data->premat, co);
+
+ if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
+ const MDeformWeight *dw = dvert->dw;
+ int deformed = 0;
+ unsigned int j;
+ for (j = dvert->totweight; j != 0; j--, dw++) {
+ const uint index = dw->def_nr;
+ if (index < data->defbase_len && (pchan = data->pchan_from_defbase[index])) {
+ float weight = dw->weight;
+ Bone *bone = pchan->bone;
+
+ deformed = 1;
+
+ if (bone && bone->flag & BONE_MULT_VG_ENV) {
+ weight *= distfactor_to_bone(
+ co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
+ }
+
+ pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
+ }
+ }
+ /* if there are vertexgroups but not groups with bones
+ * (like for softbody groups) */
+ if (deformed == 0 && use_envelope) {
+ for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+ contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+ }
+ }
+ }
+ }
+ else if (use_envelope) {
+ for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+ contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+ }
+ }
+ }
+
+ /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
+ if (contrib > 0.0001f) {
+ if (use_quaternion) {
+ normalize_dq(dq, contrib);
+
+ if (armature_weight != 1.0f) {
+ copy_v3_v3(dco, co);
+ mul_v3m3_dq(dco, (vert_deform_mats) ? summat : NULL, dq);
+ sub_v3_v3(dco, co);
+ mul_v3_fl(dco, armature_weight);
+ add_v3_v3(co, dco);
+ }
+ else {
+ mul_v3m3_dq(co, (vert_deform_mats) ? summat : NULL, dq);
+ }
+
+ smat = summat;
+ }
+ else {
+ mul_v3_fl(vec, armature_weight / contrib);
+ add_v3_v3v3(co, vec, co);
+ }
+
+ if (vert_deform_mats) {
+ float pre[3][3], post[3][3], tmpmat[3][3];
+
+ copy_m3_m4(pre, data->premat);
+ copy_m3_m4(post, data->postmat);
+ copy_m3_m3(tmpmat, vert_deform_mats[i]);
+
+ if (!use_quaternion) { /* quaternion already is scale corrected */
+ mul_m3_fl(smat, armature_weight / contrib);
+ }
+
+ mul_m3_series(vert_deform_mats[i], post, smat, pre, tmpmat);
+ }
+ }
+
+ /* always, check above code */
+ mul_m4_v3(data->postmat, co);
+
+ /* interpolate with previous modifier position using weight group */
+ if (vert_coords_prev) {
+ float mw = 1.0f - prevco_weight;
+ vert_coords[i][0] = prevco_weight * vert_coords[i][0] + mw * co[0];
+ vert_coords[i][1] = prevco_weight * vert_coords[i][1] + mw * co[1];
+ vert_coords[i][2] = prevco_weight * vert_coords[i][2] + mw * co[2];
+ }
+}
+
+static void armature_deform_coords_impl(Object *ob_arm,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ const int vert_coords_len,
+ const int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ const Mesh *me_target,
+ bGPDstroke *gps_target)
+{
+ bArmature *arm = ob_arm->data;
+ bPoseChannel **pchan_from_defbase = NULL;
+ const MDeformVert *dverts = NULL;
+ bDeformGroup *dg;
+ 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_len = 0; /* safety for vertexgroup index overflow */
+ int i, dverts_len = 0; /* safety for vertexgroup overflow */
+ bool use_dverts = false;
+ int armature_def_nr;
+
+ /* in editmode, or not an armature */
+ if (arm->edbo || (ob_arm->pose == NULL)) {
+ return;
+ }
+
+ if ((ob_arm->pose->flag & POSE_RECALC) != 0) {
+ CLOG_ERROR(&LOG,
+ "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
+ ob_arm->id.name);
+ BLI_assert(0);
+ }
+
+ /* get the def_nr for the overall armature vertex group if present */
+ armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name);
+
+ if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
+ defbase_len = BLI_listbase_count(&ob_target->defbase);
+
+ if (ob_target->type == OB_MESH) {
+ Mesh *me = ob_target->data;
+ dverts = me->dvert;
+ if (dverts) {
+ dverts_len = me->totvert;
+ }
+ }
+ else if (ob_target->type == OB_LATTICE) {
+ Lattice *lt = ob_target->data;
+ dverts = lt->dvert;
+ if (dverts) {
+ dverts_len = lt->pntsu * lt->pntsv * lt->pntsw;
+ }
+ }
+ else if (ob_target->type == OB_GPENCIL) {
+ dverts = gps_target->dvert;
+ if (dverts) {
+ dverts_len = gps_target->totpoints;
+ }
+ }
+ }
+
+ /* get a vertex-deform-index to posechannel array */
+ if (deformflag & ARM_DEF_VGROUP) {
+ if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
+ /* if we have a Mesh, only use dverts if it has them */
+ if (me_target) {
+ use_dverts = (me_target->dvert != NULL);
+ }
+ else if (dverts) {
+ use_dverts = true;
+ }
+
+ if (use_dverts) {
+ pchan_from_defbase = MEM_callocN(sizeof(*pchan_from_defbase) * defbase_len, "defnrToBone");
+ /* TODO(sergey): Some considerations here:
+ *
+ * - Check whether keeping this consistent across frames gives speedup.
+ */
+ for (i = 0, dg = ob_target->defbase.first; dg; i++, dg = dg->next) {
+ pchan_from_defbase[i] = BKE_pose_channel_find_name(ob_arm->pose, dg->name);
+ /* exclude non-deforming bones */
+ if (pchan_from_defbase[i]) {
+ if (pchan_from_defbase[i]->bone->flag & BONE_NO_DEFORM) {
+ pchan_from_defbase[i] = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ArmatureUserdata data = {
+ .ob_arm = ob_arm,
+ .ob_target = ob_target,
+ .me_target = me_target,
+ .vert_coords = vert_coords,
+ .vert_deform_mats = vert_deform_mats,
+ .vert_coords_prev = vert_coords_prev,
+ .use_envelope = use_envelope,
+ .use_quaternion = use_quaternion,
+ .invert_vgroup = invert_vgroup,
+ .use_dverts = use_dverts,
+ .armature_def_nr = armature_def_nr,
+ .dverts = dverts,
+ .dverts_len = dverts_len,
+ .pchan_from_defbase = pchan_from_defbase,
+ .defbase_len = defbase_len,
+ };
+
+ float obinv[4][4];
+ invert_m4_m4(obinv, ob_target->obmat);
+
+ mul_m4_m4m4(data.postmat, obinv, ob_arm->obmat);
+ invert_m4_m4(data.premat, data.postmat);
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 32;
+ BLI_task_parallel_range(0, vert_coords_len, &data, armature_vert_task, &settings);
+
+ if (pchan_from_defbase) {
+ MEM_freeN(pchan_from_defbase);
+ }
+}
+
+void BKE_armature_deform_coords_with_gpencil_stroke(Object *ob_arm,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ bGPDstroke *gps_target)
+{
+ armature_deform_coords_impl(ob_arm,
+ ob_target,
+ vert_coords,
+ vert_deform_mats,
+ vert_coords_len,
+ deformflag,
+ vert_coords_prev,
+ defgrp_name,
+ NULL,
+ gps_target);
+}
+
+void BKE_armature_deform_coords_with_mesh(Object *ob_arm,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ const Mesh *me_target)
+{
+ armature_deform_coords_impl(ob_arm,
+ ob_target,
+ vert_coords,
+ vert_deform_mats,
+ vert_coords_len,
+ deformflag,
+ vert_coords_prev,
+ defgrp_name,
+ me_target,
+ NULL);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index e67cf8573f3..0b65f53708f 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -29,7 +29,6 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -43,7 +42,6 @@
/* for dereferencing pointers */
#include "DNA_key_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
#include "BKE_curve.h"
@@ -54,7 +52,6 @@
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
-#include "BKE_material.h"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c
new file mode 100644
index 00000000000..36632982b5c
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -0,0 +1,398 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Deform coordinates by a curve object (used by modifier).
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_anim_path.h"
+#include "BKE_curve.h"
+#include "BKE_lattice.h"
+#include "BKE_modifier.h"
+
+#include "BKE_deform.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Curve Deform Internal Utilities
+ * \{ */
+
+/* calculations is in local space of deformed object
+ * so we store in latmat transform from path coord inside object
+ */
+typedef struct {
+ float dmin[3], dmax[3];
+ float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
+ int no_rot_axis;
+} CurveDeform;
+
+static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
+{
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_m4m4(cd->objectspace, ob->imat, par->obmat);
+ invert_m4_m4(cd->curvespace, cd->objectspace);
+ copy_m3_m4(cd->objectspace3, cd->objectspace);
+ cd->no_rot_axis = 0;
+}
+
+/* this makes sure we can extend for non-cyclic.
+ *
+ * returns OK: 1/0
+ */
+static bool where_on_path_deform(
+ Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius)
+{
+ BevList *bl;
+ float ctime1;
+ int cycl = 0;
+
+ /* test for cyclic */
+ bl = ob->runtime.curve_cache->bev.first;
+ if (!bl->nr) {
+ return false;
+ }
+ if (bl->poly > -1) {
+ cycl = 1;
+ }
+
+ if (cycl == 0) {
+ ctime1 = CLAMPIS(ctime, 0.0f, 1.0f);
+ }
+ else {
+ ctime1 = ctime;
+ }
+
+ /* vec needs 4 items */
+ if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
+
+ if (cycl == 0) {
+ Path *path = ob->runtime.curve_cache->path;
+ float dvec[3];
+
+ if (ctime < 0.0f) {
+ sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
+ mul_v3_fl(dvec, ctime * (float)path->len);
+ add_v3_v3(vec, dvec);
+ if (quat) {
+ copy_qt_qt(quat, path->data[0].quat);
+ }
+ if (radius) {
+ *radius = path->data[0].radius;
+ }
+ }
+ else if (ctime > 1.0f) {
+ sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec);
+ mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len);
+ add_v3_v3(vec, dvec);
+ if (quat) {
+ copy_qt_qt(quat, path->data[path->len - 1].quat);
+ }
+ if (radius) {
+ *radius = path->data[path->len - 1].radius;
+ }
+ /* weight - not used but could be added */
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+/* for each point, rotate & translate to curve */
+/* use path, since it has constant distances */
+/* co: local coord, result local too */
+/* returns quaternion for rotation, using cd->no_rot_axis */
+/* axis is using another define!!! */
+static bool calc_curve_deform(
+ Object *par, float co[3], const short axis, CurveDeform *cd, float r_quat[4])
+{
+ Curve *cu = par->data;
+ float fac, loc[4], dir[3], new_quat[4], radius;
+ short index;
+ const bool is_neg_axis = (axis > 2);
+
+ if (par->runtime.curve_cache == NULL) {
+ /* Happens with a cyclic dependencies. */
+ return false;
+ }
+
+ if (par->runtime.curve_cache->path == NULL) {
+ return false; /* happens on append, cyclic dependencies and empty curves */
+ }
+
+ /* options */
+ if (is_neg_axis) {
+ index = axis - 3;
+ if (cu->flag & CU_STRETCH) {
+ fac = -(co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
+ }
+ else {
+ fac = -(co[index] - cd->dmax[index]) / (par->runtime.curve_cache->path->totdist);
+ }
+ }
+ else {
+ index = axis;
+ if (cu->flag & CU_STRETCH) {
+ fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
+ }
+ else {
+ if (LIKELY(par->runtime.curve_cache->path->totdist > FLT_EPSILON)) {
+ fac = +(co[index] - cd->dmin[index]) / (par->runtime.curve_cache->path->totdist);
+ }
+ else {
+ fac = 0.0f;
+ }
+ }
+ }
+
+ if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */
+ float quat[4], cent[3];
+
+ if (cd->no_rot_axis) { /* set by caller */
+
+ /* This is not exactly the same as 2.4x, since the axis is having rotation removed rather
+ * than changing the axis before calculating the tilt but serves much the same purpose. */
+ float dir_flat[3] = {0, 0, 0}, q[4];
+ copy_v3_v3(dir_flat, dir);
+ dir_flat[cd->no_rot_axis - 1] = 0.0f;
+
+ normalize_v3(dir);
+ normalize_v3(dir_flat);
+
+ rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
+
+ mul_qt_qtqt(new_quat, q, new_quat);
+ }
+
+ /* Logic for 'cent' orientation *
+ *
+ * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
+ *
+ * Use a curve modifier to stretch a cube out, color each side RGB,
+ * positive side light, negative dark.
+ * view with X up (default), from the angle that you can see 3 faces RGB colors (light),
+ * anti-clockwise
+ * Notice X,Y,Z Up all have light colors and each ordered CCW.
+ *
+ * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
+ *
+ * note: moved functions into quat_apply_track/vec_apply_track
+ * */
+ copy_qt_qt(quat, new_quat);
+ copy_v3_v3(cent, co);
+
+ /* zero the axis which is not used,
+ * the big block of text above now applies to these 3 lines */
+ quat_apply_track(
+ quat,
+ axis,
+ (axis == 0 || axis == 2) ? 1 : 0); /* up flag is a dummy, set so no rotation is done */
+ vec_apply_track(cent, axis);
+ cent[index] = 0.0f;
+
+ /* scale if enabled */
+ if (cu->flag & CU_PATH_RADIUS) {
+ mul_v3_fl(cent, radius);
+ }
+
+ /* local rotation */
+ normalize_qt(quat);
+ mul_qt_v3(quat, cent);
+
+ /* translation */
+ add_v3_v3v3(co, cent, loc);
+
+ if (r_quat) {
+ copy_qt_qt(r_quat, quat);
+ }
+
+ return true;
+ }
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Curve Deform #BKE_curve_deform_coords API
+ *
+ * #BKE_curve_deform and related functions.
+ * \{ */
+
+void BKE_curve_deform_coords(Object *ob_curve,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const MDeformVert *dvert,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis)
+{
+ Curve *cu;
+ int a;
+ CurveDeform cd;
+ const bool is_neg_axis = (defaxis > 2);
+ const bool invert_vgroup = (flag & MOD_CURVE_INVERT_VGROUP) != 0;
+
+ if (ob_curve->type != OB_CURVE) {
+ return;
+ }
+
+ cu = ob_curve->data;
+
+ init_curve_deform(ob_curve, ob_target, &cd);
+
+ /* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
+ if (is_neg_axis == false) {
+ cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f;
+ cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f;
+ }
+ else {
+ /* negative, these bounds give a good rest position */
+ cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f;
+ cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f;
+ }
+
+ if (dvert) {
+ const MDeformVert *dvert_iter;
+ float vec[3];
+
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ for (a = 0, dvert_iter = dvert; a < vert_coords_len; a++, dvert_iter++) {
+ const float weight = invert_vgroup ?
+ 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
+ BKE_defvert_find_weight(dvert_iter, defgrp_index);
+
+ if (weight > 0.0f) {
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ copy_v3_v3(vec, vert_coords[a]);
+ calc_curve_deform(ob_curve, vec, defaxis, &cd, NULL);
+ interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
+ }
+ }
+ }
+ else {
+ /* set mesh min/max bounds */
+ INIT_MINMAX(cd.dmin, cd.dmax);
+
+ for (a = 0, dvert_iter = dvert; a < vert_coords_len; a++, dvert_iter++) {
+ const float weight = invert_vgroup ?
+ 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
+ BKE_defvert_find_weight(dvert_iter, defgrp_index);
+ if (weight > 0.0f) {
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
+ }
+ }
+
+ for (a = 0, dvert_iter = dvert; a < vert_coords_len; a++, dvert_iter++) {
+ const float weight = invert_vgroup ?
+ 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
+ BKE_defvert_find_weight(dvert_iter, defgrp_index);
+
+ if (weight > 0.0f) {
+ /* already in 'cd.curvespace', prev for loop */
+ copy_v3_v3(vec, vert_coords[a]);
+ calc_curve_deform(ob_curve, vec, defaxis, &cd, NULL);
+ interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
+ }
+ }
+ }
+ }
+ else {
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ for (a = 0; a < vert_coords_len; a++) {
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ calc_curve_deform(ob_curve, vert_coords[a], defaxis, &cd, NULL);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
+ }
+ }
+ else {
+ /* set mesh min max bounds */
+ INIT_MINMAX(cd.dmin, cd.dmax);
+
+ for (a = 0; a < vert_coords_len; a++) {
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
+ }
+
+ for (a = 0; a < vert_coords_len; a++) {
+ /* already in 'cd.curvespace', prev for loop */
+ calc_curve_deform(ob_curve, vert_coords[a], defaxis, &cd, NULL);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
+ }
+ }
+ }
+}
+
+/* input vec and orco = local coord in armature space */
+/* orco is original not-animated or deformed reference point */
+/* result written in vec and mat */
+void BKE_curve_deform_co(Object *ob_curve,
+ Object *ob_target,
+ const float orco[3],
+ float vec[3],
+ float mat[3][3],
+ const int no_rot_axis)
+{
+ CurveDeform cd;
+ float quat[4];
+
+ if (ob_curve->type != OB_CURVE) {
+ unit_m3(mat);
+ return;
+ }
+
+ init_curve_deform(ob_curve, ob_target, &cd);
+ cd.no_rot_axis = no_rot_axis; /* option to only rotate for XY, for example */
+
+ copy_v3_v3(cd.dmin, orco);
+ copy_v3_v3(cd.dmax, orco);
+
+ mul_m4_v3(cd.curvespace, vec);
+
+ if (calc_curve_deform(ob_curve, vec, ob_target->trackflag, &cd, quat)) {
+ float qmat[3][3];
+
+ quat_to_mat3(qmat, quat);
+ mul_m3_m3m3(mat, qmat, cd.objectspace3);
+ }
+ else {
+ unit_m3(mat);
+ }
+
+ mul_m4_v3(cd.objectspace, vec);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 666eb16c75f..c3b2fd9e35d 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -31,7 +31,6 @@
#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -40,16 +39,13 @@
#include "DNA_defaults.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BKE_anim_path.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_idtype.h"
-#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
@@ -349,695 +345,6 @@ Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt)
return lt_copy;
}
-typedef struct LatticeDeformData {
- Object *object;
- float *latticedata;
- float latmat[4][4];
-} LatticeDeformData;
-
-LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob)
-{
- /* we make an array with all differences */
- Lattice *lt = oblatt->data;
- BPoint *bp;
- DispList *dl = oblatt->runtime.curve_cache ?
- BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) :
- NULL;
- const float *co = dl ? dl->verts : NULL;
- float *fp, imat[4][4];
- float fu, fv, fw;
- int u, v, w;
- float *latticedata;
- float latmat[4][4];
- LatticeDeformData *lattice_deform_data;
-
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
- }
- bp = lt->def;
-
- fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw,
- "latticedata");
-
- /* for example with a particle system: (ob == NULL) */
- if (ob == NULL) {
- /* in deformspace, calc matrix */
- invert_m4_m4(latmat, oblatt->obmat);
-
- /* back: put in deform array */
- invert_m4_m4(imat, latmat);
- }
- else {
- /* in deformspace, calc matrix */
- invert_m4_m4(imat, oblatt->obmat);
- mul_m4_m4m4(latmat, imat, ob->obmat);
-
- /* back: put in deform array */
- invert_m4_m4(imat, latmat);
- }
-
- for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
- for (v = 0, fv = lt->fv; v < lt->pntsv; v++, fv += lt->dv) {
- for (u = 0, fu = lt->fu; u < lt->pntsu; u++, bp++, co += 3, fp += 3, fu += lt->du) {
- if (dl) {
- fp[0] = co[0] - fu;
- fp[1] = co[1] - fv;
- fp[2] = co[2] - fw;
- }
- else {
- fp[0] = bp->vec[0] - fu;
- fp[1] = bp->vec[1] - fv;
- fp[2] = bp->vec[2] - fw;
- }
-
- mul_mat3_m4_v3(imat, fp);
- }
- }
- }
-
- lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
- lattice_deform_data->latticedata = latticedata;
- lattice_deform_data->object = oblatt;
- copy_m4_m4(lattice_deform_data->latmat, latmat);
-
- return lattice_deform_data;
-}
-
-void calc_latt_deform(LatticeDeformData *lattice_deform_data, float co[3], float weight)
-{
- Object *ob = lattice_deform_data->object;
- Lattice *lt = ob->data;
- float u, v, w, tu[4], tv[4], tw[4];
- float vec[3];
- int idx_w, idx_v, idx_u;
- int ui, vi, wi, uu, vv, ww;
-
- /* vgroup influence */
- int defgrp_index = -1;
- float co_prev[3], weight_blend = 0.0f;
- MDeformVert *dvert = BKE_lattice_deform_verts_get(ob);
- float *__restrict latticedata = lattice_deform_data->latticedata;
-
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
- }
- if (latticedata == NULL) {
- return;
- }
-
- if (lt->vgroup[0] && dvert) {
- defgrp_index = BKE_object_defgroup_name_index(ob, lt->vgroup);
- copy_v3_v3(co_prev, co);
- }
-
- /* co is in local coords, treat with latmat */
- mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
-
- /* u v w coords */
-
- if (lt->pntsu > 1) {
- u = (vec[0] - lt->fu) / lt->du;
- ui = (int)floor(u);
- u -= ui;
- key_curve_position_weights(u, tu, lt->typeu);
- }
- else {
- tu[0] = tu[2] = tu[3] = 0.0;
- tu[1] = 1.0;
- ui = 0;
- }
-
- if (lt->pntsv > 1) {
- v = (vec[1] - lt->fv) / lt->dv;
- vi = (int)floor(v);
- v -= vi;
- key_curve_position_weights(v, tv, lt->typev);
- }
- else {
- tv[0] = tv[2] = tv[3] = 0.0;
- tv[1] = 1.0;
- vi = 0;
- }
-
- if (lt->pntsw > 1) {
- w = (vec[2] - lt->fw) / lt->dw;
- wi = (int)floor(w);
- w -= wi;
- key_curve_position_weights(w, tw, lt->typew);
- }
- else {
- tw[0] = tw[2] = tw[3] = 0.0;
- tw[1] = 1.0;
- wi = 0;
- }
-
- for (ww = wi - 1; ww <= wi + 2; ww++) {
- w = tw[ww - wi + 1];
-
- if (w != 0.0f) {
- if (ww > 0) {
- if (ww < lt->pntsw) {
- idx_w = ww * lt->pntsu * lt->pntsv;
- }
- else {
- idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
- }
- }
- else {
- idx_w = 0;
- }
-
- for (vv = vi - 1; vv <= vi + 2; vv++) {
- v = w * tv[vv - vi + 1];
-
- if (v != 0.0f) {
- if (vv > 0) {
- if (vv < lt->pntsv) {
- idx_v = idx_w + vv * lt->pntsu;
- }
- else {
- idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu;
- }
- }
- else {
- idx_v = idx_w;
- }
-
- for (uu = ui - 1; uu <= ui + 2; uu++) {
- u = weight * v * tu[uu - ui + 1];
-
- if (u != 0.0f) {
- if (uu > 0) {
- if (uu < lt->pntsu) {
- idx_u = idx_v + uu;
- }
- else {
- idx_u = idx_v + (lt->pntsu - 1);
- }
- }
- else {
- idx_u = idx_v;
- }
-
- madd_v3_v3fl(co, &latticedata[idx_u * 3], u);
-
- if (defgrp_index != -1) {
- weight_blend += (u * BKE_defvert_find_weight(dvert + idx_u, defgrp_index));
- }
- }
- }
- }
- }
- }
- }
-
- if (defgrp_index != -1) {
- interp_v3_v3v3(co, co_prev, co, weight_blend);
- }
-}
-
-void end_latt_deform(LatticeDeformData *lattice_deform_data)
-{
- if (lattice_deform_data->latticedata) {
- MEM_freeN(lattice_deform_data->latticedata);
- }
-
- MEM_freeN(lattice_deform_data);
-}
-
-/* -------------------------------------------------------------------- */
-/** \name Curve Deform Internal Utilities
- * \{ */
-
-/* calculations is in local space of deformed object
- * so we store in latmat transform from path coord inside object
- */
-typedef struct {
- float dmin[3], dmax[3];
- float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
- int no_rot_axis;
-} CurveDeform;
-
-static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
-{
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_m4m4(cd->objectspace, ob->imat, par->obmat);
- invert_m4_m4(cd->curvespace, cd->objectspace);
- copy_m3_m4(cd->objectspace3, cd->objectspace);
- cd->no_rot_axis = 0;
-}
-
-/* this makes sure we can extend for non-cyclic.
- *
- * returns OK: 1/0
- */
-static bool where_on_path_deform(
- Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius)
-{
- BevList *bl;
- float ctime1;
- int cycl = 0;
-
- /* test for cyclic */
- bl = ob->runtime.curve_cache->bev.first;
- if (!bl->nr) {
- return false;
- }
- if (bl->poly > -1) {
- cycl = 1;
- }
-
- if (cycl == 0) {
- ctime1 = CLAMPIS(ctime, 0.0f, 1.0f);
- }
- else {
- ctime1 = ctime;
- }
-
- /* vec needs 4 items */
- if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
-
- if (cycl == 0) {
- Path *path = ob->runtime.curve_cache->path;
- float dvec[3];
-
- if (ctime < 0.0f) {
- sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
- mul_v3_fl(dvec, ctime * (float)path->len);
- add_v3_v3(vec, dvec);
- if (quat) {
- copy_qt_qt(quat, path->data[0].quat);
- }
- if (radius) {
- *radius = path->data[0].radius;
- }
- }
- else if (ctime > 1.0f) {
- sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec);
- mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len);
- add_v3_v3(vec, dvec);
- if (quat) {
- copy_qt_qt(quat, path->data[path->len - 1].quat);
- }
- if (radius) {
- *radius = path->data[path->len - 1].radius;
- }
- /* weight - not used but could be added */
- }
- }
- return true;
- }
- return false;
-}
-
-/* for each point, rotate & translate to curve */
-/* use path, since it has constant distances */
-/* co: local coord, result local too */
-/* returns quaternion for rotation, using cd->no_rot_axis */
-/* axis is using another define!!! */
-static bool calc_curve_deform(
- Object *par, float co[3], const short axis, CurveDeform *cd, float r_quat[4])
-{
- Curve *cu = par->data;
- float fac, loc[4], dir[3], new_quat[4], radius;
- short index;
- const bool is_neg_axis = (axis > 2);
-
- if (par->runtime.curve_cache == NULL) {
- /* Happens with a cyclic dependencies. */
- return false;
- }
-
- if (par->runtime.curve_cache->path == NULL) {
- return false; /* happens on append, cyclic dependencies and empty curves */
- }
-
- /* options */
- if (is_neg_axis) {
- index = axis - 3;
- if (cu->flag & CU_STRETCH) {
- fac = -(co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
- }
- else {
- fac = -(co[index] - cd->dmax[index]) / (par->runtime.curve_cache->path->totdist);
- }
- }
- else {
- index = axis;
- if (cu->flag & CU_STRETCH) {
- fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
- }
- else {
- if (LIKELY(par->runtime.curve_cache->path->totdist > FLT_EPSILON)) {
- fac = +(co[index] - cd->dmin[index]) / (par->runtime.curve_cache->path->totdist);
- }
- else {
- fac = 0.0f;
- }
- }
- }
-
- if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */
- float quat[4], cent[3];
-
- if (cd->no_rot_axis) { /* set by caller */
-
- /* This is not exactly the same as 2.4x, since the axis is having rotation removed rather
- * than changing the axis before calculating the tilt but serves much the same purpose. */
- float dir_flat[3] = {0, 0, 0}, q[4];
- copy_v3_v3(dir_flat, dir);
- dir_flat[cd->no_rot_axis - 1] = 0.0f;
-
- normalize_v3(dir);
- normalize_v3(dir_flat);
-
- rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
-
- mul_qt_qtqt(new_quat, q, new_quat);
- }
-
- /* Logic for 'cent' orientation *
- *
- * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
- *
- * Use a curve modifier to stretch a cube out, color each side RGB,
- * positive side light, negative dark.
- * view with X up (default), from the angle that you can see 3 faces RGB colors (light),
- * anti-clockwise
- * Notice X,Y,Z Up all have light colors and each ordered CCW.
- *
- * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
- *
- * note: moved functions into quat_apply_track/vec_apply_track
- * */
- copy_qt_qt(quat, new_quat);
- copy_v3_v3(cent, co);
-
- /* zero the axis which is not used,
- * the big block of text above now applies to these 3 lines */
- quat_apply_track(
- quat,
- axis,
- (axis == 0 || axis == 2) ? 1 : 0); /* up flag is a dummy, set so no rotation is done */
- vec_apply_track(cent, axis);
- cent[index] = 0.0f;
-
- /* scale if enabled */
- if (cu->flag & CU_PATH_RADIUS) {
- mul_v3_fl(cent, radius);
- }
-
- /* local rotation */
- normalize_qt(quat);
- mul_qt_v3(quat, cent);
-
- /* translation */
- add_v3_v3v3(co, cent, loc);
-
- if (r_quat) {
- copy_qt_qt(r_quat, quat);
- }
-
- return true;
- }
- return false;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Curve Deform #BKE_curve_deform_coords API
- *
- * #BKE_curve_deform and related functions.
- * \{ */
-
-void BKE_curve_deform_coords(Object *ob_curve,
- Object *ob_target,
- float (*vert_coords)[3],
- const int vert_coords_len,
- const MDeformVert *dvert,
- const int defgrp_index,
- const short flag,
- const short defaxis)
-{
- Curve *cu;
- int a;
- CurveDeform cd;
- const bool is_neg_axis = (defaxis > 2);
- const bool invert_vgroup = (flag & MOD_CURVE_INVERT_VGROUP) != 0;
-
- if (ob_curve->type != OB_CURVE) {
- return;
- }
-
- cu = ob_curve->data;
-
- init_curve_deform(ob_curve, ob_target, &cd);
-
- /* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
- if (is_neg_axis == false) {
- cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f;
- cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f;
- }
- else {
- /* negative, these bounds give a good rest position */
- cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f;
- cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f;
- }
-
- if (dvert) {
- const MDeformVert *dvert_iter;
- float vec[3];
-
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- for (a = 0, dvert_iter = dvert; a < vert_coords_len; a++, dvert_iter++) {
- const float weight = invert_vgroup ?
- 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
- BKE_defvert_find_weight(dvert_iter, defgrp_index);
-
- if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- copy_v3_v3(vec, vert_coords[a]);
- calc_curve_deform(ob_curve, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- }
- else {
- /* set mesh min/max bounds */
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for (a = 0, dvert_iter = dvert; a < vert_coords_len; a++, dvert_iter++) {
- const float weight = invert_vgroup ?
- 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
- BKE_defvert_find_weight(dvert_iter, defgrp_index);
- if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
- }
- }
-
- for (a = 0, dvert_iter = dvert; a < vert_coords_len; a++, dvert_iter++) {
- const float weight = invert_vgroup ?
- 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
- BKE_defvert_find_weight(dvert_iter, defgrp_index);
-
- if (weight > 0.0f) {
- /* already in 'cd.curvespace', prev for loop */
- copy_v3_v3(vec, vert_coords[a]);
- calc_curve_deform(ob_curve, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- }
- }
- else {
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- for (a = 0; a < vert_coords_len; a++) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- calc_curve_deform(ob_curve, vert_coords[a], defaxis, &cd, NULL);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- else {
- /* set mesh min max bounds */
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for (a = 0; a < vert_coords_len; a++) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
- }
-
- for (a = 0; a < vert_coords_len; a++) {
- /* already in 'cd.curvespace', prev for loop */
- calc_curve_deform(ob_curve, vert_coords[a], defaxis, &cd, NULL);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- }
-}
-
-/* input vec and orco = local coord in armature space */
-/* orco is original not-animated or deformed reference point */
-/* result written in vec and mat */
-void BKE_curve_deform_co(Object *ob_curve,
- Object *ob_target,
- const float orco[3],
- float vec[3],
- float mat[3][3],
- const int no_rot_axis)
-{
- CurveDeform cd;
- float quat[4];
-
- if (ob_curve->type != OB_CURVE) {
- unit_m3(mat);
- return;
- }
-
- init_curve_deform(ob_curve, ob_target, &cd);
- cd.no_rot_axis = no_rot_axis; /* option to only rotate for XY, for example */
-
- copy_v3_v3(cd.dmin, orco);
- copy_v3_v3(cd.dmax, orco);
-
- mul_m4_v3(cd.curvespace, vec);
-
- if (calc_curve_deform(ob_curve, vec, ob_target->trackflag, &cd, quat)) {
- float qmat[3][3];
-
- quat_to_mat3(qmat, quat);
- mul_m3_m3m3(mat, qmat, cd.objectspace3);
- }
- else {
- unit_m3(mat);
- }
-
- mul_m4_v3(cd.objectspace, vec);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Lattice Deform #BKE_lattice_deform_coords API
- *
- * #BKE_lattice_deform_coords and related functions.
- * \{ */
-
-typedef struct LatticeDeformUserdata {
- LatticeDeformData *lattice_deform_data;
- float (*vert_coords)[3];
- const MDeformVert *dvert;
- int defgrp_index;
- float fac;
- bool invert_vgroup;
-} LatticeDeformUserdata;
-
-static void lattice_deform_vert_task(void *__restrict userdata,
- const int index,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- const LatticeDeformUserdata *data = userdata;
-
- if (data->dvert != NULL) {
- const float weight = data->invert_vgroup ?
- 1.0f -
- BKE_defvert_find_weight(data->dvert + index, data->defgrp_index) :
- BKE_defvert_find_weight(data->dvert + index, data->defgrp_index);
- if (weight > 0.0f) {
- calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
- }
- }
- else {
- calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], data->fac);
- }
-}
-
-static void lattice_deform_coords_impl(Object *ob_lattice,
- Object *ob_target,
- float (*vert_coords)[3],
- const int vert_coords_len,
- const short flag,
- const char *defgrp_name,
- const float fac,
- const Mesh *me_target)
-{
- LatticeDeformData *lattice_deform_data;
- const MDeformVert *dvert = NULL;
- int defgrp_index = -1;
-
- if (ob_lattice->type != OB_LATTICE) {
- return;
- }
-
- lattice_deform_data = init_latt_deform(ob_lattice, ob_target);
-
- /* Check whether to use vertex groups (only possible if ob_target is a Mesh or Lattice).
- * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
- */
- if (defgrp_name && defgrp_name[0] && ob_target && ELEM(ob_target->type, OB_MESH, OB_LATTICE)) {
- defgrp_index = BKE_object_defgroup_name_index(ob_target, defgrp_name);
-
- if (defgrp_index != -1) {
- /* if there's derived data without deformverts, don't use vgroups */
- if (me_target) {
- dvert = CustomData_get_layer(&me_target->vdata, CD_MDEFORMVERT);
- }
- else if (ob_target->type == OB_LATTICE) {
- dvert = ((Lattice *)ob_target->data)->dvert;
- }
- else {
- dvert = ((Mesh *)ob_target->data)->dvert;
- }
- }
- }
-
- LatticeDeformUserdata data = {
- .lattice_deform_data = lattice_deform_data,
- .vert_coords = vert_coords,
- .dvert = dvert,
- .defgrp_index = defgrp_index,
- .fac = fac,
- .invert_vgroup = (flag & MOD_LATTICE_INVERT_VGROUP) != 0,
- };
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 32;
- BLI_task_parallel_range(0, vert_coords_len, &data, lattice_deform_vert_task, &settings);
-
- end_latt_deform(lattice_deform_data);
-}
-
-void BKE_lattice_deform_coords(Object *ob_lattice,
- Object *ob_target,
- float (*vert_coords)[3],
- int vert_coords_len,
- short flag,
- const char *defgrp_name,
- float fac)
-{
- lattice_deform_coords_impl(
- ob_lattice, ob_target, vert_coords, vert_coords_len, flag, defgrp_name, fac, NULL);
-}
-
-void BKE_lattice_deform_coords_with_mesh(Object *ob_lattice,
- Object *ob_target,
- float (*vert_coords)[3],
- const int vert_coords_len,
- const short flag,
- const char *defgrp_name,
- const float fac,
- const Mesh *me_target)
-{
- lattice_deform_coords_impl(
- ob_lattice, ob_target, vert_coords, vert_coords_len, flag, defgrp_name, fac, me_target);
-}
-
-/** \} */
-
bool object_deform_mball(Object *ob, ListBase *dispbase)
{
if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
new file mode 100644
index 00000000000..7468ae8b3a4
--- /dev/null
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -0,0 +1,389 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Deform coordinates by a lattice object (used by modifier).
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_modifier.h"
+
+#include "BKE_deform.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Lattice Deform API
+ * \{ */
+
+typedef struct LatticeDeformData {
+ Object *object;
+ float *latticedata;
+ float latmat[4][4];
+} LatticeDeformData;
+
+LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob)
+{
+ /* we make an array with all differences */
+ Lattice *lt = oblatt->data;
+ BPoint *bp;
+ DispList *dl = oblatt->runtime.curve_cache ?
+ BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) :
+ NULL;
+ const float *co = dl ? dl->verts : NULL;
+ float *fp, imat[4][4];
+ float fu, fv, fw;
+ int u, v, w;
+ float *latticedata;
+ float latmat[4][4];
+ LatticeDeformData *lattice_deform_data;
+
+ if (lt->editlatt) {
+ lt = lt->editlatt->latt;
+ }
+ bp = lt->def;
+
+ fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw,
+ "latticedata");
+
+ /* for example with a particle system: (ob == NULL) */
+ if (ob == NULL) {
+ /* in deformspace, calc matrix */
+ invert_m4_m4(latmat, oblatt->obmat);
+
+ /* back: put in deform array */
+ invert_m4_m4(imat, latmat);
+ }
+ else {
+ /* in deformspace, calc matrix */
+ invert_m4_m4(imat, oblatt->obmat);
+ mul_m4_m4m4(latmat, imat, ob->obmat);
+
+ /* back: put in deform array */
+ invert_m4_m4(imat, latmat);
+ }
+
+ for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
+ for (v = 0, fv = lt->fv; v < lt->pntsv; v++, fv += lt->dv) {
+ for (u = 0, fu = lt->fu; u < lt->pntsu; u++, bp++, co += 3, fp += 3, fu += lt->du) {
+ if (dl) {
+ fp[0] = co[0] - fu;
+ fp[1] = co[1] - fv;
+ fp[2] = co[2] - fw;
+ }
+ else {
+ fp[0] = bp->vec[0] - fu;
+ fp[1] = bp->vec[1] - fv;
+ fp[2] = bp->vec[2] - fw;
+ }
+
+ mul_mat3_m4_v3(imat, fp);
+ }
+ }
+ }
+
+ lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
+ lattice_deform_data->latticedata = latticedata;
+ lattice_deform_data->object = oblatt;
+ copy_m4_m4(lattice_deform_data->latmat, latmat);
+
+ return lattice_deform_data;
+}
+
+void calc_latt_deform(LatticeDeformData *lattice_deform_data, float co[3], float weight)
+{
+ Object *ob = lattice_deform_data->object;
+ Lattice *lt = ob->data;
+ float u, v, w, tu[4], tv[4], tw[4];
+ float vec[3];
+ int idx_w, idx_v, idx_u;
+ int ui, vi, wi, uu, vv, ww;
+
+ /* vgroup influence */
+ int defgrp_index = -1;
+ float co_prev[3], weight_blend = 0.0f;
+ MDeformVert *dvert = BKE_lattice_deform_verts_get(ob);
+ float *__restrict latticedata = lattice_deform_data->latticedata;
+
+ if (lt->editlatt) {
+ lt = lt->editlatt->latt;
+ }
+ if (latticedata == NULL) {
+ return;
+ }
+
+ if (lt->vgroup[0] && dvert) {
+ defgrp_index = BKE_object_defgroup_name_index(ob, lt->vgroup);
+ copy_v3_v3(co_prev, co);
+ }
+
+ /* co is in local coords, treat with latmat */
+ mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
+
+ /* u v w coords */
+
+ if (lt->pntsu > 1) {
+ u = (vec[0] - lt->fu) / lt->du;
+ ui = (int)floor(u);
+ u -= ui;
+ key_curve_position_weights(u, tu, lt->typeu);
+ }
+ else {
+ tu[0] = tu[2] = tu[3] = 0.0;
+ tu[1] = 1.0;
+ ui = 0;
+ }
+
+ if (lt->pntsv > 1) {
+ v = (vec[1] - lt->fv) / lt->dv;
+ vi = (int)floor(v);
+ v -= vi;
+ key_curve_position_weights(v, tv, lt->typev);
+ }
+ else {
+ tv[0] = tv[2] = tv[3] = 0.0;
+ tv[1] = 1.0;
+ vi = 0;
+ }
+
+ if (lt->pntsw > 1) {
+ w = (vec[2] - lt->fw) / lt->dw;
+ wi = (int)floor(w);
+ w -= wi;
+ key_curve_position_weights(w, tw, lt->typew);
+ }
+ else {
+ tw[0] = tw[2] = tw[3] = 0.0;
+ tw[1] = 1.0;
+ wi = 0;
+ }
+
+ for (ww = wi - 1; ww <= wi + 2; ww++) {
+ w = tw[ww - wi + 1];
+
+ if (w != 0.0f) {
+ if (ww > 0) {
+ if (ww < lt->pntsw) {
+ idx_w = ww * lt->pntsu * lt->pntsv;
+ }
+ else {
+ idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
+ }
+ }
+ else {
+ idx_w = 0;
+ }
+
+ for (vv = vi - 1; vv <= vi + 2; vv++) {
+ v = w * tv[vv - vi + 1];
+
+ if (v != 0.0f) {
+ if (vv > 0) {
+ if (vv < lt->pntsv) {
+ idx_v = idx_w + vv * lt->pntsu;
+ }
+ else {
+ idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu;
+ }
+ }
+ else {
+ idx_v = idx_w;
+ }
+
+ for (uu = ui - 1; uu <= ui + 2; uu++) {
+ u = weight * v * tu[uu - ui + 1];
+
+ if (u != 0.0f) {
+ if (uu > 0) {
+ if (uu < lt->pntsu) {
+ idx_u = idx_v + uu;
+ }
+ else {
+ idx_u = idx_v + (lt->pntsu - 1);
+ }
+ }
+ else {
+ idx_u = idx_v;
+ }
+
+ madd_v3_v3fl(co, &latticedata[idx_u * 3], u);
+
+ if (defgrp_index != -1) {
+ weight_blend += (u * BKE_defvert_find_weight(dvert + idx_u, defgrp_index));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (defgrp_index != -1) {
+ interp_v3_v3v3(co, co_prev, co, weight_blend);
+ }
+}
+
+void end_latt_deform(LatticeDeformData *lattice_deform_data)
+{
+ if (lattice_deform_data->latticedata) {
+ MEM_freeN(lattice_deform_data->latticedata);
+ }
+
+ MEM_freeN(lattice_deform_data);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Lattice Deform #BKE_lattice_deform_coords API
+ *
+ * #BKE_lattice_deform_coords and related functions.
+ * \{ */
+
+typedef struct LatticeDeformUserdata {
+ LatticeDeformData *lattice_deform_data;
+ float (*vert_coords)[3];
+ const MDeformVert *dvert;
+ int defgrp_index;
+ float fac;
+ bool invert_vgroup;
+} LatticeDeformUserdata;
+
+static void lattice_deform_vert_task(void *__restrict userdata,
+ const int index,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ const LatticeDeformUserdata *data = userdata;
+
+ if (data->dvert != NULL) {
+ const float weight = data->invert_vgroup ?
+ 1.0f -
+ BKE_defvert_find_weight(data->dvert + index, data->defgrp_index) :
+ BKE_defvert_find_weight(data->dvert + index, data->defgrp_index);
+ if (weight > 0.0f) {
+ calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
+ }
+ }
+ else {
+ calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], data->fac);
+ }
+}
+
+static void lattice_deform_coords_impl(Object *ob_lattice,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float fac,
+ const Mesh *me_target)
+{
+ LatticeDeformData *lattice_deform_data;
+ const MDeformVert *dvert = NULL;
+ int defgrp_index = -1;
+
+ if (ob_lattice->type != OB_LATTICE) {
+ return;
+ }
+
+ lattice_deform_data = init_latt_deform(ob_lattice, ob_target);
+
+ /* Check whether to use vertex groups (only possible if ob_target is a Mesh or Lattice).
+ * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
+ */
+ if (defgrp_name && defgrp_name[0] && ob_target && ELEM(ob_target->type, OB_MESH, OB_LATTICE)) {
+ defgrp_index = BKE_object_defgroup_name_index(ob_target, defgrp_name);
+
+ if (defgrp_index != -1) {
+ /* if there's derived data without deformverts, don't use vgroups */
+ if (me_target) {
+ dvert = CustomData_get_layer(&me_target->vdata, CD_MDEFORMVERT);
+ }
+ else if (ob_target->type == OB_LATTICE) {
+ dvert = ((Lattice *)ob_target->data)->dvert;
+ }
+ else {
+ dvert = ((Mesh *)ob_target->data)->dvert;
+ }
+ }
+ }
+
+ LatticeDeformUserdata data = {
+ .lattice_deform_data = lattice_deform_data,
+ .vert_coords = vert_coords,
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .fac = fac,
+ .invert_vgroup = (flag & MOD_LATTICE_INVERT_VGROUP) != 0,
+ };
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 32;
+ BLI_task_parallel_range(0, vert_coords_len, &data, lattice_deform_vert_task, &settings);
+
+ end_latt_deform(lattice_deform_data);
+}
+
+void BKE_lattice_deform_coords(Object *ob_lattice,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ int vert_coords_len,
+ short flag,
+ const char *defgrp_name,
+ float fac)
+{
+ lattice_deform_coords_impl(
+ ob_lattice, ob_target, vert_coords, vert_coords_len, flag, defgrp_name, fac, NULL);
+}
+
+void BKE_lattice_deform_coords_with_mesh(Object *ob_lattice,
+ Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float fac,
+ const Mesh *me_target)
+{
+ lattice_deform_coords_impl(
+ ob_lattice, ob_target, vert_coords, vert_coords_len, flag, defgrp_name, fac, me_target);
+}
+
+/** \} */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index fde5ebcff8d..776e5521179 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -36,10 +36,10 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_armature.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_lattice.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 800de546a5a..c8697f90b95 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -34,9 +34,9 @@
#include "DNA_screen_types.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh.h"
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index a081612e063..b55e48f46ce 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -33,8 +33,8 @@
#include "DNA_screen_types.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_editmesh.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh.h"