Changeset View
Standalone View
source/blender/modifiers/intern/MOD_weld.c
| Context not available. | |||||
| uint indexA = overlap_iter->indexA; | uint indexA = overlap_iter->indexA; | ||||
| uint indexB = overlap_iter->indexB; | uint indexB = overlap_iter->indexB; | ||||
| uint va_dst = vert_dest_map[indexA]; | uint va_dst = vert_dest_map[indexA]; | ||||
| while (va_dst != vert_dest_map[va_dst]) { | |||||
mano-wii: The purpose of this function is to find out if `vert_dest_map` has been configured correctly… | |||||
weaselAuthorUnsubmitted Done Inline ActionsIf I would do the idea from the other inline comment with the function, then I could probably change it back. weasel: If I would do the idea from the other inline comment with the function, then I could probably… | |||||
| va_dst = vert_dest_map[va_dst]; | |||||
| } | |||||
| uint vb_dst = vert_dest_map[indexB]; | uint vb_dst = vert_dest_map[indexB]; | ||||
| while (vb_dst != vert_dest_map[vb_dst]) { | |||||
| vb_dst = vert_dest_map[vb_dst]; | |||||
| } | |||||
| BLI_assert(va_dst == vb_dst); | BLI_assert(va_dst == vb_dst); | ||||
| } | } | ||||
| Context not available. | |||||
| * \{ */ | * \{ */ | ||||
| static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, | static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, | ||||
| const BVHTreeOverlap *overlap, | |||||
| const uint overlap_len, | |||||
| uint *r_vert_dest_map, | uint *r_vert_dest_map, | ||||
| WeldVert **r_wvert, | WeldVert **r_wvert, | ||||
| uint *r_wvert_len, | uint *r_wvert_len) | ||||
| uint *r_vert_kill_len) | |||||
| { | { | ||||
| uint *v_dest_iter = &r_vert_dest_map[0]; | /* Fix #r_vert_dest_map for next step. */ | ||||
| for (uint i = mvert_len; i--; v_dest_iter++) { | for (uint i = 0; i < mvert_len; i++) { | ||||
| *v_dest_iter = OUT_OF_CONTEXT; | if (i == r_vert_dest_map[i]) { | ||||
| } | r_vert_dest_map[i] = OUT_OF_CONTEXT; | ||||
| uint vert_kill_len = 0; | |||||
| const BVHTreeOverlap *overlap_iter = &overlap[0]; | |||||
| for (uint i = 0; i < overlap_len; i++, overlap_iter++) { | |||||
| uint indexA = overlap_iter->indexA; | |||||
| uint indexB = overlap_iter->indexB; | |||||
| BLI_assert(indexA < indexB); | |||||
| uint va_dst = r_vert_dest_map[indexA]; | |||||
| uint vb_dst = r_vert_dest_map[indexB]; | |||||
| if (va_dst == OUT_OF_CONTEXT) { | |||||
| if (vb_dst == OUT_OF_CONTEXT) { | |||||
| vb_dst = indexA; | |||||
| r_vert_dest_map[indexB] = vb_dst; | |||||
| } | |||||
| r_vert_dest_map[indexA] = vb_dst; | |||||
| vert_kill_len++; | |||||
| } | |||||
| else if (vb_dst == OUT_OF_CONTEXT) { | |||||
| r_vert_dest_map[indexB] = va_dst; | |||||
| vert_kill_len++; | |||||
| } | } | ||||
| else if (va_dst != vb_dst) { | else { | ||||
| uint v_new, v_old; | uint v = i; | ||||
| if (va_dst < vb_dst) { | while (v != r_vert_dest_map[v] && r_vert_dest_map[v] != OUT_OF_CONTEXT) { | ||||
| v_new = va_dst; | v = r_vert_dest_map[v]; | ||||
| v_old = vb_dst; | |||||
| } | |||||
| else { | |||||
| v_new = vb_dst; | |||||
| v_old = va_dst; | |||||
| } | |||||
| BLI_assert(r_vert_dest_map[v_old] == v_old); | |||||
| BLI_assert(r_vert_dest_map[v_new] == v_new); | |||||
| vert_kill_len++; | |||||
| const BVHTreeOverlap *overlap_iter_b = &overlap[0]; | |||||
| for (uint j = i + 1; j--; overlap_iter_b++) { | |||||
| indexA = overlap_iter_b->indexA; | |||||
| indexB = overlap_iter_b->indexB; | |||||
| va_dst = r_vert_dest_map[indexA]; | |||||
| vb_dst = r_vert_dest_map[indexB]; | |||||
| if (ELEM(v_old, vb_dst, va_dst)) { | |||||
| r_vert_dest_map[indexA] = v_new; | |||||
| r_vert_dest_map[indexB] = v_new; | |||||
| } | |||||
| } | } | ||||
| BLI_assert(r_vert_dest_map[v_old] == v_new); | r_vert_dest_map[v] = v; | ||||
| r_vert_dest_map[i] = v; | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| wvert = MEM_mallocN(sizeof(*wvert) * mvert_len, __func__); | wvert = MEM_mallocN(sizeof(*wvert) * mvert_len, __func__); | ||||
| wv = &wvert[0]; | wv = &wvert[0]; | ||||
| v_dest_iter = &r_vert_dest_map[0]; | uint *v_dest_iter = &r_vert_dest_map[0]; | ||||
| for (uint i = 0; i < mvert_len; i++, v_dest_iter++) { | for (uint i = 0; i < mvert_len; i++, v_dest_iter++) { | ||||
| if (*v_dest_iter != OUT_OF_CONTEXT) { | if (*v_dest_iter != OUT_OF_CONTEXT) { | ||||
| wv->vert_dest = *v_dest_iter; | wv->vert_dest = *v_dest_iter; | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| #ifdef USE_WELD_DEBUG | |||||
| weld_assert_vert_dest_map_setup(overlap, overlap_len, r_vert_dest_map); | |||||
| #endif | |||||
| *r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len); | *r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len); | ||||
| *r_wvert_len = wvert_len; | *r_wvert_len = wvert_len; | ||||
| *r_vert_kill_len = vert_kill_len; | |||||
| } | } | ||||
| static void weld_vert_groups_setup(const uint mvert_len, | static void weld_vert_groups_setup(const uint mvert_len, | ||||
| Context not available. | |||||
| /** \name Weld Mesh API | /** \name Weld Mesh API | ||||
| * \{ */ | * \{ */ | ||||
| static void weld_mesh_context_create(const Mesh *mesh, | static void weld_mesh_context_create(const Mesh *mesh, WeldMesh *r_weld_mesh) | ||||
| BVHTreeOverlap *overlap, | |||||
| const uint overlap_len, | |||||
| WeldMesh *r_weld_mesh) | |||||
| { | { | ||||
| const MEdge *medge = mesh->medge; | const MEdge *medge = mesh->medge; | ||||
| const MLoop *mloop = mesh->mloop; | const MLoop *mloop = mesh->mloop; | ||||
| Context not available. | |||||
| const uint mloop_len = mesh->totloop; | const uint mloop_len = mesh->totloop; | ||||
| const uint mpoly_len = mesh->totpoly; | const uint mpoly_len = mesh->totpoly; | ||||
| uint *vert_dest_map = MEM_mallocN(sizeof(*vert_dest_map) * mvert_len, __func__); | uint *vert_dest_map = r_weld_mesh->vert_groups_map; | ||||
| uint *edge_dest_map = MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__); | uint *edge_dest_map = MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__); | ||||
| struct WeldGroup *v_links = MEM_callocN(sizeof(*v_links) * mvert_len, __func__); | struct WeldGroup *v_links = MEM_callocN(sizeof(*v_links) * mvert_len, __func__); | ||||
| WeldVert *wvert; | WeldVert *wvert; | ||||
| uint wvert_len; | uint wvert_len; | ||||
| weld_vert_ctx_alloc_and_setup(mvert_len, | weld_vert_ctx_alloc_and_setup(mvert_len, vert_dest_map, &wvert, &wvert_len); | ||||
| overlap, | |||||
| overlap_len, | |||||
| vert_dest_map, | |||||
| &wvert, | |||||
| &wvert_len, | |||||
| &r_weld_mesh->vert_kill_len); | |||||
| uint *edge_ctx_map; | uint *edge_ctx_map; | ||||
| WeldEdge *wedge; | WeldEdge *wedge; | ||||
| Context not available. | |||||
| &r_weld_mesh->edge_groups_buffer, | &r_weld_mesh->edge_groups_buffer, | ||||
| &r_weld_mesh->edge_groups); | &r_weld_mesh->edge_groups); | ||||
| r_weld_mesh->vert_groups_map = vert_dest_map; | |||||
| r_weld_mesh->edge_groups_map = edge_dest_map; | r_weld_mesh->edge_groups_map = edge_dest_map; | ||||
| MEM_freeN(v_links); | MEM_freeN(v_links); | ||||
| MEM_freeN(wvert); | MEM_freeN(wvert); | ||||
| Context not available. | |||||
| const MPoly *mpoly, *mp; | const MPoly *mpoly, *mp; | ||||
| uint totvert, totedge, totloop, totpoly; | uint totvert, totedge, totloop, totpoly; | ||||
| uint i; | uint i; | ||||
| uint vert_kill_len = 0; | |||||
| mvert = mesh->mvert; | mvert = mesh->mvert; | ||||
| totvert = mesh->totvert; | totvert = mesh->totvert; | ||||
| if (wmd->merge_dist == 0.0f) { | |||||
mano-wiiUnsubmitted Done Inline ActionsWhy return earlier if the merge_dist value is 0.0f? mano-wii: Why return earlier if the `merge_dist` value is `0.0f`? | |||||
weaselAuthorUnsubmitted Done Inline ActionsI guess I can move this to the next patch, as there, it is actually kind of important. weasel: I guess I can move this to the next patch, as there, it is actually kind of important. | |||||
| return mesh; | |||||
| } | |||||
| /* Vertex Group. */ | /* Vertex Group. */ | ||||
| const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); | const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); | ||||
| if (defgrp_index != -1) { | if (defgrp_index != -1) { | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| if (v_mask && v_mask_act == 0) { | |||||
| MEM_freeN(v_mask); | |||||
| return mesh; | |||||
| } | |||||
| /* Get overlap map. */ | /* Get overlap map. */ | ||||
| /* TODO: For a better performanse use KD-Tree. */ | /* TODO: For a better performanse use KD-Tree. */ | ||||
| struct BVHTreeFromMesh treedata; | struct BVHTreeFromMesh treedata; | ||||
| Context not available. | |||||
| data.mvert = mvert; | data.mvert = mvert; | ||||
| data.merge_dist_sq = square_f(wmd->merge_dist); | data.merge_dist_sq = square_f(wmd->merge_dist); | ||||
| /* Vertex destination map. (here short as vm). */ | |||||
| uint *vm = MEM_malloc_arrayN(totvert, sizeof(*mvert), __func__); | |||||
mano-wiiUnsubmitted Done Inline ActionsYou can use range_vn_u here. mano-wii: You can use `range_vn_u` here. | |||||
weaselAuthorUnsubmitted Done Inline ActionsI would rather use vert_dest_map to be consistent if vm is to short. weasel: I would rather use `vert_dest_map` to be consistent if `vm` is to short. | |||||
mano-wiiUnsubmitted Done Inline Actionsrange_vn_u is a function. mano-wii: `range_vn_u` is a function.
(See `void range_vn_u(unsigned int *array_tar, const int size… | |||||
| for (i = 0; i < totvert; i++) { | |||||
| vm[i] = i; | |||||
| } | |||||
| uint overlap_len; | uint overlap_len; | ||||
| BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree, | BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree, | ||||
| bvhtree, | bvhtree, | ||||
| Context not available. | |||||
| free_bvhtree_from_mesh(&treedata); | free_bvhtree_from_mesh(&treedata); | ||||
| const BVHTreeOverlap *overlap_iter = &overlap[0]; | |||||
| for (i = 0; i < overlap_len; i++, overlap_iter++) { | |||||
| uint indexA = overlap_iter->indexA; | |||||
| uint indexB = overlap_iter->indexB; | |||||
| BLI_assert(indexA < indexB); | |||||
| uint va_dst = vm[indexA]; | |||||
| while (va_dst != vm[va_dst]) { | |||||
| va_dst = vm[va_dst]; | |||||
| } | |||||
| uint vb_dst = vm[indexB]; | |||||
| while (vb_dst != vm[vb_dst]) { | |||||
| vb_dst = vm[vb_dst]; | |||||
| } | |||||
| if (va_dst == vb_dst) { | |||||
| continue; | |||||
| } | |||||
| if (va_dst > vb_dst) { | |||||
| SWAP(uint, va_dst, vb_dst); | |||||
| } | |||||
| vert_kill_len++; | |||||
| vm[vb_dst] = va_dst; | |||||
| } | |||||
| #ifdef USE_WELD_DEBUG | |||||
| weld_assert_vert_dest_map_setup(overlap, overlap_len, vm); | |||||
| #endif | |||||
| MEM_freeN(overlap); | |||||
| if (overlap_len) { | if (overlap_len) { | ||||
| WeldMesh weld_mesh; | WeldMesh weld_mesh; | ||||
| weld_mesh_context_create(mesh, overlap, overlap_len, &weld_mesh); | weld_mesh.vert_groups_map = vm; | ||||
| weld_mesh.vert_kill_len = vert_kill_len; | |||||
mano-wiiUnsubmitted Not Done Inline ActionsWhen creating the code, I sought to create/configure the entire weld_mesh object inside the weld_mesh_context_create function (especially because this is the purpose of this function). Unless there are good reasons, I would prefer that all this logic be moved into weld_vert_ctx_alloc_and_setup. mano-wii: When creating the code, I sought to create/configure the entire `weld_mesh` object inside the… | |||||
weaselAuthorUnsubmitted Done Inline ActionsI was expecting this comment. The problem is line 1721 with that if statement. It's nice to have that there and I want to keep it, but that means the proximity evaluation has to stay before that. Now again, I would move it all inside if overlap would be always necessary, but with the next patch, the variable would not even be initialized in simple mode. What I can do as a better solution is to make a new function before weld_vert_ctx_alloc_and_setup which would create the vertex merge map and would also be able to do different things depending on the settings. Then I could remove vert_groups_map from weld_mesh and pass it along with vert_kill_len as an argument to weld_mesh_context_create instead. weasel: I was expecting this comment. The problem is line 1721 with that `if` statement. It's nice to… | |||||
| weld_mesh_context_create(mesh, &weld_mesh); | |||||
| mloop = mesh->mloop; | mloop = mesh->mloop; | ||||
| mpoly = mesh->mpoly; | mpoly = mesh->mpoly; | ||||
| Context not available. | |||||
| weld_mesh_context_free(&weld_mesh); | weld_mesh_context_free(&weld_mesh); | ||||
| } | } | ||||
| else { | |||||
| MEM_freeN(vm); | |||||
| } | |||||
| MEM_freeN(overlap); | |||||
| return result; | return result; | ||||
| } | } | ||||
| Context not available. | |||||
The purpose of this function is to find out if vert_dest_map has been configured correctly without the need for this loop.
So either you are calling it at the wrong moment or these changes are not necessary.