Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Parborg <darkdefende@gmail.com>2019-08-26 19:34:11 +0300
committerSebastian Parborg <darkdefende@gmail.com>2019-09-13 11:36:05 +0300
commit57e55906f04a48a951fbbcfd7c197eef35ad4387 (patch)
treea4246ffdd501027a37d7329dca05de4d9ed19b15 /source/blender/blenkernel/intern/mesh_remesh_voxel.c
parent1c44d08a69eb3e66c7f942d748f549d6b8ca138f (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.c146
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;