/** * Triangulates the given (convex or concave) simple polygon to a list of triangle vertices. * \param vertices pairs describing vertices of the polygon, in either clockwise or counterclockwise order. * \return triples of triangle indices in clockwise order. * Note the returned array is reused for later calls to the same method. */ void BLI_polyfill_calc_ex( const float (*coords)[2], const unsigned int coords_tot, unsigned int (*r_tris)[3], unsigned int *r_indices, eSign *r_coords_sign) { PolyFill pf; /* localize */ unsigned int *indices = r_indices; eSign *coords_sign = r_coords_sign; unsigned int i; /* assign all polyfill members here */ pf.indices = r_indices; pf.coords = coords; pf.coords_tot = coords_tot; pf.coords_sign = r_coords_sign; #ifdef USE_CONVEX_SKIP pf.coords_tot_concave = 0; #endif pf.tris = r_tris; pf.tris_tot = 0; if ((coords_tot < 3) || cross_poly_v2((int)coords_tot, (float(*)[2])coords) > 0.0f) { for (i = 0; i < coords_tot; i++) { indices[i] = i; } } else { /* reversed */ unsigned int n = coords_tot - 1; for (i = 0; i < coords_tot; i++) { indices[i] = (n - i); } } for (i = 0; i < coords_tot; i++) { coords_sign[i] = pf_coord_sign_calc(&pf, i); #ifdef USE_CONVEX_SKIP if (coords_sign[i] != CONVEX) { pf.coords_tot_concave += 1; } #endif } pf_triangulate(&pf); }
/** * Triangulates the given (convex or concave) simple polygon to a list of triangle vertices. * * \param coords pairs describing vertices of the polygon, in either clockwise or counterclockwise order. * \return triples of triangle indices in clockwise order. * Note the returned array is reused for later calls to the same method. */ static void polyfill_prepare( PolyFill *pf, const float (*coords)[2], const unsigned int coords_tot, int coords_sign, unsigned int (*r_tris)[3], PolyIndex *r_indices) { /* localize */ PolyIndex *indices = r_indices; unsigned int i; /* assign all polyfill members here */ pf->indices = r_indices; pf->coords = coords; pf->coords_tot = coords_tot; #ifdef USE_CONVEX_SKIP pf->coords_tot_concave = 0; #endif pf->tris = r_tris; pf->tris_tot = 0; if (coords_sign == 0) { coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1; } else { /* chech we're passing in correcty args */ #ifndef NDEBUG if (coords_sign == 1) { BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f); } else { BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f); } #endif } if (coords_sign == 1) { for (i = 0; i < coords_tot; i++) { indices[i].next = &indices[i + 1]; indices[i].prev = &indices[i - 1]; indices[i].index = i; } } else { /* reversed */ unsigned int n = coords_tot - 1; for (i = 0; i < coords_tot; i++) { indices[i].next = &indices[i + 1]; indices[i].prev = &indices[i - 1]; indices[i].index = (n - i); } } indices[0].prev = &indices[coords_tot - 1]; indices[coords_tot - 1].next = &indices[0]; for (i = 0; i < coords_tot; i++) { PolyIndex *pi = &indices[i]; pf_coord_sign_calc(pf, pi); #ifdef USE_CONVEX_SKIP if (pi->sign != CONVEX) { pf->coords_tot_concave += 1; } #endif } }
static void pf_triangulate(PolyFill *pf) { /* localize */ PolyIndex *pi_ear; #ifdef USE_CLIP_EVEN PolyIndex *pi_ear_init = pf->indices; #endif #ifdef USE_CLIP_SWEEP bool reverse = false; #endif while (pf->coords_tot > 3) { PolyIndex *pi_prev, *pi_next; eSign sign_orig_prev, sign_orig_next; pi_ear = pf_ear_tip_find( pf #ifdef USE_CLIP_EVEN , pi_ear_init #endif #ifdef USE_CLIP_SWEEP , reverse #endif ); #ifdef USE_CLIP_SWEEP #ifdef USE_CLIP_EVEN if (pi_ear != pi_ear_init) { reverse = !reverse; } #else if (pi_ear != pf->indices) { reverse = !reverse; } #endif #endif #ifdef USE_CONVEX_SKIP if (pi_ear->sign != CONVEX) { pf->coords_tot_concave -= 1; } #endif pi_prev = pi_ear->prev; pi_next = pi_ear->next; pf_ear_tip_cut(pf, pi_ear); /* The type of the two vertices adjacent to the clipped vertex may have changed. */ sign_orig_prev = pi_prev->sign; sign_orig_next = pi_next->sign; /* check if any verts became convex the (else if) * case is highly unlikely but may happen with degenerate polygons */ if (sign_orig_prev != CONVEX) { pf_coord_sign_calc(pf, pi_prev); #ifdef USE_CONVEX_SKIP if (pi_prev->sign == CONVEX) { pf->coords_tot_concave -= 1; #ifdef USE_KDTREE kdtree2d_node_remove(&pf->kdtree, pi_prev->index); #endif } #endif } if (sign_orig_next != CONVEX) { pf_coord_sign_calc(pf, pi_next); #ifdef USE_CONVEX_SKIP if (pi_next->sign == CONVEX) { pf->coords_tot_concave -= 1; #ifdef USE_KDTREE kdtree2d_node_remove(&pf->kdtree, pi_next->index); #endif } #endif } #ifdef USE_CLIP_EVEN #ifdef USE_CLIP_SWEEP pi_ear_init = reverse ? pi_next->next : pi_prev->prev; #else pi_ear_init = pi_next->next; #endif #endif } if (pf->coords_tot == 3) { unsigned int *tri = pf_tri_add(pf); pi_ear = pf->indices; tri[0] = pi_ear->index; pi_ear = pi_ear->next; tri[1] = pi_ear->index; pi_ear = pi_ear->next; tri[2] = pi_ear->index; } }
static void pf_triangulate(PolyFill *pf) { /* localize */ eSign *coords_sign = pf->coords_sign; unsigned int index_ear_tip = 0; while (pf->coords_tot > 3) { unsigned int i_prev, i_next; #ifdef USE_CONVEX_SKIP eSign sign_orig_prev, sign_orig_next; #endif #ifdef USE_CLIP_EVEN index_ear_tip = pf_ear_tip_find(pf, index_ear_tip); #else index_ear_tip = pf_ear_tip_find(pf); #endif #ifdef USE_CONVEX_SKIP if (coords_sign[index_ear_tip] != CONVEX) { pf->coords_tot_concave -= 1; } #endif pf_ear_tip_cut(pf, index_ear_tip); /* The type of the two vertices adjacent to the clipped vertex may have changed. */ i_prev = pf_index_prev(pf, index_ear_tip); i_next = (index_ear_tip == pf->coords_tot) ? 0 : index_ear_tip; #ifdef USE_CONVEX_SKIP sign_orig_prev = coords_sign[i_prev]; sign_orig_next = coords_sign[i_next]; #endif coords_sign[i_prev] = pf_coord_sign_calc(pf, i_prev); coords_sign[i_next] = pf_coord_sign_calc(pf, i_next); #ifdef USE_CONVEX_SKIP /* check if any verts became convex the (else if) * case is highly unlikely but may happen with degenerate polygons */ if ((sign_orig_prev != CONVEX) && (coords_sign[i_prev] == CONVEX)) pf->coords_tot_concave -= 1; else if (UNLIKELY((sign_orig_prev == CONVEX) && (coords_sign[i_prev] != CONVEX))) pf->coords_tot_concave += 1; if ((sign_orig_next != CONVEX) && (coords_sign[i_next] == CONVEX)) pf->coords_tot_concave -= 1; else if (UNLIKELY((sign_orig_next == CONVEX) && (coords_sign[i_next] != CONVEX))) pf->coords_tot_concave += 1; #endif #ifdef USE_CLIP_EVEN index_ear_tip = i_prev; #endif } if (pf->coords_tot == 3) { unsigned int *tri = pf_tri_add(pf); tri[0] = pf->indices[0]; tri[1] = pf->indices[1]; tri[2] = pf->indices[2]; } }