Page MenuHome

OpenVDB Voxel Remesher

Authored by Pablo Dobarro (pablodp606) on Aug 2 2019, 10:52 PM.
"Love" token, awarded by Draise."Love" token, awarded by Frozen_Death_Knight."Love" token, awarded by brilliant_ape."Like" token, awarded by belich."Love" token, awarded by dgsantana."Like" token, awarded by TheRedWaxPolice.



The voxel remesher introduces a new workflow for sculpting without any of the limitations of Dyntopo (no geometry errors or performance penalty when blocking shapes). It is also useful for simulations and 3D printing.

This patch includes:

  • Voxel remesh operator, voxel size mesh property and general remesh flags.
  • Paint mask reprojection.
  • Geometry undo/redo for sculpt mode. This should support remesh operations as well as future tools that modify the topology of the sculpt in a single step, like trimming tools or mesh insert brushes.
  • UI changes in the sculpt topbar and the mesh properties pannel.

Also, when Quadriflow is ready, it will share most of this code. We still need to think about how to integrate both methods in the UI.

This patch depends on D5364

Diff Detail

rB Blender

Event Timeline

Brecht Van Lommel (brecht) requested changes to this revision.Aug 13 2019, 6:28 PM

Quick review from reading through the code, did not actually test the functionality yet.


calloc -> malloc for both, slightly faster.


Don't copy, make a pointer: MVert *mvert = &mesh->mvert[i];


Also use pointer here.


Tessfaces can be removed here, they should be just for temporary conversion.


Private header files from other modules should not be used if it can be avoided.

Can whatever is used be exposed in ED_sculpt.h instead?


It's generally not needed to tests things again that were already checked in the poll function, it's guaranteed to run before exec.

CTX_wm_operator_poll_msg_set can be used to report the reason the operator is not available ahead of time in the tooltip, rather than when it executes.


Indentation seems uneven here.


This can be called right after BKE_mesh_nomain_to_mesh.


Voxel remesh -> Voxel Remesh


This description could explain better what the operator does and what it is for. Maybe it should also explain that all data layers will be lost.


gometry -> geometry


I think it would be better to make a nomain copy of the Mesh datablock, and then restore it with BKE_mesh_nomain_to_mesh.

It's not clear to me that just restoring the data layers is safe.


This should be initialized to a reasonable default for existing meshes in versioning_280.c and new meshes in mesh.c.


A proper range for something like this is hard to define since you don't know the mesh scale or what kind of units the scene is using.

The hard max should be FLT_MAX at least, I see no reason to limit that.


Description could be changed to explain how this relates to face size.

I wouldn't mention OpenVDB in descriptions at all, that seems like an implementation detail.


rna_Mesh_update_draw should be enough for this and the other two properties, no need to re-evaluate the modifier stack or dependency graph when these change.

This revision now requires changes to proceed.Aug 13 2019, 6:28 PM
Pablo Dobarro (pablodp606) marked 16 inline comments as done.
  • Update for revision

A few warnings to fix:

/home/brecht/dev/blender/source/blender/editors/sculpt_paint/sculpt_undo.c:429:52: warning: unused parameter 'C' [-Wunused-parameter]
static void sculpt_undo_geometry_restore(bContext *C,
/home/brecht/dev/blender/source/blender/editors/sculpt_paint/sculpt_undo.c:432:57: warning: unused parameter 'ss' [-Wunused-parameter]
                                         SculptSession *ss)
/home/brecht/dev/blender/source/blender/editors/sculpt_paint/sculpt_undo.c:770:11: warning: enumeration value 'SCULPT_UNDO_GEOMETRY' not handled in switch [-Wswitch]
  switch (type) {
/home/brecht/dev/blender/source/blender/editors/sculpt_paint/sculpt_undo.c:1042:11: warning: enumeration value 'SCULPT_UNDO_GEOMETRY' not handled in switch [-Wswitch]
  switch (type) {
4 warnings generated.
/home/brecht/dev/blender/intern/openvdb/intern/ warning: enumeration value 'OPENVDB_LEVELSET_FILTER_NONE' not handled in switch [-Wswitch]
  switch (filter_type) {
1 warning generated.

The code currently will not build when WITH_OPENVDB is OFF.

To fix that:

  • Put this chunk of code in a Mesh *BKE_remesh_to_mesh_nomain(Mesh *mesh, float voxel_size); function in remesh.c.
  • Then #ifdef WITH_OPENVDB all the code in remesh.c that uses the OpenVDB C API.
  • Let BKE_remesh_to_mesh_nomain return NULL when WITH_OPENVDB is OFF.
  • Remove OpenVB include and functions from BKE_remesh.h.

This should be changed to CD_MASK_MESH, which I believe will fix these messages that we have in the console now:

write_customdata error: layer '':7 - can't be written to file

A better name for this could be Preserve Paint Mask. Not sure users care that reprojection is involved.

But does this need to be an option at all, any reason to not always do it? I guess it can be a bit slow on high poly meshes.

Brecht Van Lommel (brecht) requested changes to this revision.Aug 14 2019, 4:45 PM

So in testing the tool, I think the user interface is fine.

If there is a way to improve the quality as hinted in D5364#124370, that would be good.

This isn't really surprising, but what I noticed is that when you keep clicking Voxel Remesh on e.g. the Suzanne mesh, it shrinks quite quickly. I'm not sure if there is a way to tweak the filters to be more volume preserving without being worse in other ways though.

This revision now requires changes to proceed.Aug 14 2019, 4:45 PM
Pablo Dobarro (pablodp606) marked 3 inline comments as done.
  • Fix warnings, fix build without OpenVDB

@Brecht Van Lommel (brecht) I'm not sure how that smoothing is done in the addon, I don't know if that is done in OpenVDB or if it is done with modifiers on top of the remesher result. I was thinking of adding a shrinkwrap to the previous mesh to avoid shrinking with high voxel sizes, but it may cause some geometry issues.
In the sculpt branch there is also a preserve vertex colors option. When these options are enabled the remesher is noticeable slower if the input is a high poly mesh. Maybe we want to keep the option in case some users wants to use this to fix a photo scanned model or use it for 3D printing.

A (single?) option to preserve as many data layers as possible could be good, I guess that would be a separate patch.

Maybe it's possible to reuse code from the data transfer operator for this. Or you could adapt that mask reprojection code and make it use generic CustomData_interp to support all types of data layers.

I have just a few further comments, which I trust you can fix before committing.


You can do this so the value does not get overwritten until the subversion bump:

if (mesh->voxel_size == 0.0f) {
  mesh->voxel_size = 0.1f;

Rename this to remesh_voxel_size in DNA too.


Rename to preserve in the property name too, for consistency.

This revision is now accepted and ready to land.Aug 14 2019, 6:02 PM
This revision was automatically updated to reflect the committed changes.
Pablo Dobarro (pablodp606) marked 3 inline comments as done.
Sybren A. Stüvel (sybren) added inline comments.

This segfaults when there is no active object. Same for the other use of ob->whatever below.

I have committed a quick fix in 8c0dea72b6791a07100487de556ab352106f7f44, as it breaks the F3 operator search.


should this have a return false; in there?