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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-06-29 09:18:26 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-06-30 09:53:55 +0300
commit2d4ec90497443dc28e342c539e65010c7f4a04bb (patch)
tree62d29a8c932d8b94f43fddf818c581432fb287a2 /source
parent501d2443d03cce18985fab3ffad5d23238748f3e (diff)
Transform: support multi-threading for most modes
Multi-threading support for transform modes: bevel-weight, crease, push-pull, rotate, shear, shrink-fatten, skin-resize, to-sphere, trackball & translate. This is done using a parallel loop over transform data. From testing a 1.5million polygon mesh on a 32 core system the overall performance gains were between ~20-28% To ensure the code is thread-safe arguments to shared data are const. Reviewed By: mano-wii
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/transform/transform_data.h2
-rw-r--r--source/blender/editors/transform/transform_mode_edge_bevelweight.c70
-rw-r--r--source/blender/editors/transform/transform_mode_edge_crease.c76
-rw-r--r--source/blender/editors/transform/transform_mode_push_pull.c110
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c51
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c217
-rw-r--r--source/blender/editors/transform/transform_mode_shear.c134
-rw-r--r--source/blender/editors/transform/transform_mode_shrink_fatten.c72
-rw-r--r--source/blender/editors/transform/transform_mode_skin_resize.c92
-rw-r--r--source/blender/editors/transform/transform_mode_tosphere.c123
-rw-r--r--source/blender/editors/transform/transform_mode_trackball.c76
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c210
12 files changed, 934 insertions, 299 deletions
diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h
index 59b76c2eec5..606453e356b 100644
--- a/source/blender/editors/transform/transform_data.h
+++ b/source/blender/editors/transform/transform_data.h
@@ -149,6 +149,8 @@ typedef struct TransData {
short protectflag;
} TransData;
+#define TRANSDATA_THREAD_LIMIT 1024
+
/** #TransData.flag */
enum {
TD_SELECTED = 1 << 0,
diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
index 3ce52ed3296..425bfec241e 100644
--- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c
+++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
@@ -25,6 +25,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -40,6 +41,50 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Bevel Weight) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_BevelWeight {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float weight;
+};
+
+static void transdata_elem_bevel_weight(const TransInfo *UNUSED(t),
+ const TransDataContainer *UNUSED(tc),
+ TransData *td,
+ const float weight)
+{
+ if (td->val == NULL) {
+ return;
+ }
+ *td->val = td->ival + weight * td->factor;
+ if (*td->val < 0.0f) {
+ *td->val = 0.0f;
+ }
+ if (*td->val > 1.0f) {
+ *td->val = 1.0f;
+ }
+}
+
+static void transdata_elem_bevel_weight_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_BevelWeight *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_bevel_weight(data->t, data->tc, td, data->weight);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Bevel Weight)
* \{ */
@@ -83,18 +128,25 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->val) {
- *td->val = td->ival + weight * td->factor;
- if (*td->val < 0.0f) {
- *td->val = 0.0f;
- }
- if (*td->val > 1.0f) {
- *td->val = 1.0f;
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
}
+ transdata_elem_bevel_weight(t, tc, td, weight);
}
}
+ else {
+ struct TransDataArgs_BevelWeight data = {
+ .t = t,
+ .tc = tc,
+ .weight = weight,
+ };
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_bevel_weight_fn, &settings);
+ }
}
recalcData(t);
diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c
index 23fa20b68ff..91e2507e544 100644
--- a/source/blender/editors/transform/transform_mode_edge_crease.c
+++ b/source/blender/editors/transform/transform_mode_edge_crease.c
@@ -25,6 +25,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -40,6 +41,51 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Crease) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_Crease {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float crease;
+};
+
+static void transdata_elem_crease(const TransInfo *UNUSED(t),
+ const TransDataContainer *UNUSED(tc),
+ TransData *td,
+ const float crease)
+{
+ if (td->val == NULL) {
+ return;
+ }
+
+ *td->val = td->ival + crease * td->factor;
+ if (*td->val < 0.0f) {
+ *td->val = 0.0f;
+ }
+ if (*td->val > 1.0f) {
+ *td->val = 1.0f;
+ }
+}
+
+static void transdata_elem_crease_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_Crease *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_crease(data->t, data->tc, td, data->crease);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Crease)
* \{ */
@@ -83,22 +129,25 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (td->val) {
- *td->val = td->ival + crease * td->factor;
- if (*td->val < 0.0f) {
- *td->val = 0.0f;
- }
- if (*td->val > 1.0f) {
- *td->val = 1.0f;
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
}
+ transdata_elem_crease(t, tc, td, crease);
}
}
+ else {
+ struct TransDataArgs_Crease data = {
+ .t = t,
+ .tc = tc,
+ .crease = crease,
+ };
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_crease_fn, &settings);
+ }
}
recalcData(t);
@@ -124,4 +173,5 @@ void initCrease(TransInfo *t)
t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
+
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c
index b08e479a3d0..098698b0e79 100644
--- a/source/blender/editors/transform/transform_mode_push_pull.c
+++ b/source/blender/editors/transform/transform_mode_push_pull.c
@@ -25,6 +25,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -41,12 +42,75 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Push/Pull) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_PushPull {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+
+ float distance;
+ const float axis_global[3];
+ bool is_data_space;
+};
+
+static void transdata_elem_push_pull(const TransInfo *t,
+ const TransDataContainer *tc,
+ TransData *td,
+ const float distance,
+ const float axis_global[3],
+ const bool is_data_space)
+{
+ float vec[3];
+ sub_v3_v3v3(vec, tc->center_local, td->center);
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ float axis[3];
+ copy_v3_v3(axis, axis_global);
+ t->con.applyRot(t, tc, td, axis, NULL);
+
+ mul_m3_v3(td->smtx, axis);
+ if (isLockConstraint(t)) {
+ float dvec[3];
+ project_v3_v3v3(dvec, vec, axis);
+ sub_v3_v3(vec, dvec);
+ }
+ else {
+ project_v3_v3v3(vec, vec, axis);
+ }
+ }
+ normalize_v3_length(vec, distance * td->factor);
+ if (is_data_space) {
+ mul_m3_v3(td->smtx, vec);
+ }
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+}
+
+static void transdata_elem_push_pull_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_PushPull *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_push_pull(
+ data->t, data->tc, td, data->distance, data->axis_global, data->is_data_space);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Push/Pull)
* \{ */
static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3], axis_global[3];
+ float axis_global[3];
float distance;
int i;
char str[UI_MAX_DRAW_STR];
@@ -80,34 +144,26 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
const bool is_data_space = (t->options & CTX_POSE_BONE) != 0;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- sub_v3_v3v3(vec, tc->center_local, td->center);
- if (t->con.applyRot && t->con.mode & CON_APPLY) {
- float axis[3];
- copy_v3_v3(axis, axis_global);
- t->con.applyRot(t, tc, td, axis, NULL);
-
- mul_m3_v3(td->smtx, axis);
- if (isLockConstraint(t)) {
- float dvec[3];
- project_v3_v3v3(dvec, vec, axis);
- sub_v3_v3(vec, dvec);
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
}
- else {
- project_v3_v3v3(vec, vec, axis);
- }
- }
- normalize_v3_length(vec, distance * td->factor);
- if (is_data_space) {
- mul_m3_v3(td->smtx, vec);
- }
- add_v3_v3v3(td->loc, td->iloc, vec);
+ transdata_elem_push_pull(t, tc, td, distance, axis_global, is_data_space);
+ }
+ }
+ else {
+ struct TransDataArgs_PushPull data = {
+ .t = t,
+ .tc = tc,
+ .axis_global = {UNPACK3(axis_global)},
+ .is_data_space = is_data_space,
+ };
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_push_pull_fn, &settings);
}
}
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index 6af16dee9b7..65f4623b3be 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -39,6 +40,30 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Resize) Element
+ * \{ */
+
+struct ElemResizeData {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float mat[3][3];
+};
+
+static void element_resize_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct ElemResizeData *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ ElementResize(data->t, data->tc, td, data->mat);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Resize)
* \{ */
@@ -123,13 +148,27 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
copy_m3_m3(t->mat, mat); /* used in gizmo */
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SKIP) {
- continue;
- }
- ElementResize(t, tc, td, mat);
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ ElementResize(t, tc, td, mat);
+ }
+ }
+ else {
+ struct ElemResizeData data = {
+ .t = t,
+ .tc = tc,
+ };
+ copy_m3_m3(data.mat, mat);
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, element_resize_fn, &settings);
}
}
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index 066cdf20e93..44a29cfac45 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -37,6 +38,140 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Rotation) Matrix Cache
+ * \{ */
+
+struct RotateMatrixCache {
+ /**
+ * Counter for needed updates (when we need to update to non-default matrix,
+ * we also need another update on next iteration to go back to default matrix,
+ * hence the '2' value used here, instead of a mere boolean).
+ */
+ short do_update_matrix;
+ float mat[3][3];
+};
+
+static void rmat_cache_init(struct RotateMatrixCache *rmc, const float angle, const float axis[3])
+{
+ axis_angle_normalized_to_mat3(rmc->mat, axis, angle);
+ rmc->do_update_matrix = 0;
+}
+
+static void rmat_cache_reset(struct RotateMatrixCache *rmc)
+{
+ rmc->do_update_matrix = 2;
+}
+
+static void rmat_cache_update(struct RotateMatrixCache *rmc,
+ const float axis[3],
+ const float angle)
+{
+ if (rmc->do_update_matrix > 0) {
+ axis_angle_normalized_to_mat3(rmc->mat, axis, angle);
+ rmc->do_update_matrix--;
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (Rotation) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_Rotate {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ const float axis[3];
+ float angle;
+ float angle_step;
+ bool is_large_rotation;
+};
+
+struct TransDataArgs_RotateTLS {
+ struct RotateMatrixCache rmc;
+};
+
+static void transdata_elem_rotate(const TransInfo *t,
+ const TransDataContainer *tc,
+ TransData *td,
+ const float axis[3],
+ const float angle,
+ const float angle_step,
+ const bool is_large_rotation,
+ struct RotateMatrixCache *rmc)
+{
+ float axis_buffer[3];
+ const float *axis_final = axis;
+
+ float angle_final = angle;
+ if (t->con.applyRot) {
+ copy_v3_v3(axis_buffer, axis);
+ axis_final = axis_buffer;
+ t->con.applyRot(t, tc, td, axis_buffer, NULL);
+ angle_final = angle * td->factor;
+ /* Even though final angle might be identical to orig value,
+ * we have to update the rotation matrix in that case... */
+ rmat_cache_reset(rmc);
+ }
+ else if (t->flag & T_PROP_EDIT) {
+ angle_final = angle * td->factor;
+ }
+
+ /* Rotation is very likely to be above 180°, we need to do rotation by steps.
+ * Note that this is only needed when doing 'absolute' rotation
+ * (i.e. from initial rotation again, typically when using numinput).
+ * regular incremental rotation (from mouse/widget/...) will be called often enough,
+ * hence steps are small enough to be properly handled without that complicated trick.
+ * Note that we can only do that kind of stepped rotation if we have initial rotation values
+ * (and access to some actual rotation value storage).
+ * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing).
+ * Also need to be in Euler rotation mode, the others never allow more than one turn anyway.
+ */
+ if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) {
+ copy_v3_v3(td->ext->rot, td->ext->irot);
+ for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final);
+ angle_progress += angle_step) {
+ axis_angle_normalized_to_mat3(rmc->mat, axis_final, angle_progress);
+ ElementRotation(t, tc, td, rmc->mat, t->around);
+ }
+ rmat_cache_reset(rmc);
+ }
+ else if (angle_final != angle) {
+ rmat_cache_reset(rmc);
+ }
+
+ rmat_cache_update(rmc, axis_final, angle_final);
+
+ ElementRotation(t, tc, td, rmc->mat, t->around);
+}
+
+static void transdata_elem_rotate_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict tls)
+{
+ struct TransDataArgs_Rotate *data = iter_data_v;
+ struct TransDataArgs_RotateTLS *tls_data = tls->userdata_chunk;
+
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_rotate(data->t,
+ data->tc,
+ td,
+ data->axis,
+ data->angle,
+ data->angle_step,
+ data->is_large_rotation,
+ &tls_data->rmc);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Rotation)
* \{ */
@@ -115,12 +250,9 @@ static float large_rotation_limit(float angle)
static void applyRotationValue(TransInfo *t,
float angle,
- float axis[3],
+ const float axis[3],
const bool is_large_rotation)
{
- float mat[3][3];
- int i;
-
const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
/* We cannot use something too close to 180°, or 'continuous' rotation may fail
* due to computing error... */
@@ -132,60 +264,37 @@ static void applyRotationValue(TransInfo *t,
angle = large_rotation_limit(angle);
}
- axis_angle_normalized_to_mat3(mat, axis, angle);
- /* Counter for needed updates (when we need to update to non-default matrix,
- * we also need another update on next iteration to go back to default matrix,
- * hence the '2' value used here, instead of a mere boolean). */
- short do_update_matrix = 0;
+ struct RotateMatrixCache rmc = {0};
+ rmat_cache_init(&rmc, angle, axis);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- float angle_final = angle;
- if (t->con.applyRot) {
- t->con.applyRot(t, tc, td, axis, NULL);
- angle_final = angle * td->factor;
- /* Even though final angle might be identical to orig value,
- * we have to update the rotation matrix in that case... */
- do_update_matrix = 2;
- }
- else if (t->flag & T_PROP_EDIT) {
- angle_final = angle * td->factor;
- }
-
- /* Rotation is very likely to be above 180°, we need to do rotation by steps.
- * Note that this is only needed when doing 'absolute' rotation
- * (i.e. from initial rotation again, typically when using numinput).
- * regular incremental rotation (from mouse/widget/...) will be called often enough,
- * hence steps are small enough to be properly handled without that complicated trick.
- * Note that we can only do that kind of stepped rotation if we have initial rotation values
- * (and access to some actual rotation value storage).
- * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing).
- * Also need to be in Euler rotation mode, the others never allow more than one turn anyway.
- */
- if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) {
- copy_v3_v3(td->ext->rot, td->ext->irot);
- for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final);
- angle_progress += angle_step) {
- axis_angle_normalized_to_mat3(mat, axis, angle_progress);
- ElementRotation(t, tc, td, mat, t->around);
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
}
- do_update_matrix = 2;
+ transdata_elem_rotate(t, tc, td, axis, angle, angle_step, is_large_rotation, &rmc);
}
- else if (angle_final != angle) {
- do_update_matrix = 2;
- }
-
- if (do_update_matrix > 0) {
- axis_angle_normalized_to_mat3(mat, axis, angle_final);
- do_update_matrix--;
- }
-
- ElementRotation(t, tc, td, mat, t->around);
+ }
+ else {
+ struct TransDataArgs_Rotate data = {
+ .t = t,
+ .tc = tc,
+ .axis = {UNPACK3(axis)},
+ .angle = angle,
+ .angle_step = angle_step,
+ .is_large_rotation = is_large_rotation,
+ };
+ struct TransDataArgs_RotateTLS tls_data = {
+ .rmc = rmc,
+ };
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.userdata_chunk = &tls_data;
+ settings.userdata_chunk_size = sizeof(tls_data);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_rotate_fn, &settings);
}
}
}
diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c
index 23ee55bf6c5..ab5dd11a926 100644
--- a/source/blender/editors/transform/transform_mode_shear.c
+++ b/source/blender/editors/transform/transform_mode_shear.c
@@ -27,6 +27,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -44,6 +45,79 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Shear) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_Shear {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float totmat[3][3];
+ bool is_local_center;
+};
+
+static void transdata_elem_shear(const TransInfo *t,
+ const TransDataContainer *tc,
+ TransData *td,
+ const float totmat[3][3],
+ const bool is_local_center)
+{
+ float tmat[3][3];
+ const float *center;
+ if (t->flag & T_EDIT) {
+ mul_m3_series(tmat, td->smtx, totmat, td->mtx);
+ }
+ else {
+ copy_m3_m3(tmat, totmat);
+ }
+
+ if (is_local_center) {
+ center = td->center;
+ }
+ else {
+ center = tc->center_local;
+ }
+
+ float vec[3];
+ sub_v3_v3v3(vec, td->iloc, center);
+ mul_m3_v3(tmat, vec);
+ add_v3_v3(vec, center);
+ sub_v3_v3(vec, td->iloc);
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* Grease pencil multi-frame falloff. */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+}
+
+static void transdata_elem_shear_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_Shear *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_shear(data->t, data->tc, td, data->totmat, data->is_local_center);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Shear)
* \{ */
@@ -117,8 +191,7 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3];
- float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3];
+ float smat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3];
float value;
int i;
char str[UI_MAX_DRAW_STR];
@@ -160,47 +233,26 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
mul_m3_series(totmat, axismat_inv, smat, axismat);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- const float *center;
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if (t->flag & T_EDIT) {
- mul_m3_series(tmat, td->smtx, totmat, td->mtx);
- }
- else {
- copy_m3_m3(tmat, totmat);
- }
-
- if (is_local_center) {
- center = td->center;
- }
- else {
- center = tc->center_local;
- }
-
- sub_v3_v3v3(vec, td->iloc, center);
- mul_m3_v3(tmat, vec);
- add_v3_v3(vec, center);
- sub_v3_v3(vec, td->iloc);
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
- }
- else {
- mul_v3_fl(vec, td->factor);
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
}
+ transdata_elem_shear(t, tc, td, totmat, is_local_center);
}
- else {
- mul_v3_fl(vec, td->factor);
- }
-
- add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+ else {
+ struct TransDataArgs_Shear data = {
+ .t = t,
+ .tc = tc,
+ .is_local_center = is_local_center,
+ };
+ copy_m3_m3(data.totmat, totmat);
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_shear_fn, &settings);
}
}
diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c
index d2d73a14396..4cdaab599b4 100644
--- a/source/blender/editors/transform/transform_mode_shrink_fatten.c
+++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c
@@ -25,6 +25,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -43,6 +44,47 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Shrink-Fatten) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_ShrinkFatten {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float distance;
+};
+
+static void transdata_elem_shrink_fatten(const TransInfo *t,
+ const TransDataContainer *UNUSED(tc),
+ TransData *td,
+ const float distance)
+{
+ /* Get the final offset. */
+ float tdistance = distance * td->factor;
+ if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) {
+ tdistance *= td->ext->isize[0]; /* shell factor */
+ }
+
+ madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
+}
+
+static void transdata_elem_shrink_fatten_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_ShrinkFatten *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_shrink_fatten(data->t, data->tc, td, data->distance);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Shrink-Fatten)
* \{ */
@@ -114,20 +156,24 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
/* done with header string */
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tdistance; /* temp dist */
- if (td->flag & TD_SKIP) {
- continue;
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+ transdata_elem_shrink_fatten(t, tc, td, distance);
}
-
- /* get the final offset */
- tdistance = distance * td->factor;
- if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) {
- tdistance *= td->ext->isize[0]; /* shell factor */
- }
-
- madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
+ }
+ else {
+ struct TransDataArgs_ShrinkFatten data = {
+ .t = t,
+ .tc = tc,
+ .distance = distance,
+ };
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_shrink_fatten_fn, &settings);
}
}
diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c
index 75ad83b0787..45336602c5a 100644
--- a/source/blender/editors/transform/transform_mode_skin_resize.c
+++ b/source/blender/editors/transform/transform_mode_skin_resize.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -38,6 +39,58 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Skin) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_SkinResize {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float mat[3][3];
+};
+
+static void transdata_elem_skin_resize(const TransInfo *t,
+ const TransDataContainer *UNUSED(tc),
+ TransData *td,
+ const float mat[3][3])
+{
+ float tmat[3][3], smat[3][3];
+ float fsize[3];
+
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
+ }
+ else {
+ copy_m3_m3(tmat, mat);
+ }
+
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, tmat);
+ }
+
+ mat3_to_size(fsize, tmat);
+ td->loc[0] = td->iloc[0] * (1 + (fsize[0] - 1) * td->factor);
+ td->loc[1] = td->iloc[1] * (1 + (fsize[1] - 1) * td->factor);
+}
+
+static void transdata_elem_skin_resize_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_SkinResize *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_skin_resize(data->t, data->tc, td, data->mat);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Skin)
* \{ */
@@ -67,29 +120,24 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
headerResize(t, t->values_final, str, sizeof(str));
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tmat[3][3], smat[3][3];
- float fsize[3];
- if (td->flag & TD_SKIP) {
- continue;
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+ transdata_elem_skin_resize(t, tc, td, mat);
}
-
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
- }
- else {
- copy_m3_m3(tmat, mat);
- }
-
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, tmat);
- }
-
- mat3_to_size(fsize, tmat);
- td->loc[0] = td->iloc[0] * (1 + (fsize[0] - 1) * td->factor);
- td->loc[1] = td->iloc[1] * (1 + (fsize[1] - 1) * td->factor);
+ }
+ else {
+ struct TransDataArgs_SkinResize data = {
+ .t = t,
+ .tc = tc,
+ };
+ copy_m3_m3(data.mat, mat);
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_skin_resize_fn, &settings);
}
}
diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c
index 9bca9b2e9e6..8587d5ae140 100644
--- a/source/blender/editors/transform/transform_mode_tosphere.c
+++ b/source/blender/editors/transform/transform_mode_tosphere.c
@@ -25,6 +25,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "MEM_guardedalloc.h"
@@ -111,6 +112,74 @@ static void to_sphere_radius_update(TransInfo *t)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Transform (ToSphere) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_ToSphere {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ float ratio;
+ const struct ToSphereInfo to_sphere_info;
+ bool is_local_center;
+ bool is_data_space;
+};
+
+static void transdata_elem_to_sphere(const TransInfo *UNUSED(t),
+ const TransDataContainer *tc,
+ TransData *td,
+ const float ratio,
+ const struct ToSphereInfo *to_sphere_info,
+ const bool is_local_center,
+ const bool is_data_space)
+{
+ float vec[3];
+ const float *center = is_local_center ? td->center : tc->center_local;
+ if (is_data_space) {
+ copy_v3_v3(vec, td->center);
+ }
+ else {
+ copy_v3_v3(vec, td->iloc);
+ }
+
+ sub_v3_v3(vec, center);
+ const float radius = normalize_v3(vec);
+ const float tratio = ratio * td->factor;
+ mul_v3_fl(vec, radius * (1.0f - tratio) + to_sphere_info->radius * tratio);
+ add_v3_v3(vec, center);
+
+ if (is_data_space) {
+ sub_v3_v3(vec, td->center);
+ mul_m3_v3(td->smtx, vec);
+ add_v3_v3(vec, td->iloc);
+ }
+
+ copy_v3_v3(td->loc, vec);
+}
+
+static void transdata_elem_to_sphere_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_ToSphere *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_to_sphere(data->t,
+ data->tc,
+ td,
+ data->ratio,
+ &data->to_sphere_info,
+ data->is_local_center,
+ data->is_data_space);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (ToSphere)
* \{ */
@@ -119,8 +188,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
const bool is_local_center = transdata_check_local_center(t, t->around);
const bool is_data_space = (t->options & CTX_POSE_BONE) != 0;
- float vec[3];
- float ratio, radius;
+ float ratio;
int i;
char str[UI_MAX_DRAW_STR];
@@ -147,40 +215,33 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, sizeof(str), TIP_("To Sphere: %.4f %s"), ratio, t->proptext);
}
- const struct ToSphereInfo *data = t->custom.mode.data;
- if (data->prop_size_prev != t->prop_size) {
+ const struct ToSphereInfo *to_sphere_info = t->custom.mode.data;
+ if (to_sphere_info->prop_size_prev != t->prop_size) {
to_sphere_radius_update(t);
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tratio;
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- const float *center = is_local_center ? td->center : tc->center_local;
- if (is_data_space) {
- copy_v3_v3(vec, td->center);
- }
- else {
- copy_v3_v3(vec, td->iloc);
- }
-
- sub_v3_v3(vec, center);
- radius = normalize_v3(vec);
- tratio = ratio * td->factor;
- mul_v3_fl(vec, radius * (1.0f - tratio) + data->radius * tratio);
- add_v3_v3(vec, center);
-
- if (is_data_space) {
- sub_v3_v3(vec, td->center);
- mul_m3_v3(td->smtx, vec);
- add_v3_v3(vec, td->iloc);
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+ transdata_elem_to_sphere(t, tc, td, ratio, to_sphere_info, is_local_center, is_data_space);
}
-
- copy_v3_v3(td->loc, vec);
+ }
+ else {
+ struct TransDataArgs_ToSphere data = {
+ .t = t,
+ .tc = tc,
+ .ratio = ratio,
+ .to_sphere_info = *to_sphere_info,
+ .is_local_center = is_local_center,
+ .is_data_space = is_data_space,
+ };
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_to_sphere_fn, &settings);
}
}
diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c
index d05077ef1ef..157283d08da 100644
--- a/source/blender/editors/transform/transform_mode_trackball.c
+++ b/source/blender/editors/transform/transform_mode_trackball.c
@@ -25,6 +25,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_unit.h"
@@ -40,6 +41,51 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Rotation - Trackball) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_Trackball {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ const float axis[3];
+ const float angle;
+ float mat[3][3];
+};
+
+static void transdata_elem_trackball(const TransInfo *t,
+ const TransDataContainer *tc,
+ TransData *td,
+ const float axis[3],
+ const float angle,
+ const float mat[3][3])
+{
+ float mat_buf[3][3];
+ const float(*mat_final)[3] = mat;
+ if (t->flag & T_PROP_EDIT) {
+ axis_angle_normalized_to_mat3(mat_buf, axis, td->factor * angle);
+ mat_final = mat_buf;
+ }
+ ElementRotation(t, tc, td, mat_final, t->around);
+}
+
+static void transdata_elem_trackball_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_Trackball *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_trackball(data->t, data->tc, td, data->axis, data->angle, data->mat);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Rotation - Trackball)
* \{ */
@@ -59,17 +105,27 @@ static void applyTrackballValue(TransInfo *t,
axis_angle_normalized_to_mat3(mat, axis, angle);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SKIP) {
- continue;
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+ transdata_elem_trackball(t, tc, td, axis, angle, mat);
}
-
- if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
- }
-
- ElementRotation(t, tc, td, mat, t->around);
+ }
+ else {
+ struct TransDataArgs_Trackball data = {
+ .t = t,
+ .tc = tc,
+ .axis = {UNPACK3(axis)},
+ .angle = angle,
+ };
+ copy_m3_m3(data.mat, mat);
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_trackball_fn, &settings);
}
}
}
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 49afd7f0421..55bfedf26b8 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -29,6 +29,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -49,6 +50,121 @@
#include "transform_snap.h"
/* -------------------------------------------------------------------- */
+/** \name Transform (Translation) Element
+ * \{ */
+
+/**
+ * \note Small arrays / data-structures should be stored copied for faster memory access.
+ */
+struct TransDataArgs_Translate {
+ const TransInfo *t;
+ const TransDataContainer *tc;
+ const float tc_pivot[3];
+ const float vec[3];
+ bool apply_snap_align_rotation;
+ bool is_valid_snapping_normal;
+};
+
+static void transdata_elem_translate(const TransInfo *t,
+ const TransDataContainer *tc,
+ TransData *td,
+ const float pivot[3],
+ const float vec[3],
+ const bool apply_snap_align_rotation,
+ const bool is_valid_snapping_normal)
+{
+ float rotate_offset[3] = {0};
+ bool use_rotate_offset = false;
+
+ /* Handle snapping rotation before doing the translation. */
+ if (apply_snap_align_rotation) {
+ float mat[3][3];
+
+ if (is_valid_snapping_normal) {
+ const float *original_normal;
+
+ /* In pose mode, we want to align normals with Y axis of bones. */
+ if (t->options & CTX_POSE_BONE) {
+ original_normal = td->axismtx[1];
+ }
+ else {
+ original_normal = td->axismtx[2];
+ }
+
+ rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
+ }
+ else {
+ unit_m3(mat);
+ }
+
+ ElementRotation_ex(t, tc, td, mat, pivot);
+
+ if (td->loc) {
+ use_rotate_offset = true;
+ sub_v3_v3v3(rotate_offset, td->loc, td->iloc);
+ }
+ }
+
+ float tvec[3];
+
+ if (t->con.applyVec) {
+ t->con.applyVec(t, tc, td, vec, tvec);
+ }
+ else {
+ copy_v3_v3(tvec, vec);
+ }
+
+ mul_m3_v3(td->smtx, tvec);
+
+ if (use_rotate_offset) {
+ add_v3_v3(tvec, rotate_offset);
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* Grease pencil multi-frame falloff. */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(tvec, td->factor);
+ }
+ }
+ else {
+ /* Proportional editing falloff. */
+ mul_v3_fl(tvec, td->factor);
+ }
+
+ protectedTransBits(td->protectflag, tvec);
+
+ if (td->loc) {
+ add_v3_v3v3(td->loc, td->iloc, tvec);
+ }
+
+ constraintTransLim(t, td);
+}
+
+static void transdata_elem_translate_fn(void *__restrict iter_data_v,
+ const int iter,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ struct TransDataArgs_Translate *data = iter_data_v;
+ TransData *td = &data->tc->data[iter];
+ if (td->flag & TD_SKIP) {
+ return;
+ }
+ transdata_elem_translate(data->t,
+ data->tc,
+ td,
+ data->tc_pivot,
+ data->vec,
+ data->apply_snap_align_rotation,
+ data->is_valid_snapping_normal);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Transform (Translation)
* \{ */
@@ -242,14 +358,13 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
static void applyTranslationValue(TransInfo *t, const float vec[3])
{
const bool apply_snap_align_rotation = usingSnappingNormal(t);
- float tvec[3];
+ const bool is_valid_snapping_normal = apply_snap_align_rotation && validSnappingNormal(t);
/* Ideally "apply_snap_align_rotation" would only be used when a snap point is found:
* `t->tsnap.status & POINT_INIT` - perhaps this function isn't the best place to apply rotation.
* However snapping rotation needs to be handled before doing the translation
* (unless the pivot is also translated). */
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
float pivot[3];
if (apply_snap_align_rotation) {
copy_v3_v3(pivot, t->tsnap.snapTarget);
@@ -259,79 +374,28 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
}
}
- TransData *td = tc->data;
- for (int i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- float rotate_offset[3] = {0};
- bool use_rotate_offset = false;
-
- /* Handle snapping rotation before doing the translation. */
- if (apply_snap_align_rotation) {
- float mat[3][3];
-
- if (validSnappingNormal(t)) {
- const float *original_normal;
-
- /* In pose mode, we want to align normals with Y axis of bones. */
- if (t->options & CTX_POSE_BONE) {
- original_normal = td->axismtx[1];
- }
- else {
- original_normal = td->axismtx[2];
- }
-
- rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
- }
- else {
- unit_m3(mat);
- }
-
- ElementRotation_ex(t, tc, td, mat, pivot);
-
- if (td->loc) {
- use_rotate_offset = true;
- sub_v3_v3v3(rotate_offset, td->loc, td->iloc);
+ if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
+ TransData *td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SKIP) {
+ continue;
}
+ transdata_elem_translate(
+ t, tc, td, pivot, vec, apply_snap_align_rotation, is_valid_snapping_normal);
}
-
- if (t->con.applyVec) {
- t->con.applyVec(t, tc, td, vec, tvec);
- }
- else {
- copy_v3_v3(tvec, vec);
- }
-
- mul_m3_v3(td->smtx, tvec);
-
- if (use_rotate_offset) {
- add_v3_v3(tvec, rotate_offset);
- }
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* Grease pencil multi-frame falloff. */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
- }
- else {
- mul_v3_fl(tvec, td->factor);
- }
- }
- else {
- /* Proportional editing falloff. */
- mul_v3_fl(tvec, td->factor);
- }
-
- protectedTransBits(td->protectflag, tvec);
-
- if (td->loc) {
- add_v3_v3v3(td->loc, td->iloc, tvec);
- }
-
- constraintTransLim(t, td);
+ }
+ else {
+ struct TransDataArgs_Translate data = {
+ .t = t,
+ .tc = tc,
+ .tc_pivot = {UNPACK3(pivot)},
+ .vec = {UNPACK3(vec)},
+ .apply_snap_align_rotation = apply_snap_align_rotation,
+ .is_valid_snapping_normal = is_valid_snapping_normal,
+ };
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_translate_fn, &settings);
}
}
}