diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-08-14 21:46:10 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-08-14 21:46:51 +0300 |
commit | 655f5818a589539b286641450c00d27a5cac2bff (patch) | |
tree | bbbdb97b48792f26e0ff0daee997d767e4b93411 /source/blender/blenkernel/intern/mesh_remesh_voxel.c | |
parent | 76e5b4bee4ed4b7bce5ffb7f9cbf0b5615c7473b (diff) |
Cleanup: use BKE_mesh_ prefix for the remesh API
These functions deal with voxel remeshing of Mesh data,
and aren't related to MOD_remesh.c for e.g.
Name so other kinds of remeshing wont cause confusion.
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_remesh_voxel.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_remesh_voxel.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c new file mode 100644 index 00000000000..17347842216 --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c @@ -0,0 +1,200 @@ +/* + * 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) 2019 by Blender Foundation + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <time.h> +#include <float.h> +#include <ctype.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_library.h" +#include "BKE_customdata.h" +#include "BKE_bvhutils.h" +#include "BKE_mesh_remesh_voxel.h" /* own include */ + +#ifdef WITH_OPENVDB +# include "openvdb_capi.h" +#endif + +#ifdef WITH_OPENVDB +struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create( + Mesh *mesh, struct OpenVDBTransform *transform) +{ + 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)); + + unsigned int totfaces = BKE_mesh_runtime_looptri_len(mesh); + unsigned int totverts = 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 = &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]; + } + + struct OpenVDBLevelSet *level_set = OpenVDBLevelSet_create(false, NULL); + OpenVDBLevelSet_mesh_to_level_set(level_set, verts, faces, totverts, totfaces, transform); + + MEM_freeN(verts); + MEM_freeN(faces); + MEM_freeN(verttri); + + return level_set; +} + +Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_set, + double isovalue, + double adaptivity, + bool relax_disoriented_triangles) +{ +# ifdef WITH_OPENVDB + struct OpenVDBVolumeToMeshData output_mesh; + OpenVDBLevelSet_volume_to_mesh( + level_set, &output_mesh, isovalue, adaptivity, relax_disoriented_triangles); +# endif + + Mesh *mesh = BKE_mesh_new_nomain( + output_mesh.totvertices, 0, output_mesh.totquads + output_mesh.tottriangles, 0, 0); + int q = output_mesh.totquads; + + for (int i = 0; i < output_mesh.totvertices; i++) { + float vco[3] = {output_mesh.vertices[i * 3], + output_mesh.vertices[i * 3 + 1], + output_mesh.vertices[i * 3 + 2]}; + copy_v3_v3(mesh->mvert[i].co, vco); + } + + for (int i = 0; i < output_mesh.totquads; i++) { + mesh->mface[i].v4 = output_mesh.quads[i * 4]; + mesh->mface[i].v3 = output_mesh.quads[i * 4 + 1]; + mesh->mface[i].v2 = output_mesh.quads[i * 4 + 2]; + mesh->mface[i].v1 = output_mesh.quads[i * 4 + 3]; + } + + for (int i = 0; i < output_mesh.tottriangles; i++) { + mesh->mface[i + q].v4 = 0; + mesh->mface[i + q].v3 = output_mesh.triangles[i * 3]; + mesh->mface[i + q].v2 = output_mesh.triangles[i * 3 + 1]; + mesh->mface[i + q].v1 = output_mesh.triangles[i * 3 + 2]; + } + + BKE_mesh_calc_edges_tessface(mesh); + BKE_mesh_convert_mfaces_to_mpolys(mesh); + BKE_mesh_tessface_clear(mesh); + BKE_mesh_calc_normals(mesh); + + MEM_freeN(output_mesh.quads); + MEM_freeN(output_mesh.vertices); + + if (output_mesh.tottriangles > 0) { + MEM_freeN(output_mesh.triangles); + } + + return mesh; +} +#endif + +Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size) +{ + Mesh *new_mesh = NULL; +#ifdef WITH_OPENVDB + struct OpenVDBLevelSet *level_set; + struct OpenVDBTransform *xform = OpenVDBTransform_create(); + OpenVDBTransform_create_linear_transform(xform, (double)voxel_size); + level_set = BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create(mesh, xform); + new_mesh = BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(level_set, 0.0, 0.0, false); + OpenVDBLevelSet_free(level_set); + OpenVDBTransform_free(xform); +#else + UNUSED_VARS(mesh, voxel_size); +#endif + return new_mesh; +} + +void BKE_remesh_reproject_paint_mask(Mesh *target, Mesh *source) +{ + BVHTreeFromMesh bvhtree = { + .nearest_callback = NULL, + }; + BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); + MVert *target_verts = CustomData_get_layer(&target->vdata, CD_MVERT); + + float *target_mask; + if (CustomData_has_layer(&target->vdata, CD_PAINT_MASK)) { + target_mask = CustomData_get_layer(&target->vdata, CD_PAINT_MASK); + } + else { + target_mask = CustomData_add_layer( + &target->vdata, CD_PAINT_MASK, CD_CALLOC, NULL, target->totvert); + } + + float *source_mask; + if (CustomData_has_layer(&source->vdata, CD_PAINT_MASK)) { + source_mask = CustomData_get_layer(&source->vdata, CD_PAINT_MASK); + } + else { + source_mask = CustomData_add_layer( + &source->vdata, CD_PAINT_MASK, CD_CALLOC, NULL, source->totvert); + } + + for (int i = 0; i < target->totvert; i++) { + float from_co[3]; + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + copy_v3_v3(from_co, target_verts[i].co); + BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); + if (nearest.index != -1) { + target_mask[i] = source_mask[nearest.index]; + } + } + free_bvhtree_from_mesh(&bvhtree); +} |