Blender  V2.93
kelvinlet.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BKE_kelvinlet.h"
25 
26 /* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity
27  * Pixar Technical Memo #17-03 */
28 
30  KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
31 {
32  params->a = 1.0f / (4.0f * (float)M_PI * shear_modulus);
33  params->b = params->a / (4.0f * (1.0f - poisson_ratio));
34  params->c = 2 * (3.0f * params->a - 2.0f * params->b);
35 
36  /* Used in scale and twist. */
37  params->f = force;
38 
39  /* This can be exposed if needed */
40  const float radius_e[KELVINLET_MAX_ITERATIONS] = {1.0f, 2.0f, 2.0f};
41  params->radius_scaled[0] = radius * radius_e[0];
42  params->radius_scaled[1] = params->radius_scaled[0] * radius_e[1];
43  params->radius_scaled[2] = params->radius_scaled[1] * radius_e[2];
44 }
45 
46 static void init_kelvinlet_grab(float radius_e[3],
47  float kelvinlet[3],
48  const float radius,
49  const KelvinletParams *params,
50  const int num_iterations)
51 {
52  const float a = params->a;
53  const float b = params->b;
54  const float *radius_scaled = params->radius_scaled;
55 
56  for (int i = 0; i < num_iterations; i++) {
57  radius_e[i] = sqrtf(pow2f(radius) + pow2f(params->radius_scaled[i]));
58  }
59 
60  /* Regularized Kelvinlets: Formula (6) */
61  for (int i = 0; i < num_iterations; i++) {
62  kelvinlet[i] = ((a - b) / radius_e[i]) + ((b * pow2f(radius)) / pow3f(radius_e[i])) +
63  ((a * pow2f(radius_scaled[i])) / (2.0f * pow3f(radius_e[i])));
64  }
65 }
66 
67 void BKE_kelvinlet_grab(float radius_elem_disp[3],
68  const KelvinletParams *params,
69  const float elem_orig_co[3],
70  const float brush_location[3],
71  const float brush_delta[3])
72 {
73  float radius_e[3], kelvinlet[3];
74  const float c = params->c;
75  const float radius = len_v3v3(brush_location, elem_orig_co);
76 
77  init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 1);
78 
79  const float fade = kelvinlet[0] * c;
80 
81  mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
82 }
83 
84 void BKE_kelvinlet_grab_biscale(float radius_elem_disp[3],
85  const KelvinletParams *params,
86  const float elem_orig_co[3],
87  const float brush_location[3],
88  const float brush_delta[3])
89 {
90  float radius_e[3], kelvinlet[3];
91  const float c = params->c;
92  const float *radius_scaled = params->radius_scaled;
93  float radius = len_v3v3(brush_location, elem_orig_co);
94 
95  init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 2);
96 
97  const float u = kelvinlet[0] - kelvinlet[1];
98  const float fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1]));
99 
100  mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
101 }
102 
103 void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3],
104  const KelvinletParams *params,
105  const float elem_orig_co[3],
106  const float brush_location[3],
107  const float brush_delta[3])
108 {
109  float radius_e[3], kelvinlet[3], weights[3];
110  const float c = params->c;
111  const float *radius_scaled = params->radius_scaled;
112  const float radius = len_v3v3(brush_location, elem_orig_co);
113 
114  init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 3);
115 
116  weights[0] = 1.0f;
117  weights[1] = -((pow2f(radius_scaled[2]) - pow2f(radius_scaled[0])) /
118  (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1])));
119  weights[2] = ((pow2f(radius_scaled[1]) - pow2f(radius_scaled[0])) /
120  (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1])));
121 
122  const float u = weights[0] * kelvinlet[0] + weights[1] * kelvinlet[1] +
123  weights[2] * kelvinlet[2];
124  const float fade = u * c /
125  (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] +
126  weights[2] / radius_scaled[2]);
127 
128  mul_v3_v3fl(radius_elem_disp, brush_delta, fade);
129 }
130 
131 typedef void (*kelvinlet_fn)(
132  float[3], const float *, const float *, const float *, const KelvinletParams *);
133 
135  float r_disp[3],
136  const float vertex_co[3],
137  const float location[3],
138  const float normal[3],
139  const KelvinletParams *p)
140 {
141  float k[4][3], k_it[4][3];
142  kelvinlet(k[0], vertex_co, location, normal, p);
143  copy_v3_v3(k_it[0], k[0]);
144  mul_v3_fl(k_it[0], 0.5f);
145  add_v3_v3v3(k_it[0], vertex_co, k_it[0]);
146  kelvinlet(k[1], k_it[0], location, normal, p);
147  copy_v3_v3(k_it[1], k[1]);
148  mul_v3_fl(k_it[1], 0.5f);
149  add_v3_v3v3(k_it[1], vertex_co, k_it[1]);
150  kelvinlet(k[2], k_it[1], location, normal, p);
151  copy_v3_v3(k_it[2], k[2]);
152  add_v3_v3v3(k_it[2], vertex_co, k_it[2]);
153  sub_v3_v3v3(k_it[2], k_it[2], location);
154  kelvinlet(k[3], k_it[2], location, normal, p);
155  copy_v3_v3(r_disp, k[0]);
156  madd_v3_v3fl(r_disp, k[1], 2.0f);
157  madd_v3_v3fl(r_disp, k[2], 2.0f);
158  add_v3_v3(r_disp, k[3]);
159  mul_v3_fl(r_disp, 1.0f / 6.0f);
160 }
161 
162 /* Regularized Kelvinlets: Formula (16) */
163 static void kelvinlet_scale(float disp[3],
164  const float vertex_co[3],
165  const float location[3],
166  const float UNUSED(normal[3]),
167  const KelvinletParams *p)
168 {
169  float radius_vertex[3];
170  sub_v3_v3v3(radius_vertex, vertex_co, location);
171  const float radius = len_v3(radius_vertex);
172  const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0]));
173  const float u = (2.0f * p->b - p->a) * ((1.0f / pow3f(radius_e))) +
174  ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e)));
175  const float fade = u * p->c;
176  mul_v3_v3fl(disp, radius_vertex, fade * p->f);
177 }
178 
179 void BKE_kelvinlet_scale(float radius_elem_disp[3],
180  const KelvinletParams *params,
181  const float elem_orig_co[3],
182  const float brush_location[3],
183  const float surface_normal[3])
184 {
186  kelvinlet_scale, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params);
187 }
188 
189 /* Regularized Kelvinlets: Formula (15) */
190 static void kelvinlet_twist(float disp[3],
191  const float vertex_co[3],
192  const float location[3],
193  const float normal[3],
194  const KelvinletParams *p)
195 {
196  float radius_vertex[3], q_r[3];
197  sub_v3_v3v3(radius_vertex, vertex_co, location);
198  const float radius = len_v3(radius_vertex);
199  const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0]));
200  const float u = -p->a * ((1.0f / pow3f(radius_e))) +
201  ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e)));
202  const float fade = u * p->c;
203  cross_v3_v3v3(q_r, normal, radius_vertex);
204  mul_v3_v3fl(disp, q_r, fade * p->f);
205 }
206 
207 void BKE_kelvinlet_twist(float radius_elem_disp[3],
208  const KelvinletParams *params,
209  const float elem_orig_co[3],
210  const float brush_location[3],
211  const float surface_normal[3])
212 {
214  kelvinlet_twist, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params);
215 }
typedef float(TangentPoint)[2]
#define KELVINLET_MAX_ITERATIONS
Definition: BKE_kelvinlet.h:34
MINLINE float pow2f(float x)
MINLINE float pow3f(float x)
#define M_PI
Definition: BLI_math_base.h:38
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)
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:67
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:103
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:46
void BKE_kelvinlet_init_params(KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
Definition: kelvinlet.c:29
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:84
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:134
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:179
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:190
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:163
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:207
void(* kelvinlet_fn)(float[3], const float *, const float *, const float *, const KelvinletParams *)
Definition: kelvinlet.c:131
#define sqrtf(x)
MINLINE float pow5f(float x)
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
float radius_scaled[KELVINLET_MAX_ITERATIONS]
Definition: BKE_kelvinlet.h:43
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: svm_noise.h:37