[Bf-blender-cvs] [4d8b238e4bd] fracture_modifier: first attempt for better automerging
Martin Felke
noreply at git.blender.org
Thu Jun 8 01:15:48 CEST 2017
Commit: 4d8b238e4bdc15823419dcaa4f7b80a7002a6edb
Author: Martin Felke
Date: Thu Jun 8 01:15:16 2017 +0200
Branches: fracture_modifier
https://developer.blender.org/rB4d8b238e4bdc15823419dcaa4f7b80a7002a6edb
first attempt for better automerging
===================================================================
M source/blender/blenloader/intern/readfile.c
M source/blender/makesdna/DNA_modifier_types.h
M source/blender/modifiers/intern/MOD_fracture.c
===================================================================
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 54be9f0441f..f63cbe46d78 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5233,6 +5233,8 @@ static void load_fracture_modifier(FileData* fd, FractureModifierData *fmd)
fmd->visible_mesh = NULL;
fmd->dm = NULL;
fmd->visible_mesh_cached = NULL;
+ fmd->shared_verts.first = NULL;
+ fmd->shared_verts.last = NULL;
/*HARDCODING this for now, until we can version it properly, say with 2.75 ? */
if (fd->fileversion < 275) {
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 2280480dc2e..8705b1f0746 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1686,6 +1686,7 @@ typedef struct FractureModifierData {
MeshIslandSequence *current_mi_entry; /*analogous to current shard entry */
ListBase fracture_ids; /*volatile storage of shards being "hit" or fractured currently, needs to be cleaned up after usage! */
ListBase fracture_settings;
+ ListBase shared_verts;
int active_setting;
diff --git a/source/blender/modifiers/intern/MOD_fracture.c b/source/blender/modifiers/intern/MOD_fracture.c
index 58843b469e1..a7eac7135e3 100644
--- a/source/blender/modifiers/intern/MOD_fracture.c
+++ b/source/blender/modifiers/intern/MOD_fracture.c
@@ -93,6 +93,18 @@ static Shard* find_shard(ListBase *shards, ShardID id);
static void cleanup_arrange_shard(FractureModifierData *fmd, Shard *s, float cent[]);
static MeshIsland* find_meshisland(ListBase* meshIslands, int id);
static void do_halving(FractureModifierData *fmd, Object* ob, DerivedMesh *dm, DerivedMesh *orig_dm, bool is_prehalving, ShardID id);
+static void free_shared_verts(FractureModifierData* fmd);
+
+typedef struct SharedVertGroup {
+ struct SharedVertGroup* next, *prev;
+ int index;
+ ListBase verts;
+} SharedVertGroup;
+
+typedef struct SharedVert {
+ struct SharedVert* next, *prev;
+ int index;
+} SharedVert;
//TODO XXX Make BKE
static FracMesh* copy_fracmesh(FracMesh* fm)
@@ -459,6 +471,8 @@ static void free_modifier(FractureModifierData *fmd, bool do_free_seq, bool do_f
fmd->face_pairs = NULL;
}
+ free_shared_verts(fmd);
+
//called on deleting modifier, object or quitting blender...
//why was this necessary again ?!
if (fmd->dm) {
@@ -3185,6 +3199,50 @@ static void find_other_face(FractureModifierData *fmd, int i, BMesh* bm, Object*
}
}
+static void prepare_automerge(FractureModifierData *fmd, BMesh *bm)
+{
+ SharedVert *sv;
+ SharedVertGroup *vg;
+
+ for (vg = fmd->shared_verts.first; vg; vg = vg->next) {
+ BMVert* v1, *v2;
+ float co[3];
+ int verts = 0;
+
+ v1 = bm->vtable[vg->index];
+ copy_v3_v3(co, v1->co);
+ verts = 1;
+
+ //printf("Index: %d %d\n", vg->index, verts);
+ for (sv = vg->verts.first; sv; sv = sv->next)
+ {
+ v2 = bm->vtable[sv->index];
+ add_v3_v3(co, v2->co);
+ verts++;
+ //printf("Index2: %d\n", sv->index);
+ }
+
+ mul_v3_fl(co, 1.0f/(float)verts);
+ //print_v3("co", co);
+
+ verts = 0;
+
+ for (sv = vg->verts.first; sv; sv = sv->next)
+ {
+ v2 = bm->vtable[sv->index];
+ if (len_squared_v3v3(co, v2->co) <= fmd->automerge_dist * fmd->automerge_dist)
+ {
+ copy_v3_v3(v2->co, co);
+ }
+ }
+
+ if (len_squared_v3v3(co, v1->co) <= fmd->automerge_dist * fmd->automerge_dist)
+ {
+ copy_v3_v3(v1->co, co);
+ }
+ }
+}
+
static DerivedMesh *do_autoHide(FractureModifierData *fmd, DerivedMesh *dm, Object *ob)
{
int totpoly = dm->getNumPolys(dm);
@@ -3193,45 +3251,56 @@ static DerivedMesh *do_autoHide(FractureModifierData *fmd, DerivedMesh *dm, Obje
DerivedMesh *result;
BMFace **faces = MEM_mallocN(sizeof(BMFace *), "faces");
int del_faces = 0;
+ bool do_merge = false;
DM_to_bmesh_ex(dm, bm, true);
- BM_mesh_elem_index_ensure(bm, BM_FACE);
- BM_mesh_elem_table_ensure(bm, BM_FACE);
+ BM_mesh_elem_index_ensure(bm, BM_FACE | BM_VERT);
+ BM_mesh_elem_table_ensure(bm, BM_FACE | BM_VERT);
BM_mesh_elem_toolflags_ensure(bm);
BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE | BM_VERT , BM_ELEM_SELECT, false);
- for (i = 0; i < totpoly; i++) {
- find_other_face(fmd, i, bm, ob, &faces, &del_faces);
+ if (fmd->automerge_dist > 0)
+ {
+ //make vert groups together here, if vert is close enough
+ prepare_automerge(fmd, bm);
}
- for (i = 0; i < del_faces; i++) {
- BMFace *f = faces[i];
- if (f->l_first->e != NULL) { /* a lame check.... */
- BMIter iter;
- BMVert *v;
- BM_ITER_ELEM(v, &iter, f, BM_VERTS_OF_FACE)
- {
- BM_elem_flag_enable(v, BM_ELEM_SELECT);
- }
+ if (fmd->autohide_dist > 0 && fmd->face_pairs)
+ {
+ for (i = 0; i < totpoly; i++) {
+ find_other_face(fmd, i, bm, ob, &faces, &del_faces);
+ }
+
+ for (i = 0; i < del_faces; i++) {
+ BMFace *f = faces[i];
+ if (f->l_first->e != NULL) { /* a lame check.... */
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_ELEM(v, &iter, f, BM_VERTS_OF_FACE)
+ {
+ BM_elem_flag_enable(v, BM_ELEM_SELECT);
+ }
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ }
}
- }
- BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "delete_keep_normals geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES);
+ BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "delete_keep_normals geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES);
- if (del_faces == 0) {
- /*fallback if you want to merge verts but use no filling method, whose faces could be hidden (and you dont have any selection then) */
- BM_mesh_elem_hflag_enable_all(bm, BM_FACE | BM_EDGE | BM_VERT , BM_ELEM_SELECT, false);
+ if (del_faces == 0) {
+ /*fallback if you want to merge verts but use no filling method, whose faces could be hidden (and you dont have any selection then) */
+ BM_mesh_elem_hflag_enable_all(bm, BM_FACE | BM_EDGE | BM_VERT , BM_ELEM_SELECT, false);
+ }
}
- if (fmd->automerge_dist > 0) {
+ if (fmd->automerge_dist > 0 && do_merge) {
+
//separate this, because it costs performance and might not work so well with thin objects, but its useful for smooth objects
BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
"automerge_keep_normals verts=%hv dist=%f", BM_ELEM_SELECT,
- fmd->automerge_dist); /*need to merge larger cracks*/
+ 0.001f); /*need to merge larger cracks*/
if (fmd->fix_normals) {
/* dissolve sharp edges with limit dissolve
@@ -3668,13 +3737,14 @@ static DerivedMesh *output_dm(FractureModifierData* fmd, DerivedMesh *dm, Object
}
}
- if (fmd->autohide_dist > 0 && fmd->face_pairs) {
+ if (fmd->autohide_dist > 0 || fmd->automerge_dist > 0) {
//printf("Autohide \n");
dm_final = do_autoHide(fmd, fmd->visible_mesh_cached, ob);
}
else {
dm_final = CDDM_copy(fmd->visible_mesh_cached);
}
+
return dm_final;
}
else {
@@ -3784,6 +3854,113 @@ static void do_refresh_constraints(FractureModifierData *fmd, Object *ob)
printf("Constraints: %d\n", BLI_listbase_count(&fmd->meshConstraints));
}
+static void make_shared_vert_groups(FractureModifierData* fmd, DerivedMesh* dm)
+{
+ /* make kdtree of all verts of dm, then find closest(rangesearch) verts for each vert*/
+ MVert* mvert = dm->getVertArray(dm), *mv = NULL;
+ int totvert = dm->getNumVerts(dm);
+ KDTree *tree = BLI_kdtree_new(totvert);
+ GHash* visit = BLI_ghash_int_new("visited_verts");
+ int i = 0;
+
+ //printf("Make Face Pairs\n");
+ int groups = 0;
+
+ for (i = 0, mv = mvert; i < totvert; mv++, i++) {
+ BLI_kdtree_insert(tree, i, mv->co);
+ }
+
+ BLI_kdtree_balance(tree);
+
+ /*now find groups of close verts*/
+
+ for (i = 0, mv = mvert; i < totvert; mv++, i++) {
+ int index = -1, j = 0, r = 0;
+ KDTreeNearest *n = NULL;
+
+ r = BLI_kdtree_range_search(tree, mv->co, &n, fmd->autohide_dist);
+ /*2nd nearest means not ourselves...*/
+
+ if (r > 1) {
+ SharedVertGroup *gvert = MEM_mallocN(sizeof(SharedVertGroup), "sharedVertGroup");
+ gvert->index = i;
+ gvert->verts.first = NULL;
+ gvert->verts.last = NULL;
+
+ for (j = 1; j < r; j++)
+ {
+ index = n[j].index;
+ if (!BLI_ghash_haskey(visit, SET_INT_IN_POINTER(i)))
+ {
+ BLI_ghash_insert(visit, SET_INT_IN_POINTER(index), SET_INT_IN_POINTER(i));
+
+ SharedVert *svert = MEM_mallocN(sizeof(SharedVert), "sharedVert");
+ svert->index = index;
+ BLI_addtail(&gvert->verts, svert);
+ }
+ }
+
+ if (gvert->verts.first != NULL)
+ {
+ BLI_addtail(&fmd->shared_verts, gvert);
+ groups++;
+ }
+ else {
+ MEM_freeN(gvert);
+ }
+ }
+
+ if (n != NULL) {
+ MEM_freeN(n);
+ }
+ }
+
+ printf("shared vert groups: %d\n", groups);
+ BLI_ghash_free(visit, NULL, NULL);
+ BLI_kdtree_free(tree);
+}
+
+static void free_shared_verts(FractureModifierData* fmd)
+{
+ SharedVertGroup *vg;
+ SharedVert *sv;
+
+ while (fmd->shared_verts.first)
+ {
+ vg = fmd->shared_verts.first;
+ BLI_remlink(&fmd->shared_verts, vg);
+ while (vg->verts.first) {
+ sv = vg->verts.first;
+ BLI_remlink(&vg->verts, sv);
+ MEM_freeN(sv);
+ }
+ MEM_freeN(vg);
+ }
+
+ fmd->shared_verts.first = NULL;
+ fmd->shared_verts.last = NULL;
+}
+
+static void do_refresh_automerge(FractureModifierData* fmd, Object *ob)
+{
+ free_shared_verts(fmd);
+
+ /* in case of re-using existing islands this one might become invalid for automerge, so force fallback */
+ if (fmd->dm && fmd->dm->getNumVerts(fmd->dm) > 0)
+ {
+ make_shared_vert_groups(fmd, fmd->dm);
+ }
+ else if (fmd->visible_mesh)
+ {
+ DerivedMesh *fdm = CDDM_from_bmesh(fmd->visible_mesh, true);
+ make_shared_vert_groups(fmd, fdm);
+
+ fdm->needsFree = 1;
+ fdm->release(fdm);
+ fdm = NULL;
+ }
+}
+
static void do_refresh_autohide(FractureModifierData *fmd, Object *ob)
{
fmd->refresh_autohide = false;
@@ -3976,6 +4153,8 @@ static DerivedMesh *doSimulate(FractureModifierData *fmd, Object *ob, DerivedMes
i++;
}
}
+
+ //do_refresh_automerge(fmd, ob);
}
if (old_cached) {
@@ -3990,6 +4169,7 @@ static DerivedMesh *doSimulate(FractureModifierData *fmd, Object *ob, DerivedMes
if (fmd->refresh_au
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list