[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51520] trunk/blender: add un-subdivude as an optional method for the decimate modifier, gives more even geometry & nicer results in some cases.
Campbell Barton
ideasman42 at gmail.com
Tue Oct 23 06:26:41 CEST 2012
Revision: 51520
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51520
Author: campbellbarton
Date: 2012-10-23 04:26:39 +0000 (Tue, 23 Oct 2012)
Log Message:
-----------
add un-subdivude as an optional method for the decimate modifier, gives more even geometry & nicer results in some cases.
Modified Paths:
--------------
trunk/blender/release/scripts/startup/bl_ui/properties_data_modifier.py
trunk/blender/source/blender/bmesh/CMakeLists.txt
trunk/blender/source/blender/bmesh/intern/bmesh_decimate.h
trunk/blender/source/blender/bmesh/intern/bmesh_decimate_collapse.c
trunk/blender/source/blender/bmesh/operators/bmo_unsubdivide.c
trunk/blender/source/blender/makesdna/DNA_modifier_types.h
trunk/blender/source/blender/makesdna/intern/makesdna.c
trunk/blender/source/blender/makesrna/intern/rna_modifier.c
trunk/blender/source/blender/modifiers/intern/MOD_decimate.c
Added Paths:
-----------
trunk/blender/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
Modified: trunk/blender/release/scripts/startup/bl_ui/properties_data_modifier.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/properties_data_modifier.py 2012-10-23 03:45:35 UTC (rev 51519)
+++ trunk/blender/release/scripts/startup/bl_ui/properties_data_modifier.py 2012-10-23 04:26:39 UTC (rev 51520)
@@ -211,10 +211,17 @@
layout.row().prop(md, "deform_axis", expand=True)
def DECIMATE(self, layout, ob, md):
- layout.prop(md, "ratio")
row = layout.row()
- row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- row.prop(md, "invert_vertex_group")
+ row.prop(md, "decimate_type", expand=True)
+
+ if md.decimate_type == 'COLLAPSE':
+ layout.prop(md, "ratio")
+ row = layout.row()
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex_group")
+ else: # assume UNSUBDIV
+ layout.prop(md, "iterations")
+
layout.label(text="Face Count" + ": %d" % md.face_count)
def DISPLACE(self, layout, ob, md):
Modified: trunk/blender/source/blender/bmesh/CMakeLists.txt
===================================================================
--- trunk/blender/source/blender/bmesh/CMakeLists.txt 2012-10-23 03:45:35 UTC (rev 51519)
+++ trunk/blender/source/blender/bmesh/CMakeLists.txt 2012-10-23 04:26:39 UTC (rev 51520)
@@ -65,6 +65,7 @@
intern/bmesh_core.c
intern/bmesh_core.h
intern/bmesh_decimate_collapse.c
+ intern/bmesh_decimate_unsubdivide.c
intern/bmesh_decimate.h
intern/bmesh_inline.h
intern/bmesh_interp.c
Modified: trunk/blender/source/blender/bmesh/intern/bmesh_decimate.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_decimate.h 2012-10-23 03:45:35 UTC (rev 51519)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_decimate.h 2012-10-23 04:26:39 UTC (rev 51520)
@@ -29,4 +29,7 @@
void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights);
+void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only);
+void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations);
+
#endif /* __BMESH_DECIMATE_H__ */
Modified: trunk/blender/source/blender/bmesh/intern/bmesh_decimate_collapse.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_decimate_collapse.c 2012-10-23 03:45:35 UTC (rev 51519)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_decimate_collapse.c 2012-10-23 04:26:39 UTC (rev 51520)
@@ -20,10 +20,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/bmesh/intern/bmesh_decimate.c
+/** \file blender/bmesh/intern/bmesh_decimate_collapse.c
* \ingroup bmesh
*
- * BMesh decimator.
+ * BMesh decimator that uses an edge collapse method.
*/
#include <stddef.h>
Added: trunk/blender/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c (rev 0)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c 2012-10-23 04:26:39 UTC (rev 51520)
@@ -0,0 +1,342 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/intern/bmesh_decimate_unsubdivide.c
+ * \ingroup bmesh
+ *
+ * BMesh decimator that uses a grid un-subdivide method.
+ */
+
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+
+static int bm_vert_dissolve_fan_test(BMVert *v)
+{
+ /* check if we should walk over these verts */
+ BMIter iter;
+ BMEdge *e;
+
+ unsigned int tot_edge = 0;
+ unsigned int tot_edge_boundary = 0;
+ unsigned int tot_edge_manifold = 0;
+ unsigned int tot_edge_wire = 0;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ tot_edge_boundary++;
+ }
+ else if (BM_edge_is_manifold(e)) {
+ tot_edge_manifold++;
+ }
+ else if (BM_edge_is_wire(e)) {
+ tot_edge_wire++;
+ }
+ tot_edge++;
+ }
+
+ if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) {
+ return TRUE;
+ }
+ else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) {
+ return TRUE;
+ }
+ else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) {
+ return TRUE;
+ }
+ else if ((tot_edge == 2) && (tot_edge_wire == 2)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
+{
+ /* collapse under 2 conditions.
+ * - vert connects to 4 manifold edges (and 4 faces).
+ * - vert connecrs to 1 manifold edge, 2 boundary edges (and 2 faces).
+ *
+ * This covers boundary verts of a quad grid and center verts.
+ * note that surrounding faces dont have to be quads.
+ */
+
+ BMIter iter;
+ BMEdge *e;
+
+ unsigned int tot_loop = 0;
+ unsigned int tot_edge = 0;
+ unsigned int tot_edge_boundary = 0;
+ unsigned int tot_edge_manifold = 0;
+ unsigned int tot_edge_wire = 0;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ tot_edge_boundary++;
+ }
+ else if (BM_edge_is_manifold(e)) {
+ tot_edge_manifold++;
+ }
+ else if (BM_edge_is_wire(e)) {
+ tot_edge_wire++;
+ }
+ tot_edge++;
+ }
+
+ if (tot_edge == 2) {
+ /* check for 2 wire verts only */
+ if (tot_edge_wire == 2) {
+ return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
+ }
+ }
+ else if (tot_edge == 4) {
+ /* check for 4 faces surrounding */
+ if (tot_edge_boundary == 0 && tot_edge_manifold == 4) {
+ /* good to go! */
+ tot_loop = 4;
+ }
+ }
+ else if (tot_edge == 3) {
+ /* check for 2 faces surrounding at a boundary */
+ if (tot_edge_boundary == 2 && tot_edge_manifold == 1) {
+ /* good to go! */
+ tot_loop = 2;
+ }
+ else if (tot_edge_boundary == 0 && tot_edge_manifold == 3) {
+ /* good to go! */
+ tot_loop = 3;
+ }
+ }
+
+ if (tot_loop) {
+ BMLoop *f_loop[4];
+ unsigned int i;
+
+ /* ensure there are exactly tot_loop loops */
+ BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL);
+ BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)f_loop, tot_loop);
+
+ for (i = 0; i < tot_loop; i++) {
+ BMLoop *l = f_loop[i];
+ if (l->f->len > 3) {
+ BLI_assert(l->prev->v != l->next->v);
+ BM_face_split(bm, l->f, l->prev->v, l->next->v, NULL, NULL, TRUE);
+ }
+ }
+
+ return BM_vert_dissolve(bm, v);
+ }
+
+ return FALSE;
+}
+
+enum {
+ VERT_INDEX_DO_COLLAPSE = -1,
+ VERT_INDEX_INIT = 0,
+ VERT_INDEX_IGNORE = 1
+};
+
+// #define USE_WALKER /* gives uneven results, disable for now */
+
+/* - BMVert.flag & BM_ELEM_TAG: shows we touched this vert
+ * - BMVert.index == -1: shows we will remove this vert
+ */
+
+/**
+ * \param tag_only so we can call this from an operator */
+void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only)
+{
+#ifdef USE_WALKER
+# define ELE_VERT_TAG 1
+#else
+ BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
+ BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
+ unsigned vert_seek_a_tot = 0;
+ unsigned vert_seek_b_tot = 0;
+#endif
+
+ BMVert *v;
+ BMIter iter;
+
+ const unsigned int offset = 0;
+ const unsigned int nth = 2;
+
+ int iter_step;
+
+ /* if tag_only is set, we assyme the caller knows what verts to tag
+ * needed for the operator */
+ if (tag_only == FALSE) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ }
+
+ for (iter_step = 0; iter_step < iterations; iter_step++) {
+ int iter_done;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) {
+#ifdef USE_WALKER
+ BMO_elem_flag_enable(bm, v, ELE_VERT_TAG);
+#endif
+ BM_elem_index_set(v, VERT_INDEX_INIT); /* set_dirty! */
+ }
+ else {
+ BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
+ }
+ }
+ /* done with selecting tagged verts */
+
+
+ /* main loop, keep tagging until we can't tag any more islands */
+ while (TRUE) {
+#ifdef USE_WALKER
+ BMWalker walker;
+#else
+ unsigned int depth = 1;
+ unsigned int i;
+#endif
+ BMVert *v_first = NULL;
+ BMVert *v;
+
+ /* we could avoid iterating from the start each time */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (v->e && (BM_elem_index_get(v) == VERT_INDEX_INIT)) {
+#ifdef USE_WALKER
+ if (BMO_elem_flag_test(bm, v, ELE_VERT_TAG))
+#endif
+ {
+ /* check again incase the topology changed */
+ if (bm_vert_dissolve_fan_test(v)) {
+ v_first = v;
+ }
+ break;
+ }
+ }
+ }
+ if (v_first == NULL) {
+ break;
+ }
+
+#ifdef USE_WALKER
+ /* Walk over selected elements starting at active */
+ BMW_init(&walker, bm, BMW_CONNECTED_VERTEX,
+ ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP,
+ BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
+ BMW_NIL_LAY);
+
+ BLI_assert(walker.order == BMW_BREADTH_FIRST);
+ for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) {
+ /* Deselect elements that aren't at "nth" depth from active */
+ if (BM_elem_index_get(v) == VERT_INDEX_INIT) {
+ if ((offset + BMW_current_depth(&walker)) % nth) {
+ /* tag for removal */
+ BM_elem_index_set(v, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
+ }
+ else {
+ /* works better to allow these verts to be checked again */
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list