Changeset View
Changeset View
Standalone View
Standalone View
source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
| Show First 20 Lines • Show All 285 Lines • ▼ Show 20 Lines | #define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1) | ||||
| uint loop_index = 0; | uint loop_index = 0; | ||||
| uint poly_index = 0; | uint poly_index = 0; | ||||
| bool has_singularities = false; | bool has_singularities = false; | ||||
| /* Vert edge adjacent map. */ | /* Vert edge adjacent map. */ | ||||
| OldVertEdgeRef **vert_adj_edges = MEM_calloc_arrayN( | OldVertEdgeRef **vert_adj_edges = MEM_calloc_arrayN( | ||||
| numVerts, sizeof(*vert_adj_edges), "vert_adj_edges in solidify"); | numVerts, sizeof(*vert_adj_edges), "vert_adj_edges in solidify"); | ||||
| /* original vertex positions (changed for degenerate geometry) */ | |||||
| float (*orig_mvert_co)[3] = MEM_malloc_arrayN( | |||||
| numVerts, sizeof(*orig_mvert_co), "orig_mvert_co in solidify"); | |||||
| /* fill in the original vertex positions */ | |||||
| for (uint i = 0; i < numVerts; i++) { | |||||
| orig_mvert_co[i][0] = orig_mvert[i].co[0]; | |||||
| orig_mvert_co[i][1] = orig_mvert[i].co[1]; | |||||
| orig_mvert_co[i][2] = orig_mvert[i].co[2]; | |||||
| } | |||||
| /* Create edge to #NewEdgeRef map. */ | /* Create edge to #NewEdgeRef map. */ | ||||
| { | { | ||||
| OldEdgeFaceRef **edge_adj_faces = MEM_calloc_arrayN( | OldEdgeFaceRef **edge_adj_faces = MEM_calloc_arrayN( | ||||
| numEdges, sizeof(*edge_adj_faces), "edge_adj_faces in solidify"); | numEdges, sizeof(*edge_adj_faces), "edge_adj_faces in solidify"); | ||||
| /* Create link_faces for edges. */ | /* Create link_faces for edges. */ | ||||
| { | { | ||||
| Show All 37 Lines | /* Create edge to #NewEdgeRef map. */ | ||||
| uint *vert_adj_edges_len = MEM_calloc_arrayN( | uint *vert_adj_edges_len = MEM_calloc_arrayN( | ||||
| numVerts, sizeof(*vert_adj_edges_len), "vert_adj_edges_len in solidify"); | numVerts, sizeof(*vert_adj_edges_len), "vert_adj_edges_len in solidify"); | ||||
| /* Calculate edge lengths and len vert_adj edges. */ | /* Calculate edge lengths and len vert_adj edges. */ | ||||
| { | { | ||||
| bool *face_singularity = MEM_calloc_arrayN( | bool *face_singularity = MEM_calloc_arrayN( | ||||
| numPolys, sizeof(*face_singularity), "face_sides_arr in solidify"); | numPolys, sizeof(*face_singularity), "face_sides_arr in solidify"); | ||||
| const float tolerance_sqr = smd->tolerance * smd->tolerance; | |||||
| uint *combined_verts = MEM_calloc_arrayN( | |||||
| numVerts, sizeof(*combined_verts), "combined_verts in solidify"); | |||||
| ed = orig_medge; | ed = orig_medge; | ||||
| for (uint i = 0; i < numEdges; i++, ed++) { | for (uint i = 0; i < numEdges; i++, ed++) { | ||||
| if (edge_adj_faces_len[i] > 0) { | if (edge_adj_faces_len[i] > 0) { | ||||
| const uint v1 = vm[ed->v1]; | uint v1 = vm[ed->v1]; | ||||
| const uint v2 = vm[ed->v2]; | uint v2 = vm[ed->v2]; | ||||
| if (v1 != v2) { | if (v1 != v2) { | ||||
| sub_v3_v3v3(edgedir, orig_mvert[v2].co, orig_mvert[v1].co); | if (v2 < v1) { | ||||
| SWAP(uint, v1, v2); | |||||
| } | |||||
| sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]); | |||||
| orig_edge_lengths[i] = len_squared_v3(edgedir); | orig_edge_lengths[i] = len_squared_v3(edgedir); | ||||
| if (orig_edge_lengths[i] <= FLT_EPSILON) { | if (orig_edge_lengths[i] <= tolerance_sqr) { | ||||
| if (v2 > v1) { | mul_v3_fl(edgedir, (combined_verts[v2] + 1) / (float)(combined_verts[v1] + combined_verts[v2] + 2)); | ||||
| add_v3_v3(orig_mvert_co[v1], edgedir); | |||||
| for (uint j = v2; j < numVerts; j++) { | for (uint j = v2; j < numVerts; j++) { | ||||
| if (vm[j] == v2) { | if (vm[j] == v2) { | ||||
| vm[j] = v1; | vm[j] = v1; | ||||
| vert_adj_edges_len[v1] += vert_adj_edges_len[j]; | |||||
| vert_adj_edges_len[j] = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| else if (v2 < v1) { | |||||
| for (uint j = v1; j < numVerts; j++) { | |||||
| if (vm[j] == v1) { | |||||
| vm[j] = v2; | |||||
| vert_adj_edges_len[v2] += vert_adj_edges_len[j]; | |||||
| vert_adj_edges_len[j] = 0; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| vert_adj_edges_len[v1] += vert_adj_edges_len[v2]; | |||||
| vert_adj_edges_len[v2] = 0; | |||||
| combined_verts[v1] += combined_verts[v2] + 1; | |||||
| if (do_shell) { | if (do_shell) { | ||||
| numNewLoops -= edge_adj_faces_len[i] * 2; | numNewLoops -= edge_adj_faces_len[i] * 2; | ||||
| } | } | ||||
| edge_adj_faces_len[i] = 0; | edge_adj_faces_len[i] = 0; | ||||
| MEM_freeN(edge_adj_faces[i]->faces); | MEM_freeN(edge_adj_faces[i]->faces); | ||||
| MEM_freeN(edge_adj_faces[i]->faces_reversed); | MEM_freeN(edge_adj_faces[i]->faces_reversed); | ||||
| MEM_freeN(edge_adj_faces[i]); | MEM_freeN(edge_adj_faces[i]); | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | /* Calculate edge lengths and len vert_adj edges. */ | ||||
| MEM_freeN(edge_adj_faces[i]->faces); | MEM_freeN(edge_adj_faces[i]->faces); | ||||
| MEM_freeN(edge_adj_faces[i]->faces_reversed); | MEM_freeN(edge_adj_faces[i]->faces_reversed); | ||||
| MEM_freeN(edge_adj_faces[i]); | MEM_freeN(edge_adj_faces[i]); | ||||
| edge_adj_faces[i] = NULL; | edge_adj_faces[i] = NULL; | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(face_singularity); | MEM_freeN(face_singularity); | ||||
| MEM_freeN(combined_verts); | |||||
| } | } | ||||
| /* Create vert_adj_edges for verts. */ | /* Create vert_adj_edges for verts. */ | ||||
| { | { | ||||
| ed = orig_medge; | ed = orig_medge; | ||||
| for (uint i = 0; i < numEdges; i++, ed++) { | for (uint i = 0; i < numEdges; i++, ed++) { | ||||
| if (edge_adj_faces_len[i] > 0) { | if (edge_adj_faces_len[i] > 0) { | ||||
| const uint vs[2] = {vm[ed->v1], vm[ed->v2]}; | const uint vs[2] = {vm[ed->v1], vm[ed->v2]}; | ||||
| ▲ Show 20 Lines • Show All 223 Lines • ▼ Show 20 Lines | /* Create edge to #NewEdgeRef map. */ | ||||
| /* Create #NewEdgeRef array. */ | /* Create #NewEdgeRef array. */ | ||||
| { | { | ||||
| ed = orig_medge; | ed = orig_medge; | ||||
| for (uint i = 0; i < numEdges; i++, ed++) { | for (uint i = 0; i < numEdges; i++, ed++) { | ||||
| const uint v1 = vm[ed->v1]; | const uint v1 = vm[ed->v1]; | ||||
| const uint v2 = vm[ed->v2]; | const uint v2 = vm[ed->v2]; | ||||
| if (edge_adj_faces_len[i] > 0) { | if (edge_adj_faces_len[i] > 0) { | ||||
| sub_v3_v3v3(edgedir, orig_mvert[v2].co, orig_mvert[v1].co); | sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]); | ||||
| mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]); | mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]); | ||||
| OldEdgeFaceRef *adj_faces = edge_adj_faces[i]; | OldEdgeFaceRef *adj_faces = edge_adj_faces[i]; | ||||
| const uint adj_len = adj_faces->faces_len; | const uint adj_len = adj_faces->faces_len; | ||||
| const uint *adj_faces_faces = adj_faces->faces; | const uint *adj_faces_faces = adj_faces->faces; | ||||
| const bool *adj_faces_reversed = adj_faces->faces_reversed; | const bool *adj_faces_reversed = adj_faces->faces_reversed; | ||||
| uint new_edges_len = 0; | uint new_edges_len = 0; | ||||
| FaceKeyPair *sorted_faces = MEM_malloc_arrayN( | FaceKeyPair *sorted_faces = MEM_malloc_arrayN( | ||||
| ▲ Show 20 Lines • Show All 812 Lines • ▼ Show 20 Lines | for (uint i = 0; i < numVerts; i++, mv++, gs_ptr++) { | ||||
| ml = ml_next + (face->face->totloop - 1); | ml = ml_next + (face->face->totloop - 1); | ||||
| MLoop *ml_prev = ml - 1; | MLoop *ml_prev = ml - 1; | ||||
| for (int m = 0; m < face->face->totloop && vm[ml->v] != i; | for (int m = 0; m < face->face->totloop && vm[ml->v] != i; | ||||
| m++, ml_next++) { | m++, ml_next++) { | ||||
| ml_prev = ml; | ml_prev = ml; | ||||
| ml = ml_next; | ml = ml_next; | ||||
| } | } | ||||
| angle = angle_v3v3v3( | angle = angle_v3v3v3( | ||||
| orig_mvert[vm[ml_prev->v]].co, mv->co, orig_mvert[vm[ml_next->v]].co); | orig_mvert_co[vm[ml_prev->v]], orig_mvert_co[i], orig_mvert_co[vm[ml_next->v]]); | ||||
| if (face->reversed) { | if (face->reversed) { | ||||
| total_angle_back += angle * ofs * ofs; | total_angle_back += angle * ofs * ofs; | ||||
| } | } | ||||
| else { | else { | ||||
| total_angle += angle * ofs * ofs; | total_angle += angle * ofs * ofs; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | for (uint i = 0; i < numVerts; i++, mv++, gs_ptr++) { | ||||
| } | } | ||||
| /* Set move_nor for boundary fix. */ | /* Set move_nor for boundary fix. */ | ||||
| if (!disable_boundary_fix && g->edges_len > 2) { | if (!disable_boundary_fix && g->edges_len > 2) { | ||||
| edge_ptr = g->edges + 1; | edge_ptr = g->edges + 1; | ||||
| float tmp[3]; | float tmp[3]; | ||||
| uint k; | uint k; | ||||
| for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) { | for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) { | ||||
| MEdge *e = orig_medge + (*edge_ptr)->old_edge; | MEdge *e = orig_medge + (*edge_ptr)->old_edge; | ||||
| sub_v3_v3v3(tmp, orig_mvert[vm[e->v1] == i ? e->v2 : e->v1].co, mv->co); | sub_v3_v3v3(tmp, orig_mvert_co[vm[e->v1] == i ? e->v2 : e->v1], orig_mvert_co[i]); | ||||
| add_v3_v3(move_nor, tmp); | add_v3_v3(move_nor, tmp); | ||||
| } | } | ||||
| if (k == 1) { | if (k == 1) { | ||||
| disable_boundary_fix = true; | disable_boundary_fix = true; | ||||
| } | } | ||||
| else { | else { | ||||
| disable_boundary_fix = normalize_v3(move_nor) == 0.0f; | disable_boundary_fix = normalize_v3(move_nor) == 0.0f; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| disable_boundary_fix = true; | disable_boundary_fix = true; | ||||
| } | } | ||||
| } | } | ||||
| /* Fix boundary verts. */ | /* Fix boundary verts. */ | ||||
| if (!disable_boundary_fix) { | if (!disable_boundary_fix) { | ||||
| /* Constraint normal, nor * constr_nor == 0 after this fix. */ | /* Constraint normal, nor * constr_nor == 0 after this fix. */ | ||||
| float constr_nor[3]; | float constr_nor[3]; | ||||
| MEdge *e0_edge = orig_medge + g->edges[0]->old_edge; | MEdge *e0_edge = orig_medge + g->edges[0]->old_edge; | ||||
| MEdge *e1_edge = orig_medge + g->edges[g->edges_len - 1]->old_edge; | MEdge *e1_edge = orig_medge + g->edges[g->edges_len - 1]->old_edge; | ||||
| float e0[3]; | float e0[3]; | ||||
| float e1[3]; | float e1[3]; | ||||
| sub_v3_v3v3( | sub_v3_v3v3( | ||||
| e0, orig_mvert[vm[e0_edge->v1] == i ? e0_edge->v2 : e0_edge->v1].co, mv->co); | e0, orig_mvert_co[vm[e0_edge->v1] == i ? e0_edge->v2 : e0_edge->v1], orig_mvert_co[i]); | ||||
| sub_v3_v3v3( | sub_v3_v3v3( | ||||
| e1, orig_mvert[vm[e1_edge->v1] == i ? e1_edge->v2 : e1_edge->v1].co, mv->co); | e1, orig_mvert_co[vm[e1_edge->v1] == i ? e1_edge->v2 : e1_edge->v1], orig_mvert_co[i]); | ||||
| if (smd->nonmanifold_boundary_mode == MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT) { | if (smd->nonmanifold_boundary_mode == MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT) { | ||||
| cross_v3_v3v3(constr_nor, e0, e1); | cross_v3_v3v3(constr_nor, e0, e1); | ||||
| } | } | ||||
| else { | else { | ||||
| float f0[3]; | float f0[3]; | ||||
| float f1[3]; | float f1[3]; | ||||
| if (g->edges[0]->faces[0]->reversed) { | if (g->edges[0]->faces[0]->reversed) { | ||||
| negate_v3_v3(f0, poly_nors[g->edges[0]->faces[0]->index]); | negate_v3_v3(f0, poly_nors[g->edges[0]->faces[0]->index]); | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | for (uint i = 0; i < numVerts; i++, mv++, gs_ptr++) { | ||||
| } | } | ||||
| } | } | ||||
| if (min_length < offset) { | if (min_length < offset) { | ||||
| scalar_vgroup *= min_length / offset; | scalar_vgroup *= min_length / offset; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| mul_v3_fl(nor, scalar_vgroup); | mul_v3_fl(nor, scalar_vgroup); | ||||
| add_v3_v3v3(g->co, nor, mv->co); | add_v3_v3v3(g->co, nor, orig_mvert_co[i]); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(g->co, mv->co); | copy_v3_v3(g->co, orig_mvert_co[i]); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(orig_mvert_co); | |||||
| if (null_faces) { | if (null_faces) { | ||||
| MEM_freeN(null_faces); | MEM_freeN(null_faces); | ||||
| } | } | ||||
| /* TODO create vertdata for intersection fixes (intersection fixing per topology region). */ | /* TODO create vertdata for intersection fixes (intersection fixing per topology region). */ | ||||
| /* Correction for adjacent one sided groups around a vert to | /* Correction for adjacent one sided groups around a vert to | ||||
| * prevent edge duplicates and null polys. */ | * prevent edge duplicates and null polys. */ | ||||
| ▲ Show 20 Lines • Show All 653 Lines • Show Last 20 Lines | |||||