Commit: e2f23d91b989e05ff743260d18c85a17f78439a9 Author: Pablo Dobarro Date: Thu Mar 14 21:54:27 2019 +0100 Branches: sculpt-mode-features https://developer.blender.org/rBe2f23d91b989e05ff743260d18c85a17f78439a9
OpenVDB Voxel remesher: Initial implementation This introduces a new workflow for sculpting. The voxel remesher works with Dyntopo disabled. The user needs to run it manually once he/she considers that the topology is too stretched to continue sculpting normally. OpenVDB evaluates the mesh volume as a level set with a given voxel size and it always outputs an all quads manifold mesh. It automatically solves self-intersections and geometry errors produced by booleans, which Dyntopo can't solve right now. Once the new mesh is calculated, the user can continue sculpting without the overhead of having Dyntopo enabled. It still needs a proper UI and it has some issues. Undo is not working on a remeshed object. =================================================================== M intern/openvdb/CMakeLists.txt A intern/openvdb/intern/openvdb_level_set.cc A intern/openvdb/intern/openvdb_level_set.h M intern/openvdb/openvdb_capi.cc M intern/openvdb/openvdb_capi.h M source/blender/editors/object/CMakeLists.txt M source/blender/editors/object/object_edit.c M source/blender/editors/object/object_intern.h M source/blender/editors/object/object_ops.c =================================================================== diff --git a/intern/openvdb/CMakeLists.txt b/intern/openvdb/CMakeLists.txt index ddec43f30a3..c231099bb03 100644 --- a/intern/openvdb/CMakeLists.txt +++ b/intern/openvdb/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC . intern + ../guardedalloc ) set(INC_SYS @@ -53,12 +54,14 @@ if(WITH_OPENVDB) intern/openvdb_dense_convert.cc intern/openvdb_reader.cc intern/openvdb_writer.cc + intern/openvdb_level_set.cc openvdb_capi.cc openvdb_util.cc intern/openvdb_dense_convert.h intern/openvdb_reader.h intern/openvdb_writer.h + intern/openvdb_level_set.h openvdb_util.h ) diff --git a/intern/openvdb/intern/openvdb_level_set.cc b/intern/openvdb/intern/openvdb_level_set.cc new file mode 100644 index 00000000000..068148f4e04 --- /dev/null +++ b/intern/openvdb/intern/openvdb_level_set.cc @@ -0,0 +1,66 @@ +/* + * 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. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + */ + + +#include "openvdb_level_set.h" +#include "openvdb_util.h" +#include "openvdb_capi.h" +#include "MEM_guardedalloc.h" + +void OpenVDB_level_set_remesh(struct OpenVDBRemeshData *rmd){ + + std::vector<openvdb::Vec3s> points; + std::vector<openvdb::Vec3I > triangles; + std::vector<openvdb::Vec4I > quads; + std::vector<openvdb::Vec3s> out_points; + std::vector<openvdb::Vec4I > out_quads; + const openvdb::math::Transform xform; + + for(int i = 0; i < rmd->totverts; i++) { + openvdb::Vec3s v(rmd->verts[i * 3 ], rmd->verts[i * 3 + 1], rmd->verts[i * 3 + 2]); + points.push_back(v); + } + + for(int i = 0; i < rmd->totfaces; i++) { + openvdb::Vec3I f(rmd->faces[i * 3 ], rmd->faces[i * 3 + 1], rmd->faces[i * 3 + 2]); + triangles.push_back(f); + } + + openvdb::initialize(); + openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform((double)rmd->voxel_size); + const openvdb::FloatGrid::Ptr grid = openvdb::tools::meshToLevelSet<openvdb::FloatGrid>(*transform, points, triangles, quads, 1); + openvdb::tools::volumeToMesh<openvdb::FloatGrid>(*grid, out_points, out_quads, (double)rmd->isovalue); + rmd->out_verts = (float *)MEM_malloc_arrayN(out_points.size(), 3 * sizeof (float), "openvdb remesher out verts"); + rmd->out_faces = (unsigned int*)MEM_malloc_arrayN(out_quads.size(), 4 * sizeof (unsigned int), "openvdb remesh out quads"); + rmd->out_totverts = out_points.size(); + rmd->out_totfaces = out_quads.size(); + + for(int i = 0; i < out_points.size(); i++) { + rmd->out_verts[i * 3] = out_points[i].x(); + rmd->out_verts[i * 3 + 1] = out_points[i].y(); + rmd->out_verts[i * 3 + 2] = out_points[i].z(); + } + + for(int i = 0; i < out_quads.size(); i++) { + rmd->out_faces[i * 4] = out_quads[i].x(); + rmd->out_faces[i * 4 + 1] = out_quads[i].y(); + rmd->out_faces[i * 4 + 2] = out_quads[i].z(); + rmd->out_faces[i * 4 + 3] = out_quads[i].w(); + } +} diff --git a/intern/openvdb/intern/openvdb_level_set.h b/intern/openvdb/intern/openvdb_level_set.h new file mode 100644 index 00000000000..bd1c57a4e86 --- /dev/null +++ b/intern/openvdb/intern/openvdb_level_set.h @@ -0,0 +1,29 @@ +/* + * 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. + * + * The Original Code is Copyright (C) 2015 Blender Foundation. + * All rights reserved. + */ + +#ifndef __OPENVDB_LEVEL_SET_H__ +#define __OPENVDB_LEVEL_SET_H__ + +#include <openvdb/openvdb.h> +#include <openvdb/tools/MeshToVolume.h> +#include <openvdb/tools/VolumeToMesh.h> + +void OpenVDB_level_set_remesh(struct OpenVDBRemeshData *rmd); + +#endif /* __OPENVDB_LEVEL_SET_H__ */ diff --git a/intern/openvdb/openvdb_capi.cc b/intern/openvdb/openvdb_capi.cc index 997c7638537..07f44de231d 100644 --- a/intern/openvdb/openvdb_capi.cc +++ b/intern/openvdb/openvdb_capi.cc @@ -20,6 +20,7 @@ #include "openvdb_capi.h" #include "openvdb_dense_convert.h" #include "openvdb_util.h" +#include "openvdb_level_set.h" struct OpenVDBFloatGrid { int unused; }; struct OpenVDBIntGrid { int unused; }; @@ -234,3 +235,8 @@ void OpenVDBReader_get_meta_mat4(OpenVDBReader *reader, const char *name, float { reader->mat4sMeta(name, value); } + + +void OpenVDB_voxel_remesh(struct OpenVDBRemeshData *rmd){ + OpenVDB_level_set_remesh(rmd); +} diff --git a/intern/openvdb/openvdb_capi.h b/intern/openvdb/openvdb_capi.h index 7af16509753..1af81f70e1b 100644 --- a/intern/openvdb/openvdb_capi.h +++ b/intern/openvdb/openvdb_capi.h @@ -29,6 +29,21 @@ struct OpenVDBWriter; struct OpenVDBFloatGrid; struct OpenVDBIntGrid; struct OpenVDBVectorGrid; +struct OpenVDBRemeshData { + float *verts; + unsigned int *faces; + int totfaces; + int totverts; + + float *out_verts; + unsigned int *out_faces; + int out_totverts; + int out_totfaces; + + float voxel_size; + float isovalue; +}; + int OpenVDB_getVersionHex(void); @@ -93,6 +108,9 @@ void OpenVDBReader_get_meta_v3(struct OpenVDBReader *reader, const char *name, f void OpenVDBReader_get_meta_v3_int(struct OpenVDBReader *reader, const char *name, int value[3]); void OpenVDBReader_get_meta_mat4(struct OpenVDBReader *reader, const char *name, float value[4][4]); +void OpenVDB_voxel_remesh(struct OpenVDBRemeshData *rmd); + + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index f15427e61ac..3211784e126 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -78,4 +78,17 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_OPENVDB) + add_definitions(-DWITH_OPENVDB) + list(APPEND INC + ../../../../intern/openvdb + ) + + if(WITH_OPENVDB_BLOSC) + add_definitions( + -DWITH_OPENVDB_BLOSC + ) + endif() +endif() + blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 977f5f30d94..88cdb74ac71 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -32,6 +32,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -78,6 +79,8 @@ #include "BKE_editmesh.h" #include "BKE_report.h" #include "BKE_workspace.h" +#include "BKE_mesh_runtime.h" +#include "BKE_library.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -110,6 +113,10 @@ #include "object_intern.h" // own include +#ifdef WITH_OPENVDB + #include "openvdb_capi.h" +#endif + /* prototypes */ typedef struct MoveToCollectionData MoveToCollectionData; static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu); @@ -1735,3 +1742,107 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot) "Name of the newly added collection"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } + + +static int remesh_exec(bContext *C, wmOperator *op) +{ + bool linked_data = false; + + Object *ob = CTX_data_active_object(C); + Main *bmain = CTX_data_main(C); + struct OpenVDBRemeshData rmd; + + ID *data; + data = ob->data; + if (data && ID_IS_LINKED(data)) { + linked_data = true; + return OPERATOR_CANCELLED; + } + + if (ob->type == OB_MESH) { + Mesh *mesh = ob->data; + BKE_mesh_runtime_looptri_recalc(mesh); + const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh); + MVertTri *verttri = MEM_callocN(sizeof(*verttri) * BKE_mesh_runtime_looptri_len(mesh), "remesh_looptri"); + BKE_mesh_runtime_verttri_from_looptri(verttri, mesh->mloop, looptri, BKE_mesh_runtime_looptri_len(mesh)); + + rmd.totfaces = BKE_mesh_runtime_looptri_len(mesh); + rmd.totverts = mesh->totvert; + rmd.verts = (float *)MEM_calloc_arrayN(rmd.totverts * 3, sizeof(float), "remesh_input_verts"); + rmd.faces = (unsigned int *)MEM_calloc_arrayN(rmd.totfaces * 3, sizeof(unsigned int), "remesh_intput_faces"); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "voxel_size"); + rmd.voxel_size = RNA_property_float_get(op->ptr, prop); + rmd.isovalue = 0.0f; + + for(int i = 0; i < mesh->totvert; i++) { + MVert mvert = mesh->mvert[i]; + rmd.verts[i * 3] = mvert.co[0]; + rmd.verts[i * 3 + 1] = mvert.co[1]; + rmd.verts[i * 3 + 2] = mvert.co[2]; + } + + for(int i = 0; i < rmd.totfaces; i++) { + MVertTri vt = verttri[i]; + rmd.faces[i * 3] = vt.tri[0]; + rmd.faces[i * 3 + 1] = vt.tri[1]; + rmd.faces[i * 3 + 2] = vt.tri[2]; + } + + OpenVDB_voxel_remesh(&rmd); + + Mesh *newMesh = BKE_mesh_new_nomain(rmd.out_totverts, 0, rmd.out_totfaces, 0, 0); + + for(int i = 0; i < rmd.out_totverts; i++) { + float vco[3] = { rmd.out_verts[i * 3], rmd.out_verts[i * 3 + 1], rmd.out_verts[i * 3 + 2]}; + copy_v3_v3(newMesh->mvert[i].co, vco); + + } + for(int i = 0; i < rmd.out_totfaces; i++) { + newMesh->mface[i].v4 = rmd.out_faces[i * 4]; + @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs