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:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_anim_path.h14
-rw-r--r--source/blender/blenkernel/BKE_armature.h42
-rw-r--r--source/blender/blenkernel/BKE_cloth.h7
-rw-r--r--source/blender/blenkernel/BKE_curve.h46
-rw-r--r--source/blender/blenkernel/BKE_deform.h12
-rw-r--r--source/blender/blenkernel/BKE_lattice.h80
-rw-r--r--source/blender/blenkernel/BKE_mesh_wrapper.h2
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt3
-rw-r--r--source/blender/blenkernel/intern/anim_path.c96
-rw-r--r--source/blender/blenkernel/intern/armature.c640
-rw-r--r--source/blender/blenkernel/intern/armature_deform.c688
-rw-r--r--source/blender/blenkernel/intern/cloth.c1
-rw-r--r--source/blender/blenkernel/intern/collection.c37
-rw-r--r--source/blender/blenkernel/intern/curve.c3
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c504
-rw-r--r--source/blender/blenkernel/intern/deform.c10
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c648
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c470
-rw-r--r--source/blender/blenkernel/intern/lib_id.c2
-rw-r--r--source/blender/blenkernel/intern/lib_override.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_wrapper.c4
-rw-r--r--source/blender/blenkernel/intern/modifier.c5
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c21
-rw-r--r--source/blender/blenkernel/intern/particle_system.c6
-rw-r--r--source/blender/blenkernel/intern/pointcache.c62
28 files changed, 2107 insertions, 1317 deletions
diff --git a/source/blender/blenkernel/BKE_anim_path.h b/source/blender/blenkernel/BKE_anim_path.h
index 64bcedefa58..4de853303ad 100644
--- a/source/blender/blenkernel/BKE_anim_path.h
+++ b/source/blender/blenkernel/BKE_anim_path.h
@@ -36,13 +36,13 @@ struct Path;
void free_path(struct Path *path);
void calc_curvepath(struct Object *ob, struct ListBase *nurbs);
-int where_on_path(struct Object *ob,
- float ctime,
- float vec[4],
- float dir[3],
- float quat[4],
- float *radius,
- float *weight);
+bool where_on_path(const struct Object *ob,
+ float ctime,
+ float r_vec[4],
+ float r_dir[3],
+ float r_quat[4],
+ float *r_radius,
+ float *r_weight);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index c22e7a24afe..6fb6675a05a 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -28,15 +28,18 @@
extern "C" {
#endif
+struct BMEditMesh;
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 +345,45 @@ 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(const struct Object *ob_arm,
+ const 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(const struct Object *ob_arm,
+ const 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);
+
+void BKE_armature_deform_coords_with_editmesh(const struct Object *ob_arm,
+ const 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 BMEditMesh *em_target);
+
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index f5073ff7aa5..f25482570b1 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -93,9 +93,10 @@ typedef struct Cloth {
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct EdgeSet *edgeset; /* used for selfcollisions */
int last_frame;
- float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */
- struct MEdge *edges; /* Used for hair collisions. */
- struct GHash *sew_edge_graph; /* Sewing edges represented using a GHash */
+ float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */
+ float average_acceleration[3]; /* Moving average of overall acceleration. */
+ struct MEdge *edges; /* Used for hair collisions. */
+ struct GHash *sew_edge_graph; /* Sewing edges represented using a GHash */
} Cloth;
/**
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 40f73ccfe84..d32ab474229 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -29,11 +29,13 @@
extern "C" {
#endif
+struct BMEditMesh;
struct BezTriple;
struct Curve;
struct Depsgraph;
struct GHash;
struct ListBase;
+struct MDeformVert;
struct Main;
struct Nurb;
struct Object;
@@ -278,7 +280,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 +303,38 @@ 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(const struct Object *ob_curve,
+ const 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_coords_with_editmesh(const Object *ob_curve,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis,
+ struct BMEditMesh *em_target);
+
+void BKE_curve_deform_co(const struct Object *ob_curve,
+ const struct Object *ob_target,
+ const float orco[3],
+ float vec[3],
+ const int no_rot_axis,
+ float r_mat[3][3]);
+
+/** \} */
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index c86b877b575..04b85aebb39 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -40,14 +40,16 @@ struct bDeformGroup;
struct bDeformGroup *BKE_object_defgroup_new(struct Object *ob, const char *name);
void BKE_defgroup_copy_list(struct ListBase *lb1, const struct ListBase *lb2);
struct bDeformGroup *BKE_defgroup_duplicate(const struct bDeformGroup *ingroup);
-struct bDeformGroup *BKE_object_defgroup_find_name(struct Object *ob, const char *name);
-int *BKE_object_defgroup_flip_map(struct Object *ob, int *flip_map_len, const bool use_default);
-int *BKE_object_defgroup_flip_map_single(struct Object *ob,
+struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, const char *name);
+int *BKE_object_defgroup_flip_map(const struct Object *ob,
+ int *flip_map_len,
+ const bool use_default);
+int *BKE_object_defgroup_flip_map_single(const struct Object *ob,
int *flip_map_len,
const bool use_default,
int defgroup);
-int BKE_object_defgroup_flip_index(struct Object *ob, int index, const bool use_default);
-int BKE_object_defgroup_name_index(struct Object *ob, const char *name);
+int BKE_object_defgroup_flip_index(const struct Object *ob, int index, const bool use_default);
+int BKE_object_defgroup_name_index(const struct Object *ob, const char *name);
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
struct MDeformWeight *BKE_defvert_find_index(const struct MDeformVert *dv, const int defgroup);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 3cd8c69a263..bb23ad63020 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -30,6 +30,7 @@
extern "C" {
#endif
+struct BMEditMesh;
struct BPoint;
struct Depsgraph;
struct Lattice;
@@ -45,48 +46,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);
-void curve_deform_verts(struct Object *cuOb,
- struct Object *target,
- float (*vert_coords)[3],
- int numVerts,
- struct MDeformVert *dvert,
- const int defgrp_index,
- short flag,
- short defaxis);
-void curve_deform_vector(struct Object *cuOb,
- struct Object *target,
- float orco[3],
- float vec[3],
- float mat[3][3],
- int no_rot_axis);
-
-void lattice_deform_verts(struct Object *laOb,
- struct Object *target,
- struct Mesh *mesh,
- float (*vert_coords)[3],
- int numVerts,
- short flag,
- const char *vgroup,
- float influence);
-void armature_deform_verts(struct Object *armOb,
- struct Object *target,
- const struct Mesh *mesh,
- float (*vert_coords)[3],
- float (*defMats)[3][3],
- int numVerts,
- int deformflag,
- float (*prevCos)[3],
- const char *defgrp_name,
- struct bGPDstroke *gps);
-
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,
@@ -97,7 +59,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
-struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice);
+struct MDeformVert *BKE_lattice_deform_verts_get(const struct Object *lattice);
struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt);
struct BoundBox *BKE_lattice_boundbox_get(struct Object *ob);
@@ -137,6 +99,44 @@ 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 *BKE_lattice_deform_data_create(
+ const struct Object *oblatt, const struct Object *ob) ATTR_WARN_UNUSED_RESULT;
+void BKE_lattice_deform_data_eval_co(struct LatticeDeformData *lattice_deform_data,
+ float co[3],
+ float weight);
+void BKE_lattice_deform_data_destroy(struct LatticeDeformData *lattice_deform_data);
+
+void BKE_lattice_deform_coords(const struct Object *ob_lattice,
+ const 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(const struct Object *ob_lattice,
+ const 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);
+
+void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float influence,
+ struct BMEditMesh *em_target);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh_wrapper.h b/source/blender/blenkernel/BKE_mesh_wrapper.h
index ec6a1e3457c..00e2dd08726 100644
--- a/source/blender/blenkernel/BKE_mesh_wrapper.h
+++ b/source/blender/blenkernel/BKE_mesh_wrapper.h
@@ -31,7 +31,7 @@ extern "C" {
struct Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(
struct BMEditMesh *em,
const struct CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
+ const float (*vert_coords)[3],
const struct Mesh *me_settings);
struct Mesh *BKE_mesh_wrapper_from_editmesh(struct BMEditMesh *em,
const struct CustomData_MeshMasks *cd_mask_extra,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 4d30c5c7fce..144e091d971 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -24,6 +24,7 @@
* \ingroup bke
*/
+#include "BLI_ghash.h"
#include "BLI_utildefines.h"
#include "DNA_object_enums.h"
@@ -268,6 +269,7 @@ typedef struct SculptClothLengthConstraint {
typedef struct SculptClothSimulation {
SculptClothLengthConstraint *length_constraints;
int tot_length_constraints;
+ GSet *created_length_constraints;
int capacity_length_constraints;
float *length_constraint_tweak;
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 45cd4933f80..92e0904c568 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/asset_engine.c
intern/autoexec.c
@@ -100,6 +101,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
@@ -139,6 +141,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/anim_path.c b/source/blender/blenkernel/intern/anim_path.c
index e073bd6fc82..628e54971ce 100644
--- a/source/blender/blenkernel/intern/anim_path.c
+++ b/source/blender/blenkernel/intern/anim_path.c
@@ -42,9 +42,11 @@ static CLG_LogRef LOG = {"bke.anim"};
/* ******************************************************************** */
/* Curve Paths - for curve deforms and/or curve following */
-/* free curve path data
- * NOTE: frees the path itself!
- * NOTE: this is increasingly inaccurate with non-uniform BevPoint subdivisions [#24633]
+/**
+ * Free curve path data
+ *
+ * \note Frees the path itself!
+ * \note This is increasingly inaccurate with non-uniform #BevPoint subdivisions T24633.
*/
void free_path(Path *path)
{
@@ -54,8 +56,9 @@ void free_path(Path *path)
MEM_freeN(path);
}
-/* calculate a curve-deform path for a curve
- * - only called from displist.c -> do_makeDispListCurveTypes
+/**
+ * Calculate a curve-deform path for a curve
+ * - Only called from displist.c -> #do_makeDispListCurveTypes
*/
void calc_curvepath(Object *ob, ListBase *nurbs)
{
@@ -192,39 +195,40 @@ static int interval_test(const int min, const int max, int p1, const int cycl)
return p1;
}
-/* calculate the deformation implied by the curve path at a given parametric position,
+/**
+ * Calculate the deformation implied by the curve path at a given parametric position,
* and returns whether this operation succeeded.
*
- * note: ctime is normalized range <0-1>
+ * \param ctime: Time is normalized range <0-1>.
*
- * returns OK: 1/0
+ * \return success.
*/
-int where_on_path(Object *ob,
- float ctime,
- float vec[4],
- float dir[3],
- float quat[4],
- float *radius,
- float *weight)
+bool where_on_path(const Object *ob,
+ float ctime,
+ float r_vec[4],
+ float r_dir[3],
+ float r_quat[4],
+ float *r_radius,
+ float *r_weight)
{
Curve *cu;
- Nurb *nu;
- BevList *bl;
- Path *path;
- PathPoint *pp, *p0, *p1, *p2, *p3;
+ const Nurb *nu;
+ const BevList *bl;
+ const Path *path;
+ const PathPoint *pp, *p0, *p1, *p2, *p3;
float fac;
float data[4];
int cycl = 0, s0, s1, s2, s3;
- ListBase *nurbs;
+ const ListBase *nurbs;
if (ob == NULL || ob->type != OB_CURVE) {
- return 0;
+ return false;
}
cu = ob->data;
if (ob->runtime.curve_cache == NULL || ob->runtime.curve_cache->path == NULL ||
ob->runtime.curve_cache->path->data == NULL) {
CLOG_WARN(&LOG, "no path!");
- return 0;
+ return false;
}
path = ob->runtime.curve_cache->path;
pp = path->data;
@@ -232,10 +236,10 @@ int where_on_path(Object *ob,
/* test for cyclic */
bl = ob->runtime.curve_cache->bev.first;
if (!bl) {
- return 0;
+ return false;
}
if (!bl->nr) {
- return 0;
+ return false;
}
if (bl->poly > -1) {
cycl = 1;
@@ -262,7 +266,7 @@ int where_on_path(Object *ob,
/* NOTE: commented out for follow constraint
*
- * If it's ever be uncommented watch out for curve_deform_verts()
+ * If it's ever be uncommented watch out for BKE_curve_deform_coords()
* which used to temporary set CU_FOLLOW flag for the curve and no
* longer does it (because of threading issues of such a thing.
*/
@@ -270,10 +274,10 @@ int where_on_path(Object *ob,
key_curve_tangent_weights(1.0f - fac, data, KEY_BSPLINE);
- interp_v3_v3v3v3v3(dir, p0->vec, p1->vec, p2->vec, p3->vec, data);
+ interp_v3_v3v3v3v3(r_dir, p0->vec, p1->vec, p2->vec, p3->vec, data);
- /* make compatible with vectoquat */
- negate_v3(dir);
+ /* Make compatible with #vec_to_quat. */
+ negate_v3(r_dir);
//}
nurbs = BKE_curve_editNurbs_get(cu);
@@ -296,16 +300,16 @@ int where_on_path(Object *ob,
key_curve_position_weights(1.0f - fac, data, KEY_BSPLINE);
}
- vec[0] = data[0] * p0->vec[0] + data[1] * p1->vec[0] + data[2] * p2->vec[0] +
- data[3] * p3->vec[0]; /* X */
- vec[1] = data[0] * p0->vec[1] + data[1] * p1->vec[1] + data[2] * p2->vec[1] +
- data[3] * p3->vec[1]; /* Y */
- vec[2] = data[0] * p0->vec[2] + data[1] * p1->vec[2] + data[2] * p2->vec[2] +
- data[3] * p3->vec[2]; /* Z */
- vec[3] = data[0] * p0->vec[3] + data[1] * p1->vec[3] + data[2] * p2->vec[3] +
- data[3] * p3->vec[3]; /* Tilt, should not be needed since we have quat still used */
+ r_vec[0] = /* X */
+ data[0] * p0->vec[0] + data[1] * p1->vec[0] + data[2] * p2->vec[0] + data[3] * p3->vec[0];
+ r_vec[1] = /* Y */
+ data[0] * p0->vec[1] + data[1] * p1->vec[1] + data[2] * p2->vec[1] + data[3] * p3->vec[1];
+ r_vec[2] = /* Z */
+ data[0] * p0->vec[2] + data[1] * p1->vec[2] + data[2] * p2->vec[2] + data[3] * p3->vec[2];
+ r_vec[3] = /* Tilt, should not be needed since we have quat still used */
+ data[0] * p0->vec[3] + data[1] * p1->vec[3] + data[2] * p2->vec[3] + data[3] * p3->vec[3];
- if (quat) {
+ if (r_quat) {
float totfac, q1[4], q2[4];
totfac = data[0] + data[3];
@@ -326,22 +330,22 @@ int where_on_path(Object *ob,
totfac = data[0] + data[1] + data[2] + data[3];
if (totfac > FLT_EPSILON) {
- interp_qt_qtqt(quat, q1, q2, (data[1] + data[2]) / totfac);
+ interp_qt_qtqt(r_quat, q1, q2, (data[1] + data[2]) / totfac);
}
else {
- copy_qt_qt(quat, q2);
+ copy_qt_qt(r_quat, q2);
}
}
- if (radius) {
- *radius = data[0] * p0->radius + data[1] * p1->radius + data[2] * p2->radius +
- data[3] * p3->radius;
+ if (r_radius) {
+ *r_radius = data[0] * p0->radius + data[1] * p1->radius + data[2] * p2->radius +
+ data[3] * p3->radius;
}
- if (weight) {
- *weight = data[0] * p0->weight + data[1] * p1->weight + data[2] * p2->weight +
- data[3] * p3->weight;
+ if (r_weight) {
+ *r_weight = data[0] * p0->weight + data[1] * p1->weight + data[2] * p2->weight +
+ data[3] * p3->weight;
}
- return 1;
+ return true;
}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 36921bd2662..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,13 +62,13 @@
#include "BIK_api.h"
-#include "atomic_ops.h"
-
#include "CLG_log.h"
static CLG_LogRef LOG = {"bke.armature"};
-/*************************** Prototypes ***************************/
+/* -------------------------------------------------------------------- */
+/** \name Prototypes
+ * \{ */
static void copy_bonechildren(Bone *bone_dst,
const Bone *bone_src,
@@ -87,7 +78,11 @@ static void copy_bonechildren(Bone *bone_dst,
static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst);
-/*********************** Armature Datablock ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Data-block
+ * \{ */
/**
* Only copy internal data of Armature ID from source
@@ -187,7 +182,11 @@ IDTypeInfo IDType_ID_AR = {
.foreach_id = armature_foreach_id,
};
-/* **************** Generic Functions, data level *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic Data-Level Functions
+ * \{ */
bArmature *BKE_armature_add(Main *bmain, const char *name)
{
@@ -284,6 +283,12 @@ bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm)
return arm_copy;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Transform Copy
+ * \{ */
+
static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src)
{
bone_dst->roll = bone_src->roll;
@@ -313,6 +318,14 @@ void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Transform by 4x4 Matrix
+ *
+ * \see #ED_armature_edit_transform for the edit-mode version of this function.
+ * \{ */
+
/** Helper for #ED_armature_transform */
static void armature_transform_recurse(ListBase *bonebase,
const float mat[4][4],
@@ -408,6 +421,14 @@ void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do
armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, NULL, NULL);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Bone Find by Name
+ *
+ * Using fast #GHash look-ups when available.
+ * \{ */
+
static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name)
{
Bone *curBone, *rbone;
@@ -480,6 +501,12 @@ void BKE_armature_bone_hash_free(bArmature *arm)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Bone Flags
+ * \{ */
+
bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
{
if (bone->flag & flag) {
@@ -493,6 +520,12 @@ bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Layer Refresh Used
+ * \{ */
+
static void armature_refresh_layer_used_recursive(bArmature *arm, ListBase *bones)
{
LISTBASE_FOREACH (Bone *, bone, bones) {
@@ -518,6 +551,12 @@ void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmatu
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Layer Refresh Used
+ * \{ */
+
/* Finds the best possible extension to the name on a particular axis. (For renaming, check for
* unique names afterwards) strip_number: removes number extensions (TODO: not used)
* axis: the axis to name on
@@ -654,7 +693,11 @@ int bone_autoside_name(
}
}
-/* ************* B-Bone support ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature B-Bone Support
+ * \{ */
/* Compute a set of bezier parameter values that produce approximately equally spaced points. */
static void equalize_cubic_bezier(const float control[4][3],
@@ -1209,8 +1252,6 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
return param->segments;
}
-/* ************ Armature Deform ******************* */
-
static void allocate_bbone_cache(bPoseChannel *pchan, int segments)
{
bPoseChannel_Runtime *runtime = &pchan->runtime;
@@ -1331,498 +1372,11 @@ void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan,
*r_blend_next = blend;
}
-/* 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;
-}
-
-typedef struct ArmatureUserdata {
- Object *armOb;
- Object *target;
- const Mesh *mesh;
- float (*vertexCos)[3];
- float (*defMats)[3][3];
- float (*prevCos)[3];
-
- bool use_envelope;
- bool use_quaternion;
- bool invert_vgroup;
- bool use_dverts;
-
- int armature_def_nr;
-
- int target_totvert;
- MDeformVert *dverts;
-
- int defbase_tot;
- bPoseChannel **defnrToPC;
-
- 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 vertexCos)[3] = data->vertexCos;
- float(*const defMats)[3][3] = data->defMats;
- float(*const prevCos)[3] = data->prevCos;
- 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;
-
- 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 {
- sumvec[0] = sumvec[1] = sumvec[2] = 0.0f;
- vec = sumvec;
-
- if (defMats) {
- zero_m3(summat);
- smat = summat;
- }
- }
-
- if (use_dverts || armature_def_nr != -1) {
- if (data->mesh) {
- BLI_assert(i < data->mesh->totvert);
- if (data->mesh->dvert != NULL) {
- dvert = data->mesh->dvert + i;
- }
- else {
- dvert = NULL;
- }
- }
- else if (data->dverts && i < data->target_totvert) {
- 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 prevCos too */
- if (prevCos) {
- 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 = prevCos ? prevCos[i] : vertexCos[i];
-
- /* Apply the object's matrix */
- mul_m4_v3(data->premat, co);
-
- if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
- 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_tot && (pchan = data->defnrToPC[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->armOb->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->armOb->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, (defMats) ? summat : NULL, dq);
- sub_v3_v3(dco, co);
- mul_v3_fl(dco, armature_weight);
- add_v3_v3(co, dco);
- }
- else {
- mul_v3m3_dq(co, (defMats) ? summat : NULL, dq);
- }
-
- smat = summat;
- }
- else {
- mul_v3_fl(vec, armature_weight / contrib);
- add_v3_v3v3(co, vec, co);
- }
-
- if (defMats) {
- 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, defMats[i]);
-
- if (!use_quaternion) { /* quaternion already is scale corrected */
- mul_m3_fl(smat, armature_weight / contrib);
- }
-
- mul_m3_series(defMats[i], post, smat, pre, tmpmat);
- }
- }
-
- /* always, check above code */
- mul_m4_v3(data->postmat, co);
-
- /* interpolate with previous modifier position using weight group */
- if (prevCos) {
- float mw = 1.0f - prevco_weight;
- vertexCos[i][0] = prevco_weight * vertexCos[i][0] + mw * co[0];
- vertexCos[i][1] = prevco_weight * vertexCos[i][1] + mw * co[1];
- vertexCos[i][2] = prevco_weight * vertexCos[i][2] + mw * co[2];
- }
-}
-
-void armature_deform_verts(Object *armOb,
- Object *target,
- const Mesh *mesh,
- float (*vertexCos)[3],
- float (*defMats)[3][3],
- int numVerts,
- int deformflag,
- float (*prevCos)[3],
- const char *defgrp_name,
- bGPDstroke *gps)
-{
- bArmature *arm = armOb->data;
- bPoseChannel **defnrToPC = NULL;
- 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_tot = 0; /* safety for vertexgroup index overflow */
- int i, target_totvert = 0; /* safety for vertexgroup overflow */
- bool use_dverts = false;
- int armature_def_nr;
-
- /* in editmode, or not an armature */
- if (arm->edbo || (armOb->pose == NULL)) {
- return;
- }
-
- if ((armOb->pose->flag & POSE_RECALC) != 0) {
- CLOG_ERROR(&LOG,
- "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
- armOb->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(target, defgrp_name);
-
- if (ELEM(target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- defbase_tot = BLI_listbase_count(&target->defbase);
-
- if (target->type == OB_MESH) {
- Mesh *me = target->data;
- dverts = me->dvert;
- if (dverts) {
- target_totvert = me->totvert;
- }
- }
- else if (target->type == OB_LATTICE) {
- Lattice *lt = target->data;
- dverts = lt->dvert;
- if (dverts) {
- target_totvert = lt->pntsu * lt->pntsv * lt->pntsw;
- }
- }
- else if (target->type == OB_GPENCIL) {
- dverts = gps->dvert;
- if (dverts) {
- target_totvert = gps->totpoints;
- }
- }
- }
-
- /* get a vertex-deform-index to posechannel array */
- if (deformflag & ARM_DEF_VGROUP) {
- if (ELEM(target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- /* if we have a Mesh, only use dverts if it has them */
- if (mesh) {
- use_dverts = (mesh->dvert != NULL);
- }
- else if (dverts) {
- use_dverts = true;
- }
-
- if (use_dverts) {
- defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone");
- /* TODO(sergey): Some considerations here:
- *
- * - Check whether keeping this consistent across frames gives speedup.
- */
- 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;
- }
- }
- }
- }
- }
- }
-
- ArmatureUserdata data = {.armOb = armOb,
- .target = target,
- .mesh = mesh,
- .vertexCos = vertexCos,
- .defMats = defMats,
- .prevCos = prevCos,
- .use_envelope = use_envelope,
- .use_quaternion = use_quaternion,
- .invert_vgroup = invert_vgroup,
- .use_dverts = use_dverts,
- .armature_def_nr = armature_def_nr,
- .target_totvert = target_totvert,
- .dverts = dverts,
- .defbase_tot = defbase_tot,
- .defnrToPC = defnrToPC};
-
- float obinv[4][4];
- invert_m4_m4(obinv, target->obmat);
-
- mul_m4_m4m4(data.postmat, obinv, armOb->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, numVerts, &data, armature_vert_task, &settings);
-
- if (defnrToPC) {
- MEM_freeN(defnrToPC);
- }
-}
-
-/* ************ END Armature Deform ******************* */
+/* -------------------------------------------------------------------- */
+/** \name Bone Space to Space Conversion API
+ * \{ */
void get_objectspace_bone_matrix(struct Bone *bone,
float M_accumulatedMatrix[4][4],
@@ -1832,8 +1386,6 @@ void get_objectspace_bone_matrix(struct Bone *bone,
copy_m4_m4(M_accumulatedMatrix, bone->arm_mat);
}
-/* **************** Space to Space API ****************** */
-
/* Convert World-Space Matrix to Pose-Space Matrix */
void BKE_armature_mat_world_to_pose(Object *ob, float inmat[4][4], float outmat[4][4])
{
@@ -1868,6 +1420,12 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl
copy_v3_v3(outloc, nLocMat[3]);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Matrix Calculation API
+ * \{ */
+
/* Simple helper, computes the offset bone matrix.
* offs_bone = yoffs(b-1) + root(b) + bonemat(b). */
void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4])
@@ -2156,6 +1714,14 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl
copy_v3_v3(outloc, nLocMat[3]);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Matrix Read/Write API
+ *
+ * High level functions for transforming bones and reading the transform values.
+ * \{ */
+
void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph,
Object *ob,
bPoseChannel *pchan,
@@ -2255,8 +1821,13 @@ void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
mul_m4_m4m4(delta_mat, imat, pose_mat);
}
-/* **************** Rotation Mode Conversions ****************************** */
-/* Used for Objects and Pose Channels, since both can have multiple rotation representations */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Rotation Mode Conversions
+ *
+ * Used for Objects and Pose Channels, since both can have multiple rotation representations.
+ * \{ */
/* Called from RNA when rotation mode changes
* - the result should be that the rotations given in the provided pointers have had conversions
@@ -2308,9 +1879,15 @@ void BKE_rotMode_change_values(
}
}
-/* **************** The new & simple (but OK!) armature evaluation ********* */
+/** \} */
-/* ****************** And how it works! ****************************************
+/* -------------------------------------------------------------------- */
+/** \name Bone Vector, Roll Conversion
+ *
+ * Used for Objects and Pose Channels, since both can have multiple rotation representations.
+ *
+ * How it Works
+ * ============
*
* This is the bone transformation trick; they're hierarchical so each bone(b)
* is in the coord system of bone(b-1):
@@ -2326,7 +1903,7 @@ void BKE_rotMode_change_values(
*
* pose_mat(b)= arm_mat(b) * chan_mat(b)
*
- * *************************************************************************** */
+ * \{ */
/* Computes vector and roll based on a rotation.
* "mat" must contain only a rotation, and no scaling. */
@@ -2494,6 +2071,12 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3])
vec_roll_to_mat3_normalized(nor, roll, mat);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Bone Matrix Calculation (Recursive)
+ * \{ */
+
/**
* Recursive part, calculates rest-position of entire tree of children.
* \note Used when exiting edit-mode too.
@@ -2548,6 +2131,12 @@ void BKE_armature_where_is(bArmature *arm)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Rebuild
+ * \{ */
+
/* if bone layer is protected, copy the data from from->pose
* when used with linked libraries this copies from the linked pose into the local pose */
static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
@@ -2828,7 +2417,11 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
}
}
-/* ********************** THE POSE SOLVER ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Solver
+ * \{ */
/* loc/rot/size to given mat4 */
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float chan_mat[4][4])
@@ -3024,7 +2617,12 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
}
}
-/************** Bounding box ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Calculate Bounding Box (Armature & Pose)
+ * \{ */
+
static int minmax_armature(Object *ob, float r_min[3], float r_max[3])
{
bPoseChannel *pchan;
@@ -3106,7 +2704,11 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden
return changed;
}
-/************** Graph evaluation ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Graph Evaluation
+ * \{ */
bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data)
{
@@ -3145,3 +2747,5 @@ bPoseChannel *BKE_armature_splineik_solver_find_root(bPoseChannel *pchan,
}
return rootchan;
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c
new file mode 100644
index 00000000000..e757e30e524
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature_deform.c
@@ -0,0 +1,688 @@
+/*
+ * 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_editmesh.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 {
+ const Object *ob_arm;
+ const 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];
+
+ /** Specific data types. */
+ struct {
+ int cd_dvert_offset;
+ } bmesh;
+} ArmatureUserdata;
+
+static void armature_vert_task_with_dvert(const ArmatureUserdata *data,
+ const int i,
+ const MDeformVert *dvert)
+{
+ 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;
+
+ 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 (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_vert_task(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ const ArmatureUserdata *data = userdata;
+ const MDeformVert *dvert;
+ if (data->use_dverts || data->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;
+ }
+
+ armature_vert_task_with_dvert(data, i, dvert);
+}
+
+static void armature_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter)
+{
+ const ArmatureUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v, data->bmesh.cd_dvert_offset);
+ armature_vert_task_with_dvert(data, BM_elem_index_get(v), dvert);
+}
+
+static void armature_vert_task_editmesh_no_dvert(void *__restrict userdata, MempoolIterData *iter)
+{
+ const ArmatureUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ armature_vert_task_with_dvert(data, BM_elem_index_get(v), NULL);
+}
+
+static void armature_deform_coords_impl(const Object *ob_arm,
+ const 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,
+ BMEditMesh *em_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;
+ int cd_dvert_offset = -1;
+
+ /* 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) {
+ if (em_target == NULL) {
+ 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 (em_target) {
+ cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
+ use_dverts = (cd_dvert_offset != -1);
+ }
+ else 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,
+ .bmesh =
+ {
+ .cd_dvert_offset = cd_dvert_offset,
+ },
+ };
+
+ 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);
+
+ if (em_target != NULL) {
+ /* While this could cause an extra loop over mesh data, in most cases this will
+ * have already been properly set. */
+ BM_mesh_elem_index_ensure(em_target->bm, BM_VERT);
+
+ if (use_dverts) {
+ BLI_task_parallel_mempool(em_target->bm->vpool, &data, armature_vert_task_editmesh, true);
+ }
+ else {
+ BLI_task_parallel_mempool(
+ em_target->bm->vpool, &data, armature_vert_task_editmesh_no_dvert, true);
+ }
+ }
+ else {
+ 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(const Object *ob_arm,
+ const 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,
+ NULL,
+ gps_target);
+}
+
+void BKE_armature_deform_coords_with_mesh(const Object *ob_arm,
+ const 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,
+ NULL);
+}
+
+void BKE_armature_deform_coords_with_editmesh(const Object *ob_arm,
+ const 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,
+ BMEditMesh *em_target)
+{
+ armature_deform_coords_impl(ob_arm,
+ ob_target,
+ vert_coords,
+ vert_deform_mats,
+ vert_coords_len,
+ deformflag,
+ vert_coords_prev,
+ defgrp_name,
+ NULL,
+ em_target,
+ NULL);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 0b9780ac81c..ce6143116a1 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -146,6 +146,7 @@ void cloth_init(ClothModifierData *clmd)
clmd->sim_parms->uniform_pressure_force = 0.0f;
clmd->sim_parms->target_volume = 0.0f;
clmd->sim_parms->pressure_factor = 1.0f;
+ clmd->sim_parms->fluid_density = 0.0f;
clmd->sim_parms->vgroup_pressure = 0;
// also from softbodies
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 290b181f172..a9d3c7c1b65 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -716,6 +716,31 @@ static void collection_tag_update_parent_recursive(Main *bmain,
}
}
+static Collection *collection_parent_editable_find_recursive(Collection *collection)
+{
+ if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) {
+ return collection;
+ }
+
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return NULL;
+ }
+
+ LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->parents) {
+ if (!ID_IS_LINKED(collection_parent->collection) &&
+ !ID_IS_OVERRIDE_LIBRARY(collection_parent->collection)) {
+ return collection_parent->collection;
+ }
+ Collection *editable_collection = collection_parent_editable_find_recursive(
+ collection_parent->collection);
+ if (editable_collection != NULL) {
+ return editable_collection;
+ }
+ }
+
+ return NULL;
+}
+
static bool collection_object_add(
Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us)
{
@@ -786,6 +811,15 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
return false;
}
+ collection = collection_parent_editable_find_recursive(collection);
+
+ /* Only case where this pointer can be NULL is when scene itself is linked, this case should
+ * never be reached. */
+ BLI_assert(collection != NULL);
+ if (collection == NULL) {
+ return false;
+ }
+
if (!collection_object_add(bmain, collection, ob, 0, true)) {
return false;
}
@@ -808,7 +842,8 @@ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, O
bool is_instantiated = false;
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
- if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) {
+ if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection) &&
+ BKE_collection_has_object(collection, ob_src)) {
collection_object_add(bmain, collection, ob_dst, 0, true);
is_instantiated = true;
}
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..d4f197521a1
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -0,0 +1,504 @@
+/*
+ * 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_editmesh.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 matrices to transform points to/from local-space.
+ */
+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(const Object *ob_curve, const Object *ob_target, CurveDeform *cd)
+{
+ float imat[4][4];
+ invert_m4_m4(imat, ob_target->obmat);
+ mul_m4_m4m4(cd->objectspace, imat, ob_curve->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.
+ *
+ * \return Success.
+ */
+static bool where_on_path_deform(const Object *ob_curve,
+ float ctime,
+ float r_vec[4],
+ float r_dir[3],
+ float r_quat[4],
+ float *r_radius)
+{
+ BevList *bl;
+ float ctime1;
+ int cycl = 0;
+
+ /* test for cyclic */
+ bl = ob_curve->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_curve, ctime1, r_vec, r_dir, r_quat, r_radius, NULL)) {
+
+ if (cycl == 0) {
+ Path *path = ob_curve->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(r_vec, dvec);
+ if (r_quat) {
+ copy_qt_qt(r_quat, path->data[0].quat);
+ }
+ if (r_radius) {
+ *r_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(r_vec, dvec);
+ if (r_quat) {
+ copy_qt_qt(r_quat, path->data[path->len - 1].quat);
+ }
+ if (r_radius) {
+ *r_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.
+ *
+ * \param co: local coord, result local too.
+ * \param r_quat: returns quaternion for rotation,
+ * using #CurveDeform.no_rot_axis axis is using another define.
+ */
+static bool calc_curve_deform(
+ const Object *ob_curve, float co[3], const short axis, const CurveDeform *cd, float r_quat[4])
+{
+ Curve *cu = ob_curve->data;
+ float fac, loc[4], dir[3], new_quat[4], radius;
+ short index;
+ const bool is_neg_axis = (axis > 2);
+
+ if (ob_curve->runtime.curve_cache == NULL) {
+ /* Happens with a cyclic dependencies. */
+ return false;
+ }
+
+ if (ob_curve->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]) / (ob_curve->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(ob_curve->runtime.curve_cache->path->totdist > FLT_EPSILON)) {
+ fac = +(co[index] - cd->dmin[index]) / (ob_curve->runtime.curve_cache->path->totdist);
+ }
+ else {
+ fac = 0.0f;
+ }
+ }
+ }
+
+ if (where_on_path_deform(ob_curve, 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.
+ * \{ */
+
+static void curve_deform_coords_impl(const Object *ob_curve,
+ const 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,
+ BMEditMesh *em_target)
+{
+ Curve *cu;
+ int a;
+ CurveDeform cd;
+ const bool is_neg_axis = (defaxis > 2);
+ const bool invert_vgroup = (flag & MOD_CURVE_INVERT_VGROUP) != 0;
+ bool use_dverts = false;
+ int cd_dvert_offset;
+
+ if (ob_curve->type != OB_CURVE) {
+ return;
+ }
+
+ cu = ob_curve->data;
+
+ init_curve_deform(ob_curve, ob_target, &cd);
+
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ /* Dummy bounds. */
+ 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;
+ }
+ }
+ else {
+ /* Set mesh min/max bounds. */
+ INIT_MINMAX(cd.dmin, cd.dmax);
+ }
+
+ if (em_target != NULL) {
+ cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
+ if (cd_dvert_offset != -1) {
+ use_dverts = true;
+ }
+ }
+ else {
+ if (dvert != NULL) {
+ use_dverts = true;
+ }
+ }
+
+ if (use_dverts) {
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+
+#define DEFORM_OP(dvert) \
+ { \
+ const float weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dvert, defgrp_index) : \
+ BKE_defvert_find_weight(dvert, defgrp_index); \
+ if (weight > 0.0f) { \
+ float vec[3]; \
+ 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]); \
+ } \
+ } \
+ ((void)0)
+
+ if (em_target != NULL) {
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_MESH_INDEX (v, &iter, em_target->bm, BM_VERTS_OF_MESH, a) {
+ dvert = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
+ DEFORM_OP(dvert);
+ }
+ }
+ else {
+ for (a = 0; a < vert_coords_len; a++) {
+ DEFORM_OP(&dvert[a]);
+ }
+ }
+
+#undef DEFORM_OP
+ }
+ else {
+
+#define DEFORM_OP_MINMAX(dvert) \
+ { \
+ const float weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dvert, defgrp_index) : \
+ BKE_defvert_find_weight(dvert, defgrp_index); \
+ if (weight > 0.0f) { \
+ mul_m4_v3(cd.curvespace, vert_coords[a]); \
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]); \
+ } \
+ } \
+ ((void)0)
+
+ /* already in 'cd.curvespace', prev for loop */
+#define DEFORM_OP_CLAMPED(dvert) \
+ { \
+ const float weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dvert, defgrp_index) : \
+ BKE_defvert_find_weight(dvert, defgrp_index); \
+ if (weight > 0.0f) { \
+ float vec[3]; \
+ 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]); \
+ } \
+ } \
+ ((void)0)
+
+ if (em_target != NULL) {
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_MESH_INDEX (v, &iter, em_target->bm, BM_VERTS_OF_MESH, a) {
+ dvert = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
+ DEFORM_OP_MINMAX(dvert);
+ }
+
+ BM_ITER_MESH_INDEX (v, &iter, em_target->bm, BM_VERTS_OF_MESH, a) {
+ dvert = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
+ DEFORM_OP_CLAMPED(dvert);
+ }
+ }
+ else {
+
+ for (a = 0; a < vert_coords_len; a++) {
+ DEFORM_OP_MINMAX(&dvert[a]);
+ }
+
+ for (a = 0; a < vert_coords_len; a++) {
+ DEFORM_OP_CLAMPED(&dvert[a]);
+ }
+ }
+ }
+
+#undef DEFORM_OP_MINMAX
+#undef DEFORM_OP_CLAMPED
+ }
+ 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 {
+ 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]);
+ }
+ }
+ }
+}
+
+void BKE_curve_deform_coords(const Object *ob_curve,
+ const 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_deform_coords_impl(
+ ob_curve, ob_target, vert_coords, vert_coords_len, dvert, defgrp_index, flag, defaxis, NULL);
+}
+
+void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis,
+ BMEditMesh *em_target)
+{
+ curve_deform_coords_impl(ob_curve,
+ ob_target,
+ vert_coords,
+ vert_coords_len,
+ NULL,
+ defgrp_index,
+ flag,
+ defaxis,
+ em_target);
+}
+
+/**
+ * \param orco: Input vec and orco = local coord in curve space
+ * orco is original not-animated or deformed reference point.
+ *
+ * The result written in vec and r_mat.
+ */
+void BKE_curve_deform_co(const Object *ob_curve,
+ const Object *ob_target,
+ const float orco[3],
+ float vec[3],
+ const int no_rot_axis,
+ float r_mat[3][3])
+{
+ CurveDeform cd;
+ float quat[4];
+
+ if (ob_curve->type != OB_CURVE) {
+ unit_m3(r_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(r_mat, qmat, cd.objectspace3);
+ }
+ else {
+ unit_m3(r_mat);
+ }
+
+ mul_m4_v3(cd.objectspace, vec);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 9a3965a86f6..b97935d57f2 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -486,14 +486,14 @@ void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int
}
}
-bDeformGroup *BKE_object_defgroup_find_name(Object *ob, const char *name)
+bDeformGroup *BKE_object_defgroup_find_name(const Object *ob, const char *name)
{
return (name && name[0] != '\0') ?
BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name)) :
NULL;
}
-int BKE_object_defgroup_name_index(Object *ob, const char *name)
+int BKE_object_defgroup_name_index(const Object *ob, const char *name)
{
return (name && name[0] != '\0') ?
BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) :
@@ -503,7 +503,7 @@ int BKE_object_defgroup_name_index(Object *ob, const char *name)
/**
* \note caller must free.
*/
-int *BKE_object_defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default)
+int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default)
{
int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase);
@@ -545,7 +545,7 @@ int *BKE_object_defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_
/**
* \note caller must free.
*/
-int *BKE_object_defgroup_flip_map_single(Object *ob,
+int *BKE_object_defgroup_flip_map_single(const Object *ob,
int *flip_map_len,
const bool use_default,
int defgroup)
@@ -580,7 +580,7 @@ int *BKE_object_defgroup_flip_map_single(Object *ob,
}
}
-int BKE_object_defgroup_flip_index(Object *ob, int index, const bool use_default)
+int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_default)
{
bDeformGroup *dg = BLI_findlink(&ob->defbase, index);
int flip_index = -1;
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index b889b91e366..2f8500bd1df 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -286,11 +286,11 @@ void BKE_gpencil_lattice_init(Object *ob)
return;
}
if (mmd->cache_data) {
- end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
}
/* init deform data */
- mmd->cache_data = (struct LatticeDeformData *)init_latt_deform(latob, ob);
+ mmd->cache_data = BKE_lattice_deform_data_create(latob, ob);
}
}
}
@@ -303,7 +303,7 @@ void BKE_gpencil_lattice_clear(Object *ob)
if (md->type == eGpencilModifierType_Lattice) {
LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
if ((mmd) && (mmd->cache_data)) {
- end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
mmd->cache_data = NULL;
}
}
@@ -859,7 +859,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
}
ob->runtime.gpd_eval = gpencil_copy_for_eval(ob->runtime.gpd_orig);
gpencil_assign_object_eval(ob);
- BKE_gpencil_update_orig_pointers(ob_orig, (Object *)ob);
+ BKE_gpencil_update_orig_pointers(ob_orig, ob);
}
/* Calculate gpencil modifiers */
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index e7a2421a625..8820434cbcf 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"
@@ -299,7 +295,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
copy_m4_m4(mat, ltOb->obmat);
unit_m4(ltOb->obmat);
- lattice_deform_verts(ltOb, NULL, NULL, vert_coords, uNew * vNew * wNew, 0, NULL, 1.0f);
+ BKE_lattice_deform_coords(ltOb, NULL, vert_coords, uNew * vNew * wNew, 0, NULL, 1.0f);
copy_m4_m4(ltOb->obmat, mat);
lt->typeu = typeu;
@@ -349,651 +345,13 @@ 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);
-}
-
-/* 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;
-}
-
-void curve_deform_verts(Object *cuOb,
- Object *target,
- float (*vert_coords)[3],
- int numVerts,
- MDeformVert *dvert,
- const int defgrp_index,
- short flag,
- 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 (cuOb->type != OB_CURVE) {
- return;
- }
-
- cu = cuOb->data;
-
- init_curve_deform(cuOb, 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) {
- MDeformVert *dvert_iter;
- float vec[3];
-
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- for (a = 0, dvert_iter = dvert; a < numVerts; 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(cuOb, 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 < numVerts; 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 < numVerts; 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(cuOb, 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 < numVerts; a++) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- calc_curve_deform(cuOb, 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 < numVerts; a++) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
- }
-
- for (a = 0; a < numVerts; a++) {
- /* already in 'cd.curvespace', prev for loop */
- calc_curve_deform(cuOb, 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 curve_deform_vector(
- Object *cuOb, Object *target, float orco[3], float vec[3], float mat[3][3], int no_rot_axis)
-{
- CurveDeform cd;
- float quat[4];
-
- if (cuOb->type != OB_CURVE) {
- unit_m3(mat);
- return;
- }
-
- init_curve_deform(cuOb, 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(cuOb, vec, 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);
-}
-
-typedef struct LatticeDeformUserdata {
- LatticeDeformData *lattice_deform_data;
- float (*vert_coords)[3];
- 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);
- }
-}
-
-void lattice_deform_verts(Object *laOb,
- Object *target,
- Mesh *mesh,
- float (*vert_coords)[3],
- int numVerts,
- short flag,
- const char *vgroup,
- float fac)
-{
- LatticeDeformData *lattice_deform_data;
- MDeformVert *dvert = NULL;
- int defgrp_index = -1;
-
- if (laOb->type != OB_LATTICE) {
- return;
- }
-
- lattice_deform_data = init_latt_deform(laOb, target);
-
- /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice).
- * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
- */
- if (vgroup && vgroup[0] && target && ELEM(target->type, OB_MESH, OB_LATTICE)) {
- defgrp_index = BKE_object_defgroup_name_index(target, vgroup);
-
- if (defgrp_index != -1) {
- /* if there's derived data without deformverts, don't use vgroups */
- if (mesh) {
- dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
- }
- else if (target->type == OB_LATTICE) {
- dvert = ((Lattice *)target->data)->dvert;
- }
- else {
- dvert = ((Mesh *)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, numVerts, &data, lattice_deform_vert_task, &settings);
-
- end_latt_deform(lattice_deform_data);
-}
-
bool object_deform_mball(Object *ob, ListBase *dispbase)
{
if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
DispList *dl;
for (dl = dispbase->first; dl; dl = dl->next) {
- lattice_deform_verts(ob->parent, ob, NULL, (float(*)[3])dl->verts, dl->nr, 0, NULL, 1.0f);
+ BKE_lattice_deform_coords(ob->parent, ob, (float(*)[3])dl->verts, dl->nr, 0, NULL, 1.0f);
}
return true;
@@ -1194,7 +552,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
}
}
-struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *oblatt)
+struct MDeformVert *BKE_lattice_deform_verts_get(const struct Object *oblatt)
{
Lattice *lt = (Lattice *)oblatt->data;
BLI_assert(oblatt->type == OB_LATTICE);
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
new file mode 100644
index 00000000000..2b3349d4d9a
--- /dev/null
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -0,0 +1,470 @@
+/*
+ * 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_editmesh.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_modifier.h"
+
+#include "BKE_deform.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Lattice Deform API
+ * \{ */
+
+typedef struct LatticeDeformData {
+ const Object *object;
+ float *latticedata;
+ float latmat[4][4];
+} LatticeDeformData;
+
+LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const 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 BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data,
+ float co[3],
+ float weight)
+{
+ const 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;
+ const 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 BKE_lattice_deform_data_destroy(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;
+
+ /** Specific data types. */
+ struct {
+ int cd_dvert_offset;
+ } bmesh;
+} LatticeDeformUserdata;
+
+static void lattice_deform_vert_with_dvert(const LatticeDeformUserdata *data,
+ const int index,
+ const MDeformVert *dvert)
+{
+ if (dvert != NULL) {
+ const float weight = data->invert_vgroup ?
+ 1.0f - BKE_defvert_find_weight(dvert, data->defgrp_index) :
+ BKE_defvert_find_weight(dvert, data->defgrp_index);
+ if (weight > 0.0f) {
+ BKE_lattice_deform_data_eval_co(
+ data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
+ }
+ }
+ else {
+ BKE_lattice_deform_data_eval_co(
+ data->lattice_deform_data, data->vert_coords[index], data->fac);
+ }
+}
+
+static void lattice_deform_vert_task(void *__restrict userdata,
+ const int index,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ const LatticeDeformUserdata *data = userdata;
+ lattice_deform_vert_with_dvert(data, index, data->dvert ? &data->dvert[index] : NULL);
+}
+
+static void lattice_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter)
+{
+ const LatticeDeformUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v, data->bmesh.cd_dvert_offset);
+ lattice_deform_vert_with_dvert(data, BM_elem_index_get(v), dvert);
+}
+
+static void lattice_vert_task_editmesh_no_dvert(void *__restrict userdata, MempoolIterData *iter)
+{
+ const LatticeDeformUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ lattice_deform_vert_with_dvert(data, BM_elem_index_get(v), NULL);
+}
+
+static void lattice_deform_coords_impl(const Object *ob_lattice,
+ const 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,
+ BMEditMesh *em_target)
+{
+ LatticeDeformData *lattice_deform_data;
+ const MDeformVert *dvert = NULL;
+ int defgrp_index = -1;
+ int cd_dvert_offset = -1;
+
+ if (ob_lattice->type != OB_LATTICE) {
+ return;
+ }
+
+ lattice_deform_data = BKE_lattice_deform_data_create(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 (em_target) {
+ cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
+ }
+ else 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,
+ .bmesh =
+ {
+ .cd_dvert_offset = cd_dvert_offset,
+ },
+ };
+
+ if (em_target != NULL) {
+ /* While this could cause an extra loop over mesh data, in most cases this will
+ * have already been properly set. */
+ BM_mesh_elem_index_ensure(em_target->bm, BM_VERT);
+
+ if (cd_dvert_offset != -1) {
+ BLI_task_parallel_mempool(em_target->bm->vpool, &data, lattice_vert_task_editmesh, true);
+ }
+ else {
+ BLI_task_parallel_mempool(
+ em_target->bm->vpool, &data, lattice_vert_task_editmesh_no_dvert, true);
+ }
+ }
+ else {
+ 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);
+ }
+
+ BKE_lattice_deform_data_destroy(lattice_deform_data);
+}
+
+void BKE_lattice_deform_coords(const Object *ob_lattice,
+ const 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, NULL);
+}
+
+void BKE_lattice_deform_coords_with_mesh(const Object *ob_lattice,
+ const 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,
+ NULL);
+}
+
+void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float influence,
+ struct BMEditMesh *em_target)
+{
+ lattice_deform_coords_impl(ob_lattice,
+ ob_target,
+ vert_coords,
+ vert_coords_len,
+ flag,
+ defgrp_name,
+ influence,
+ NULL,
+ em_target);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 3ad429c5f5a..ca23ec90c97 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1694,7 +1694,7 @@ static void library_make_local_copying_check(ID *id,
continue;
}
- /* Shapekeys are considered 'private' to their owner ID here, and never tagged
+ /* Shape-keys are considered 'private' to their owner ID here, and never tagged
* (since they cannot be linked), so we have to switch effective parent to their owner.
*/
if (GS(par_id->name) == ID_KE) {
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index d16428ccd60..d6f037f64a4 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -197,7 +197,6 @@ static ID *lib_override_library_create_from(Main *bmain, ID *reference_id)
id_us_min(local_id);
BKE_lib_override_library_init(local_id, reference_id);
- local_id->override_library->flag |= OVERRIDE_LIBRARY_AUTO;
return local_id;
}
@@ -736,13 +735,15 @@ bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
* Generating diff values and applying overrides are much cheaper.
*
* \return true if new overriding op was created, or some local data was reset. */
-bool BKE_lib_override_library_operations_create(Main *bmain, ID *local, const bool force_auto)
+bool BKE_lib_override_library_operations_create(Main *bmain,
+ ID *local,
+ const bool UNUSED(force_auto))
{
BLI_assert(local->override_library != NULL);
const bool is_template = (local->override_library->reference == NULL);
bool ret = false;
- if (!is_template && (force_auto || local->override_library->flag & OVERRIDE_LIBRARY_AUTO)) {
+ if (!is_template) {
/* Do not attempt to generate overriding rules from an empty place-holder generated by link
* code when it cannot find to actual library/ID. Much better to keep the local datablock as
* is in the file in that case, until broken lib is fixed. */
@@ -804,7 +805,7 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if ((ID_IS_OVERRIDE_LIBRARY(id) && force_auto) ||
- (ID_IS_OVERRIDE_LIBRARY_AUTO(id) && (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) {
+ (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH)) {
BKE_lib_override_library_operations_create(bmain, id, force_auto);
id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
}
diff --git a/source/blender/blenkernel/intern/mesh_wrapper.c b/source/blender/blenkernel/intern/mesh_wrapper.c
index 98b77256ad7..6a8bc698b11 100644
--- a/source/blender/blenkernel/intern/mesh_wrapper.c
+++ b/source/blender/blenkernel/intern/mesh_wrapper.c
@@ -53,7 +53,7 @@
Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
const CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
+ const float (*vert_coords)[3],
const Mesh *me_settings)
{
Mesh *me = BKE_id_new_nomain(ID_ME, NULL);
@@ -83,7 +83,7 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
#endif
EditMeshData *edit_data = me->runtime.edit_data;
- edit_data->vertexCos = vertexCos;
+ edit_data->vertexCos = vert_coords;
return me;
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index d4b7d05c228..7c77746ea1c 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -878,10 +878,7 @@ void BKE_modifier_free_temporary_data(ModifierData *md)
if (md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->prevCos) {
- MEM_freeN(amd->prevCos);
- amd->prevCos = NULL;
- }
+ MEM_SAFE_FREE(amd->vert_coords_prev);
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 474142e8555..4c6354f12a1 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -1053,7 +1053,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index eb485e1522f..c201cb83c44 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -410,7 +410,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
}
}
if (lattice) {
- lattice_deform_data = init_latt_deform(lattice, NULL);
+ lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL);
}
}
@@ -3150,7 +3150,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
/* lattices have to be calculated separately to avoid mixups between effector calculations */
if (psys->lattice_deform_data) {
for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
- calc_latt_deform(psys->lattice_deform_data, ca->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, ca->co, psys->lattice_strength);
}
}
}
@@ -3185,7 +3186,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
psys->totcached = totpart;
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
@@ -4413,7 +4414,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
}
if (psys->lattice_deform_data && edit == 0) {
- calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
}
@@ -4696,7 +4698,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
do_child_modifiers(&modifier_ctx, mat, state, t);
if (psys->lattice_deform_data) {
- calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
else {
@@ -4760,7 +4763,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
if (sim->psys->lattice_deform_data) {
- calc_latt_deform(sim->psys->lattice_deform_data, state->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ sim->psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
@@ -4970,12 +4974,13 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par
hkey = pa->hair;
for (h = 0; h < pa->totkey; h++, hkey++) {
mul_m4_v3(hairmat, hkey->co);
- calc_latt_deform(psys->lattice_deform_data, hkey->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, hkey->co, psys->lattice_strength);
mul_m4_v3(imat, hkey->co);
}
}
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
/* protect the applied shape */
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 31d51a74e7f..606291a9ae0 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -536,7 +536,7 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
}
if (ctx->sim.psys->lattice_deform_data) {
- end_latt_deform(ctx->sim.psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(ctx->sim.psys->lattice_deform_data);
ctx->sim.psys->lattice_deform_data = NULL;
}
@@ -4126,7 +4126,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_
}
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
@@ -4616,7 +4616,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
/* cleanup */
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 9cd17310f07..836fe59d7bd 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -138,6 +138,7 @@ static int ptcache_data_size[] = {
static int ptcache_extra_datasize[] = {
0,
sizeof(ParticleSpring),
+ sizeof(float) * 3,
};
/* forward declarations */
@@ -176,6 +177,23 @@ static int ptcache_basic_header_write(PTCacheFile *pf)
return 1;
}
+static void ptcache_add_extra_data(PTCacheMem *pm,
+ unsigned int type,
+ unsigned int count,
+ void *data)
+{
+ PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: extra data descriptor");
+
+ extra->type = type;
+ extra->totdata = count;
+
+ size_t size = extra->totdata * ptcache_extra_datasize[extra->type];
+
+ extra->data = MEM_mallocN(size, "Point cache: extra data");
+ memcpy(extra->data, data, size);
+
+ BLI_addtail(&pm->extradata, extra);
+}
/* Softbody functions */
static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
{
@@ -467,21 +485,12 @@ static int ptcache_particle_totwrite(void *psys_v, int cfra)
static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
{
ParticleSystem *psys = psys_v;
- PTCacheExtra *extra = NULL;
if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid &&
psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS && psys->tot_fluidsprings &&
psys->fluid_springs) {
- extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
-
- extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
- extra->totdata = psys->tot_fluidsprings;
-
- extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type],
- "Point cache: extra data");
- memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
-
- BLI_addtail(&pm->extradata, extra);
+ ptcache_add_extra_data(
+ pm, BPHYS_EXTRA_FLUID_SPRINGS, psys->tot_fluidsprings, psys->fluid_springs);
}
}
@@ -575,6 +584,33 @@ static void ptcache_cloth_interpolate(
/* should vert->xconst be interpolated somehow too? - jahka */
}
+static void ptcache_cloth_extra_write(void *cloth_v, PTCacheMem *pm, int UNUSED(cfra))
+{
+ ClothModifierData *clmd = cloth_v;
+ Cloth *cloth = clmd->clothObject;
+
+ if (!is_zero_v3(cloth->average_acceleration)) {
+ ptcache_add_extra_data(pm, BPHYS_EXTRA_CLOTH_ACCELERATION, 1, cloth->average_acceleration);
+ }
+}
+static void ptcache_cloth_extra_read(void *cloth_v, PTCacheMem *pm, float UNUSED(cfra))
+{
+ ClothModifierData *clmd = cloth_v;
+ Cloth *cloth = clmd->clothObject;
+ PTCacheExtra *extra = pm->extradata.first;
+
+ zero_v3(cloth->average_acceleration);
+
+ for (; extra; extra = extra->next) {
+ switch (extra->type) {
+ case BPHYS_EXTRA_CLOTH_ACCELERATION: {
+ copy_v3_v3(cloth->average_acceleration, extra->data);
+ break;
+ }
+ }
+ }
+}
+
static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
{
ClothModifierData *clmd = cloth_v;
@@ -1681,8 +1717,8 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->write_stream = NULL;
pid->read_stream = NULL;
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
+ pid->write_extra_data = ptcache_cloth_extra_write;
+ pid->read_extra_data = ptcache_cloth_extra_read;
pid->interpolate_extra_data = NULL;
pid->write_header = ptcache_basic_header_write;