Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern/MOD_weld.c')
-rw-r--r--source/blender/modifiers/intern/MOD_weld.c280
1 files changed, 131 insertions, 149 deletions
diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c
index 855f96df82f..1a25c24fedc 100644
--- a/source/blender/modifiers/intern/MOD_weld.c
+++ b/source/blender/modifiers/intern/MOD_weld.c
@@ -27,23 +27,32 @@
* - Review weight and vertex color interpolation.;
*/
+//#define USE_WELD_DEBUG
+//#define USE_WELD_NORMALS
+//#define USE_BVHTREEKDOP
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
-#include "BLI_kdopbvh.h"
+#include "BLI_bitmap.h"
+#include "BLI_kdtree.h"
#include "BLI_math.h"
#include "BLT_translation.h"
+#include "DNA_defaults.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
-#include "BKE_bvhutils.h"
+#ifdef USE_BVHTREEKDOP
+# include "BKE_bvhutils.h"
+#endif
+
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
@@ -60,9 +69,6 @@
#include "MOD_modifiertypes.h"
#include "MOD_ui_common.h"
-//#define USE_WELD_DEBUG
-//#define USE_WELD_NORMALS
-
/* Indicates when the element was not computed. */
#define OUT_OF_CONTEXT (uint)(-1)
/* Indicates if the edge or face will be collapsed. */
@@ -136,9 +142,6 @@ typedef struct WeldMesh {
/* Group of vertices to be merged. */
struct WeldGroup *vert_groups;
uint *vert_groups_buffer;
- /* From the original index of the vertex, this indicates which group it is or is going to be
- * merged. */
- uint *vert_groups_map;
/* Group of edges to be merged. */
struct WeldGroupEdge *edge_groups;
@@ -202,21 +205,6 @@ static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter *iter,
static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter *iter);
-static void weld_assert_vert_dest_map_setup(const BVHTreeOverlap *overlap,
- const uint overlap_len,
- const uint *vert_dest_map)
-{
- const BVHTreeOverlap *overlap_iter = &overlap[0];
- for (uint i = overlap_len; i--; overlap_iter++) {
- uint indexA = overlap_iter->indexA;
- uint indexB = overlap_iter->indexB;
- uint va_dst = vert_dest_map[indexA];
- uint vb_dst = vert_dest_map[indexB];
-
- BLI_assert(va_dst == vb_dst);
- }
-}
-
static void weld_assert_edge_kill_len(const WeldEdge *wedge,
const uint wedge_len,
const uint supposed_kill_len)
@@ -383,69 +371,10 @@ static void weld_assert_poly_len(const WeldPoly *wp, const WeldLoop *wloop)
* \{ */
static void weld_vert_ctx_alloc_and_setup(const uint mvert_len,
- const BVHTreeOverlap *overlap,
- const uint overlap_len,
uint *r_vert_dest_map,
WeldVert **r_wvert,
- uint *r_wvert_len,
- uint *r_vert_kill_len)
+ uint *r_wvert_len)
{
- uint *v_dest_iter = &r_vert_dest_map[0];
- for (uint i = mvert_len; i--; v_dest_iter++) {
- *v_dest_iter = OUT_OF_CONTEXT;
- }
-
- uint vert_kill_len = 0;
- const BVHTreeOverlap *overlap_iter = &overlap[0];
- for (uint i = 0; i < overlap_len; i++, overlap_iter++) {
- uint indexA = overlap_iter->indexA;
- uint indexB = overlap_iter->indexB;
-
- BLI_assert(indexA < indexB);
-
- uint va_dst = r_vert_dest_map[indexA];
- uint vb_dst = r_vert_dest_map[indexB];
- if (va_dst == OUT_OF_CONTEXT) {
- if (vb_dst == OUT_OF_CONTEXT) {
- vb_dst = indexA;
- r_vert_dest_map[indexB] = vb_dst;
- }
- r_vert_dest_map[indexA] = vb_dst;
- vert_kill_len++;
- }
- else if (vb_dst == OUT_OF_CONTEXT) {
- r_vert_dest_map[indexB] = va_dst;
- vert_kill_len++;
- }
- else if (va_dst != vb_dst) {
- uint v_new, v_old;
- if (va_dst < vb_dst) {
- v_new = va_dst;
- v_old = vb_dst;
- }
- else {
- v_new = vb_dst;
- v_old = va_dst;
- }
- BLI_assert(r_vert_dest_map[v_old] == v_old);
- BLI_assert(r_vert_dest_map[v_new] == v_new);
- vert_kill_len++;
-
- const BVHTreeOverlap *overlap_iter_b = &overlap[0];
- for (uint j = i + 1; j--; overlap_iter_b++) {
- indexA = overlap_iter_b->indexA;
- indexB = overlap_iter_b->indexB;
- va_dst = r_vert_dest_map[indexA];
- vb_dst = r_vert_dest_map[indexB];
- if (ELEM(v_old, vb_dst, va_dst)) {
- r_vert_dest_map[indexA] = v_new;
- r_vert_dest_map[indexB] = v_new;
- }
- }
- BLI_assert(r_vert_dest_map[v_old] == v_new);
- }
- }
-
/* Vert Context. */
uint wvert_len = 0;
@@ -453,7 +382,7 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len,
wvert = MEM_mallocN(sizeof(*wvert) * mvert_len, __func__);
wv = &wvert[0];
- v_dest_iter = &r_vert_dest_map[0];
+ uint *v_dest_iter = &r_vert_dest_map[0];
for (uint i = 0; i < mvert_len; i++, v_dest_iter++) {
if (*v_dest_iter != OUT_OF_CONTEXT) {
wv->vert_dest = *v_dest_iter;
@@ -463,13 +392,8 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len,
}
}
-#ifdef USE_WELD_DEBUG
- weld_assert_vert_dest_map_setup(overlap, overlap_len, r_vert_dest_map);
-#endif
-
*r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len);
*r_wvert_len = wvert_len;
- *r_vert_kill_len = vert_kill_len;
}
static void weld_vert_groups_setup(const uint mvert_len,
@@ -1395,8 +1319,8 @@ static void weld_poly_loop_ctx_setup(const MLoop *mloop,
* \{ */
static void weld_mesh_context_create(const Mesh *mesh,
- BVHTreeOverlap *overlap,
- const uint overlap_len,
+ uint *vert_dest_map,
+ const uint vert_kill_len,
WeldMesh *r_weld_mesh)
{
const MEdge *medge = mesh->medge;
@@ -1407,19 +1331,13 @@ static void weld_mesh_context_create(const Mesh *mesh,
const uint mloop_len = mesh->totloop;
const uint mpoly_len = mesh->totpoly;
- uint *vert_dest_map = MEM_mallocN(sizeof(*vert_dest_map) * mvert_len, __func__);
uint *edge_dest_map = MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__);
struct WeldGroup *v_links = MEM_callocN(sizeof(*v_links) * mvert_len, __func__);
WeldVert *wvert;
uint wvert_len;
- weld_vert_ctx_alloc_and_setup(mvert_len,
- overlap,
- overlap_len,
- vert_dest_map,
- &wvert,
- &wvert_len,
- &r_weld_mesh->vert_kill_len);
+ r_weld_mesh->vert_kill_len = vert_kill_len;
+ weld_vert_ctx_alloc_and_setup(mvert_len, vert_dest_map, &wvert, &wvert_len);
uint *edge_ctx_map;
WeldEdge *wedge;
@@ -1462,7 +1380,6 @@ static void weld_mesh_context_create(const Mesh *mesh,
&r_weld_mesh->edge_groups_buffer,
&r_weld_mesh->edge_groups);
- r_weld_mesh->vert_groups_map = vert_dest_map;
r_weld_mesh->edge_groups_map = edge_dest_map;
MEM_freeN(v_links);
MEM_freeN(wvert);
@@ -1474,7 +1391,6 @@ static void weld_mesh_context_free(WeldMesh *weld_mesh)
{
MEM_freeN(weld_mesh->vert_groups);
MEM_freeN(weld_mesh->vert_groups_buffer);
- MEM_freeN(weld_mesh->vert_groups_map);
MEM_freeN(weld_mesh->edge_groups);
MEM_freeN(weld_mesh->edge_groups_buffer);
@@ -1633,6 +1549,7 @@ static void customdata_weld(
/** \name Weld Modifier Main
* \{ */
+#ifdef USE_BVHTREEKDOP
struct WeldOverlapData {
const MVert *mvert;
float merge_dist_sq;
@@ -1648,6 +1565,7 @@ static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, in
}
return false;
}
+#endif
static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh)
{
@@ -1661,7 +1579,6 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
const MLoop *mloop;
const MPoly *mpoly, *mp;
uint totvert, totedge, totloop, totpoly;
- uint i;
mvert = mesh->mvert;
totvert = mesh->totvert;
@@ -1675,7 +1592,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0;
dv = &dvert[0];
v_mask = BLI_BITMAP_NEW(totvert, __func__);
- for (i = 0; i < totvert; i++, dv++) {
+ for (uint i = 0; i < totvert; i++, dv++) {
const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f;
if (found != invert_vgroup) {
BLI_BITMAP_ENABLE(v_mask, i);
@@ -1685,48 +1602,113 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
}
}
- /* Get overlap map. */
- /* TODO: For a better performanse use KD-Tree. */
- struct BVHTreeFromMesh treedata;
- BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata,
- mvert,
- totvert,
- false,
- v_mask,
- v_mask_act,
- wmd->merge_dist / 2,
- 2,
- 6,
- 0,
- NULL,
- NULL);
+ /* From the original index of the vertex.
+ * This indicates which vert it is or is going to be merged. */
+ uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__);
+ uint vert_kill_len = 0;
+#ifdef USE_BVHTREEKDOP
+ {
+ /* Get overlap map. */
+ struct BVHTreeFromMesh treedata;
+ BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata,
+ mvert,
+ totvert,
+ false,
+ v_mask,
+ v_mask_act,
+ wmd->merge_dist / 2,
+ 2,
+ 6,
+ 0,
+ NULL,
+ NULL);
+
+ if (bvhtree) {
+ struct WeldOverlapData data;
+ data.mvert = mvert;
+ data.merge_dist_sq = square_f(wmd->merge_dist);
+
+ uint overlap_len;
+ BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree,
+ bvhtree,
+ &overlap_len,
+ bvhtree_weld_overlap_cb,
+ &data,
+ 1,
+ BVH_OVERLAP_RETURN_PAIRS);
+
+ free_bvhtree_from_mesh(&treedata);
+ if (overlap) {
+ range_vn_u(vert_dest_map, totvert, 0);
+
+ const BVHTreeOverlap *overlap_iter = &overlap[0];
+ for (uint i = 0; i < overlap_len; i++, overlap_iter++) {
+ uint indexA = overlap_iter->indexA;
+ uint indexB = overlap_iter->indexB;
+
+ BLI_assert(indexA < indexB);
+
+ uint va_dst = vert_dest_map[indexA];
+ while (va_dst != vert_dest_map[va_dst]) {
+ va_dst = vert_dest_map[va_dst];
+ }
+ uint vb_dst = vert_dest_map[indexB];
+ while (vb_dst != vert_dest_map[vb_dst]) {
+ vb_dst = vert_dest_map[vb_dst];
+ }
+ if (va_dst == vb_dst) {
+ continue;
+ }
+ if (va_dst > vb_dst) {
+ SWAP(uint, va_dst, vb_dst);
+ }
+ vert_kill_len++;
+ vert_dest_map[vb_dst] = va_dst;
+ }
- if (v_mask) {
- MEM_freeN(v_mask);
- }
+ /* Fix #r_vert_dest_map for next step. */
+ for (uint i = 0; i < totvert; i++) {
+ if (i == vert_dest_map[i]) {
+ vert_dest_map[i] = OUT_OF_CONTEXT;
+ }
+ else {
+ uint v = i;
+ while (v != vert_dest_map[v] && vert_dest_map[v] != OUT_OF_CONTEXT) {
+ v = vert_dest_map[v];
+ }
+ vert_dest_map[v] = v;
+ vert_dest_map[i] = v;
+ }
+ }
- if (bvhtree == NULL) {
- return result;
+ MEM_freeN(overlap);
+ }
+ }
}
+#else
+ {
+ KDTree_3d *tree = BLI_kdtree_3d_new(v_mask ? v_mask_act : totvert);
+ for (uint i = 0; i < totvert; i++) {
+ if (!v_mask || BLI_BITMAP_TEST(v_mask, i)) {
+ BLI_kdtree_3d_insert(tree, i, mvert[i].co);
+ }
+ vert_dest_map[i] = OUT_OF_CONTEXT;
+ }
- struct WeldOverlapData data;
- data.mvert = mvert;
- data.merge_dist_sq = square_f(wmd->merge_dist);
-
- uint overlap_len;
- BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree,
- bvhtree,
- &overlap_len,
- bvhtree_weld_overlap_cb,
- &data,
- wmd->max_interactions,
- BVH_OVERLAP_RETURN_PAIRS);
+ BLI_kdtree_3d_balance(tree);
+ vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast(
+ tree, wmd->merge_dist, false, (int *)vert_dest_map);
+ BLI_kdtree_3d_free(tree);
+ }
+#endif
- free_bvhtree_from_mesh(&treedata);
+ if (v_mask) {
+ MEM_freeN(v_mask);
+ }
- if (overlap_len) {
+ if (vert_kill_len) {
WeldMesh weld_mesh;
- weld_mesh_context_create(mesh, overlap, overlap_len, &weld_mesh);
+ weld_mesh_context_create(mesh, vert_dest_map, vert_kill_len, &weld_mesh);
mloop = mesh->mloop;
mpoly = mesh->mpoly;
@@ -1745,10 +1727,10 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
/* Vertices */
- uint *vert_final = weld_mesh.vert_groups_map;
+ uint *vert_final = vert_dest_map;
uint *index_iter = &vert_final[0];
int dest_index = 0;
- for (i = 0; i < totvert; i++, index_iter++) {
+ for (uint i = 0; i < totvert; i++, index_iter++) {
int source_index = i;
int count = 0;
while (i < totvert && *index_iter == OUT_OF_CONTEXT) {
@@ -1783,7 +1765,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
uint *edge_final = weld_mesh.edge_groups_map;
index_iter = &edge_final[0];
dest_index = 0;
- for (i = 0; i < totedge; i++, index_iter++) {
+ for (uint i = 0; i < totedge; i++, index_iter++) {
int source_index = i;
int count = 0;
while (i < totedge && *index_iter == OUT_OF_CONTEXT) {
@@ -1831,7 +1813,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
uint r_i = 0;
int loop_cur = 0;
uint *group_buffer = BLI_array_alloca(group_buffer, weld_mesh.max_poly_len);
- for (i = 0; i < totpoly; i++, mp++) {
+ for (uint i = 0; i < totpoly; i++, mp++) {
int loop_start = loop_cur;
uint poly_ctx = weld_mesh.poly_map[i];
if (poly_ctx == OUT_OF_CONTEXT) {
@@ -1877,7 +1859,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
}
WeldPoly *wp = &weld_mesh.wpoly_new[0];
- for (i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) {
+ for (uint i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) {
int loop_start = loop_cur;
WeldLoopOfPolyIter iter;
if (!weld_iter_loop_of_poly_begin(
@@ -1918,7 +1900,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
weld_mesh_context_free(&weld_mesh);
}
- MEM_freeN(overlap);
+ MEM_freeN(vert_dest_map);
return result;
}
@@ -1932,9 +1914,9 @@ static void initData(ModifierData *md)
{
WeldModifierData *wmd = (WeldModifierData *)md;
- wmd->merge_dist = 0.001f;
- wmd->max_interactions = 1;
- wmd->defgrp_name[0] = '\0';
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
+
+ MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeldModifierData), modifier);
}
static void requiredDataMask(Object *UNUSED(ob),
@@ -1959,7 +1941,6 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE);
- uiItemR(layout, ptr, "max_interactions", 0, NULL, ICON_NONE);
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
modifier_panel_end(layout, ptr);
@@ -1974,10 +1955,12 @@ ModifierTypeInfo modifierType_Weld = {
/* name */ "Weld",
/* structName */ "WeldModifierData",
/* structSize */ sizeof(WeldModifierData),
+ /* srna */ &RNA_WeldModifier,
/* type */ eModifierTypeType_Constructive,
/* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping |
eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode |
eModifierTypeFlag_AcceptsCVs,
+ /* icon */ ICON_AUTOMERGE_OFF, /* TODO: Use correct icon. */
/* copyData */ BKE_modifier_copydata_generic,
@@ -1997,7 +1980,6 @@ ModifierTypeInfo modifierType_Weld = {
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
- /* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
/* freeRuntimeData */ NULL,