[Bf-blender-cvs] [896dbf836ba] soc-2019-npr: Fix strack smash for deg edges, move opti flip to own function
Sebastian Parborg
noreply at git.blender.org
Tue Jun 18 10:23:18 CEST 2019
Commit: 896dbf836ba68870ca2dcf0039e9014bddf63a28
Author: Sebastian Parborg
Date: Thu Nov 8 00:45:59 2018 +0100
Branches: soc-2019-npr
https://developer.blender.org/rB896dbf836ba68870ca2dcf0039e9014bddf63a28
Fix strack smash for deg edges, move opti flip to own function
===================================================================
M source/blender/modifiers/intern/MOD_mybmesh.c
===================================================================
diff --git a/source/blender/modifiers/intern/MOD_mybmesh.c b/source/blender/modifiers/intern/MOD_mybmesh.c
index 774d5c3fd11..e09057deaac 100644
--- a/source/blender/modifiers/intern/MOD_mybmesh.c
+++ b/source/blender/modifiers/intern/MOD_mybmesh.c
@@ -135,8 +135,9 @@ typedef struct {
BLI_Buffer *C_verts;
BLI_Buffer *cusp_verts;
BLI_Buffer *radi_vert_buffer;
- //Radial edge vert start idx
+ //Idx of next inserted vert
int new_vert_idx;
+ //Radial edge vert start idx
int radi_start_idx;
struct OpenSubdiv_Evaluator *eval;
@@ -276,7 +277,8 @@ static float get_facing_dir_nor(const float cam_loc[3], const float P[3], const
static BMVert* split_edge_and_move_nor(MeshData *m_d, BMesh *bm, BMEdge *edge, const float new_pos[3], const float new_no[3]){
//Split edge one time and move the created vert to new_pos
BMVert *vert;
- BMFace *face_arr[2];
+ int face_count = BM_edge_face_count(edge);
+ BMFace **face_arr = BLI_array_alloca(face_arr, face_count);
BMIter iter;
BMFace *face;
@@ -287,10 +289,10 @@ static BMVert* split_edge_and_move_nor(MeshData *m_d, BMesh *bm, BMEdge *edge, c
face_arr[i] = face;
}
- //if (i > 2){
- // print_v3("deg coord", edge->v1->co);
- // printf("Deg face!\n");
- //}
+ if (i > 2){
+ print_v3("deg coord", edge->v1->co);
+ printf("Deg face!\n");
+ }
//printf("Split edge!\n");
@@ -1920,6 +1922,7 @@ static void cusp_detection( MeshData *m_d ){
if(cusp_triangle(m_d->eval, m_d->cam_loc, face_index, &c_tri, &cusp)){
//We found a cusp!
float uv_1[2], uv_2[2], uv_3[2];
+ float edge_dir[3];
BMEdge *edge;
BMVert *cusp_e_vert;
@@ -1934,6 +1937,7 @@ static void cusp_detection( MeshData *m_d ){
uv_3[1] = v_arr[2];
edge = BM_edge_exists( vert_arr[0], vert_arr[1] );
cusp_e_vert = vert_arr[2];
+ sub_v3_v3v3(edge_dir, vert_arr[1]->co, vert_arr[0]->co);
} else if(b_arr[0] == b_arr[2]){
uv_1[0] = u_arr[0];
uv_2[0] = u_arr[2];
@@ -1944,6 +1948,7 @@ static void cusp_detection( MeshData *m_d ){
uv_3[1] = v_arr[1];
edge = BM_edge_exists( vert_arr[0], vert_arr[2] );
cusp_e_vert = vert_arr[1];
+ sub_v3_v3v3(edge_dir, vert_arr[2]->co, vert_arr[0]->co);
} else {
uv_1[0] = u_arr[1];
uv_2[0] = u_arr[2];
@@ -1954,6 +1959,7 @@ static void cusp_detection( MeshData *m_d ){
uv_3[1] = v_arr[0];
edge = BM_edge_exists( vert_arr[1], vert_arr[2] );
cusp_e_vert = vert_arr[0];
+ sub_v3_v3v3(edge_dir, vert_arr[2]->co, vert_arr[1]->co);
}
{
@@ -1965,13 +1971,53 @@ static void cusp_detection( MeshData *m_d ){
int v1_idx = BM_elem_index_get(edge->v1);
int v2_idx = BM_elem_index_get(edge->v2);
- if( isect_line_line_v2_point( uv_1, uv_2, uv_3, cusp_uv, edge_uv ) != ISECT_LINE_LINE_CROSS ){
- printf("Couldn't find intersection point to edge from cusp!\n");
- //TODO this is a big error so quit instead
- continue;
- }
+ //The paper suggests using a paramter space search to get the new edge intersection point
+ //however in practice this seemes to be too unpresice
+
+ //if( isect_line_line_v2_point( uv_1, uv_2, uv_3, cusp_uv, edge_uv ) != ISECT_LINE_LINE_CROSS ){
+ // printf("Couldn't find intersection point to edge from cusp!\n");
+ // //TODO this is a big error so quit instead
+ // continue;
+ //}
+
+ //m_d->eval->evaluateLimit(m_d->eval, face_index, edge_uv[0], edge_uv[1], P, du, dv);
+
+ {
+ //Search edge for sign crossing and split it!
+ float step = 0.5f;
+ float step_len = 0.25f;
+
+ float plane[4], plane_no[3], temp[3];
+ float face_dir;
+ bool search_dir;
+
+ sub_v3_v3v3(temp, cusp.cusp_co, cusp_e_vert->co);
+ cross_v3_v3v3(plane_no, temp, cusp.cusp_no);
+
+ search_dir = ( dot_v3v3(plane_no, edge_dir) < 0 );
- m_d->eval->evaluateLimit(m_d->eval, face_index, edge_uv[0], edge_uv[1], P, du, dv);
+ //TODO get search normal pointing from uv_1 to uv_2
+ plane_from_point_normal_v3(plane, cusp.cusp_co, plane_no);
+
+ for(int i = 0; i < 10; i++){
+ interp_v2_v2v2( edge_uv, uv_1, uv_2, step);
+ m_d->eval->evaluateLimit(m_d->eval, face_index, edge_uv[0], edge_uv[1], P, du, dv);
+ face_dir = dist_signed_to_plane_v3(P, plane);
+
+ if( fabs(face_dir) < 1e-14 ){
+ //We got lucky and found the zero crossing!
+ printf("--->> got lucky\n");
+ break;
+ }
+
+ if( (face_dir < 0) != search_dir ){
+ step += step_len;
+ } else {
+ step -= step_len;
+ }
+ step_len = step_len/2.0f;
+ }
+ }
float cusp_dist_to_edge1 = dist_to_line_v3(cusp.cusp_co, cusp_e_vert->co, edge->v1->co);
float cusp_dist_to_edge2 = dist_to_line_v3(cusp.cusp_co, cusp_e_vert->co, edge->v2->co);
@@ -2629,10 +2675,11 @@ static void radial_flip( MeshData *m_d ){
BMVert *edge_vert;
e = edge_arr[edge_i];
- if(e->v1 != vert){
- edge_vert = e->v1;
- } else {
- edge_vert = e->v2;
+ edge_vert = BM_edge_other_vert(e, vert);
+
+ if( edge_vert == NULL ){
+ //We have flipped this edge so it is no longer connected to "vert"
+ continue;
}
if( radial_C_vert( edge_vert, m_d ) ){
@@ -2653,9 +2700,6 @@ static void radial_flip( MeshData *m_d ){
BMLoop *l1, *l2;
BM_edge_calc_rotate(e, true, &l1, &l2);
- // new_v1 = l1->v;
- // new_v2 = l2->v;
-
if( BM_elem_index_get(l1->v) < m_d->radi_start_idx &&
BM_elem_index_get(l2->v) < m_d->radi_start_idx ){
//The flip will not increase the number of standard radial triangles
@@ -2676,7 +2720,6 @@ static void radial_flip( MeshData *m_d ){
mul_v2_m3v3(mat_coords[2], mat, l2->v->co);
if( !isect_point_tri_v2(mat_new_pos, mat_coords[0], mat_coords[1], mat_coords[2]) ){
-
//We can simply rotate it!
BM_edge_rotate(m_d->bm, e, true, 0);
flips++;
@@ -2685,9 +2728,11 @@ static void radial_flip( MeshData *m_d ){
}
//printf("Try to dissolve vert!\n");
-
+ //We will try to flip edges so that edge_vert is only connected with three edges
+ //This way, we can dissolve edge_vert and it will leave a nice triangle face
{
int edge_count2 = BM_vert_edge_count(edge_vert);
+ int flip_edges = edge_count2 - 3;
BMEdge *cur_e = e;
BMEdge **edge_arr2 = BLI_array_alloca(edge_arr2, edge_count2);
edge_idx = 0;
@@ -2698,7 +2743,8 @@ static void radial_flip( MeshData *m_d ){
BMLoop *first_loop = BM_face_vert_share_loop( cur_e->l->f, edge_vert);
BMLoop *cur_loop = first_loop;
- if( edge_count2 - 3 < 1 ){
+ if( flip_edges < 1 ){
+ //Too few edges to be able to fix it with a vertex dissolve
continue;
}
@@ -2712,34 +2758,35 @@ static void radial_flip( MeshData *m_d ){
}
while (((cur_loop = BM_vert_step_fan_loop(cur_loop, &cur_e)) != first_loop) && (cur_loop != NULL)) {
+ //Add all fan edges besides radial edges and the initial edge
+ //These will be removed by the dissolve later
if(cur_e == e || cur_e == rad1_edge || cur_e == rad2_edge){
continue;
}
edge_arr2[edge_idx] = cur_e;
edge_idx++;
-
}
if(cur_loop == NULL){
continue;
}
- for( edge_idx = 0; edge_idx < edge_count2 - 3; edge_idx++){
+ for( edge_idx = 0; edge_idx < flip_edges; edge_idx++){
BMLoop *loop1, *loop2;
BM_edge_calc_rotate(edge_arr2[edge_idx], true, &loop1, &loop2);
if( BM_edge_rotate_check_degenerate(edge_arr2[edge_idx], loop1, loop2) ){
BM_edge_rotate(m_d->bm, edge_arr2[edge_idx], true, 0);
} else {
- //Try to rotate from the other side instead
+ //Try to continue rotating from the other side
//printf("Try from other side!\n");
break;
}
}
- if( edge_idx != edge_count2 - 3 ){
- int op_idx = edge_count2 -4;
+ if( edge_idx != flip_edges ){
+ int op_idx = flip_edges - 1;
bool failed_rotate = false;
for(; edge_idx <= op_idx; op_idx--){
@@ -3115,6 +3162,132 @@ static void create_fan_copy(BMesh *bm_copy, BMFace *input_face, GHash *vhash, GH
}
}
+static void opti_edge_flip( MeshData *m_d, BLI_Buffer *inco_faces ){
+ int face_i;
+ int initial_inco_len = inco_faces->count; //Don't try to split inco faces added in this step
+
+ for(face_i = 0; face_i < initial_inco_len; face_i++){
+ IncoFace *inface = &BLI_buffer_at(inco_faces, IncoFace, face_i);
+
+ BMEdge *edge;
+ BMIter iter_e;
+ BMEdge *best_edge = NULL;
+
+ if( inface->face == NULL ){
+ //Already fixed this edge
+ continue;
+ }
+
+ BMesh *bm_fan_copy;
+ bm_fan_copy = BM_mesh_create(&bm_mesh_allocsize_default, &((struct BMeshCreateParams){0}));
+
+ GHash *vhash = BLI_ghash_ptr_new("opti edge split vhash");
+ GHash *ehash = BLI_ghash_ptr_new("opti edge split ehash");
+ GHash *fhash = BLI_ghash_ptr_new("opti face split fhash");
+
+ create_fan_copy(bm_fan_copy, inface->face, vhash, ehash, fhash);
+
+ BM_ITER_ELEM (edge, &iter_e, inface->face, BM_EDGES_OF_FACE) {
+
+ if( !BM_edge_rotate_check(edge) ){
+ continue;
+ }
+
+ BLI_Buffer *cv;
+ cv = m_d->C_verts;
+ BMLoop *l1, *l2;
+ BM_edge_calc_rotate(edge, true, &l1, &l2);
+ if( !(is_vert_in_buffer(edge->v1, cv) && is_vert_in_buffer(edge->v2, cv)) &&
+ !(is_vert_in_buffer(l1->v, cv) && is_vert_in_buffer(l2->v, cv)) ){
+ //This is not a radial triangle edge, see if we can flip it
+
+ if( !BM_edge_rotate_check_degenerate(edge, l1, l2) ){
+ continue;
+ }
+ BMesh *bm_temp = BM_mesh_copy(bm_fan_copy);
+ BMEdge *copy_e = BLI_ghash_lookup(ehash, edge);
+ BMEdge *temp_e = BM_edge_at_index_find(bm_temp, BM_elem_index_get(copy_e));
+
+ //Calculate nr of info faces of egde
+ int nr_inco_faces = 0;
+ float P[3], no[3];
+ float face_dir;
+ float cur_diff_facing = 0;
+ BMFace *face;
+ BMIter iter_f;
+ BM_ITER_ELEM (face, &iter_f, edge, BM_FACES_OF_EDGE) {
+ BM_face_calc_normal(face, no);
+ BM_face_calc_center_mean(face, P);
+
+ //Calc
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list