Add Voxel Mode to the Remesh modifier

This adds the Voxel Mode to the current remesh modifier. It works
exactly the same way as the voxel remesh operator and uses the same
properties to control the remeshing. We can exand this with more options
in the future (fix poles, reprojection...)

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D7292
This commit is contained in:
Pablo Dobarro 2020-03-31 17:06:17 +02:00
parent 38685b5a39
commit 6c036a65c9
5 changed files with 101 additions and 37 deletions

View File

@ -1317,17 +1317,22 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.prop(md, "mode")
row = layout.row()
row.prop(md, "octree_depth")
row.prop(md, "scale")
if md.mode == 'VOXEL':
layout.prop(md, "voxel_size")
layout.prop(md, "adaptivity")
else:
row.prop(md, "octree_depth")
row.prop(md, "scale")
if md.mode == 'SHARP':
layout.prop(md, "sharpness")
if md.mode == 'SHARP':
layout.prop(md, "sharpness")
layout.prop(md, "use_remove_disconnected")
row = layout.row()
row.active = md.use_remove_disconnected
row.prop(md, "threshold")
layout.prop(md, "use_smooth_shade")
layout.prop(md, "use_remove_disconnected")
row = layout.row()
row.active = md.use_remove_disconnected
row.prop(md, "threshold")
@staticmethod
def vertex_weight_mask(layout, ob, md):

View File

@ -4878,5 +4878,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
/* Remesh Modifier Voxel Mode. */
if (!DNA_struct_elem_find(fd->filesdna, "RemeshModifierData", "float", "voxel_size")) {
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Remesh) {
RemeshModifierData *rmd = (RemeshModifierData *)md;
rmd->voxel_size = 0.1f;
rmd->adaptivity = 0.0f;
}
}
}
}
}
}

View File

@ -1608,6 +1608,8 @@ typedef enum eRemeshModifierMode {
MOD_REMESH_MASS_POINT = 1,
/* keeps sharp edges */
MOD_REMESH_SHARP_FEATURES = 2,
/* Voxel remesh */
MOD_REMESH_VOXEL = 3,
} eRemeshModifierMode;
typedef struct RemeshModifierData {
@ -1623,10 +1625,13 @@ typedef struct RemeshModifierData {
/* octree depth */
char depth;
char flag;
char mode;
char _pad;
/* OpenVDB Voxel remesh properties. */
float voxel_size;
float adaptivity;
} RemeshModifierData;
/* Skin modifier */

View File

@ -5128,6 +5128,11 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
0,
"Sharp",
"Output a surface that reproduces sharp edges and corners from the input mesh"},
{MOD_REMESH_VOXEL,
"VOXEL",
0,
"Voxel",
"Output a mesh corresponding to the volume of the original mesh"},
{0, NULL, 0, NULL, NULL},
};
@ -5181,6 +5186,25 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
"edges closer to the input");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "voxel_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "voxel_size");
RNA_def_property_ui_range(prop, 0.0001, 2, 0.1, 3);
RNA_def_property_ui_text(prop,
"Voxel Size",
"Size of the voxel in object space used for volume evaluation. Lower "
"values preserve finer details");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "adaptivity", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "adaptivity");
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
RNA_def_property_ui_text(
prop,
"Adaptivity",
"Reduces the final face count by simplifying geometry where detail is not needed, "
"generating triangles. A value greater than 0 disables Fix Poles");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_remove_disconnected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_REMESH_FLOOD_FILL);
RNA_def_property_ui_text(prop, "Remove Disconnected Pieces", "");

View File

@ -34,6 +34,7 @@
#include "MOD_modifiertypes.h"
#include "BKE_mesh.h"
#include "BKE_mesh_remesh_voxel.h"
#include "BKE_mesh_runtime.h"
#include <assert.h>
@ -54,8 +55,10 @@ static void initData(ModifierData *md)
rmd->depth = 4;
rmd->hermite_num = 1;
rmd->flag = MOD_REMESH_FLOOD_FILL;
rmd->mode = MOD_REMESH_SHARP_FEATURES;
rmd->mode = MOD_REMESH_VOXEL;
rmd->threshold = 1;
rmd->voxel_size = 0.1f;
rmd->adaptivity = 0.0f;
}
#ifdef WITH_MOD_REMESH
@ -144,37 +147,51 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(c
rmd = (RemeshModifierData *)md;
init_dualcon_mesh(&input, mesh);
if (rmd->flag & MOD_REMESH_FLOOD_FILL) {
flags |= DUALCON_FLOOD_FILL;
if (rmd->mode == MOD_REMESH_VOXEL) {
/* OpenVDB modes. */
if (rmd->voxel_size == 0.0f) {
return NULL;
}
result = BKE_mesh_remesh_voxel_to_mesh_nomain(mesh, rmd->voxel_size, rmd->adaptivity, 0.0f);
}
else {
/* Dualcon modes. */
init_dualcon_mesh(&input, mesh);
switch (rmd->mode) {
case MOD_REMESH_CENTROID:
mode = DUALCON_CENTROID;
break;
case MOD_REMESH_MASS_POINT:
mode = DUALCON_MASS_POINT;
break;
case MOD_REMESH_SHARP_FEATURES:
mode = DUALCON_SHARP_FEATURES;
break;
if (rmd->flag & MOD_REMESH_FLOOD_FILL) {
flags |= DUALCON_FLOOD_FILL;
}
switch (rmd->mode) {
case MOD_REMESH_CENTROID:
mode = DUALCON_CENTROID;
break;
case MOD_REMESH_MASS_POINT:
mode = DUALCON_MASS_POINT;
break;
case MOD_REMESH_SHARP_FEATURES:
mode = DUALCON_SHARP_FEATURES;
break;
case MOD_REMESH_VOXEL:
/* Should have been processed before as an OpenVDB operation. */
BLI_assert(false);
break;
}
output = dualcon(&input,
dualcon_alloc_output,
dualcon_add_vert,
dualcon_add_quad,
flags,
mode,
rmd->threshold,
rmd->hermite_num,
rmd->scale,
rmd->depth);
result = output->mesh;
MEM_freeN(output);
}
output = dualcon(&input,
dualcon_alloc_output,
dualcon_add_vert,
dualcon_add_quad,
flags,
mode,
rmd->threshold,
rmd->hermite_num,
rmd->scale,
rmd->depth);
result = output->mesh;
MEM_freeN(output);
if (rmd->flag & MOD_REMESH_SMOOTH_SHADING) {
MPoly *mpoly = result->mpoly;
int i, totpoly = result->totpoly;