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:
authorPablo Dobarro <pablodp606@gmail.com>2019-11-26 20:43:44 +0300
committerPablo Dobarro <pablodp606@gmail.com>2019-11-27 19:08:15 +0300
commit0e4014ef9215ffe38108b7596a29bd3c5c41bbd1 (patch)
tree65fe97e0e01fcb2ad510bf9ecb9b5ed3c09161d6 /source/blender
parentb6d436ae28311a8e2e7ea0079b1fa1fb046909ab (diff)
Sculpt/Paint: Move Elastic Deform Kelvinlets to BKE
After this commit it should be possible to share the same deformation formulas that are used in the Elastic Deform brush with other areas of Blender such as Grease Pencil or proportional editing. This also removes a lot of code from sculpt.c that is not direclty related to sculpting. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D6281
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_kelvinlet.h77
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/kelvinlet.c215
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c179
5 files changed, 316 insertions, 161 deletions
diff --git a/source/blender/blenkernel/BKE_kelvinlet.h b/source/blender/blenkernel/BKE_kelvinlet.h
new file mode 100644
index 00000000000..fbf7d3ede1f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_kelvinlet.h
@@ -0,0 +1,77 @@
+/*
+ * 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) Blender Foundation.
+ * All rights reserved.
+ */
+#ifndef __BKE_KELVINLET_H__
+#define __BKE_KELVINLET_H__
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BLI_math.h"
+
+/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
+ * Pixar Technical Memo #17-03 */
+
+#define KELVINLET_MAX_ITERATIONS 3
+
+typedef struct KelvinletParams {
+ float a;
+ float b;
+ float c;
+
+ float f;
+
+ float radius_scaled[KELVINLET_MAX_ITERATIONS];
+} KelvinletParams;
+
+/* Initialize KelvinletParams to store the parameters that will affect the deformation produced by
+ * a Kelvinlet */
+void BKE_kelvinlet_init_params(
+ KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio);
+
+/* Regularized Kelvinlets */
+/* All these functions output the displacement that should be applied to each element. */
+/* The initial coordinates of that element should not be modified during the transformation */
+void BKE_kelvinlet_grab(float r_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float brush_delta[3]);
+void BKE_kelvinlet_grab_biscale(float r_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float brush_delta[3]);
+void BKE_kelvinlet_grab_triscale(float r_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float brush_delta[3]);
+void BKE_kelvinlet_scale(float r_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float surface_normal[3]);
+void BKE_kelvinlet_twist(float r_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float surface_normal[3]);
+
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 883518b7a9d..88a3629ea3f 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -129,6 +129,7 @@ set(SRC
intern/image_gen.c
intern/image_save.c
intern/ipo.c
+ intern/kelvinlet.c
intern/key.c
intern/keyconfig.c
intern/lattice.c
@@ -292,6 +293,7 @@ set(SRC
BKE_image.h
BKE_image_save.h
BKE_ipo.h
+ BKE_kelvinlet.h
BKE_key.h
BKE_keyconfig.h
BKE_lattice.h
diff --git a/source/blender/blenkernel/intern/kelvinlet.c b/source/blender/blenkernel/intern/kelvinlet.c
new file mode 100644
index 00000000000..a7b48107873
--- /dev/null
+++ b/source/blender/blenkernel/intern/kelvinlet.c
@@ -0,0 +1,215 @@
+/*
+ * 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) Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BKE_kelvinlet.h"
+
+/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
+ * Pixar Technical Memo #17-03 */
+
+void BKE_kelvinlet_init_params(
+ KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
+{
+ params->a = 1.0f / (4.0f * (float)M_PI * shear_modulus);
+ params->b = params->a / (4.0f * (1.0f - poisson_ratio));
+ params->c = 2 * (3.0f * params->a - 2.0f * params->b);
+
+ /* Used in scale and twist. */
+ params->f = force;
+
+ /* This can be exposed if needed */
+ const float radius_e[KELVINLET_MAX_ITERATIONS] = {1.0f, 2.0f, 2.0f};
+ params->radius_scaled[0] = radius * radius_e[0];
+ params->radius_scaled[1] = params->radius_scaled[0] * radius_e[1];
+ params->radius_scaled[2] = params->radius_scaled[1] * radius_e[2];
+}
+
+static void init_kelvinlet_grab(float radius_e[3],
+ float kelvinlet[3],
+ const float radius,
+ const KelvinletParams *params,
+ const int num_iterations)
+{
+ const float a = params->a;
+ const float b = params->b;
+ const float *radius_scaled = params->radius_scaled;
+
+ for (int i = 0; i < num_iterations; i++) {
+ radius_e[i] = sqrtf(pow2f(radius) + pow2f(params->radius_scaled[i]));
+ }
+
+ /* Regularized Kelvinlets: Formula (6) */
+ for (int i = 0; i < num_iterations; i++) {
+ kelvinlet[i] = ((a - b) / radius_e[i]) + ((b * pow2f(radius)) / pow3f(radius_e[i])) +
+ ((a * pow2f(radius_scaled[i])) / (2.0f * pow3f(radius_e[i])));
+ }
+}
+
+void BKE_kelvinlet_grab(float radius_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float brush_delta[3])
+{
+ float radius_e[3], kelvinlet[3];
+ const float c = params->c;
+ const float radius = len_v3v3(brush_location, elem_orig_co);
+
+ init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 1);
+
+ const float fade = kelvinlet[0] * c;
+
+ mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
+}
+
+void BKE_kelvinlet_grab_biscale(float radius_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float brush_delta[3])
+{
+ float radius_e[3], kelvinlet[3];
+ const float c = params->c;
+ const float *radius_scaled = params->radius_scaled;
+ float radius = len_v3v3(brush_location, elem_orig_co);
+
+ init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 2);
+
+ const float u = kelvinlet[0] - kelvinlet[1];
+ const float fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1]));
+
+ mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
+}
+
+void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float brush_delta[3])
+{
+ float radius_e[3], kelvinlet[3], weights[3];
+ const float c = params->c;
+ const float *radius_scaled = params->radius_scaled;
+ const float radius = len_v3v3(brush_location, elem_orig_co);
+
+ init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 3);
+
+ weights[0] = 1.0f;
+ weights[1] = -((pow2f(radius_scaled[2]) - pow2f(radius_scaled[0])) /
+ (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1])));
+ weights[2] = ((pow2f(radius_scaled[1]) - pow2f(radius_scaled[0])) /
+ (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1])));
+
+ const float u = weights[0] * kelvinlet[0] + weights[1] * kelvinlet[1] +
+ weights[2] * kelvinlet[2];
+ const float fade = u * c /
+ (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] +
+ weights[2] / radius_scaled[2]);
+
+ mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
+}
+
+typedef void (*kelvinlet_fn)(
+ float[3], const float *, const float *, const float *, const KelvinletParams *);
+
+static void sculpt_kelvinet_integrate(kelvinlet_fn kelvinlet,
+ float r_disp[3],
+ const float vertex_co[3],
+ const float location[3],
+ const float normal[3],
+ const KelvinletParams *p)
+{
+ float k[4][3], k_it[4][3];
+ kelvinlet(k[0], vertex_co, location, normal, p);
+ copy_v3_v3(k_it[0], k[0]);
+ mul_v3_fl(k_it[0], 0.5f);
+ add_v3_v3v3(k_it[0], vertex_co, k_it[0]);
+ kelvinlet(k[1], k_it[0], location, normal, p);
+ copy_v3_v3(k_it[1], k[1]);
+ mul_v3_fl(k_it[1], 0.5f);
+ add_v3_v3v3(k_it[1], vertex_co, k_it[1]);
+ kelvinlet(k[2], k_it[1], location, normal, p);
+ copy_v3_v3(k_it[2], k[2]);
+ add_v3_v3v3(k_it[2], vertex_co, k_it[2]);
+ sub_v3_v3v3(k_it[2], k_it[2], location);
+ kelvinlet(k[3], k_it[2], location, normal, p);
+ copy_v3_v3(r_disp, k[0]);
+ madd_v3_v3fl(r_disp, k[1], 2.0f);
+ madd_v3_v3fl(r_disp, k[2], 2.0f);
+ add_v3_v3(r_disp, k[3]);
+ mul_v3_fl(r_disp, 1.0f / 6.0f);
+}
+
+/* Regularized Kelvinlets: Formula (16) */
+static void kelvinlet_scale(float disp[3],
+ const float vertex_co[3],
+ const float location[3],
+ const float UNUSED(normal[3]),
+ const KelvinletParams *p)
+{
+ float radius_vertex[3];
+ sub_v3_v3v3(radius_vertex, vertex_co, location);
+ const float radius = len_v3(radius_vertex);
+ const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0]));
+ const float u = (2.0f * p->b - p->a) * ((1.0f / pow3f(radius_e))) +
+ ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e)));
+ const float fade = u * p->c;
+ mul_v3_v3fl(disp, radius_vertex, fade * p->f);
+}
+
+void BKE_kelvinlet_scale(float radius_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float surface_normal[3])
+{
+ sculpt_kelvinet_integrate(
+ kelvinlet_scale, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params);
+}
+
+/* Regularized Kelvinlets: Formula (15) */
+static void kelvinlet_twist(float disp[3],
+ const float vertex_co[3],
+ const float location[3],
+ const float normal[3],
+ const KelvinletParams *p)
+{
+ float radius_vertex[3], q_r[3];
+ sub_v3_v3v3(radius_vertex, vertex_co, location);
+ const float radius = len_v3(radius_vertex);
+ const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0]));
+ const float u = -p->a * ((1.0f / pow3f(radius_e))) +
+ ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e)));
+ const float fade = u * p->c;
+ cross_v3_v3v3(q_r, normal, radius_vertex);
+ mul_v3_v3fl(disp, q_r, fade * p->f);
+}
+
+void BKE_kelvinlet_twist(float radius_elem_disp[3],
+ const KelvinletParams *params,
+ const float elem_orig_co[3],
+ const float brush_location[3],
+ const float surface_normal[3])
+{
+ sculpt_kelvinet_integrate(
+ kelvinlet_twist, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params);
+}
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 4c86b9d3396..85c6425bb2f 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -58,6 +58,10 @@ MINLINE float pow4f(float x)
{
return pow2f(pow2f(x));
}
+MINLINE float pow5f(float x)
+{
+ return pow4f(x) * x;
+}
MINLINE float pow7f(float x)
{
return pow2f(pow3f(x)) * x;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 2964d53bc48..9d0048ff847 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -48,6 +48,7 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
+#include "BKE_kelvinlet.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -3404,98 +3405,6 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
}
-/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
- * Pixar Technical Memo #17-03 */
-
-typedef struct KelvinletParams {
- float f;
- float a;
- float b;
- float c;
- float radius_scaled;
-} KelvinletParams;
-
-static int sculpt_kelvinlet_get_scale_iteration_count(eBrushElasticDeformType type)
-{
- if (type == BRUSH_ELASTIC_DEFORM_GRAB) {
- return 1;
- }
- if (type == BRUSH_ELASTIC_DEFORM_GRAB_BISCALE) {
- return 2;
- }
- if (type == BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE) {
- return 3;
- }
- return 0;
-}
-
-static void sculpt_kelvinet_integrate(void (*kelvinlet)(float disp[3],
- const float vertex_co[3],
- const float location[3],
- float normal[3],
- KelvinletParams *p),
- float r_disp[3],
- const float vertex_co[3],
- const float location[3],
- float normal[3],
- KelvinletParams *p)
-{
- float k[4][3], k_it[4][3];
- kelvinlet(k[0], vertex_co, location, normal, p);
- copy_v3_v3(k_it[0], k[0]);
- mul_v3_fl(k_it[0], 0.5f);
- add_v3_v3v3(k_it[0], vertex_co, k_it[0]);
- kelvinlet(k[1], k_it[0], location, normal, p);
- copy_v3_v3(k_it[1], k[1]);
- mul_v3_fl(k_it[1], 0.5f);
- add_v3_v3v3(k_it[1], vertex_co, k_it[1]);
- kelvinlet(k[2], k_it[1], location, normal, p);
- copy_v3_v3(k_it[2], k[2]);
- add_v3_v3v3(k_it[2], vertex_co, k_it[2]);
- sub_v3_v3v3(k_it[2], k_it[2], location);
- kelvinlet(k[3], k_it[2], location, normal, p);
- copy_v3_v3(r_disp, k[0]);
- madd_v3_v3fl(r_disp, k[1], 2);
- madd_v3_v3fl(r_disp, k[2], 2);
- add_v3_v3(r_disp, k[3]);
- mul_v3_fl(r_disp, 1.0f / 6.0f);
-}
-
-/* Regularized Kelvinlets: Formula (16) */
-static void sculpt_kelvinlet_scale(float disp[3],
- const float vertex_co[3],
- const float location[3],
- float UNUSED(normal[3]),
- KelvinletParams *p)
-{
- float r_v[3];
- sub_v3_v3v3(r_v, vertex_co, location);
- float r = len_v3(r_v);
- float r_e = sqrtf(r * r + p->radius_scaled * p->radius_scaled);
- float u = (2.0f * p->b - p->a) * ((1.0f / (r_e * r_e * r_e))) +
- ((3.0f * p->radius_scaled * p->radius_scaled) / (2.0f * r_e * r_e * r_e * r_e * r_e));
- float fade = u * p->c;
- mul_v3_v3fl(disp, r_v, fade * p->f);
-}
-
-/* Regularized Kelvinlets: Formula (15) */
-static void sculpt_kelvinlet_twist(float disp[3],
- const float vertex_co[3],
- const float location[3],
- float normal[3],
- KelvinletParams *p)
-{
- float r_v[3], q_r[3];
- sub_v3_v3v3(r_v, vertex_co, location);
- float r = len_v3(r_v);
- float r_e = sqrtf(r * r + p->radius_scaled * p->radius_scaled);
- float u = -p->a * ((1.0f / (r_e * r_e * r_e))) +
- ((3.0f * p->radius_scaled * p->radius_scaled) / (2.0f * r_e * r_e * r_e * r_e * r_e));
- float fade = u * p->c;
- cross_v3_v3v3(q_r, normal, r_v);
- mul_v3_v3fl(disp, q_r, fade * p->f);
-}
-
static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -3516,23 +3425,6 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- /* Maybe this can be exposed to the user */
- float radius_e[3] = {1.0f, 2.0f, 2.0f};
- float r_e[3];
- float kvl[3];
- float radius_scaled[3];
-
- radius_scaled[0] = ss->cache->radius * radius_e[0];
- radius_scaled[1] = radius_scaled[0] * radius_e[1];
- radius_scaled[2] = radius_scaled[1] * radius_e[2];
-
- float shear_modulus = 1.0f;
- float poisson_ratio = brush->elastic_deform_volume_preservation;
-
- float a = 1.0f / (4.0f * (float)M_PI * shear_modulus);
- float b = a / (4.0f * (1.0f - poisson_ratio));
- float c = 2 * (3.0f * a - 2.0f * b);
-
float dir;
if (ss->cache->mouse[0] > ss->cache->initial_mouse[0]) {
dir = 1.0f;
@@ -3547,73 +3439,38 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
dir = -dir;
}
}
+
+ KelvinletParams params;
+ float force = len_v3(grab_delta) * dir * bstrength;
+ BKE_kelvinlet_init_params(
+ &params, ss->cache->radius, force, 1.0f, brush->elastic_deform_volume_preservation);
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_orig_vert_data_update(&orig_data, &vd);
- float fade, final_disp[3], weights[3];
- float r = len_v3v3(location, orig_data.co);
- KelvinletParams params;
- params.a = a;
- params.b = b;
- params.c = c;
- params.radius_scaled = radius_scaled[0];
-
- int multi_scale_it = sculpt_kelvinlet_get_scale_iteration_count(brush->elastic_deform_type);
- for (int it = 0; it < max_ii(1, multi_scale_it); it++) {
- r_e[it] = sqrtf(r * r + radius_scaled[it] * radius_scaled[it]);
- }
-
- /* Regularized Kelvinlets: Formula (6) */
- for (int s_it = 0; s_it < multi_scale_it; s_it++) {
- kvl[s_it] = ((a - b) / r_e[s_it]) + ((b * r * r) / (r_e[s_it] * r_e[s_it] * r_e[s_it])) +
- ((a * radius_scaled[s_it] * radius_scaled[s_it]) /
- (2.0f * r_e[s_it] * r_e[s_it] * r_e[s_it]));
- }
-
+ float final_disp[3];
switch (brush->elastic_deform_type) {
- /* Regularized Kelvinlets: Multi-scale extrapolation. Formula (11) */
case BRUSH_ELASTIC_DEFORM_GRAB:
- fade = kvl[0] * c;
- mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.f);
+ BKE_kelvinlet_grab(final_disp, &params, orig_data.co, location, grab_delta);
+ mul_v3_fl(final_disp, bstrength * 20.0f);
break;
case BRUSH_ELASTIC_DEFORM_GRAB_BISCALE: {
- const float u = kvl[0] - kvl[1];
- fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1]));
- mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.0f);
+ BKE_kelvinlet_grab_biscale(final_disp, &params, orig_data.co, location, grab_delta);
+ mul_v3_fl(final_disp, bstrength * 20.0f);
break;
}
case BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE: {
- weights[0] = 1.0f;
- weights[1] = -(
- (radius_scaled[2] * radius_scaled[2] - radius_scaled[0] * radius_scaled[0]) /
- (radius_scaled[2] * radius_scaled[2] - radius_scaled[1] * radius_scaled[1]));
- weights[2] = ((radius_scaled[1] * radius_scaled[1] - radius_scaled[0] * radius_scaled[0]) /
- (radius_scaled[2] * radius_scaled[2] - radius_scaled[1] * radius_scaled[1]));
-
- const float u = weights[0] * kvl[0] + weights[1] * kvl[1] + weights[2] * kvl[2];
- fade = u * c /
- (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] +
- weights[2] / radius_scaled[2]);
- mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.0f);
+ BKE_kelvinlet_grab_triscale(final_disp, &params, orig_data.co, location, grab_delta);
+ mul_v3_fl(final_disp, bstrength * 20.0f);
break;
}
case BRUSH_ELASTIC_DEFORM_SCALE:
- params.f = len_v3(grab_delta) * dir * bstrength;
- sculpt_kelvinet_integrate(sculpt_kelvinlet_scale,
- final_disp,
- orig_data.co,
- location,
- ss->cache->sculpt_normal_symm,
- &params);
+ BKE_kelvinlet_scale(
+ final_disp, &params, orig_data.co, location, ss->cache->sculpt_normal_symm);
break;
case BRUSH_ELASTIC_DEFORM_TWIST:
- params.f = len_v3(grab_delta) * dir * bstrength;
- sculpt_kelvinet_integrate(sculpt_kelvinlet_twist,
- final_disp,
- orig_data.co,
- location,
- ss->cache->sculpt_normal_symm,
- &params);
+ BKE_kelvinlet_twist(
+ final_disp, &params, orig_data.co, location, ss->cache->sculpt_normal_symm);
break;
}