27#include "RNA_prototypes.hh"
43 short *ne_fa_num =
nullptr;
44 short *ne_ed_num =
nullptr;
48 float (*vertexCos)[3] =
nullptr;
49 blender::Span<blender::int2> edges = {};
50 blender::OffsetIndices<int>
faces = {};
51 blender::Span<int> corner_verts = {};
52 LinearSolver *
context =
nullptr;
56 float vert_centroid[3] = {};
75 sys->vertexCos =
nullptr;
81 memset(sys->eweights, val,
sizeof(
float) * sys->edges.size());
82 memset(sys->
fweights, val,
sizeof(
float[3]) * sys->corner_verts.size());
83 memset(sys->ne_ed_num, val,
sizeof(
short) * sys->
verts_num);
84 memset(sys->ne_fa_num, val,
sizeof(
short) * sys->
verts_num);
85 memset(sys->ring_areas, val,
sizeof(
float) * sys->
verts_num);
86 memset(sys->vlengths, val,
sizeof(
float) * sys->
verts_num);
87 memset(sys->vweights, val,
sizeof(
float) * sys->
verts_num);
88 memset(sys->zerola, val,
sizeof(
bool) * sys->
verts_num);
94 sys = MEM_new<LaplacianSystem>(__func__);
110 float (*vertexCos)[3],
116 for (
const int i :
faces.index_range()) {
118 int corner_first = face.
start();
119 int corner_prev = corner_first + 1;
120 int corner_curr = corner_first + 2;
121 int corner_term = corner_first + face.
size();
123 for (; corner_curr != corner_term; corner_prev = corner_curr, corner_curr++) {
125 vertexCos[corner_verts[corner_first]],
126 vertexCos[corner_verts[corner_prev]],
127 vertexCos[corner_verts[corner_curr]]);
140 beta =
pow(vini / vend, 1.0f / 3.0f);
143 sys->vertexCos[
i][0] = (sys->vertexCos[
i][0] - sys->vert_centroid[0]) *
beta +
144 sys->vert_centroid[0];
147 sys->vertexCos[
i][1] = (sys->vertexCos[
i][1] - sys->vert_centroid[1]) *
beta +
148 sys->vert_centroid[1];
151 sys->vertexCos[
i][2] = (sys->vertexCos[
i][2] - sys->vert_centroid[2]) *
beta +
152 sys->vert_centroid[2];
166 for (
i = 0;
i < sys->edges.size();
i++) {
167 idv1 = sys->edges[
i][0];
168 idv2 = sys->edges[
i][1];
170 v1 = sys->vertexCos[idv1];
171 v2 = sys->vertexCos[idv2];
173 sys->ne_ed_num[idv1] = sys->ne_ed_num[idv1] + 1;
174 sys->ne_ed_num[idv2] = sys->ne_ed_num[idv2] + 1;
176 if (w1 < sys->min_area) {
177 sys->zerola[idv1] =
true;
178 sys->zerola[idv2] =
true;
184 sys->eweights[
i] = w1;
189 for (
const int i : sys->
faces.index_range()) {
191 int corner_next = face.
start();
192 int corner_term = corner_next + face.
size();
193 int corner_prev = corner_term - 2;
194 int corner_curr = corner_term - 1;
196 for (; corner_next != corner_term;
197 corner_prev = corner_curr, corner_curr = corner_next, corner_next++)
199 const float *v_prev = sys->vertexCos[corner_verts[corner_prev]];
200 const float *v_curr = sys->vertexCos[corner_verts[corner_curr]];
201 const float *v_next = sys->vertexCos[corner_verts[corner_next]];
203 sys->ne_fa_num[corner_verts[corner_curr]] += 1;
207 if (areaf < sys->min_area) {
208 sys->zerola[corner_verts[corner_curr]] =
true;
211 sys->ring_areas[corner_verts[corner_prev]] += areaf;
212 sys->ring_areas[corner_verts[corner_curr]] += areaf;
213 sys->ring_areas[corner_verts[corner_next]] += areaf;
219 sys->
fweights[corner_curr][0] += w1;
220 sys->
fweights[corner_curr][1] += w2;
221 sys->
fweights[corner_curr][2] += w3;
223 sys->vweights[corner_verts[corner_curr]] += w2 + w3;
224 sys->vweights[corner_verts[corner_next]] += w1 + w3;
225 sys->vweights[corner_verts[corner_prev]] += w1 + w2;
228 for (
i = 0;
i < sys->edges.size();
i++) {
229 idv1 = sys->edges[
i][0];
230 idv2 = sys->edges[
i][1];
232 if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
233 sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2])
235 sys->vlengths[idv1] += sys->eweights[
i];
236 sys->vlengths[idv2] += sys->eweights[
i];
248 for (
const int i : sys->
faces.index_range()) {
250 int corner_next = face.
start();
251 int corner_term = corner_next + face.
size();
252 int corner_prev = corner_term - 2;
253 int corner_curr = corner_term - 1;
255 for (; corner_next != corner_term;
256 corner_prev = corner_curr, corner_curr = corner_next, corner_next++)
260 if (sys->ne_ed_num[corner_verts[corner_curr]] == sys->ne_fa_num[corner_verts[corner_curr]] &&
261 sys->zerola[corner_verts[corner_curr]] ==
false)
264 corner_verts[corner_curr],
265 corner_verts[corner_next],
267 sys->vweights[corner_verts[corner_curr]]);
269 corner_verts[corner_curr],
270 corner_verts[corner_prev],
272 sys->vweights[corner_verts[corner_curr]]);
274 if (sys->ne_ed_num[corner_verts[corner_next]] == sys->ne_fa_num[corner_verts[corner_next]] &&
275 sys->zerola[corner_verts[corner_next]] ==
false)
278 corner_verts[corner_next],
279 corner_verts[corner_curr],
281 sys->vweights[corner_verts[corner_next]]);
283 corner_verts[corner_next],
284 corner_verts[corner_prev],
286 sys->vweights[corner_verts[corner_next]]);
288 if (sys->ne_ed_num[corner_verts[corner_prev]] == sys->ne_fa_num[corner_verts[corner_prev]] &&
289 sys->zerola[corner_verts[corner_prev]] ==
false)
292 corner_verts[corner_prev],
293 corner_verts[corner_curr],
295 sys->vweights[corner_verts[corner_prev]]);
297 corner_verts[corner_prev],
298 corner_verts[corner_next],
300 sys->vweights[corner_verts[corner_prev]]);
305 for (
i = 0;
i < sys->edges.size();
i++) {
306 idv1 = sys->edges[
i][0];
307 idv2 = sys->edges[
i][1];
309 if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
310 sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2] && sys->zerola[idv1] ==
false &&
311 sys->zerola[idv2] ==
false)
314 sys->
context, idv1, idv2, sys->eweights[
i] * sys->vlengths[idv1]);
316 sys->
context, idv2, idv1, sys->eweights[
i] * sys->vlengths[idv2]);
325 float vini = 0.0f, vend = 0.0f;
331 if (sys->zerola[
i] ==
false) {
332 lam = sys->ne_ed_num[
i] == sys->ne_fa_num[
i] ? (lambda >= 0.0f ? 1.0f : -1.0f) :
333 (lambda_border >= 0.0f ? 1.0f : -1.0f);
336 sys->vertexCos[
i][0]);
340 sys->vertexCos[
i][1]);
344 sys->vertexCos[
i][2]);
370 sys->edges = mesh->edges();
371 sys->
faces = mesh->faces();
372 sys->corner_verts = mesh->corner_verts();
373 sys->vertexCos = vertexCos;
374 sys->min_area = 0.00001f;
377 sys->vert_centroid[0] = 0.0f;
378 sys->vert_centroid[1] = 0.0f;
379 sys->vert_centroid[2] = 0.0f;
386 for (iter = 0; iter < smd->
repeat; iter++) {
387 for (
i = 0;
i < verts_num;
i++) {
395 if (iter == 0 && verts_num > 0) {
396 mul_v3_fl(sys->vert_centroid, 1.0f /
float(verts_num));
400 for (
i = 0;
i < verts_num;
i++) {
414 if (sys->zerola[
i] ==
false) {
416 w = sys->vweights[
i];
417 sys->vweights[
i] = (
w == 0.0f) ? 0.0f : -
fabsf(smd->
lambda) * wpaint /
w;
418 w = sys->vlengths[
i];
420 if (sys->ne_ed_num[
i] == sys->ne_fa_num[
i]) {
429 w = sys->vweights[
i] * sys->ring_areas[
i];
430 sys->vweights[
i] = (
w == 0.0f) ? 0.0f : -
fabsf(smd->
lambda) * wpaint / (4.0f *
w);
431 w = sys->vlengths[
i];
434 if (sys->ne_ed_num[
i] == sys->ne_fa_num[
i]) {
439 (4.0f * sys->ring_areas[
i]));
513 reinterpret_cast<float(*)[3]
>(positions.
data()),
530 row = &layout->
row(
true,
IFACE_(
"Axis"));
531 row->
prop(
ptr,
"use_x", toggles_flag, std::nullopt, ICON_NONE);
532 row->
prop(
ptr,
"use_y", toggles_flag, std::nullopt, ICON_NONE);
533 row->
prop(
ptr,
"use_z", toggles_flag, std::nullopt, ICON_NONE);
553 N_(
"LaplacianSmooth"),
554 "LaplacianSmoothModifierData",
556 &RNA_LaplacianSmoothModifier,
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define DNA_struct_default_get(struct_name)
@ eModifierType_LaplacianSmooth
@ MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME
@ MOD_LAPLACIANSMOOTH_NORMALIZED
@ MOD_LAPLACIANSMOOTH_INVERT_VGROUP
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static void deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
static void panel_register(ARegionType *region_type)
static void required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void panel_draw(const bContext *, Panel *panel)
static void init_data(ModifierData *md)
static void deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
static void panel_register(ARegionType *region_type)
static void laplaciansmoothModifier_do(LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float(*vertexCos)[3], int verts_num)
ModifierTypeInfo modifierType_LaplacianSmooth
static void init_laplacian_matrix(LaplacianSystem *sys)
static void delete_laplacian_system(LaplacianSystem *sys)
static LaplacianSystem * init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts)
static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag)
static void memset_laplacian_system(LaplacianSystem *sys, int val)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border)
static void fill_laplacian_matrix(LaplacianSystem *sys)
static float compute_volume(const float center[3], float(*vertexCos)[3], const blender::OffsetIndices< int > faces, const blender::Span< int > corner_verts)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const StringRefNull vgroup_prop, const std::optional< StringRefNull > invert_vgroup_prop, const std::optional< StringRefNull > text)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
void MOD_get_vgroup(const Object *ob, const Mesh *mesh, const char *name, const MDeformVert **dvert, int *defgrp_index)
@ UI_ITEM_R_FORCE_BLANK_DECORATE
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
constexpr int64_t size() const
constexpr int64_t start() const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr T * data() const
#define CD_MASK_MDEFORMVERT
void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value)
void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int index, double value)
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_right_hand_sides)
void EIG_linear_solver_delete(LinearSolver *solver)
double EIG_linear_solver_variable_get(LinearSolver *solver, int rhs, int index)
void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
bool EIG_linear_solver_solve(LinearSolver *solver)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
ccl_device_inline float beta(const float x, const float y)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)