Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| "position", | "position", | ||||
| "material_index", | "material_index", | ||||
| ".select_vert", | ".select_vert", | ||||
| ".select_edge", | ".select_edge", | ||||
| ".select_poly"}); | ".select_poly"}); | ||||
| mesh->mvert = BKE_mesh_legacy_convert_positions_to_verts( | mesh->mvert = BKE_mesh_legacy_convert_positions_to_verts( | ||||
| mesh, temp_arrays_for_legacy_format, vert_layers); | mesh, temp_arrays_for_legacy_format, vert_layers); | ||||
| mesh->mloop = BKE_mesh_legacy_convert_corners_to_loops( | |||||
| mesh, temp_arrays_for_legacy_format, loop_layers); | |||||
| BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); | BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); | ||||
| BKE_mesh_legacy_convert_selection_layers_to_flags(mesh); | BKE_mesh_legacy_convert_selection_layers_to_flags(mesh); | ||||
| BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh); | BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh); | ||||
| BKE_mesh_legacy_bevel_weight_from_layers(mesh); | BKE_mesh_legacy_bevel_weight_from_layers(mesh); | ||||
| BKE_mesh_legacy_face_set_from_generic(mesh, poly_layers); | BKE_mesh_legacy_face_set_from_generic(mesh, poly_layers); | ||||
| BKE_mesh_legacy_edge_crease_from_layers(mesh); | BKE_mesh_legacy_edge_crease_from_layers(mesh); | ||||
| BKE_mesh_legacy_sharp_edges_to_flags(mesh); | BKE_mesh_legacy_sharp_edges_to_flags(mesh); | ||||
| BKE_mesh_legacy_attribute_strings_to_flags(mesh); | BKE_mesh_legacy_attribute_strings_to_flags(mesh); | ||||
| mesh->active_color_attribute = nullptr; | mesh->active_color_attribute = nullptr; | ||||
| mesh->default_color_attribute = nullptr; | mesh->default_color_attribute = nullptr; | ||||
| BKE_mesh_legacy_convert_loose_edges_to_flag(mesh); | BKE_mesh_legacy_convert_loose_edges_to_flag(mesh); | ||||
| /* Set deprecated mesh data pointers for forward compatibility. */ | /* Set deprecated mesh data pointers for forward compatibility. */ | ||||
| mesh->medge = const_cast<MEdge *>(mesh->edges().data()); | mesh->medge = const_cast<MEdge *>(mesh->edges().data()); | ||||
| mesh->mpoly = const_cast<MPoly *>(mesh->polys().data()); | mesh->mpoly = const_cast<MPoly *>(mesh->polys().data()); | ||||
| mesh->mloop = const_cast<MLoop *>(mesh->loops().data()); | |||||
| mesh->dvert = const_cast<MDeformVert *>(mesh->deform_verts().data()); | mesh->dvert = const_cast<MDeformVert *>(mesh->deform_verts().data()); | ||||
| } | } | ||||
| CustomData_blend_write_prepare(mesh->vdata, vert_layers, names_to_skip); | CustomData_blend_write_prepare(mesh->vdata, vert_layers, names_to_skip); | ||||
| CustomData_blend_write_prepare(mesh->edata, edge_layers, names_to_skip); | CustomData_blend_write_prepare(mesh->edata, edge_layers, names_to_skip); | ||||
| CustomData_blend_write_prepare(mesh->ldata, loop_layers, names_to_skip); | CustomData_blend_write_prepare(mesh->ldata, loop_layers, names_to_skip); | ||||
| CustomData_blend_write_prepare(mesh->pdata, poly_layers, names_to_skip); | CustomData_blend_write_prepare(mesh->pdata, poly_layers, names_to_skip); | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| return is_sublayer_name(UV_VERTSEL_NAME, name) || is_sublayer_name(UV_EDGESEL_NAME, name) || | return is_sublayer_name(UV_VERTSEL_NAME, name) || is_sublayer_name(UV_EDGESEL_NAME, name) || | ||||
| is_sublayer_name(UV_PINNED_NAME, name); | is_sublayer_name(UV_PINNED_NAME, name); | ||||
| } | } | ||||
| /** Thresh is threshold for comparing vertices, UVs, vertex colors, weights, etc. */ | /** Thresh is threshold for comparing vertices, UVs, vertex colors, weights, etc. */ | ||||
| static int customdata_compare( | static int customdata_compare( | ||||
| CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh) | CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, const float thresh) | ||||
| { | { | ||||
| CustomDataLayer *l1, *l2; | CustomDataLayer *l1, *l2; | ||||
| int layer_count1 = 0, layer_count2 = 0, j; | int layer_count1 = 0, layer_count2 = 0, j; | ||||
| const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_MDEFORMVERT; | const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_MDEFORMVERT; | ||||
| const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic; | const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic; | ||||
| const Span<MLoop> loops_1 = m1->loops(); | |||||
| const Span<MLoop> loops_2 = m2->loops(); | |||||
| /* The uv selection / pin layers are ignored in the comparisons because | /* The uv selection / pin layers are ignored in the comparisons because | ||||
| * the original flags they replace were ignored as well. Because of the | * the original flags they replace were ignored as well. Because of the | ||||
| * lazy creation of these layers it would need careful handling of the | * lazy creation of these layers it would need careful handling of the | ||||
| * test files to compare these layers. For now it has been decided to | * test files to compare these layers. For now it has been decided to | ||||
| * skip them. | * skip them. | ||||
| */ | */ | ||||
| Show All 32 Lines | |||||
| l2 = c2->layers + i2; | l2 = c2->layers + i2; | ||||
| if (l1->type != l2->type || !STREQ(l1->name, l2->name) || l2->anonymous_id != nullptr) { | if (l1->type != l2->type || !STREQ(l1->name, l2->name) || l2->anonymous_id != nullptr) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* At this point `l1` and `l2` have the same name and type, so they should be compared. */ | /* At this point `l1` and `l2` have the same name and type, so they should be compared. */ | ||||
| found_corresponding_layer = true; | found_corresponding_layer = true; | ||||
| if (StringRef(l1->name) == ".corner_edge") { | |||||
| /* TODO(Hans): This attribute wasn't tested before loops were refactored into separate | |||||
| * corner edges and corner verts attributes. Remove after updating tests. */ | |||||
| continue; | |||||
| } | |||||
| switch (l1->type) { | switch (l1->type) { | ||||
| /* We're order-agnostic for edges here. */ | /* We're order-agnostic for edges here. */ | ||||
| case CD_MEDGE: { | case CD_MEDGE: { | ||||
| MEdge *e1 = (MEdge *)l1->data; | MEdge *e1 = (MEdge *)l1->data; | ||||
| MEdge *e2 = (MEdge *)l2->data; | MEdge *e2 = (MEdge *)l2->data; | ||||
| int etot = m1->totedge; | int etot = m1->totedge; | ||||
| EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); | EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); | ||||
| Show All 10 Lines | |||||
| break; | break; | ||||
| } | } | ||||
| case CD_MPOLY: { | case CD_MPOLY: { | ||||
| MPoly *p1 = (MPoly *)l1->data; | MPoly *p1 = (MPoly *)l1->data; | ||||
| MPoly *p2 = (MPoly *)l2->data; | MPoly *p2 = (MPoly *)l2->data; | ||||
| int ptot = m1->totpoly; | int ptot = m1->totpoly; | ||||
| for (j = 0; j < ptot; j++, p1++, p2++) { | for (j = 0; j < ptot; j++, p1++, p2++) { | ||||
| int k; | |||||
| if (p1->totloop != p2->totloop) { | if (p1->totloop != p2->totloop) { | ||||
| return MESHCMP_POLYMISMATCH; | return MESHCMP_POLYMISMATCH; | ||||
| } | } | ||||
| const MLoop *lp1 = &loops_1[p1->loopstart]; | |||||
| const MLoop *lp2 = &loops_2[p2->loopstart]; | |||||
| for (k = 0; k < p1->totloop; k++, lp1++, lp2++) { | |||||
| if (lp1->v != lp2->v) { | |||||
| return MESHCMP_POLYVERTMISMATCH; | |||||
| } | |||||
| } | |||||
| } | |||||
| break; | |||||
| } | |||||
| case CD_MLOOP: { | |||||
| MLoop *lp1 = (MLoop *)l1->data; | |||||
| MLoop *lp2 = (MLoop *)l2->data; | |||||
| int ltot = m1->totloop; | |||||
| for (j = 0; j < ltot; j++, lp1++, lp2++) { | |||||
| if (lp1->v != lp2->v) { | |||||
| return MESHCMP_LOOPMISMATCH; | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case CD_PROP_BYTE_COLOR: { | case CD_PROP_BYTE_COLOR: { | ||||
| MLoopCol *lp1 = (MLoopCol *)l1->data; | MLoopCol *lp1 = (MLoopCol *)l1->data; | ||||
| MLoopCol *lp2 = (MLoopCol *)l2->data; | MLoopCol *lp2 = (MLoopCol *)l2->data; | ||||
| int ltot = m1->totloop; | int ltot = m1->totloop; | ||||
| ▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | |||||
| if (me1->totpoly != me2->totpoly) { | if (me1->totpoly != me2->totpoly) { | ||||
| return "Number of faces don't match"; | return "Number of faces don't match"; | ||||
| } | } | ||||
| if (me1->totloop != me2->totloop) { | if (me1->totloop != me2->totloop) { | ||||
| return "Number of loops don't match"; | return "Number of loops don't match"; | ||||
| } | } | ||||
| if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, me2, thresh))) { | if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, thresh))) { | ||||
| return cmpcode_to_str(c); | return cmpcode_to_str(c); | ||||
| } | } | ||||
| if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, me2, thresh))) { | if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, thresh))) { | ||||
| return cmpcode_to_str(c); | return cmpcode_to_str(c); | ||||
| } | } | ||||
| if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, me2, thresh))) { | if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, thresh))) { | ||||
| return cmpcode_to_str(c); | return cmpcode_to_str(c); | ||||
| } | } | ||||
| if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, me2, thresh))) { | if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, thresh))) { | ||||
| return cmpcode_to_str(c); | return cmpcode_to_str(c); | ||||
| } | } | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| bool BKE_mesh_attribute_required(const char *name) | bool BKE_mesh_attribute_required(const char *name) | ||||
| { | { | ||||
| return StringRef(name) == "position"; | return ELEM(StringRef(name), "position", ".corner_vert", ".corner_edge"); | ||||
| } | } | ||||
| void BKE_mesh_ensure_skin_customdata(Mesh *me) | void BKE_mesh_ensure_skin_customdata(Mesh *me) | ||||
| { | { | ||||
| BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr; | BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr; | ||||
| MVertSkin *vs; | MVertSkin *vs; | ||||
| if (bm) { | if (bm) { | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| if (!CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position")) { | if (!CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position")) { | ||||
| CustomData_add_layer_named( | CustomData_add_layer_named( | ||||
| &mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position"); | &mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position"); | ||||
| } | } | ||||
| if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) { | if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) { | ||||
| CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, mesh->totedge); | CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, mesh->totedge); | ||||
| } | } | ||||
| if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) { | if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert")) { | ||||
| CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, mesh->totloop); | CustomData_add_layer_named( | ||||
| &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totloop, ".corner_vert"); | |||||
| } | |||||
| if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) { | |||||
| CustomData_add_layer_named( | |||||
| &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totloop, ".corner_edge"); | |||||
| } | } | ||||
| if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) { | if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) { | ||||
| CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly); | CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly); | ||||
| } | } | ||||
| if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) { | if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) { | ||||
| CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, mesh->totface); | CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, mesh->totface); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| me->flag |= ME_AUTOSMOOTH; | me->flag |= ME_AUTOSMOOTH; | ||||
| me->smoothresh = auto_smooth_angle; | me->smoothresh = auto_smooth_angle; | ||||
| } | } | ||||
| else { | else { | ||||
| me->flag &= ~ME_AUTOSMOOTH; | me->flag &= ~ME_AUTOSMOOTH; | ||||
| } | } | ||||
| } | } | ||||
| int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, int vert) | int poly_find_loop_from_vert(const MPoly *poly, const int *poly_corner_verts, int vert) | ||||
| { | { | ||||
| for (int j = 0; j < poly->totloop; j++, loopstart++) { | for (int j = 0; j < poly->totloop; j++) { | ||||
| if (loopstart->v == vert) { | if (poly_corner_verts[j] == vert) { | ||||
| return j; | return j; | ||||
| } | } | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| int poly_get_adj_loops_from_vert(const MPoly *poly, const MLoop *mloop, int vert, int r_adj[2]) | int poly_get_adj_loops_from_vert(const MPoly *poly, | ||||
| const int *corner_verts, | |||||
| int vert, | |||||
| int r_adj[2]) | |||||
| { | { | ||||
| int corner = poly_find_loop_from_vert(poly, &mloop[poly->loopstart], vert); | int corner = poly_find_loop_from_vert(poly, &corner_verts[poly->loopstart], vert); | ||||
| if (corner != -1) { | if (corner != -1) { | ||||
| /* vertex was found */ | /* vertex was found */ | ||||
| r_adj[0] = ME_POLY_LOOP_PREV(mloop, poly, corner)->v; | r_adj[0] = corner_verts[ME_POLY_LOOP_PREV(poly, corner)]; | ||||
| r_adj[1] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v; | r_adj[1] = corner_verts[ME_POLY_LOOP_NEXT(poly, corner)]; | ||||
| } | } | ||||
| return corner; | return corner; | ||||
| } | } | ||||
| int BKE_mesh_edge_other_vert(const MEdge *e, int v) | int BKE_mesh_edge_other_vert(const MEdge *e, int v) | ||||
| { | { | ||||
| if (e->v1 == v) { | if (e->v1 == v) { | ||||
| return e->v2; | return e->v2; | ||||
| } | } | ||||
| if (e->v2 == v) { | if (e->v2 == v) { | ||||
| return e->v1; | return e->v1; | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| void BKE_mesh_looptri_get_real_edges(const MEdge *edges, | void BKE_mesh_looptri_get_real_edges(const MEdge *edges, | ||||
| const MLoop *loops, | const int *corner_verts, | ||||
| const int *corner_edges, | |||||
| const MLoopTri *tri, | const MLoopTri *tri, | ||||
| int r_edges[3]) | int r_edges[3]) | ||||
| { | { | ||||
| for (int i = 2, i_next = 0; i_next < 3; i = i_next++) { | for (int i = 2, i_next = 0; i_next < 3; i = i_next++) { | ||||
| const MLoop *l1 = &loops[tri->tri[i]], *l2 = &loops[tri->tri[i_next]]; | const int corner_1 = tri->tri[i]; | ||||
| const MEdge *e = &edges[l1->e]; | const int corner_2 = tri->tri[i_next]; | ||||
| const int vert_1 = corner_verts[corner_1]; | |||||
| const int vert_2 = corner_verts[corner_2]; | |||||
| const int edge = corner_edges[corner_1]; | |||||
| const MEdge *e = &edges[edge]; | |||||
| bool is_real = (l1->v == e->v1 && l2->v == e->v2) || (l1->v == e->v2 && l2->v == e->v1); | bool is_real = (vert_1 == e->v1 && vert_2 == e->v2) || (vert_1 == e->v2 && vert_2 == e->v1); | ||||
| r_edges[i] = is_real ? l1->e : -1; | r_edges[i] = is_real ? edge : -1; | ||||
| } | } | ||||
| } | } | ||||
| bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3]) | bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3]) | ||||
| { | { | ||||
| using namespace blender; | using namespace blender; | ||||
| if (me->totvert == 0) { | if (me->totvert == 0) { | ||||
| return false; | return false; | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| short(*clnors)[2] = (short(*)[2])CustomData_get_layer_for_write( | short(*clnors)[2] = (short(*)[2])CustomData_get_layer_for_write( | ||||
| &mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop); | &mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop); | ||||
| const bool *sharp_edges = static_cast<const bool *>( | const bool *sharp_edges = static_cast<const bool *>( | ||||
| CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge")); | CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge")); | ||||
| const Span<float3> positions = mesh->vert_positions(); | const Span<float3> positions = mesh->vert_positions(); | ||||
| const Span<MEdge> edges = mesh->edges(); | const Span<MEdge> edges = mesh->edges(); | ||||
| const Span<MPoly> polys = mesh->polys(); | const Span<MPoly> polys = mesh->polys(); | ||||
| const Span<MLoop> loops = mesh->loops(); | |||||
| BKE_mesh_normals_loop_split(reinterpret_cast<const float(*)[3]>(positions.data()), | BKE_mesh_normals_loop_split(reinterpret_cast<const float(*)[3]>(positions.data()), | ||||
| BKE_mesh_vertex_normals_ensure(mesh), | BKE_mesh_vertex_normals_ensure(mesh), | ||||
| positions.size(), | positions.size(), | ||||
| edges.data(), | edges.data(), | ||||
| edges.size(), | edges.size(), | ||||
| loops.data(), | mesh->corner_verts().data(), | ||||
| mesh->corner_edges().data(), | |||||
| r_corner_normals, | r_corner_normals, | ||||
| loops.size(), | mesh->totloop, | ||||
| polys.data(), | polys.data(), | ||||
| BKE_mesh_poly_normals_ensure(mesh), | BKE_mesh_poly_normals_ensure(mesh), | ||||
| polys.size(), | polys.size(), | ||||
| use_split_normals, | use_split_normals, | ||||
| split_angle, | split_angle, | ||||
| sharp_edges, | sharp_edges, | ||||
| nullptr, | nullptr, | ||||
| r_lnors_spacearr, | r_lnors_spacearr, | ||||
| Show All 31 Lines | |||||