27#include "RNA_prototypes.hh"
44 short *ne_fa_num =
nullptr;
45 short *ne_ed_num =
nullptr;
49 float (*vertexCos)[3] =
nullptr;
50 blender::Span<blender::int2> edges = {};
51 blender::OffsetIndices<int>
faces = {};
52 blender::Span<int> corner_verts = {};
53 LinearSolver *
context =
nullptr;
57 float vert_centroid[3] = {};
76 sys->vertexCos =
nullptr;
82 memset(sys->eweights, val,
sizeof(
float) * sys->edges.size());
83 memset(sys->
fweights, val,
sizeof(
float[3]) * sys->corner_verts.size());
84 memset(sys->ne_ed_num, val,
sizeof(
short) * sys->
verts_num);
85 memset(sys->ne_fa_num, val,
sizeof(
short) * sys->
verts_num);
86 memset(sys->ring_areas, val,
sizeof(
float) * sys->
verts_num);
87 memset(sys->vlengths, val,
sizeof(
float) * sys->
verts_num);
88 memset(sys->vweights, val,
sizeof(
float) * sys->
verts_num);
89 memset(sys->zerola, val,
sizeof(
bool) * sys->
verts_num);
95 sys = MEM_new<LaplacianSystem>(__func__);
111 float (*vertexCos)[3],
117 for (
const int i :
faces.index_range()) {
119 int corner_first = face.
start();
120 int corner_prev = corner_first + 1;
121 int corner_curr = corner_first + 2;
122 int corner_term = corner_first + face.
size();
124 for (; corner_curr != corner_term; corner_prev = corner_curr, corner_curr++) {
126 vertexCos[corner_verts[corner_first]],
127 vertexCos[corner_verts[corner_prev]],
128 vertexCos[corner_verts[corner_curr]]);
141 beta =
pow(vini / vend, 1.0f / 3.0f);
144 sys->vertexCos[
i][0] = (sys->vertexCos[
i][0] - sys->vert_centroid[0]) *
beta +
145 sys->vert_centroid[0];
148 sys->vertexCos[
i][1] = (sys->vertexCos[
i][1] - sys->vert_centroid[1]) *
beta +
149 sys->vert_centroid[1];
152 sys->vertexCos[
i][2] = (sys->vertexCos[
i][2] - sys->vert_centroid[2]) *
beta +
153 sys->vert_centroid[2];
167 for (
i = 0;
i < sys->edges.size();
i++) {
168 idv1 = sys->edges[
i][0];
169 idv2 = sys->edges[
i][1];
171 v1 = sys->vertexCos[idv1];
172 v2 = sys->vertexCos[idv2];
174 sys->ne_ed_num[idv1] = sys->ne_ed_num[idv1] + 1;
175 sys->ne_ed_num[idv2] = sys->ne_ed_num[idv2] + 1;
177 if (w1 < sys->min_area) {
178 sys->zerola[idv1] =
true;
179 sys->zerola[idv2] =
true;
185 sys->eweights[
i] = w1;
190 for (
const int i : sys->
faces.index_range()) {
192 int corner_next = face.
start();
193 int corner_term = corner_next + face.
size();
194 int corner_prev = corner_term - 2;
195 int corner_curr = corner_term - 1;
197 for (; corner_next != corner_term;
198 corner_prev = corner_curr, corner_curr = corner_next, corner_next++)
200 const float *v_prev = sys->vertexCos[corner_verts[corner_prev]];
201 const float *v_curr = sys->vertexCos[corner_verts[corner_curr]];
202 const float *v_next = sys->vertexCos[corner_verts[corner_next]];
204 sys->ne_fa_num[corner_verts[corner_curr]] += 1;
208 if (areaf < sys->min_area) {
209 sys->zerola[corner_verts[corner_curr]] =
true;
212 sys->ring_areas[corner_verts[corner_prev]] += areaf;
213 sys->ring_areas[corner_verts[corner_curr]] += areaf;
214 sys->ring_areas[corner_verts[corner_next]] += areaf;
220 sys->
fweights[corner_curr][0] += w1;
221 sys->
fweights[corner_curr][1] += w2;
222 sys->
fweights[corner_curr][2] += w3;
224 sys->vweights[corner_verts[corner_curr]] += w2 + w3;
225 sys->vweights[corner_verts[corner_next]] += w1 + w3;
226 sys->vweights[corner_verts[corner_prev]] += w1 + w2;
229 for (
i = 0;
i < sys->edges.size();
i++) {
230 idv1 = sys->edges[
i][0];
231 idv2 = sys->edges[
i][1];
233 if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
234 sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2])
236 sys->vlengths[idv1] += sys->eweights[
i];
237 sys->vlengths[idv2] += sys->eweights[
i];
249 for (
const int i : sys->
faces.index_range()) {
251 int corner_next = face.
start();
252 int corner_term = corner_next + face.
size();
253 int corner_prev = corner_term - 2;
254 int corner_curr = corner_term - 1;
256 for (; corner_next != corner_term;
257 corner_prev = corner_curr, corner_curr = corner_next, corner_next++)
261 if (sys->ne_ed_num[corner_verts[corner_curr]] == sys->ne_fa_num[corner_verts[corner_curr]] &&
262 sys->zerola[corner_verts[corner_curr]] ==
false)
265 corner_verts[corner_curr],
266 corner_verts[corner_next],
268 sys->vweights[corner_verts[corner_curr]]);
270 corner_verts[corner_curr],
271 corner_verts[corner_prev],
273 sys->vweights[corner_verts[corner_curr]]);
275 if (sys->ne_ed_num[corner_verts[corner_next]] == sys->ne_fa_num[corner_verts[corner_next]] &&
276 sys->zerola[corner_verts[corner_next]] ==
false)
279 corner_verts[corner_next],
280 corner_verts[corner_curr],
282 sys->vweights[corner_verts[corner_next]]);
284 corner_verts[corner_next],
285 corner_verts[corner_prev],
287 sys->vweights[corner_verts[corner_next]]);
289 if (sys->ne_ed_num[corner_verts[corner_prev]] == sys->ne_fa_num[corner_verts[corner_prev]] &&
290 sys->zerola[corner_verts[corner_prev]] ==
false)
293 corner_verts[corner_prev],
294 corner_verts[corner_curr],
296 sys->vweights[corner_verts[corner_prev]]);
298 corner_verts[corner_prev],
299 corner_verts[corner_next],
301 sys->vweights[corner_verts[corner_prev]]);
306 for (
i = 0;
i < sys->edges.size();
i++) {
307 idv1 = sys->edges[
i][0];
308 idv2 = sys->edges[
i][1];
310 if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
311 sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2] && sys->zerola[idv1] ==
false &&
312 sys->zerola[idv2] ==
false)
315 sys->
context, idv1, idv2, sys->eweights[
i] * sys->vlengths[idv1]);
317 sys->
context, idv2, idv1, sys->eweights[
i] * sys->vlengths[idv2]);
326 float vini = 0.0f, vend = 0.0f;
332 if (sys->zerola[
i] ==
false) {
333 lam = sys->ne_ed_num[
i] == sys->ne_fa_num[
i] ? (lambda >= 0.0f ? 1.0f : -1.0f) :
334 (lambda_border >= 0.0f ? 1.0f : -1.0f);
337 sys->vertexCos[
i][0]);
341 sys->vertexCos[
i][1]);
345 sys->vertexCos[
i][2]);
371 sys->edges = mesh->edges();
372 sys->
faces = mesh->faces();
373 sys->corner_verts = mesh->corner_verts();
374 sys->vertexCos = vertexCos;
375 sys->min_area = 0.00001f;
378 sys->vert_centroid[0] = 0.0f;
379 sys->vert_centroid[1] = 0.0f;
380 sys->vert_centroid[2] = 0.0f;
387 for (iter = 0; iter < smd->
repeat; iter++) {
388 for (
i = 0;
i < verts_num;
i++) {
396 if (iter == 0 && verts_num > 0) {
397 mul_v3_fl(sys->vert_centroid, 1.0f /
float(verts_num));
401 for (
i = 0;
i < verts_num;
i++) {
415 if (sys->zerola[
i] ==
false) {
417 w = sys->vweights[
i];
418 sys->vweights[
i] = (
w == 0.0f) ? 0.0f : -
fabsf(smd->
lambda) * wpaint /
w;
419 w = sys->vlengths[
i];
421 if (sys->ne_ed_num[
i] == sys->ne_fa_num[
i]) {
430 w = sys->vweights[
i] * sys->ring_areas[
i];
431 sys->vweights[
i] = (
w == 0.0f) ? 0.0f : -
fabsf(smd->
lambda) * wpaint / (4.0f *
w);
432 w = sys->vlengths[
i];
435 if (sys->ne_ed_num[
i] == sys->ne_fa_num[
i]) {
440 (4.0f * sys->ring_areas[
i]));
514 reinterpret_cast<float (*)[3]
>(positions.
data()),
531 row = &layout->
row(
true,
IFACE_(
"Axis"));
532 row->
prop(
ptr,
"use_x", toggles_flag, std::nullopt, ICON_NONE);
533 row->
prop(
ptr,
"use_y", toggles_flag, std::nullopt, ICON_NONE);
534 row->
prop(
ptr,
"use_z", toggles_flag, std::nullopt, ICON_NONE);
554 N_(
"LaplacianSmooth"),
555 "LaplacianSmoothModifierData",
557 &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 CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
@ MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME
@ MOD_LAPLACIANSMOOTH_NORMALIZED
@ MOD_LAPLACIANSMOOTH_INVERT_VGROUP
@ eModifierType_LaplacianSmooth
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
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
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 use_property_split_set(bool value)
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)