Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_remesh_voxel.c
| Context not available. | |||||
| # include "openvdb_capi.h" | # include "openvdb_capi.h" | ||||
| #endif | #endif | ||||
| #ifdef WITH_QUADRIFLOW | |||||
| # include "quadriflow_capi.hpp" | |||||
| #endif | |||||
| #ifdef WITH_OPENVDB | #ifdef WITH_OPENVDB | ||||
| struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create( | struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create( | ||||
| Mesh *mesh, struct OpenVDBTransform *transform) | Mesh *mesh, struct OpenVDBTransform *transform) | ||||
| Context not available. | |||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef WITH_QUADRIFLOW | |||||
| static Mesh *BKE_mesh_remesh_quadriflow(Mesh *input_mesh, | |||||
brecht: Add comments to this function as well. | |||||
| int target_faces, | |||||
| int seed, | |||||
| bool preserve_sharp, | |||||
| bool preserve_boundary, | |||||
| bool adaptive_scale, | |||||
| void *update_cb, | |||||
| void *update_cb_data) | |||||
Done Inline ActionsFree looptris when they are done being used in this function. brecht: Free looptris when they are done being used in this function. | |||||
| { | |||||
| /* 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; | |||||
Done Inline ActionsAre these comments still relevant? I guess the quality isn't as good as we want, but probably not unstable? brecht: Are these comments still relevant?
I guess the quality isn't as good as we want, but probably… | |||||
| 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 *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size) | ||||
| { | { | ||||
| Mesh *new_mesh = NULL; | Mesh *new_mesh = NULL; | ||||
| Context not available. | |||||
Add comments to this function as well.