forked from bartvdbraak/blender
add vertex group option to decimate modifier, handy if you want to pin some parts of the geometry.
This commit is contained in:
parent
63f042250f
commit
3526ae9805
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user