diff options
author | Sebastian Parborg <darkdefende@gmail.com> | 2019-08-26 19:34:11 +0300 |
---|---|---|
committer | Sebastian Parborg <darkdefende@gmail.com> | 2019-09-13 11:36:05 +0300 |
commit | 57e55906f04a48a951fbbcfd7c197eef35ad4387 (patch) | |
tree | a4246ffdd501027a37d7329dca05de4d9ed19b15 /source/blender/blenkernel/intern/mesh_remesh_voxel.c | |
parent | 1c44d08a69eb3e66c7f942d748f549d6b8ca138f (diff) |
Add QuadriFlow remesher
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_remesh_voxel.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_remesh_voxel.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c index a5136311a22..ff7ff947e1d 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c @@ -49,6 +49,10 @@ # include "openvdb_capi.h" #endif +#ifdef WITH_QUADRIFLOW +# include "quadriflow_capi.hpp" +#endif + #ifdef WITH_OPENVDB struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create( Mesh *mesh, struct OpenVDBTransform *transform) @@ -146,6 +150,148 @@ Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *l } #endif +#ifdef WITH_QUADRIFLOW +static Mesh *BKE_mesh_remesh_quadriflow(Mesh *input_mesh, + int target_faces, + int seed, + bool preserve_sharp, + bool preserve_boundary, + bool adaptive_scale, + void *update_cb, + void *update_cb_data) +{ + /* Ensure that the triangulated mesh data is up to data */ + BKE_mesh_runtime_looptri_recalc(input_mesh); + const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh); + + /* Gather the required data for export to the internal quadiflow mesh format */ + MVertTri *verttri = MEM_callocN(sizeof(*verttri) * BKE_mesh_runtime_looptri_len(input_mesh), + "remesh_looptri"); + BKE_mesh_runtime_verttri_from_looptri( + verttri, input_mesh->mloop, looptri, BKE_mesh_runtime_looptri_len(input_mesh)); + + unsigned int totfaces = BKE_mesh_runtime_looptri_len(input_mesh); + unsigned int totverts = input_mesh->totvert; + float *verts = (float *)MEM_malloc_arrayN(totverts * 3, sizeof(float), "remesh_input_verts"); + unsigned int *faces = (unsigned int *)MEM_malloc_arrayN( + totfaces * 3, sizeof(unsigned int), "remesh_intput_faces"); + + for (unsigned int i = 0; i < totverts; i++) { + MVert *mvert = &input_mesh->mvert[i]; + verts[i * 3] = mvert->co[0]; + verts[i * 3 + 1] = mvert->co[1]; + verts[i * 3 + 2] = mvert->co[2]; + } + + for (unsigned int i = 0; i < totfaces; i++) { + MVertTri *vt = &verttri[i]; + faces[i * 3] = vt->tri[0]; + faces[i * 3 + 1] = vt->tri[1]; + faces[i * 3 + 2] = vt->tri[2]; + } + + /* Fill out the required input data */ + QuadriflowRemeshData qrd; + + qrd.totfaces = totfaces; + qrd.totverts = totverts; + qrd.verts = verts; + qrd.faces = faces; + qrd.target_faces = target_faces; + + qrd.preserve_sharp = preserve_sharp; + qrd.preserve_boundary = preserve_boundary; + qrd.adaptive_scale = adaptive_scale; + qrd.minimum_cost_flow = 0; + qrd.aggresive_sat = 0; + qrd.rng_seed = seed; + + qrd.out_faces = NULL; + + /* Run the remesher */ + QFLOW_quadriflow_remesh(&qrd, update_cb, update_cb_data); + + MEM_freeN(verts); + MEM_freeN(faces); + MEM_freeN(verttri); + + if (qrd.out_faces == NULL) { + /* The remeshing was canceled */ + return NULL; + } + + if (qrd.out_totfaces == 0) { + /* Meshing failed */ + MEM_freeN(qrd.out_faces); + MEM_freeN(qrd.out_verts); + return NULL; + } + + /* Construct the new output mesh */ + Mesh *mesh = BKE_mesh_new_nomain( + qrd.out_totverts, 0, 0, (qrd.out_totfaces * 4), qrd.out_totfaces); + + for (int i = 0; i < qrd.out_totverts; i++) { + copy_v3_v3(mesh->mvert[i].co, &qrd.out_verts[i * 3]); + } + + MPoly *mp = mesh->mpoly; + MLoop *ml = mesh->mloop; + for (int i = 0; i < qrd.out_totfaces; i++, mp++, ml += 4) { + mp->loopstart = (int)(ml - mesh->mloop); + mp->totloop = 4; + + ml[0].v = qrd.out_faces[i * 4]; + ml[1].v = qrd.out_faces[i * 4 + 1]; + ml[2].v = qrd.out_faces[i * 4 + 2]; + ml[3].v = qrd.out_faces[i * 4 + 3]; + } + + BKE_mesh_calc_edges(mesh, false, false); + BKE_mesh_calc_normals(mesh); + + MEM_freeN(qrd.out_faces); + MEM_freeN(qrd.out_verts); + + return mesh; +} +#endif + +Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(Mesh *mesh, + int target_faces, + int seed, + bool preserve_sharp, + bool preserve_boundary, + bool adaptive_scale, + void *update_cb, + void *update_cb_data) +{ + Mesh *new_mesh = NULL; +#ifdef WITH_QUADRIFLOW + if (target_faces <= 0) { + target_faces = -1; + } + new_mesh = BKE_mesh_remesh_quadriflow(mesh, + target_faces, + seed, + preserve_sharp, + preserve_boundary, + adaptive_scale, + update_cb, + update_cb_data); +#else + UNUSED_VARS(mesh, + target_faces, + seed, + preserve_sharp, + preserve_boundary, + adaptive_scale, + update_cb, + update_cb_data); +#endif + return new_mesh; +} + Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size) { Mesh *new_mesh = NULL; |