add vertex group option to decimate modifier, handy if you want to pin some parts of the geometry.

This commit is contained in:
Campbell Barton 2012-10-22 15:39:06 +00:00
parent 63f042250f
commit 3526ae9805
7 changed files with 134 additions and 25 deletions

@ -212,6 +212,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
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")
layout.label(text="Face Count" + ": %d" % md.face_count)
def DISPLACE(self, layout, ob, md):

@ -144,7 +144,7 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3],
}
static void bm_decim_build_edge_cost_single(BMEdge *e,
const Quadric *vquadrics,
const Quadric *vquadrics, const float *vweights,
Heap *eheap, HeapNode **eheap_table)
{
const Quadric *q1, *q2;
@ -180,6 +180,16 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
eheap_table[BM_elem_index_get(e)] = NULL;
return;
}
if (vweights) {
if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) &&
(vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON))
{
/* skip collapsing this edge */
eheap_table[BM_elem_index_get(e)] = NULL;
return;
}
}
/* end sanity check */
@ -188,14 +198,21 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
q1 = &vquadrics[BM_elem_index_get(e->v1)];
q2 = &vquadrics[BM_elem_index_get(e->v2)];
cost = (BLI_quadric_evaluate(q1, optimize_co) + BLI_quadric_evaluate(q2, optimize_co));
if (vweights == NULL) {
cost = (BLI_quadric_evaluate(q1, optimize_co) +
BLI_quadric_evaluate(q2, optimize_co));
}
else {
cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) +
(BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)]));
}
// print("COST %.12f\n");
eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e);
}
static void bm_decim_build_edge_cost(BMesh *bm,
const Quadric *vquadrics,
const Quadric *vquadrics, const float *vweights,
Heap *eheap, HeapNode **eheap_table)
{
BMIter iter;
@ -204,7 +221,7 @@ static void bm_decim_build_edge_cost(BMesh *bm,
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
eheap_table[i] = NULL; /* keep sanity check happy */
bm_decim_build_edge_cost_single(e, vquadrics, eheap, eheap_table);
bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table);
#ifdef USE_PRESERVE_BOUNDARY
/* init: runs second! */
@ -268,15 +285,16 @@ static int bm_decim_triangulate_begin(BMesh *bm)
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (f->len == 4) {
BMLoop *f_l[4];
BMLoop *l_iter;
BMLoop *l_a, *l_b;
l_iter = BM_FACE_FIRST_LOOP(f);
{
BMLoop *l_iter = BM_FACE_FIRST_LOOP(f);
f_l[0] = l_iter; l_iter = l_iter->next;
f_l[1] = l_iter; l_iter = l_iter->next;
f_l[2] = l_iter; l_iter = l_iter->next;
f_l[3] = l_iter; l_iter = l_iter->next;
f_l[0] = l_iter; l_iter = l_iter->next;
f_l[1] = l_iter; l_iter = l_iter->next;
f_l[2] = l_iter; l_iter = l_iter->next;
f_l[3] = l_iter;
}
if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) <
len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co))
@ -764,7 +782,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
/* collapse e the edge, removing e->v2 */
static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
Quadric *vquadrics,
Quadric *vquadrics, float *vweights,
Heap *eheap, HeapNode **eheap_table,
const CD_UseFlag customdata_flag)
{
@ -796,6 +814,12 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
/* update collapse info */
int i;
if (vweights) {
const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f);
vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) +
(vweights[BM_elem_index_get(v_other)] * fac);
}
e = NULL; /* paranoid safety check */
copy_v3_v3(v_other->co, optimize_co);
@ -825,7 +849,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
e_iter = e_first = v_other->e;
do {
BLI_assert(BM_edge_find_double(e_iter) == NULL);
bm_decim_build_edge_cost_single(e_iter, vquadrics, eheap, eheap_table);
bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table);
} while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first);
}
@ -857,7 +881,14 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
/* Main Decimate Function
* ********************** */
void BM_mesh_decimate(BMesh *bm, const float factor)
/**
* \brief BM_mesh_decimate
* \param bm The mesh
* \param factor face count multiplier [0 - 1]
* \param vertex_weights Optional array of vertex aligned weights [0 - 1],
* a vertex group is the usual source for this.
*/
void BM_mesh_decimate(BMesh *bm, const float factor, float *vweights)
{
Heap *eheap; /* edge heap */
HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
@ -885,7 +916,7 @@ void BM_mesh_decimate(BMesh *bm, const float factor)
/* build initial edge collapse cost data */
bm_decim_build_quadrics(bm, vquadrics);
bm_decim_build_edge_cost(bm, vquadrics, eheap, eheap_table);
bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table);
face_tot_target = bm->totface * factor;
bm->elem_index_dirty |= BM_FACE | BM_EDGE | BM_VERT;
@ -910,7 +941,7 @@ void BM_mesh_decimate(BMesh *bm, const float factor)
* but NULL just incase so we don't use freed node */
eheap_table[BM_elem_index_get(e)] = NULL;
bm_decim_edge_collapse(bm, e, vquadrics, eheap, eheap_table, customdata_flag);
bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag);
}

