Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/shrinkwrap.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| BKE_mesh_wrapper_ensure_mdata(mesh); | BKE_mesh_wrapper_ensure_mdata(mesh); | ||||
| if (mesh->totvert <= 0) { | if (mesh->totvert <= 0) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| data->mesh = mesh; | data->mesh = mesh; | ||||
| data->polys = BKE_mesh_polys(mesh); | data->polys = BKE_mesh_polys(mesh); | ||||
| data->corner_edges = mesh->corner_edges().data(); | |||||
| data->vert_normals = BKE_mesh_vertex_normals_ensure(mesh); | data->vert_normals = BKE_mesh_vertex_normals_ensure(mesh); | ||||
| if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) { | if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) { | ||||
| data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2); | data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2); | ||||
| return data->bvh != nullptr; | return data->bvh != nullptr; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
| add_v3_v3(direction, edge_dir); | add_v3_v3(direction, edge_dir); | ||||
| } | } | ||||
| status[index] = (status[index] == 0) ? side : -1; | status[index] = (status[index] == 0) ? side : -1; | ||||
| } | } | ||||
| static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh) | static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh) | ||||
| { | { | ||||
| using namespace blender; | |||||
| const float(*positions)[3] = BKE_mesh_vert_positions(mesh); | const float(*positions)[3] = BKE_mesh_vert_positions(mesh); | ||||
| const MEdge *medge = BKE_mesh_edges(mesh); | const MEdge *medge = BKE_mesh_edges(mesh); | ||||
| const MLoop *mloop = BKE_mesh_loops(mesh); | const Span<int> corner_verts = mesh->corner_verts(); | ||||
| const Span<int> corner_edges = mesh->corner_edges(); | |||||
| /* Count faces per edge (up to 2). */ | /* Count faces per edge (up to 2). */ | ||||
| char *edge_mode = static_cast<char *>( | char *edge_mode = static_cast<char *>( | ||||
| MEM_calloc_arrayN(size_t(mesh->totedge), sizeof(char), __func__)); | MEM_calloc_arrayN(size_t(mesh->totedge), sizeof(char), __func__)); | ||||
| for (int i = 0; i < mesh->totloop; i++) { | for (int i = 0; i < mesh->totloop; i++) { | ||||
| uint eidx = mloop[i].e; | const int eidx = corner_edges[i]; | ||||
| if (edge_mode[eidx] < 2) { | if (edge_mode[eidx] < 2) { | ||||
| edge_mode[eidx]++; | edge_mode[eidx]++; | ||||
| } | } | ||||
| } | } | ||||
| /* Build the boundary edge bitmask. */ | /* Build the boundary edge bitmask. */ | ||||
| BLI_bitmap *edge_is_boundary = BLI_BITMAP_NEW(mesh->totedge, | BLI_bitmap *edge_is_boundary = BLI_BITMAP_NEW(mesh->totedge, | ||||
| Show All 25 Lines | |||||
| const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh); | const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh); | ||||
| int totlooptri = BKE_mesh_runtime_looptri_len(mesh); | int totlooptri = BKE_mesh_runtime_looptri_len(mesh); | ||||
| BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(totlooptri, | BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(totlooptri, | ||||
| "ShrinkwrapBoundaryData::looptri_is_boundary"); | "ShrinkwrapBoundaryData::looptri_is_boundary"); | ||||
| for (int i = 0; i < totlooptri; i++) { | for (int i = 0; i < totlooptri; i++) { | ||||
| int edges[3]; | int edges[3]; | ||||
| BKE_mesh_looptri_get_real_edges(medge, mloop, &mlooptri[i], edges); | BKE_mesh_looptri_get_real_edges( | ||||
| medge, corner_verts.data(), corner_edges.data(), &mlooptri[i], edges); | |||||
| for (int j = 0; j < 3; j++) { | for (int j = 0; j < 3; j++) { | ||||
| if (edges[j] >= 0 && edge_mode[edges[j]]) { | if (edges[j] >= 0 && edge_mode[edges[j]]) { | ||||
| BLI_BITMAP_ENABLE(looptri_has_boundary, i); | BLI_BITMAP_ENABLE(looptri_has_boundary, i); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| static void mesh_looptri_target_project(void *userdata, | static void mesh_looptri_target_project(void *userdata, | ||||
| int index, | int index, | ||||
| const float co[3], | const float co[3], | ||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata; | const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata; | ||||
| const BVHTreeFromMesh *data = &tree->treeData; | const BVHTreeFromMesh *data = &tree->treeData; | ||||
| const MLoopTri *lt = &data->looptri[index]; | const MLoopTri *lt = &data->looptri[index]; | ||||
| const MLoop *loop[3] = { | const int tri_verts[3] = {data->corner_verts[lt->tri[0]], | ||||
| &data->loop[lt->tri[0]], &data->loop[lt->tri[1]], &data->loop[lt->tri[2]]}; | data->corner_verts[lt->tri[1]], | ||||
| const float *vtri_co[3] = {data->vert_positions[loop[0]->v], | data->corner_verts[lt->tri[2]]}; | ||||
| data->vert_positions[loop[1]->v], | const float *vtri_co[3] = {data->vert_positions[tri_verts[0]], | ||||
| data->vert_positions[loop[2]->v]}; | data->vert_positions[tri_verts[1]], | ||||
| data->vert_positions[tri_verts[2]]}; | |||||
| float raw_hit_co[3], hit_co[3], hit_no[3], dist_sq, vtri_no[3][3]; | float raw_hit_co[3], hit_co[3], hit_no[3], dist_sq, vtri_no[3][3]; | ||||
| /* First find the closest point and bail out if it's worse than the current solution. */ | /* First find the closest point and bail out if it's worse than the current solution. */ | ||||
| closest_on_tri_to_point_v3(raw_hit_co, co, UNPACK3(vtri_co)); | closest_on_tri_to_point_v3(raw_hit_co, co, UNPACK3(vtri_co)); | ||||
| dist_sq = len_squared_v3v3(co, raw_hit_co); | dist_sq = len_squared_v3v3(co, raw_hit_co); | ||||
| #ifdef TRACE_TARGET_PROJECT | #ifdef TRACE_TARGET_PROJECT | ||||
| printf("TRIANGLE %d (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) %g %g\n", | printf("TRIANGLE %d (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) %g %g\n", | ||||
| index, | index, | ||||
| UNPACK3(vtri_co[0]), | UNPACK3(vtri_co[0]), | ||||
| UNPACK3(vtri_co[1]), | UNPACK3(vtri_co[1]), | ||||
| UNPACK3(vtri_co[2]), | UNPACK3(vtri_co[2]), | ||||
| dist_sq, | dist_sq, | ||||
| nearest->dist_sq); | nearest->dist_sq); | ||||
| #endif | #endif | ||||
| if (dist_sq >= nearest->dist_sq) { | if (dist_sq >= nearest->dist_sq) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* Decode normals */ | /* Decode normals */ | ||||
| copy_v3_v3(vtri_no[0], tree->vert_normals[loop[0]->v]); | copy_v3_v3(vtri_no[0], tree->vert_normals[tri_verts[0]]); | ||||
| copy_v3_v3(vtri_no[1], tree->vert_normals[loop[1]->v]); | copy_v3_v3(vtri_no[1], tree->vert_normals[tri_verts[1]]); | ||||
| copy_v3_v3(vtri_no[2], tree->vert_normals[loop[2]->v]); | copy_v3_v3(vtri_no[2], tree->vert_normals[tri_verts[2]]); | ||||
| /* Solve the equations for the triangle */ | /* Solve the equations for the triangle */ | ||||
| if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) { | if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) { | ||||
| update_hit(nearest, index, co, hit_co, hit_no); | update_hit(nearest, index, co, hit_co, hit_no); | ||||
| } | } | ||||
| /* Boundary edges */ | /* Boundary edges */ | ||||
| else if (tree->boundary && BLI_BITMAP_TEST(tree->boundary->looptri_has_boundary, index)) { | else if (tree->boundary && BLI_BITMAP_TEST(tree->boundary->looptri_has_boundary, index)) { | ||||
| const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary; | const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary; | ||||
| int edges[3]; | int edges[3]; | ||||
| BKE_mesh_looptri_get_real_edges(data->edge, data->loop, lt, edges); | BKE_mesh_looptri_get_real_edges(data->edge, data->corner_verts, tree->corner_edges, lt, edges); | ||||
| for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
| if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) { | if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) { | ||||
| target_project_edge(tree, index, co, nearest, edges[i]); | target_project_edge(tree, index, co, nearest, edges[i]); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | |||||
| float r_no[3]) | float r_no[3]) | ||||
| { | { | ||||
| const BVHTreeFromMesh *treeData = &tree->treeData; | const BVHTreeFromMesh *treeData = &tree->treeData; | ||||
| const MLoopTri *tri = &treeData->looptri[looptri_idx]; | const MLoopTri *tri = &treeData->looptri[looptri_idx]; | ||||
| const float(*vert_normals)[3] = tree->vert_normals; | const float(*vert_normals)[3] = tree->vert_normals; | ||||
| /* Interpolate smooth normals if enabled. */ | /* Interpolate smooth normals if enabled. */ | ||||
| if ((tree->polys[tri->poly].flag & ME_SMOOTH) != 0) { | if ((tree->polys[tri->poly].flag & ME_SMOOTH) != 0) { | ||||
| const uint32_t vert_indices[3] = {treeData->loop[tri->tri[0]].v, | const int vert_indices[3] = {treeData->corner_verts[tri->tri[0]], | ||||
| treeData->loop[tri->tri[1]].v, | treeData->corner_verts[tri->tri[1]], | ||||
| treeData->loop[tri->tri[2]].v}; | treeData->corner_verts[tri->tri[2]]}; | ||||
| float w[3], no[3][3], tmp_co[3]; | float w[3], no[3][3], tmp_co[3]; | ||||
| /* Custom and auto smooth split normals. */ | /* Custom and auto smooth split normals. */ | ||||
| if (tree->clnors) { | if (tree->clnors) { | ||||
| copy_v3_v3(no[0], tree->clnors[tri->tri[0]]); | copy_v3_v3(no[0], tree->clnors[tri->tri[0]]); | ||||
| copy_v3_v3(no[1], tree->clnors[tri->tri[1]]); | copy_v3_v3(no[1], tree->clnors[tri->tri[1]]); | ||||
| copy_v3_v3(no[2], tree->clnors[tri->tri[2]]); | copy_v3_v3(no[2], tree->clnors[tri->tri[2]]); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||