Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/subdiv_mesh.c
| Show First 20 Lines • Show All 940 Lines • ▼ Show 20 Lines | static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context, | ||||
| MVert *subdiv_mvert = subdiv_mesh->mvert; | MVert *subdiv_mvert = subdiv_mesh->mvert; | ||||
| MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index]; | MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index]; | ||||
| subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex); | subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex); | ||||
| } | } | ||||
| /* Get neighbor edges of the given one. | /* Get neighbor edges of the given one. | ||||
| * - neighbors[0] is an edge adjacent to edge->v1. | * - neighbors[0] is an edge adjacent to edge->v1. | ||||
| * - neighbors[1] is an edge adjacent to edge->v2. */ | * - neighbors[1] is an edge adjacent to edge->v2. */ | ||||
| static void find_edge_neighbors(const SubdivMeshContext *ctx, | static void find_edge_neighbors(const Mesh *coarse_mesh, | ||||
| const MEdge *edge, | const MEdge *edge, | ||||
| const MEdge *neighbors[2]) | const MEdge *neighbors[2]) | ||||
| { | { | ||||
| const Mesh *coarse_mesh = ctx->coarse_mesh; | |||||
| const MEdge *coarse_medge = coarse_mesh->medge; | const MEdge *coarse_medge = coarse_mesh->medge; | ||||
| neighbors[0] = NULL; | neighbors[0] = NULL; | ||||
| neighbors[1] = NULL; | neighbors[1] = NULL; | ||||
| int neighbor_counters[2] = {0, 0}; | int neighbor_counters[2] = {0, 0}; | ||||
| for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) { | for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) { | ||||
| const MEdge *current_edge = &coarse_medge[edge_index]; | const MEdge *current_edge = &coarse_medge[edge_index]; | ||||
| if (current_edge == edge) { | if (current_edge == edge) { | ||||
| continue; | continue; | ||||
| Show All 13 Lines | static void find_edge_neighbors(const Mesh *coarse_mesh, | ||||
| if (neighbor_counters[0] > 1) { | if (neighbor_counters[0] > 1) { | ||||
| neighbors[0] = NULL; | neighbors[0] = NULL; | ||||
| } | } | ||||
| if (neighbor_counters[1] > 1) { | if (neighbor_counters[1] > 1) { | ||||
| neighbors[1] = NULL; | neighbors[1] = NULL; | ||||
| } | } | ||||
| } | } | ||||
| static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx, | static void points_for_loose_edges_interpolation_get(const Mesh *coarse_mesh, | ||||
| const MEdge *coarse_edge, | const MEdge *coarse_edge, | ||||
| const MEdge *neighbors[2], | const MEdge *neighbors[2], | ||||
| float points_r[4][3]) | float points_r[4][3]) | ||||
| { | { | ||||
| const Mesh *coarse_mesh = ctx->coarse_mesh; | |||||
| const MVert *coarse_mvert = coarse_mesh->mvert; | const MVert *coarse_mvert = coarse_mesh->mvert; | ||||
| /* Middle points corresponds to the edge. */ | /* Middle points corresponds to the edge. */ | ||||
| copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co); | copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co); | ||||
| copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co); | copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co); | ||||
| /* Start point, duplicate from edge start if no neighbor. */ | /* Start point, duplicate from edge start if no neighbor. */ | ||||
| if (neighbors[0] != NULL) { | if (neighbors[0] != NULL) { | ||||
| if (neighbors[0]->v1 == coarse_edge->v1) { | if (neighbors[0]->v1 == coarse_edge->v1) { | ||||
| copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co); | copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co); | ||||
| Show All 16 Lines | if (neighbors[1] != NULL) { | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| sub_v3_v3v3(points_r[3], points_r[2], points_r[1]); | sub_v3_v3v3(points_r[3], points_r[2], points_r[1]); | ||||
| add_v3_v3(points_r[3], points_r[2]); | add_v3_v3(points_r[3], points_r[2]); | ||||
| } | } | ||||
| } | } | ||||
| void BKE_subdiv_mesh_interpolate_position_on_edge(const Mesh *coarse_mesh, | |||||
| const MEdge *coarse_edge, | |||||
| const bool is_simple, | |||||
| const float u, | |||||
| float pos_r[3]) | |||||
| { | |||||
| if (is_simple) { | |||||
| const MVert *coarse_mvert = coarse_mesh->mvert; | |||||
| const MVert *vert_1 = &coarse_mvert[coarse_edge->v1]; | |||||
| const MVert *vert_2 = &coarse_mvert[coarse_edge->v2]; | |||||
| interp_v3_v3v3(pos_r, vert_1->co, vert_2->co, u); | |||||
| } | |||||
| else { | |||||
| /* Find neighbors of the coarse edge. */ | |||||
| const MEdge *neighbors[2]; | |||||
| find_edge_neighbors(coarse_mesh, coarse_edge, neighbors); | |||||
| float points[4][3]; | |||||
| points_for_loose_edges_interpolation_get(coarse_mesh, coarse_edge, neighbors, points); | |||||
| float weights[4]; | |||||
| key_curve_position_weights(u, weights, KEY_BSPLINE); | |||||
| interp_v3_v3v3v3v3(pos_r, points[0], points[1], points[2], points[3], weights); | |||||
| } | |||||
| } | |||||
| static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx, | static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx, | ||||
| const MEdge *coarse_edge, | const MEdge *coarse_edge, | ||||
| const float u, | const float u, | ||||
| const int subdiv_vertex_index) | const int subdiv_vertex_index) | ||||
| { | { | ||||
| const Mesh *coarse_mesh = ctx->coarse_mesh; | const Mesh *coarse_mesh = ctx->coarse_mesh; | ||||
| Mesh *subdiv_mesh = ctx->subdiv_mesh; | Mesh *subdiv_mesh = ctx->subdiv_mesh; | ||||
| /* This is never used for end-points (which are copied from the original). */ | /* This is never used for end-points (which are copied from the original). */ | ||||
| Show All 20 Lines | static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context, | ||||
| const int subdiv_vertex_index) | const int subdiv_vertex_index) | ||||
| { | { | ||||
| SubdivMeshContext *ctx = foreach_context->user_data; | SubdivMeshContext *ctx = foreach_context->user_data; | ||||
| const Mesh *coarse_mesh = ctx->coarse_mesh; | const Mesh *coarse_mesh = ctx->coarse_mesh; | ||||
| const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index]; | const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index]; | ||||
| Mesh *subdiv_mesh = ctx->subdiv_mesh; | Mesh *subdiv_mesh = ctx->subdiv_mesh; | ||||
| MVert *subdiv_mvert = subdiv_mesh->mvert; | MVert *subdiv_mvert = subdiv_mesh->mvert; | ||||
| const bool is_simple = ctx->subdiv->settings.is_simple; | const bool is_simple = ctx->subdiv->settings.is_simple; | ||||
| /* Find neighbors of the current loose edge. */ | |||||
| const MEdge *neighbors[2]; | |||||
| find_edge_neighbors(ctx, coarse_edge, neighbors); | |||||
| /* Interpolate custom data when not an end point. | /* Interpolate custom data when not an end point. | ||||
| * This data has already been copied from the original vertex by #subdiv_mesh_vertex_loose. */ | * This data has already been copied from the original vertex by #subdiv_mesh_vertex_loose. */ | ||||
| if (!ELEM(u, 0.0, 1.0)) { | if (!ELEM(u, 0.0, 1.0)) { | ||||
| subdiv_mesh_vertex_of_loose_edge_interpolate(ctx, coarse_edge, u, subdiv_vertex_index); | subdiv_mesh_vertex_of_loose_edge_interpolate(ctx, coarse_edge, u, subdiv_vertex_index); | ||||
| } | } | ||||
| /* Interpolate coordinate. */ | /* Interpolate coordinate. */ | ||||
| MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index]; | MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index]; | ||||
| if (is_simple) { | BKE_subdiv_mesh_interpolate_position_on_edge( | ||||
| const MVert *coarse_mvert = coarse_mesh->mvert; | coarse_mesh, coarse_edge, is_simple, u, subdiv_vertex->co); | ||||
| const MVert *vert_1 = &coarse_mvert[coarse_edge->v1]; | |||||
| const MVert *vert_2 = &coarse_mvert[coarse_edge->v2]; | |||||
| interp_v3_v3v3(subdiv_vertex->co, vert_1->co, vert_2->co, u); | |||||
| } | |||||
| else { | |||||
| float points[4][3]; | |||||
| points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points); | |||||
| float weights[4]; | |||||
| key_curve_position_weights(u, weights, KEY_BSPLINE); | |||||
| interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights); | |||||
| } | |||||
| /* Reset flags and such. */ | /* Reset flags and such. */ | ||||
| subdiv_vertex->flag = 0; | subdiv_vertex->flag = 0; | ||||
| /* TODO(sergey): This matches old behavior, but we can as well interpolate | /* TODO(sergey): This matches old behavior, but we can as well interpolate | ||||
| * it. Maybe even using vertex varying attributes. */ | * it. Maybe even using vertex varying attributes. */ | ||||
| subdiv_vertex->bweight = 0.0f; | subdiv_vertex->bweight = 0.0f; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| ▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines | |||||