real fix for [#35097], (curve cap flipping).

previous commit was incorrect, the face flipping depended on the orientation of the curve.

fix by passing the bevel direction to the fill function so we can have a reliable front/back.

This also gives some speedup for all curve filling since we can avoid calculating the normal since its already known.
This commit is contained in:
Campbell Barton 2013-04-26 21:04:12 +00:00
parent 357198d885
commit 5018ea5e29
5 changed files with 35 additions and 20 deletions

@ -95,7 +95,7 @@ void BKE_displist_make_mball(struct Scene *scene, struct Object *ob);
void BKE_displist_make_mball_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase); void BKE_displist_make_mball_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4); bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, int flipnormal); void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, const float normal_proj[3], const bool flipnormal);
float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot); float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot);

@ -444,8 +444,12 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, i
} }
} }
/**
void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal) * \param normal_proj Optional normal thats used to project the scanfill verts into 2d coords.
* Pass this along if known since it saves time calculating the normal.
* \param flipnormal Flip the normal (same as passing \a normal_proj negated)
*/
void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj[3], const bool flipnormal)
{ {
ScanFillContext sf_ctx; ScanFillContext sf_ctx;
ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last; ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last;
@ -508,7 +512,10 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal)
} }
/* XXX (obedit && obedit->actcol) ? (obedit->actcol-1) : 0)) { */ /* XXX (obedit && obedit->actcol) ? (obedit->actcol-1) : 0)) { */
if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES))) { if (totvert && (tot = BLI_scanfill_calc_ex(&sf_ctx,
BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES,
normal_proj)))
{
if (tot) { if (tot) {
dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
dlnew->type = DL_INDEX3; dlnew->type = DL_INDEX3;
@ -568,6 +575,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal)
static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
{ {
const float z_up[3] = {0.0f, 0.0f, 1.0f};
ListBase front, back; ListBase front, back;
DispList *dl, *dlnew; DispList *dl, *dlnew;
float *fp, *fp1; float *fp, *fp1;
@ -624,13 +632,13 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
dl = dl->next; dl = dl->next;
} }
BKE_displist_fill(&front, dispbase, 1); BKE_displist_fill(&front, dispbase, z_up, true);
BKE_displist_fill(&back, dispbase, 0); BKE_displist_fill(&back, dispbase, z_up, false);
BKE_displist_free(&front); BKE_displist_free(&front);
BKE_displist_free(&back); BKE_displist_free(&back);
BKE_displist_fill(dispbase, dispbase, 0); BKE_displist_fill(dispbase, dispbase, z_up, false);
} }
static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase) static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
@ -642,7 +650,8 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
bevels_to_filledpoly(cu, dispbase); bevels_to_filledpoly(cu, dispbase);
} }
else { else {
BKE_displist_fill(dispbase, dispbase, 0); /* TODO, investigate passing zup instead of NULL */
BKE_displist_fill(dispbase, dispbase, NULL,0);
} }
} }
@ -1436,6 +1445,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
DispList *dlb; DispList *dlb;
ListBase bottom_capbase = {NULL, NULL}; ListBase bottom_capbase = {NULL, NULL};
ListBase top_capbase = {NULL, NULL}; ListBase top_capbase = {NULL, NULL};
float bottom_no[3] = {0.0f};
float top_no[3] = {0.0f};
for (dlb = dlbev.first; dlb; dlb = dlb->next) { for (dlb = dlbev.first; dlb; dlb = dlb->next) {
const float bevfac1 = min_ff(cu->bevfac1, cu->bevfac2); const float bevfac1 = min_ff(cu->bevfac1, cu->bevfac2);
@ -1527,10 +1538,14 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data); rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data);
if (cu->bevobj && (cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) { if (cu->bevobj && (cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) {
if (a == 1) if (a == 1) {
fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase); fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase);
if (a == steps - 1) negate_v3_v3(bottom_no, bevp->dir);
}
if (a == steps - 1) {
fillBevelCap(nu, dlb, cur_data, &top_capbase); fillBevelCap(nu, dlb, cur_data, &top_capbase);
copy_v3_v3(top_no, bevp->dir);
}
} }
} }
@ -1539,8 +1554,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
} }
if (bottom_capbase.first) { if (bottom_capbase.first) {
BKE_displist_fill(&bottom_capbase, dispbase, false); BKE_displist_fill(&bottom_capbase, dispbase, bottom_no, false);
BKE_displist_fill(&top_capbase, dispbase, true); BKE_displist_fill(&top_capbase, dispbase, top_no, false);
BKE_displist_free(&bottom_capbase); BKE_displist_free(&bottom_capbase);
BKE_displist_free(&top_capbase); BKE_displist_free(&top_capbase);
} }

