Blender  V3.3
kelvinlet.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. All rights reserved. */
3 
8 #include "BKE_kelvinlet.h"
9 
10 /* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
11  * Pixar Technical Memo #17-03 */
12 
14  KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
15 {
16  params->a = 1.0f / (4.0f * (float)M_PI * shear_modulus);
17  params->b = params->a / (4.0f * (1.0f - poisson_ratio));
18  params->c = 2 * (3.0f * params->a - 2.0f * params->b);
19 
20  /* Used in scale and twist. */
21  params->f = force;
22 
23  /* This can be exposed if needed */
24  const float radius_e[KELVINLET_MAX_ITERATIONS] = {1.0f, 2.0f, 2.0f};
25  params->radius_scaled[0] = radius * radius_e[0];
26  params->radius_scaled[1] = params->radius_scaled[0] * radius_e[1];
27  params->radius_scaled[2] = params->radius_scaled[1] * radius_e[2];
28 }
29 
30 static void init_kelvinlet_grab(float radius_e[3],
31  float kelvinlet[3],
32  const float radius,
33  const KelvinletParams *params,
34  const int num_iterations)
35 {
36  const float a = params->a;
37  const float b = params->b;
38  const float *radius_scaled = params->radius_scaled;
39 
40  for (int i = 0; i < num_iterations; i++) {
41  radius_e[i] = sqrtf(pow2f(radius) + pow2f(params->radius_scaled[i]));
42  }
43 
44  /* Regularized Kelvinlets: Formula (6) */
45  for (int i = 0; i < num_iterations; i++) {
46  kelvinlet[i] = ((a - b) / radius_e[i]) + ((b * pow2f(radius)) / pow3f(radius_e[i])) +
47  ((a * pow2f(radius_scaled[i])) / (2.0f * pow3f(radius_e[i])));
48  }
49 }
50 
51 void BKE_kelvinlet_grab(float radius_elem_disp[3],
52  const KelvinletParams *params,
53  const float elem_orig_co[3],
54  const float brush_location[3],
55  const float brush_delta[3])
56 {
57  float radius_e[3], kelvinlet[3];
58  const float c = params->c;
59  const float radius = len_v3v3(brush_location, elem_orig_co);
60 
61  init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 1);
62 
63  const float fade = kelvinlet[0] * c;
64 
65  mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
66 }
67 
68 void BKE_kelvinlet_grab_biscale(float radius_elem_disp[3],
69  const KelvinletParams *params,
70  const float elem_orig_co[3],
71  const float brush_location[3],
72  const float brush_delta[3])
73 {
74  float radius_e[3], kelvinlet[3];
75  const float c = params->c;
76  const float *radius_scaled = params->radius_scaled;
77  float radius = len_v3v3(brush_location, elem_orig_co);
78 
79  init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 2);
80 
81  const float u = kelvinlet[0] - kelvinlet[1];
82  const float fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1]));
83 
84  mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
85 }
86 
87 void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3],
88  const KelvinletParams *params,
89  const float elem_orig_co[3],
90  const float brush_location[3],
91  const float brush_delta[3])
92 {
93  float radius_e[3], kelvinlet[3], weights[3];
94  const float c = params->c;
95  const float *radius_scaled = params->radius_scaled;
96  const float radius = len_v3v3(brush_location, elem_orig_co);
97 
98  init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 3);
99 
100  weights[0] = 1.0f;
101  weights[1] = -((pow2f(radius_scaled[2]) - pow2f(radius_scaled[0])) /
102  (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1])));
103  weights[2] = ((pow2f(radius_scaled[1]) - pow2f(radius_scaled[0])) /
104  (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1])));
105 
106  const float u = weights[0] * kelvinlet[0] + weights[1] * kelvinlet[1] +
107  weights[2] * kelvinlet[2];
108  const float fade = u * c /
109  (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] +
110  weights[2] / radius_scaled[2]);
111 
112  mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
113 }
114 
115 typedef void (*kelvinlet_fn)(
116  float[3], const float *, const float *, const float *, const KelvinletParams *);
117 
119  float r_disp[3],
120  const float vertex_co[3],
121  const float location[3],
122  const float normal[3],
123  const KelvinletParams *p)
124 {
125  float k[4][3], k_it[4][3];
126  kelvinlet(k[0], vertex_co, location, normal, p);
127  copy_v3_v3(k_it[0], k[0]);
128  mul_v3_fl(k_it[0], 0.5f);
129  add_v3_v3v3(k_it[0], vertex_co, k_it[0]);
130  kelvinlet(k[1], k_it[0], location, normal, p);
131  copy_v3_v3(k_it[1], k[1]);
132  mul_v3_fl(k_it[1], 0.5f);
133  add_v3_v3v3(k_it[1], vertex_co, k_it[1]);
134  kelvinlet(k[2], k_it[1], location, normal, p);
135  copy_v3_v3(k_it[2], k[2]);
136  add_v3_v3v3(k_it[2], vertex_co, k_it[2]);
137  sub_v3_v3v3(k_it[2], k_it[2], location);
138  kelvinlet(k[3], k_it[2], location, normal, p);
139  copy_v3_v3(r_disp, k[0]);
140  madd_v3_v3fl(r_disp, k[1], 2.0f);
141  madd_v3_v3fl(r_disp, k[2], 2.0f);
142  add_v3_v3(r_disp, k[3]);
143  mul_v3_fl(r_disp, 1.0f / 6.0f);
144 }
145 
146 /* Regularized Kelvinlets: Formula (16) */
147 static void kelvinlet_scale(float disp[3],
148  const float vertex_co[3],
149  const float location[3],
150  const float UNUSED(normal[3]),
151  const KelvinletParams *p)
152 {
153  float radius_vertex[3];
154  sub_v3_v3v3(radius_vertex, vertex_co, location);
155  const float radius = len_v3(radius_vertex);
156  const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0]));
157  const float u = (2.0f * p->b - p->a) * ((1.0f / pow3f(radius_e))) +
158  ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e)));
159  const float fade = u * p->c;
160  mul_v3_v3fl(disp, radius_vertex, fade * p->f);
161 }
162 
163 void BKE_kelvinlet_scale(float radius_elem_disp[3],
164  const KelvinletParams *params,
165  const float elem_orig_co[3],
166  const float brush_location[3],
167  const float surface_normal[3])
168 {
170  kelvinlet_scale, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params);
171 }
172 
173 /* Regularized Kelvinlets: Formula (15) */
174 static void kelvinlet_twist(float disp[3],
175  const float vertex_co[3],
176  const float location[3],
177  const float normal[3],
178  const KelvinletParams *p)
179 {
180  float radius_vertex[3], q_r[3];
181  sub_v3_v3v3(radius_vertex, vertex_co, location);
182  const float radius = len_v3(radius_vertex);
183  const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0]));
184  const float u = -p->a * ((1.0f / pow3f(radius_e))) +
185  ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e)));
186  const float fade = u * p->c;
187  cross_v3_v3v3(q_r, normal, radius_vertex);
188  mul_v3_v3fl(disp, q_r, fade * p->f);
189 }
190 
191 void BKE_kelvinlet_twist(float radius_elem_disp[3],
192  const KelvinletParams *params,
193  const float elem_orig_co[3],
194  const float brush_location[3],
195  const float surface_normal[3])
196 {
198  kelvinlet_twist, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params);
199 }
typedef float(TangentPoint)[2]
#define KELVINLET_MAX_ITERATIONS
Definition: BKE_kelvinlet.h:18
MINLINE float pow2f(float x)
MINLINE float pow3f(float x)
#define M_PI
Definition: BLI_math_base.h:20
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define UNUSED(x)
SyclQueue void void size_t num_bytes void
IconTextureDrawCall normal
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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])
Definition: kelvinlet.c:51
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])
Definition: kelvinlet.c:87
static void init_kelvinlet_grab(float radius_e[3], float kelvinlet[3], const float radius, const KelvinletParams *params, const int num_iterations)
Definition: kelvinlet.c:30
void BKE_kelvinlet_init_params(KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
Definition: kelvinlet.c:13
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])
Definition: kelvinlet.c:68
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)
Definition: kelvinlet.c:118
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])
Definition: kelvinlet.c:163
static void kelvinlet_twist(float disp[3], const float vertex_co[3], const float location[3], const float normal[3], const KelvinletParams *p)
Definition: kelvinlet.c:174
static void kelvinlet_scale(float disp[3], const float vertex_co[3], const float location[3], const float UNUSED(normal[3]), const KelvinletParams *p)
Definition: kelvinlet.c:147
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])
Definition: kelvinlet.c:191
void(* kelvinlet_fn)(float[3], const float *, const float *, const float *, const KelvinletParams *)
Definition: kelvinlet.c:115
MINLINE float pow5f(float x)
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
float radius_scaled[KELVINLET_MAX_ITERATIONS]
Definition: BKE_kelvinlet.h:27