Add Chromium-only Blender WebEngine parity work
This commit is contained in:
206
blender-5.2.0/source/blender/blenkernel/intern/kelvinlet.cc
Normal file
206
blender-5.2.0/source/blender/blenkernel/intern/kelvinlet.cc
Normal file
@@ -0,0 +1,206 @@
|
||||
/* SPDX-FileCopyrightText: Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BKE_kelvinlet.h"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
using kelvinlet_fn =
|
||||
void (*)(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 /*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);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
Reference in New Issue
Block a user