Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_remesh_voxel.cc
| Show All 13 Lines | |||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_array.hh" | #include "BLI_array.hh" | ||||
| #include "BLI_index_range.hh" | #include "BLI_index_range.hh" | ||||
| #include "BLI_math_vec_types.hh" | #include "BLI_math_vec_types.hh" | ||||
| #include "BLI_math_vector.h" | #include "BLI_math_vector.h" | ||||
| #include "BLI_span.hh" | #include "BLI_span.hh" | ||||
| #include "BLI_task.hh" | |||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "BKE_attribute.h" | #include "BKE_attribute.h" | ||||
| #include "BKE_attribute.hh" | #include "BKE_attribute.hh" | ||||
| #include "BKE_bvhutils.h" | #include "BKE_bvhutils.h" | ||||
| #include "BKE_customdata.h" | #include "BKE_customdata.h" | ||||
| ▲ Show 20 Lines • Show All 267 Lines • ▼ Show 20 Lines | void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source) | ||||
| if (CustomData_has_layer(&target->vdata, CD_PAINT_MASK)) { | if (CustomData_has_layer(&target->vdata, CD_PAINT_MASK)) { | ||||
| target_mask = (float *)CustomData_get_layer(&target->vdata, CD_PAINT_MASK); | target_mask = (float *)CustomData_get_layer(&target->vdata, CD_PAINT_MASK); | ||||
| } | } | ||||
| else { | else { | ||||
| target_mask = (float *)CustomData_add_layer( | target_mask = (float *)CustomData_add_layer( | ||||
| &target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, nullptr, target->totvert); | &target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, nullptr, target->totvert); | ||||
| } | } | ||||
| for (int i = 0; i < target->totvert; i++) { | blender::threading::parallel_for(IndexRange(target->totvert), 4096, [&](const IndexRange range) { | ||||
| for (const int i : range) { | |||||
| float from_co[3]; | float from_co[3]; | ||||
| BVHTreeNearest nearest; | BVHTreeNearest nearest; | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| nearest.dist_sq = FLT_MAX; | nearest.dist_sq = FLT_MAX; | ||||
| copy_v3_v3(from_co, target_verts[i].co); | copy_v3_v3(from_co, target_verts[i].co); | ||||
| BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); | BLI_bvhtree_find_nearest( | ||||
| bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); | |||||
| if (nearest.index != -1) { | if (nearest.index != -1) { | ||||
| target_mask[i] = source_mask[nearest.index]; | target_mask[i] = source_mask[nearest.index]; | ||||
| } | } | ||||
| } | } | ||||
| }); | |||||
| free_bvhtree_from_mesh(&bvhtree); | free_bvhtree_from_mesh(&bvhtree); | ||||
| } | } | ||||
| void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) | void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) | ||||
| { | { | ||||
| using namespace blender; | using namespace blender; | ||||
| using namespace blender::bke; | using namespace blender::bke; | ||||
| const AttributeAccessor src_attributes = source->attributes(); | const AttributeAccessor src_attributes = source->attributes(); | ||||
| Show All 15 Lines | void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) | ||||
| const VArraySpan<int> src(src_face_sets); | const VArraySpan<int> src(src_face_sets); | ||||
| MutableSpan<int> dst = dst_face_sets.span; | MutableSpan<int> dst = dst_face_sets.span; | ||||
| const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source); | const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source); | ||||
| BVHTreeFromMesh bvhtree = {nullptr}; | BVHTreeFromMesh bvhtree = {nullptr}; | ||||
| BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2); | BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2); | ||||
| for (int i = 0; i < target->totpoly; i++) { | blender::threading::parallel_for(IndexRange(target->totpoly), 2048, [&](const IndexRange range) { | ||||
| for (const int i : range) { | |||||
| float from_co[3]; | float from_co[3]; | ||||
| BVHTreeNearest nearest; | BVHTreeNearest nearest; | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| nearest.dist_sq = FLT_MAX; | nearest.dist_sq = FLT_MAX; | ||||
| const MPoly *mpoly = &target_polys[i]; | const MPoly *mpoly = &target_polys[i]; | ||||
| BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co); | BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co); | ||||
| BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); | BLI_bvhtree_find_nearest( | ||||
| bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); | |||||
| if (nearest.index != -1) { | if (nearest.index != -1) { | ||||
| dst[i] = src[looptri[nearest.index].poly]; | dst[i] = src[looptri[nearest.index].poly]; | ||||
| } | } | ||||
| else { | else { | ||||
| dst[i] = 1; | dst[i] = 1; | ||||
| } | } | ||||
| } | } | ||||
| }); | |||||
| free_bvhtree_from_mesh(&bvhtree); | free_bvhtree_from_mesh(&bvhtree); | ||||
| dst_face_sets.finish(); | dst_face_sets.finish(); | ||||
| } | } | ||||
| void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) | void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) | ||||
| { | { | ||||
| BVHTreeFromMesh bvhtree = {nullptr}; | BVHTreeFromMesh bvhtree = {nullptr}; | ||||
| BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); | BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); | ||||
| Show All 24 Lines | while ((layer = BKE_id_attribute_from_index( | ||||
| } | } | ||||
| size_t data_size = CustomData_sizeof(layer->type); | size_t data_size = CustomData_sizeof(layer->type); | ||||
| void *target_data = target_cdata->layers[layer_i].data; | void *target_data = target_cdata->layers[layer_i].data; | ||||
| void *source_data = layer->data; | void *source_data = layer->data; | ||||
| MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); | MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); | ||||
| if (domain == ATTR_DOMAIN_POINT) { | if (domain == ATTR_DOMAIN_POINT) { | ||||
| for (int i = 0; i < target->totvert; i++) { | blender::threading::parallel_for( | ||||
| IndexRange(target->totvert), 4096, [&](const IndexRange range) { | |||||
| for (const int i : range) { | |||||
| BVHTreeNearest nearest; | BVHTreeNearest nearest; | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| nearest.dist_sq = FLT_MAX; | nearest.dist_sq = FLT_MAX; | ||||
| BLI_bvhtree_find_nearest( | BLI_bvhtree_find_nearest( | ||||
| bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); | bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); | ||||
| if (nearest.index != -1) { | if (nearest.index != -1) { | ||||
| memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size), | memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size), | ||||
| POINTER_OFFSET(source_data, size_t(nearest.index) * data_size), | POINTER_OFFSET(source_data, size_t(nearest.index) * data_size), | ||||
| data_size); | data_size); | ||||
| } | } | ||||
| } | } | ||||
| }); | |||||
| } | } | ||||
| else { | else { | ||||
| /* Lazily init vertex -> loop maps. */ | /* Lazily init vertex -> loop maps. */ | ||||
| if (!source_lmap) { | if (!source_lmap) { | ||||
| const MPoly *source_polys = (MPoly *)CustomData_get_layer(&source->pdata, CD_MPOLY); | const MPoly *source_polys = (MPoly *)CustomData_get_layer(&source->pdata, CD_MPOLY); | ||||
| const MLoop *source_loops = (MLoop *)CustomData_get_layer(&source->ldata, CD_MLOOP); | const MLoop *source_loops = (MLoop *)CustomData_get_layer(&source->ldata, CD_MLOOP); | ||||
| const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY); | const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY); | ||||
| const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP); | const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP); | ||||
| Show All 10 Lines | else { | ||||
| &target_lmap_mem, | &target_lmap_mem, | ||||
| target_polys, | target_polys, | ||||
| target_loops, | target_loops, | ||||
| target->totvert, | target->totvert, | ||||
| target->totpoly, | target->totpoly, | ||||
| target->totloop); | target->totloop); | ||||
| } | } | ||||
| for (int i = 0; i < target->totvert; i++) { | blender::threading::parallel_for( | ||||
| IndexRange(target->totvert), 2048, [&](const IndexRange range) { | |||||
| for (const int i : range) { | |||||
| BVHTreeNearest nearest; | BVHTreeNearest nearest; | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| nearest.dist_sq = FLT_MAX; | nearest.dist_sq = FLT_MAX; | ||||
| BLI_bvhtree_find_nearest( | BLI_bvhtree_find_nearest( | ||||
| bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); | bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree); | ||||
| if (nearest.index == -1) { | if (nearest.index == -1) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| MeshElemMap *source_loops = source_lmap + nearest.index; | MeshElemMap *source_loops = source_lmap + nearest.index; | ||||
| MeshElemMap *target_loops = target_lmap + i; | MeshElemMap *target_loops = target_lmap + i; | ||||
| if (target_loops->count == 0 || source_loops->count == 0) { | if (target_loops->count == 0 || source_loops->count == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* | /* | ||||
| * Average color data for loops around the source vertex into | * Average color data for loops around the source vertex into | ||||
| * the first target loop around the target vertex | * the first target loop around the target vertex | ||||
| */ | */ | ||||
| CustomData_interp(source_cdata, | CustomData_interp(source_cdata, | ||||
| target_cdata, | target_cdata, | ||||
| source_loops->indices, | source_loops->indices, | ||||
| nullptr, | nullptr, | ||||
| nullptr, | nullptr, | ||||
| source_loops->count, | source_loops->count, | ||||
| target_loops->indices[0]); | target_loops->indices[0]); | ||||
| void *elem = POINTER_OFFSET(target_data, size_t(target_loops->indices[0]) * data_size); | void *elem = POINTER_OFFSET(target_data, | ||||
| size_t(target_loops->indices[0]) * data_size); | |||||
| /* Copy to rest of target loops. */ | /* Copy to rest of target loops. */ | ||||
| for (int j = 1; j < target_loops->count; j++) { | for (int j = 1; j < target_loops->count; j++) { | ||||
| memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size), | memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size), | ||||
| elem, | elem, | ||||
| data_size); | data_size); | ||||
| } | } | ||||
| } | } | ||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| MEM_SAFE_FREE(source_lmap); | MEM_SAFE_FREE(source_lmap); | ||||
| MEM_SAFE_FREE(source_lmap_mem); | MEM_SAFE_FREE(source_lmap_mem); | ||||
| MEM_SAFE_FREE(target_lmap); | MEM_SAFE_FREE(target_lmap); | ||||
| MEM_SAFE_FREE(target_lmap_mem); | MEM_SAFE_FREE(target_lmap_mem); | ||||
| free_bvhtree_from_mesh(&bvhtree); | free_bvhtree_from_mesh(&bvhtree); | ||||
| ▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines | |||||