Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2014-08-18 15:35:51 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2014-08-18 15:38:20 +0400
commit6c7467e0da9cf241b1eac7dfe91e6aefe1d985ce (patch)
tree29575be83368f2d641221d3bf3b3e93a17ae3865 /source/blender/blenkernel/intern/displist.c
parent05cb63ecf75095444c8ce2bc11b3067bb207d8bf (diff)
Fix T41085: Blender crashes when using "spline" or "segments" for bevel curve factor.
Root of the issue goes to the fact that bevel list calculation might drop some points if they're at the same position. This made spline length calculation goes wrong. Now the length of the bevel segments is stored in the bevel list, so values are always reliable. Initial patch by Lukas Treyer with some tweaks from me.
Diffstat (limited to 'source/blender/blenkernel/intern/displist.c')
-rw-r--r--source/blender/blenkernel/intern/displist.c168
1 files changed, 53 insertions, 115 deletions
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 43c13f1c896..e01ff24dad3 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -1356,31 +1356,57 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp
BLI_addtail(dispbase, dl);
}
+static void calc_bevfac_segment_mapping(BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
+{
+ float normlen, normsum = 0.0f;
+ float *seglen = bl->seglen;
+ int *segbevcount = bl->segbevcount;
+ int bevcount = 0, nr = bl->nr;
+
+ float bev_fl = bevfac * (bl->nr - 1);
+ *r_bev = (int)bev_fl;
+
+ while (bevcount < nr - 1) {
+ normlen = *seglen / spline_length;
+ if (normsum + normlen > bevfac){
+ bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount;
+ *r_bev = (int) bev_fl;
+ *r_blend = bev_fl - *r_bev;
+ break;
+ }
+ normsum += normlen;
+ bevcount += *segbevcount;
+ segbevcount++;
+ seglen++;
+ }
+}
-static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, float spline_length, const float *bevp_array,
+static void calc_bevfac_spline_mapping(BevList *bl, float bevfac,
+ float spline_length,
int *r_bev, float *r_blend)
{
const float len_target = bevfac * spline_length;
- float len = 0.0f;
- float len_step = 0.0f;
- int i;
- for (i = 0; i < bl->nr - 1; i++) {
- float len_next;
- len_step = bevp_array[i];
- len_next = len + len_step;
+ BevPoint *bevp = bl->bevpoints;
+ float len_next = 0.0f, len = 0.0f;
+ int i = 0, nr = bl->nr;
+
+ while (nr--) {
+ bevp++;
+ len_next = len + bevp->offset;
if (len_next > len_target) {
break;
}
len = len_next;
+ i++;
}
*r_bev = i;
- *r_blend = (len_target - len) / len_step;
+ *r_blend = (len_target - len) / bevp->offset;
}
-static void calc_bevfac_mapping_default(
- BevList *bl,
- int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
+static void calc_bevfac_mapping_default(BevList *bl,
+ int *r_start, float *r_firstblend,
+ int *r_steps, float *r_lastblend)
{
*r_start = 0;
*r_steps = bl->nr;
@@ -1388,19 +1414,11 @@ static void calc_bevfac_mapping_default(
*r_lastblend = 1.0f;
}
-static void calc_bevfac_mapping(
- Curve *cu, BevList *bl, Nurb *nu, const bool use_render_resolution,
+static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
{
- const int resolu = (nu->type == CU_POLY) ?
- 1 : (use_render_resolution && (cu->resolu_ren != 0)) ?
- cu->resolu_ren : cu->resolu;
- const int segcount = ((nu->type == CU_POLY) ? bl->nr : nu->pntsu) - 1;
-
- float l, startf, endf, tmpf, total_length = 0.0f;
- float *bevp_array = NULL;
- float *segments = NULL;
- int end = 0, i, j;
+ float tmpf, total_length = 0.0f;
+ int end = 0, i;
if ((BKE_nurb_check_valid_u(nu) == false) ||
/* not essential, but skips unnecessary calculation */
@@ -1411,57 +1429,12 @@ static void calc_bevfac_mapping(
return;
}
- if ((cu->bevfac1_mapping != CU_BEVFAC_MAP_RESOLU) ||
- (cu->bevfac2_mapping != CU_BEVFAC_MAP_RESOLU))
+ if (ELEM(cu->bevfac1_mapping,
+ CU_BEVFAC_MAP_SEGMENT,
+ CU_BEVFAC_MAP_SPLINE))
{
- BezTriple *bezt, *bezt_prev;
- BevPoint *bevp, *bevp_prev;
- int bevp_i;
-
- bevp_array = MEM_mallocN(sizeof(*bevp_array) * (bl->nr - 1), "bevp_dists");
- segments = MEM_callocN(sizeof(*segments) * segcount, "bevp_segmentlengths");
- bevp_prev = bl->bevpoints;
- bevp = bevp_prev + 1;
-
- if (nu->type == CU_BEZIER) {
- bezt_prev = nu->bezt;
- bezt = bezt_prev + 1;
- for (i = 0, bevp_i = 0; i < segcount; i++, bezt_prev++, bezt++) {
- float seglen = 0.0f;
- if (bezt_prev->h2 == HD_VECT && bezt->h1 == HD_VECT) {
- seglen = len_v3v3(bevp->vec, bevp_prev->vec);
- BLI_assert(bevp_i < bl->nr - 1);
- bevp_array[bevp_i++] = seglen;
-
- bevp_prev = bevp++;
- }
- else {
- for (j = 0; j < resolu; j++, bevp_prev = bevp++) {
- l = len_v3v3(bevp->vec, bevp_prev->vec);
- seglen += l;
- BLI_assert(bevp_i < bl->nr - 1);
- bevp_array[bevp_i++] = l;
- }
- }
- BLI_assert(i < segcount);
- segments[i] = seglen;
- total_length += seglen;
- seglen = 0.0f;
- }
- }
- else {
- float seglen = 0.0f;
- for (i = 1, j = 0; i < bl->nr; i++, bevp_prev = bevp++) {
- BLI_assert(i - 1 < bl->nr);
- bevp_array[i - 1] = len_v3v3(bevp->vec, bevp_prev->vec);
- total_length += bevp_array[i - 1];
- seglen += bevp_array[i - 1];
- if ((i % resolu) == 0 || (bl->nr - 1) == i) {
- BLI_assert(j < segcount);
- segments[j++] = seglen;
- seglen = 0.0f;
- }
- }
+ for (i = 0; i < SEGMENTSU(nu); i++) {
+ total_length += bl->seglen[i];
}
}
@@ -1470,31 +1443,18 @@ static void calc_bevfac_mapping(
{
const float start_fl = cu->bevfac1 * (bl->nr - 1);
*r_start = (int)start_fl;
-
*r_firstblend = 1.0f - (start_fl - (*r_start));
break;
}
case CU_BEVFAC_MAP_SEGMENT:
{
- float sum = 0.0f;
- const float start_fl = cu->bevfac1 * (bl->nr - 1);
- *r_start = (int)start_fl;
-
- for (i = 0; i < segcount; i++) {
- l = segments[i] / total_length;
- if (sum + l > cu->bevfac1) {
- startf = i * resolu + (cu->bevfac1 - sum) / l * resolu;
- *r_start = (int) startf;
- *r_firstblend = 1.0f - (startf - *r_start);
- break;
- }
- sum += l;
- }
+ calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
+ *r_firstblend = 1.0f - *r_firstblend;
break;
}
case CU_BEVFAC_MAP_SPLINE:
{
- calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, bevp_array, r_start, r_firstblend);
+ calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
*r_firstblend = 1.0f - *r_firstblend;
break;
}
@@ -1512,27 +1472,13 @@ static void calc_bevfac_mapping(
}
case CU_BEVFAC_MAP_SEGMENT:
{
- float sum = 0.0f;
- const float end_fl = cu->bevfac2 * (bl->nr - 1);
- end = (int)end_fl;
-
+ calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
*r_steps = end - *r_start + 2;
- for (i = 0; i < segcount; i++) {
- l = segments[i] / total_length;
- if (sum + l > cu->bevfac2) {
- endf = i * resolu + (cu->bevfac2 - sum) / l * resolu;
- end = (int)endf;
- *r_lastblend = (endf - end);
- *r_steps = end - *r_start + 2;
- break;
- }
- sum += l;
- }
break;
}
case CU_BEVFAC_MAP_SPLINE:
{
- calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, bevp_array, &end, r_lastblend);
+ calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
*r_steps = end - *r_start + 2;
break;
}
@@ -1550,13 +1496,6 @@ static void calc_bevfac_mapping(
*r_steps = bl->nr - *r_start;
*r_lastblend = 1.0f;
}
-
- if (bevp_array) {
- MEM_freeN(bevp_array);
- }
- if (segments) {
- MEM_freeN(segments);
- }
}
static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
@@ -1575,7 +1514,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
ListBase dlbev;
ListBase nubase = {NULL, NULL};
- BLI_freelistN(&(ob->curve_cache->bev));
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
/* We only re-evlauate path if evaluation is not happening for orco.
* If the calculation happens for orco, we should never free data which
@@ -1667,8 +1606,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
continue;
}
- calc_bevfac_mapping(cu, bl, nu, use_render_resolution,
- &start, &firstblend, &steps, &lastblend);
+ calc_bevfac_mapping(cu, bl, nu, &start, &firstblend, &steps, &lastblend);
}
for (dlb = dlbev.first; dlb; dlb = dlb->next) {