BMesh: Add API call BM_face_calc_point_in_face
Was local to knife code, but this is generally useful.
This commit is contained in:
parent
bfaebeaee6
commit
a28e014313
|
@ -150,10 +150,14 @@ static void bm_face_calc_poly_center_mean_vertex_cos(
|
|||
/**
|
||||
* For tools that insist on using triangles, ideally we would cache this data.
|
||||
*
|
||||
* \param r_loops Store face loop pointers, (f->len)
|
||||
* \param r_index Store triangle triples, indices into \a r_loops, ((f->len - 2) * 3)
|
||||
* \param use_fixed_quad: When true, always split quad along (0 -> 2) regardless of concave corners,
|
||||
* (as done in #BM_mesh_calc_tessellation).
|
||||
* \param r_loops: Store face loop pointers, (f->len)
|
||||
* \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)`
|
||||
*/
|
||||
void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3])
|
||||
void BM_face_calc_tessellation(
|
||||
const BMFace *f, const bool use_fixed_quad,
|
||||
BMLoop **r_loops, unsigned int (*r_index)[3])
|
||||
{
|
||||
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
|
||||
BMLoop *l_iter;
|
||||
|
@ -167,7 +171,7 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (
|
|||
r_index[0][1] = 1;
|
||||
r_index[0][2] = 2;
|
||||
}
|
||||
else if (f->len == 4) {
|
||||
else if (f->len == 4 && use_fixed_quad) {
|
||||
*r_loops++ = (l_iter = l_first);
|
||||
*r_loops++ = (l_iter = l_iter->next);
|
||||
*r_loops++ = (l_iter = l_iter->next);
|
||||
|
@ -201,6 +205,46 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a point inside the face.
|
||||
*/
|
||||
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
|
||||
{
|
||||
const BMLoop *l_tri[3];
|
||||
|
||||
if (f->len == 3) {
|
||||
const BMLoop *l = BM_FACE_FIRST_LOOP(f);
|
||||
ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev);
|
||||
}
|
||||
else {
|
||||
/* tessellation here seems overkill when in many cases this will be the center,
|
||||
* but without this we can't be sure the point is inside a concave face. */
|
||||
const int tottri = f->len - 2;
|
||||
BMLoop **loops = BLI_array_alloca(loops, f->len);
|
||||
unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
|
||||
int j;
|
||||
int j_best = 0; /* use as fallback when unset */
|
||||
float area_best = -1.0f;
|
||||
|
||||
BM_face_calc_tessellation(f, false, loops, index);
|
||||
|
||||
for (j = 0; j < tottri; j++) {
|
||||
const float *p1 = loops[index[j][0]]->v->co;
|
||||
const float *p2 = loops[index[j][1]]->v->co;
|
||||
const float *p3 = loops[index[j][2]]->v->co;
|
||||
const float area = area_squared_tri_v3(p1, p2, p3);
|
||||
if (area > area_best) {
|
||||
j_best = j;
|
||||
area_best = area;
|
||||
}
|
||||
}
|
||||
|
||||
ARRAY_SET_ITEMS(l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]);
|
||||
}
|
||||
|
||||
mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the area of the face
|
||||
*/
|
||||
|
|
|
@ -34,7 +34,10 @@ struct Heap;
|
|||
|
||||
void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
|
||||
|
||||
void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]);
|
||||
void BM_face_calc_tessellation(
|
||||
const BMFace *f, const bool use_fixed_quad,
|
||||
BMLoop **r_loops, unsigned int (*r_index)[3]);
|
||||
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]);
|
||||
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
|
||||
float BM_face_calc_normal_vcos(
|
||||
const BMesh *bm, const BMFace *f, float r_no[3],
|
||||
|
|
|
@ -2299,7 +2299,7 @@ static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol)
|
|||
unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
|
||||
int j;
|
||||
|
||||
BM_face_calc_tessellation(f, loops, index);
|
||||
BM_face_calc_tessellation(f, false, loops, index);
|
||||
|
||||
for (j = 0; j < tottri; j++) {
|
||||
const float *p1 = loops[index[j][0]]->v->co;
|
||||
|
|
|
@ -3341,43 +3341,6 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
|
|||
/* Knife tool as a utility function
|
||||
* that can be used for internal slicing operations */
|
||||
|
||||
/**
|
||||
* Return a point inside the face.
|
||||
*
|
||||
* tessellation here seems way overkill,
|
||||
* but without this its very hard to know of a point is inside the face
|
||||
*/
|
||||
static void edbm_mesh_knife_face_point(BMFace *f, float r_cent[3])
|
||||
{
|
||||
const int tottri = f->len - 2;
|
||||
BMLoop **loops = BLI_array_alloca(loops, f->len);
|
||||
unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
|
||||
int j;
|
||||
int j_best = 0; /* use as fallback when unset */
|
||||
float area_best = -1.0f;
|
||||
|
||||
BM_face_calc_tessellation(f, loops, index);
|
||||
|
||||
for (j = 0; j < tottri; j++) {
|
||||
const float *p1 = loops[index[j][0]]->v->co;
|
||||
const float *p2 = loops[index[j][1]]->v->co;
|
||||
const float *p3 = loops[index[j][2]]->v->co;
|
||||
float area;
|
||||
|
||||
area = area_squared_tri_v3(p1, p2, p3);
|
||||
if (area > area_best) {
|
||||
j_best = j;
|
||||
area_best = area;
|
||||
}
|
||||
}
|
||||
|
||||
mid_v3_v3v3v3(
|
||||
r_cent,
|
||||
loops[index[j_best][0]]->v->co,
|
||||
loops[index[j_best][1]]->v->co,
|
||||
loops[index[j_best][2]]->v->co);
|
||||
}
|
||||
|
||||
static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
|
||||
{
|
||||
LinkNode *p = polys;
|
||||
|
@ -3495,7 +3458,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
|
|||
BMIter fiter;
|
||||
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
|
||||
float cent[3], cent_ss[2];
|
||||
edbm_mesh_knife_face_point(f, cent);
|
||||
BM_face_calc_point_in_face(f, cent);
|
||||
knife_project_v2(kcd, cent, cent_ss);
|
||||
if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
|
||||
BM_elem_flag_enable(f, BM_ELEM_TAG);
|
||||
|
@ -3531,7 +3494,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
|
|||
|
||||
if (found) {
|
||||
float cent[3], cent_ss[2];
|
||||
edbm_mesh_knife_face_point(f, cent);
|
||||
BM_face_calc_point_in_face(f, cent);
|
||||
knife_project_v2(kcd, cent, cent_ss);
|
||||
if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) &&
|
||||
edbm_mesh_knife_point_isect(polys, cent_ss))
|
||||
|
|
Loading…
Reference in New Issue