@ -27,6 +27,6 @@
* \ingroup bmesh
*/
void BM_mesh_decimate(BMesh *bm, const float factor);
void BM_mesh_decimate(BMesh *bm, const float factor, float *vweights);
#endif /* __BMESH_DECIMATE_H__ */

@ -362,9 +362,16 @@ typedef struct DecimateModifierData {
ModifierData modifier;
float percent;
int faceCount;
int faceCount; /* runtime only */
char defgrp_name[64]; /* MAX_VGROUP_NAME */
int flag, pad;
} DecimateModifierData;
enum {
MOD_DECIM_INVERT_VGROUP = (1 << 0)
};
/* Smooth modifier flags */
#define MOD_SMOOTH_X (1<<1)
#define MOD_SMOOTH_Y (1<<2)

@ -377,6 +377,12 @@ static void rna_SolidifyModifier_vgroup_set(PointerRNA *ptr, const char *value)
rna_object_vgroup_name_set(ptr, value, smd->defgrp_name, sizeof(smd->defgrp_name));
}
static void rna_DecimateModifier_vgroup_set(PointerRNA *ptr, const char *value)
{
DecimateModifierData *dmd = (DecimateModifierData *)ptr->data;
rna_object_vgroup_name_set(ptr, value, dmd->defgrp_name, sizeof(dmd->defgrp_name));
}
static void rna_WeightVGModifier_vgroup_set(PointerRNA *ptr, const char *value)
{
ModifierData *md = (ModifierData *)ptr->data;
@ -1119,6 +1125,17 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Ratio", "Ratio of triangles to reduce to");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DecimateModifier_vgroup_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "face_count", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "faceCount");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);

@ -32,9 +32,10 @@
* \ingroup modifiers
*/
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
@ -43,6 +44,7 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
#include "BKE_particle.h"
#include "BKE_cdderivedmesh.h"
@ -70,9 +72,22 @@ static void copyData(ModifierData *md, ModifierData *target)
DecimateModifierData *tdmd = (DecimateModifierData *) target;
tdmd->percent = dmd->percent;
BLI_strncpy(tdmd->defgrp_name, dmd->defgrp_name, sizeof(tdmd->defgrp_name));
tdmd->flag = dmd->flag;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
DecimateModifierData *dmd = (DecimateModifierData *) md;
CustomDataMask dataMask = 0;
/* ask for vertexgroups if we need them */
if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
return dataMask;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
@ -81,6 +96,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
BMEditMesh *em;
BMesh *bm;
float *vweights = NULL;
#ifdef USE_TIMEIT
TIMEIT_START(decim);
#endif
@ -93,10 +110,40 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
return dm;
}
if (dmd->defgrp_name[0]) {
MDeformVert *dvert;
int defgrp_index;
modifier_get_vgroup(ob, dm, dmd->defgrp_name, &dvert, &defgrp_index);
if (dvert) {
const unsigned int vert_tot = dm->getNumVerts(dm);
unsigned int i;
vweights = MEM_mallocN(vert_tot * sizeof(float), __func__);
if (dmd->flag & MOD_DECIM_INVERT_VGROUP) {
for (i = 0; i < vert_tot; i++) {
vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index);
}
}
else {
for (i = 0; i < vert_tot; i++) {
vweights[i] = defvert_find_weight(&dvert[i], defgrp_index);
}
}
}
}
em = DM_to_editbmesh(dm, NULL, FALSE);
bm = em->bm;
BM_mesh_decimate(bm, dmd->percent);
BM_mesh_decimate(bm, dmd->percent, vweights);
if (vweights) {
MEM_freeN(vweights);
}
dmd->faceCount = bm->totface;
@ -126,7 +173,7 @@ ModifierTypeInfo modifierType_Decimate = {
/* applyModifier */ applyModifier,
/* applyModifierEM */ NULL,
/* initData */ initData,
/* requiredDataMask */ NULL,
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
/* updateDepgraph */ NULL,

@ -42,10 +42,14 @@ struct TexResult;
void modifier_init_texture(struct Scene *scene, struct Tex *texture);
void get_texture_value(struct Tex *texture, float *tex_co, struct TexResult *texres);
void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, float (*co)[3], float (*texco)[3], int numVerts);
void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm,
float (*co)[3], float (*texco)[3], int numVerts);
void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]);
struct DerivedMesh *get_cddm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3]);
struct DerivedMesh *get_dm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int orco);
void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm, const char *name, struct MDeformVert **dvert, int *defgrp_index);
struct DerivedMesh *get_cddm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm,
float (*vertexCos)[3]);
struct DerivedMesh *get_dm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm,
float (*vertexCos)[3], int orco);
void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm,
const char *name, struct MDeformVert **dvert, int *defgrp_index);
#endif /* __MOD_UTIL_H__ */