/** * 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); }
UvVertMap *BKE_mesh_uv_vert_map_create( struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, const float limit[2], const bool selected, const bool use_winding) { UvVertMap *vmap; UvMapVert *buf; MPoly *mp; unsigned int a; int i, totuv, nverts; bool *winding = NULL; BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32); totuv = 0; /* generate UvMapVert array */ mp = mpoly; for (a = 0; a < totpoly; a++, mp++) if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) totuv += mp->totloop; if (totuv == 0) return NULL; vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap"); buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert"); vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*"); if (use_winding) { winding = MEM_callocN(sizeof(*winding) * totpoly, "winding"); } if (!vmap->vert || !vmap->buf) { BKE_mesh_uv_vert_map_free(vmap); return NULL; } mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) { float (*tf_uv)[2] = NULL; if (use_winding) { tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, (size_t)mp->totloop); } nverts = mp->totloop; for (i = 0; i < nverts; i++) { buf->tfindex = (unsigned char)i; buf->f = a; buf->separate = 0; buf->next = vmap->vert[mloop[mp->loopstart + i].v]; vmap->vert[mloop[mp->loopstart + i].v] = buf; if (use_winding) { copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv); } buf++; } if (use_winding) { winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; } } } /* sort individual uvs for each vert */ for (a = 0; a < totvert; a++) { UvMapVert *newvlist = NULL, *vlist = vmap->vert[a]; UvMapVert *iterv, *v, *lastv, *next; float *uv, *uv2, uvdiff[2]; while (vlist) { v = vlist; vlist = vlist->next; v->next = newvlist; newvlist = v; uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv; lastv = NULL; iterv = vlist; while (iterv) { next = iterv->next; uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv; sub_v2_v2v2(uvdiff, uv2, uv); if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] && (!use_winding || winding[iterv->f] == winding[v->f])) { if (lastv) lastv->next = next; else vlist = next; iterv->next = newvlist; newvlist = iterv; } else lastv = iterv; iterv = next; } newvlist->separate = 1; } vmap->vert[a] = newvlist; } if (use_winding) { MEM_freeN(winding); } BLI_buffer_free(&tf_uv_buf); return vmap; }
/** * 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 } }