@ -867,7 +867,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
float *min_xy_p, *max_xy_p; float *min_xy_p, *max_xy_p;
short a, c, poly = 0, ok = 0, toggle = 0; short a, c, poly = 0, ok = 0, toggle = 0;
int totfaces = 0; /* total faces added */ int totfaces = 0; /* total faces added */
int co_x, co_y; float mat_2d[3][3];
/* reset variables */ /* reset variables */
eve = sf_ctx->fillvertbase.first; eve = sf_ctx->fillvertbase.first;
@ -960,7 +960,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
return 0; return 0;
} }
axis_dominant_v3(&co_x, &co_y, n); axis_dominant_v3_to_m3(mat_2d, n);
} }
@ -968,8 +968,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
if (flag & BLI_SCANFILL_CALC_HOLES) { if (flag & BLI_SCANFILL_CALC_HOLES) {
eve = sf_ctx->fillvertbase.first; eve = sf_ctx->fillvertbase.first;
while (eve) { while (eve) {
eve->xy[0] = eve->co[co_x]; mul_v2_m3v3(eve->xy, mat_2d, eve->co);
eve->xy[1] = eve->co[co_y];
/* get first vertex with no poly number */ /* get first vertex with no poly number */
if (eve->poly_nr == 0) { if (eve->poly_nr == 0) {
@ -1016,8 +1015,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
eve = sf_ctx->fillvertbase.first; eve = sf_ctx->fillvertbase.first;
while (eve) { while (eve) {
eve->xy[0] = eve->co[co_x]; mul_v2_m3v3(eve->xy, mat_2d, eve->co);
eve->xy[1] = eve->co[co_y];
eve->poly_nr = poly; eve->poly_nr = poly;
eve = eve->next; eve = eve->next;
} }

@ -144,6 +144,7 @@ static void draw_triangulated(const int mcords[][2], const short tot)
DispList *dl; DispList *dl;
float *fp; float *fp;
int a; int a;
const float z_up[3] = {0.0f, 0.0f, 1.0f};
/* make displist */ /* make displist */
dl = MEM_callocN(sizeof(DispList), "poly disp"); dl = MEM_callocN(sizeof(DispList), "poly disp");
@ -159,7 +160,7 @@ static void draw_triangulated(const int mcords[][2], const short tot)
} }
/* do the fill */ /* do the fill */
BKE_displist_fill(&lb, &lb, 0); BKE_displist_fill(&lb, &lb, z_up, false);
/* do the draw */ /* do the draw */
dl = lb.first; /* filldisplist adds in head of list */ dl = lb.first; /* filldisplist adds in head of list */

@ -1343,7 +1343,8 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
} }
else if (totpoints) { else if (totpoints) {
/* now make the list to return */ /* now make the list to return */
BKE_displist_fill(&dispbase, &dispbase, 0); /* TODO, add normal arg */
BKE_displist_fill(&dispbase, &dispbase, NULL, false);
/* The faces are stored in a new DisplayList /* The faces are stored in a new DisplayList
* thats added to the head of the listbase */ * thats added to the head of the listbase */