diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-08-29 04:53:29 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-08-29 04:53:29 +0400 |
commit | 141dd5233ede83a6d3882713c95bba47cee90a68 (patch) | |
tree | 23cdf3e596bba784d101f9e32f234b399ffba4b1 /source/blender/blenkernel/intern | |
parent | 22b30da565de53a0a1d34079d72b08fdb54ec8e3 (diff) | |
parent | 8321acaf439b33cca0b054565be176047d289134 (diff) |
Merged changes in the trunk up to revision 50257.
Conflicts resolved:
source/blender/blenkernel/CMakeLists.txt
Diffstat (limited to 'source/blender/blenkernel/intern')
34 files changed, 2777 insertions, 1552 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index c456840637a..387d4775ad4 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -1798,7 +1798,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, if (seamEdges < 2 || seamEdges != v->numEdges) seam = 0; - if (!v->numEdges) { + if (!v->numEdges || ss->meshIFC.simpleSubdiv) { VertDataCopy(nCo, co, ss); } else if (_vert_isBoundary(v)) { @@ -2246,7 +2246,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) if (seamEdges < 2 || seamEdges != v->numEdges) seam = 0; - if (!v->numEdges) { + if (!v->numEdges || ss->meshIFC.simpleSubdiv) { VertDataCopy(nCo, co, ss); } else if (_vert_isBoundary(v)) { @@ -2827,6 +2827,11 @@ int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level) } } +int ccgSubSurf_getSimpleSubdiv(const CCGSubSurf *ss) +{ + return ss->meshIFC.simpleSubdiv; +} + /* Vert accessors */ CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v) diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index 33b37ac281c..0f96bcf172d 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -17,6 +17,7 @@ typedef struct CCGMeshIFC { int vertUserSize, edgeUserSize, faceUserSize; int numLayers; int vertDataSize; + int simpleSubdiv; } CCGMeshIFC; /***/ @@ -91,6 +92,7 @@ int ccgSubSurf_getEdgeSize (const CCGSubSurf *ss); int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level); int ccgSubSurf_getGridSize (const CCGSubSurf *ss); int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level); +int ccgSubSurf_getSimpleSubdiv (const CCGSubSurf *ss); CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v); CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a8a3d0cdbcb..a29484638c0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -541,7 +541,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob) CustomData_free(&me->pdata, me->totpoly); /* ok, this should now use new CD shapekey data, - * which shouuld be fed through the modifier + * which should be fed through the modifier * stack*/ if (tmp.totvert != me->totvert && !did_shapekeys && me->key) { printf("%s: YEEK! this should be recoded! Shape key loss!: ID '%s'\n", __func__, tmp.id.name); @@ -1793,7 +1793,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos { finaldm->recalcTessellation(finaldm); } - /* Even if tessellation is not needed, some modifiers migh have modified CD layers + /* Even if tessellation is not needed, some modifiers might have modified CD layers * (like mloopcol or mloopuv), hence we have to update those. */ else if (finaldm->dirty & DM_DIRTY_TESS_CDLAYERS) { /* A tessellation already exists, it should always have a CD_POLYINDEX. */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 111ac68b345..9b4f0a31e28 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -282,7 +282,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets) /* ........ */ -/* Note on evaluation optimisations: +/* Note on evaluation optimizations: * Optimisations currently used here play tricks with the depsgraph in order to try and * evaluate as few objects as strictly necessary to get nicer performance under standard * production conditions. For those people who really need the accurate version, @@ -323,7 +323,7 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) /* update scene for current frame */ static void motionpaths_calc_update_scene(Scene *scene) { -#if 1 // 'production' optimisations always on +#if 1 // 'production' optimizations always on Base *base, *last = NULL; /* only stuff that moves or needs display still */ @@ -431,7 +431,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) if (efra <= sfra) return; /* optimize the depsgraph for faster updates */ - /* TODO: whether this is used should depend on some setting for the level of optimisations used */ + /* TODO: whether this is used should depend on some setting for the level of optimizations used */ motionpaths_calc_optimise_depsgraph(scene, targets); /* calculate path over requested range */ @@ -1279,9 +1279,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->dup_group == NULL || part->dup_group->gobject.first == NULL) return; - for (go = part->dup_group->gobject.first; go; go = go->next) - if (go->ob == par) - return; + if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) { + return; + } } /* if we have a hair particle system, use the path cache */ @@ -1469,6 +1469,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p quat_to_mat4(obmat, q); obmat[3][3] = 1.0f; + /* add scaling if requested */ + if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0) + mult_m4_m4m4(obmat, obmat, size_mat); + } + else if (part->draw & PART_DRAW_NO_SCALE_OB) { + /* remove scaling */ + float size_mat[4][4], original_size[3]; + + mat4_to_size(original_size, obmat); + size_to_mat4(size_mat, original_size); + invert_m4(size_mat); + mult_m4_m4m4(obmat, obmat, size_mat); } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 79ee0e96450..04585791135 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1463,7 +1463,7 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3]) * * was 0.0000000000001, caused bug [#31333], smaller values give unstable * roll when toggling editmode again... - * No good value here, trying 0.000000001 as best compromize. :/ + * No good value here, trying 0.000000001 as best compromise. :/ */ if (dot_v3v3(axis, axis) > 1.0e-9f) { /* if nor is *not* a multiple of target ... */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 468861242d0..fde95e0767e 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -421,7 +421,7 @@ void BKE_brush_curve_preset(Brush *b, /*CurveMappingPreset*/ int preset) b->curve->preset = preset; curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE); - curvemapping_changed(b->curve, 0); + curvemapping_changed(b->curve, FALSE); } int BKE_brush_texture_set_nr(Brush *brush, int nr) @@ -1253,7 +1253,9 @@ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len) if (p >= len) return 0; else p = p / len; + curvemapping_initialize(br->curve); p = curvemapping_evaluateF(br->curve, 0, p); + if (p < 0.0f) p = 0.0f; else if (p > 1.0f) p = 1.0f; return p; @@ -1267,6 +1269,7 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len) else p = p / len; + curvemapping_initialize(br->curve); return curvemapping_evaluateF(br->curve, 0, p); } diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 20fae973756..d65c81b4f9b 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -56,13 +56,11 @@ /* ***************** operations on full struct ************* */ -CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy) +void curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy) { - CurveMapping *cumap; int a; float clipminx, clipminy, clipmaxx, clipmaxy; - cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap"); cumap->flag = CUMA_DO_CLIP; if (tot == 4) cumap->cur = 3; /* rhms, hack for 'col' curve? */ @@ -89,58 +87,93 @@ CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, floa } cumap->changed_timestamp = 0; +} + +CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy) +{ + CurveMapping *cumap; + + cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap"); + + curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy); return cumap; } -void curvemapping_free(CurveMapping *cumap) +void curvemapping_free_data(CurveMapping *cumap) { int a; - - if (cumap) { - for (a = 0; a < CM_TOT; a++) { - if (cumap->cm[a].curve) MEM_freeN(cumap->cm[a].curve); - if (cumap->cm[a].table) MEM_freeN(cumap->cm[a].table); - if (cumap->cm[a].premultable) MEM_freeN(cumap->cm[a].premultable); + + for (a = 0; a < CM_TOT; a++) { + if (cumap->cm[a].curve) { + MEM_freeN(cumap->cm[a].curve); + cumap->cm[a].curve = NULL; } + if (cumap->cm[a].table) { + MEM_freeN(cumap->cm[a].table); + cumap->cm[a].table = NULL; + } + if (cumap->cm[a].premultable) { + MEM_freeN(cumap->cm[a].premultable); + cumap->cm[a].premultable = NULL; + } + } +} + +void curvemapping_free(CurveMapping *cumap) +{ + if (cumap) { + curvemapping_free_data(cumap); MEM_freeN(cumap); } } -CurveMapping *curvemapping_copy(CurveMapping *cumap) +void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap) { int a; - + + *target = *cumap; + + for (a = 0; a < CM_TOT; a++) { + if (cumap->cm[a].curve) + target->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve); + if (cumap->cm[a].table) + target->cm[a].table = MEM_dupallocN(cumap->cm[a].table); + if (cumap->cm[a].premultable) + target->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable); + } +} + +CurveMapping *curvemapping_copy(CurveMapping *cumap) +{ if (cumap) { CurveMapping *cumapn = MEM_dupallocN(cumap); - for (a = 0; a < CM_TOT; a++) { - if (cumap->cm[a].curve) - cumapn->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve); - if (cumap->cm[a].table) - cumapn->cm[a].table = MEM_dupallocN(cumap->cm[a].table); - if (cumap->cm[a].premultable) - cumapn->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable); - } + curvemapping_copy_data(cumapn, cumap); return cumapn; } return NULL; } -void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], const float white[3]) +void curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3]) { int a; - - if (white) + + for (a = 0; a < 3; a++) { + const float delta = maxf(white[a] - black[a], 1e-5f); + r_bwmul[a] = 1.0f / delta; + } +} + +void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], const float white[3]) +{ + if (white) { copy_v3_v3(cumap->white, white); - if (black) + } + if (black) { copy_v3_v3(cumap->black, black); - - for (a = 0; a < 3; a++) { - if (cumap->white[a] == cumap->black[a]) - cumap->bwmul[a] = 0.0f; - else - cumap->bwmul[a] = 1.0f / (cumap->white[a] - cumap->black[a]); - } + } + + curvemapping_set_black_white_ex(cumap->black, cumap->white, cumap->bwmul); } /* ***************** operations on single curve ************* */ @@ -173,7 +206,7 @@ void curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point) } /* removes with flag set */ -void curvemap_remove(CurveMap *cuma, int flag) +void curvemap_remove(CurveMap *cuma, const short flag) { CurveMapPoint *cmp = MEM_mallocN((cuma->totpoint) * sizeof(CurveMapPoint), "curve points"); int a, b, removed = 0; @@ -416,7 +449,7 @@ static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *nex /* in X, out Y. * X is presumed to be outside first or last */ -static float curvemap_calc_extend(CurveMap *cuma, float x, const float first[2], const float last[2]) +static float curvemap_calc_extend(const CurveMap *cuma, float x, const float first[2], const float last[2]) { if (x <= first[0]) { if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { @@ -644,7 +677,7 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) CurveMap *cuma = cumap->cm + cumap->cur; CurveMapPoint *cmp = cuma->curve; rctf *clipr = &cumap->clipr; - float thresh = 0.01f * (clipr->xmax - clipr->xmin); + float thresh = 0.01f * BLI_RCT_SIZE_X(clipr); float dx = 0.0f, dy = 0.0f; int a; @@ -682,12 +715,12 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) dy = cmp[a].y - cmp[a + 1].y; if (sqrtf(dx * dx + dy * dy) < thresh) { if (a == 0) { - cmp[a + 1].flag |= 2; + cmp[a + 1].flag |= CUMA_VECTOR; if (cmp[a + 1].flag & CUMA_SELECT) cmp[a].flag |= CUMA_SELECT; } else { - cmp[a].flag |= 2; + cmp[a].flag |= CUMA_VECTOR; if (cmp[a].flag & CUMA_SELECT) cmp[a + 1].flag |= CUMA_SELECT; } @@ -707,7 +740,7 @@ void curvemapping_changed_all(CurveMapping *cumap) for (a = 0; a < CM_TOT; a++) { if (cumap->cm[a].curve) { cumap->cur = a; - curvemapping_changed(cumap, 0); + curvemapping_changed(cumap, FALSE); } } @@ -715,7 +748,7 @@ void curvemapping_changed_all(CurveMapping *cumap) } /* table should be verified */ -float curvemap_evaluateF(CurveMap *cuma, float value) +float curvemap_evaluateF(const CurveMap *cuma, float value) { float fi; int i; @@ -737,49 +770,67 @@ float curvemap_evaluateF(CurveMap *cuma, float value) } /* works with curve 'cur' */ -float curvemapping_evaluateF(CurveMapping *cumap, int cur, float value) +float curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value) { - CurveMap *cuma = cumap->cm + cur; - - /* allocate or bail out */ - if (cuma->table == NULL) { - curvemap_make_table(cuma, &cumap->clipr); - if (cuma->table == NULL) - return 1.0f - value; - } + const CurveMap *cuma = cumap->cm + cur; return curvemap_evaluateF(cuma, value); } /* vector case */ -void curvemapping_evaluate3F(CurveMapping *cumap, float vecout[3], const float vecin[3]) +void curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - vecout[0] = curvemapping_evaluateF(cumap, 0, vecin[0]); - vecout[1] = curvemapping_evaluateF(cumap, 1, vecin[1]); - vecout[2] = curvemapping_evaluateF(cumap, 2, vecin[2]); + vecout[0] = curvemap_evaluateF(&cumap->cm[0], vecin[0]); + vecout[1] = curvemap_evaluateF(&cumap->cm[1], vecin[1]); + vecout[2] = curvemap_evaluateF(&cumap->cm[2], vecin[2]); } /* RGB case, no black/white points, no premult */ -void curvemapping_evaluateRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3]) +void curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - vecout[0] = curvemapping_evaluateF(cumap, 0, curvemapping_evaluateF(cumap, 3, vecin[0])); - vecout[1] = curvemapping_evaluateF(cumap, 1, curvemapping_evaluateF(cumap, 3, vecin[1])); - vecout[2] = curvemapping_evaluateF(cumap, 2, curvemapping_evaluateF(cumap, 3, vecin[2])); + vecout[0] = curvemap_evaluateF(&cumap->cm[0], curvemap_evaluateF(&cumap->cm[3], vecin[0])); + vecout[1] = curvemap_evaluateF(&cumap->cm[1], curvemap_evaluateF(&cumap->cm[3], vecin[1])); + vecout[2] = curvemap_evaluateF(&cumap->cm[2], curvemap_evaluateF(&cumap->cm[3], vecin[2])); } +/** same as #curvemapping_evaluate_premulRGBF + * but black/bwmul are passed as args for the compositor + * where they can change per pixel. + * + * Use in conjunction with #curvemapping_set_black_white_ex + * + * \param black Use instead of cumap->black + * \param bwmul Use instead of cumap->bwmul + */ +void curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, float vecout[3], const float vecin[3], + const float black[3], const float bwmul[3]) +{ + vecout[0] = curvemap_evaluateF(&cumap->cm[0], (vecin[0] - black[0]) * bwmul[0]); + vecout[1] = curvemap_evaluateF(&cumap->cm[1], (vecin[1] - black[1]) * bwmul[1]); + vecout[2] = curvemap_evaluateF(&cumap->cm[2], (vecin[2] - black[2]) * bwmul[2]); +} /* RGB with black/white points and premult. tables are checked */ -void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3]) +void curvemapping_evaluate_premulRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - float fac; - - fac = (vecin[0] - cumap->black[0]) * cumap->bwmul[0]; - vecout[0] = curvemap_evaluateF(cumap->cm, fac); - - fac = (vecin[1] - cumap->black[1]) * cumap->bwmul[1]; - vecout[1] = curvemap_evaluateF(cumap->cm + 1, fac); - - fac = (vecin[2] - cumap->black[2]) * cumap->bwmul[2]; - vecout[2] = curvemap_evaluateF(cumap->cm + 2, fac); + vecout[0] = curvemap_evaluateF(&cumap->cm[0], (vecin[0] - cumap->black[0]) * cumap->bwmul[0]); + vecout[1] = curvemap_evaluateF(&cumap->cm[1], (vecin[1] - cumap->black[1]) * cumap->bwmul[1]); + vecout[2] = curvemap_evaluateF(&cumap->cm[2], (vecin[2] - cumap->black[2]) * cumap->bwmul[2]); +} + +/* same as above, byte version */ +void curvemapping_evaluate_premulRGB(const CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3]) +{ + float vecin[3], vecout[3]; + + vecin[0] = (float) vecin_byte[0] / 255.0f; + vecin[1] = (float) vecin_byte[1] / 255.0f; + vecin[2] = (float) vecin_byte[2] / 255.0f; + + curvemapping_evaluate_premulRGBF(cumap, vecout, vecin); + + vecout_byte[0] = FTOCHAR(vecout[0]); + vecout_byte[1] = FTOCHAR(vecout[1]); + vecout_byte[2] = FTOCHAR(vecout[2]); } @@ -840,7 +891,7 @@ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) curvemapping_premultiply(cumap, 1); } -int curvemapping_RGBA_does_something(CurveMapping *cumap) +int curvemapping_RGBA_does_something(const CurveMapping *cumap) { int a; @@ -876,13 +927,12 @@ void curvemapping_initialize(CurveMapping *cumap) } } -void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size) +void curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size) { int a; *size = CM_TABLE + 1; *array = MEM_callocN(sizeof(float) * (*size) * 4, "CurveMapping"); - curvemapping_initialize(cumap); for (a = 0; a < *size; a++) { if (cumap->cm[0].table) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index e2bb1aaa2c7..a2f88781cbb 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1165,7 +1165,7 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3], float p[3], int it, int stride) { - /* note that these are not purpendicular to the curve + /* note that these are not perpendicular to the curve * they need to be rotated for this, * * This could also be optimized like BKE_curve_forward_diff_bezier */ @@ -3047,29 +3047,6 @@ void BKE_nurbList_handles_set(ListBase *editnurb, short code) } } -static void swapdata(void *adr1, void *adr2, int len) -{ - - if (len <= 0) return; - - if (len < 65) { - char adr[64]; - - memcpy(adr, adr1, len); - memcpy(adr1, adr2, len); - memcpy(adr2, adr, len); - } - else { - char *adr; - - adr = (char *)MEM_mallocN(len, "curve swap"); - memcpy(adr, adr1, len); - memcpy(adr1, adr2, len); - memcpy(adr2, adr, len); - MEM_freeN(adr); - } -} - void BKE_nurb_direction_switch(Nurb *nu) { BezTriple *bezt1, *bezt2; @@ -3077,7 +3054,9 @@ void BKE_nurb_direction_switch(Nurb *nu) float *fp1, *fp2, *tempf; int a, b; - if (nu->pntsu == 1 && nu->pntsv == 1) return; + if (nu->pntsu == 1 && nu->pntsv == 1) { + return; + } if (nu->type == CU_BEZIER) { a = nu->pntsu; @@ -3086,19 +3065,22 @@ void BKE_nurb_direction_switch(Nurb *nu) if (a & 1) a += 1; /* if odd, also swap middle content */ a /= 2; while (a > 0) { - if (bezt1 != bezt2) + if (bezt1 != bezt2) { SWAP(BezTriple, *bezt1, *bezt2); + } + + swap_v3_v3(bezt1->vec[0], bezt1->vec[2]); - swapdata(bezt1->vec[0], bezt1->vec[2], 12); - if (bezt1 != bezt2) - swapdata(bezt2->vec[0], bezt2->vec[2], 12); + if (bezt1 != bezt2) { + swap_v3_v3(bezt2->vec[0], bezt2->vec[2]); + } SWAP(char, bezt1->h1, bezt1->h2); - SWAP(short, bezt1->f1, bezt1->f3); + SWAP(char, bezt1->f1, bezt1->f3); if (bezt1 != bezt2) { SWAP(char, bezt2->h1, bezt2->h2); - SWAP(short, bezt2->f1, bezt2->f3); + SWAP(char, bezt2->f1, bezt2->f3); bezt1->alfa = -bezt1->alfa; bezt2->alfa = -bezt2->alfa; } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index b04bd5bc47f..a00bea38e51 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -72,25 +72,29 @@ typedef struct LayerTypeInfo { const char *structname; /* name of the struct used, for file writing */ int structnum; /* number of structs per element, for file writing */ - /* default layer name. + /** + * default layer name. * note! when NULL this is a way to ensure there is only ever one item * see: CustomData_layertype_is_singleton() */ const char *defaultname; - /* a function to copy count elements of this layer's data + /** + * a function to copy count elements of this layer's data * (deep copy if appropriate) * if NULL, memcpy is used */ void (*copy)(const void *source, void *dest, int count); - /* a function to free any dynamically allocated components of this + /** + * a function to free any dynamically allocated components of this * layer's data (note the data pointer itself should not be freed) * size should be the size of one element of this layer's data (e.g. * LayerTypeInfo.size) */ void (*free)(void *data, int count, int size); - /* a function to interpolate between count source elements of this + /** + * a function to interpolate between count source elements of this * layer's data and store the result in dest * if weights == NULL or sub_weights == NULL, they should default to 1 * @@ -98,18 +102,24 @@ typedef struct LayerTypeInfo { * sub_weights gives the sub-element weights for each element in sources * (there should be (sub element count)^2 weights per element) * count gives the number of elements in sources + * + * \note in some cases \a dest pointer is in \a sources + * so all functions have to take this into account and delay + * applying changes while reading from sources. + * See bug [#32395] - Campbell. */ - void (*interp)(void **sources, float *weights, float *sub_weights, + void (*interp)(void **sources, const float *weights, const float *sub_weights, int count, void *dest); - /* a function to swap the data in corners of the element */ + /** a function to swap the data in corners of the element */ void (*swap)(void *data, const int *corner_indices); - /* a function to set a layer's data to default values. if NULL, the + /** + * a function to set a layer's data to default values. if NULL, the * default is assumed to be all zeros */ void (*set_default)(void *data, int count); - /* functions necessary for geometry collapse*/ + /** functions necessary for geometry collapse */ int (*equal)(void *data1, void *data2); void (*multiply)(void *data, float fac); void (*initminmax)(void *min, void *max); @@ -117,13 +127,13 @@ typedef struct LayerTypeInfo { void (*dominmax)(void *data1, void *min, void *max); void (*copyvalue)(void *source, void *dest); - /* a function to read data from a cdf file */ + /** a function to read data from a cdf file */ int (*read)(CDataFile *cdf, void *data, int count); - /* a function to write data to a cdf file */ + /** a function to write data to a cdf file */ int (*write)(CDataFile *cdf, void *data, int count); - /* a function to determine file size */ + /** a function to determine file size */ size_t (*filesize)(CDataFile *cdf, void *data, int count); } LayerTypeInfo; @@ -203,8 +213,8 @@ static void linklist_free_simple(void *link) MEM_freeN(link); } -static void layerInterp_mdeformvert(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_mdeformvert(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { MDeformVert *dvert = dest; LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */ @@ -243,6 +253,8 @@ static void layerInterp_mdeformvert(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ + /* now we know how many unique deform weights there are, so realloc */ if (dvert->dw) MEM_freeN(dvert->dw); @@ -261,8 +273,8 @@ static void layerInterp_mdeformvert(void **sources, float *weights, } -static void layerInterp_msticky(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_msticky(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { float co[2], w; MSticky *mst; @@ -276,6 +288,7 @@ static void layerInterp_msticky(void **sources, float *weights, madd_v2_v2fl(co, mst->co, w); } + /* delay writing to the destination incase dest is in sources */ mst = (MSticky *)dest; copy_v2_v2(mst->co, co); } @@ -291,13 +304,13 @@ static void layerCopy_tface(const void *source, void *dest, int count) dest_tf[i] = source_tf[i]; } -static void layerInterp_tface(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_tface(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { MTFace *tf = dest; int i, j, k; float uv[4][2] = {{0.0f}}; - float *sub_weight; + const float *sub_weight; if (count <= 0) return; @@ -318,6 +331,7 @@ static void layerInterp_tface(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ *tf = *(MTFace *)(*sources); memcpy(tf->uv, uv, sizeof(tf->uv)); } @@ -392,13 +406,13 @@ static void layerCopy_origspace_face(const void *source, void *dest, int count) dest_tf[i] = source_tf[i]; } -static void layerInterp_origspace_face(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_origspace_face(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { OrigSpaceFace *osf = dest; int i, j, k; float uv[4][2] = {{0.0f}}; - float *sub_weight; + const float *sub_weight; if (count <= 0) return; @@ -419,6 +433,8 @@ static void layerInterp_origspace_face(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ + #if 0 /* no need, this ONLY contains UV's */ *osf = *(OrigSpaceFace *)(*sources); #endif @@ -680,12 +696,12 @@ static void layerDefault_mloopcol(void *data, int count) } -static void layerInterp_mloopcol(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mloopcol(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { MLoopCol *mc = dest; int i; - float *sub_weight; + const float *sub_weight; struct { float a; float r; @@ -719,7 +735,8 @@ static void layerInterp_mloopcol(void **sources, float *weights, CLAMP(col.r, 0.0f, 255.0f); CLAMP(col.g, 0.0f, 255.0f); CLAMP(col.b, 0.0f, 255.0f); - + + /* delay writing to the destination incase dest is in sources */ mc->r = (int)col.r; mc->g = (int)col.g; mc->b = (int)col.b; @@ -768,11 +785,10 @@ static void layerAdd_mloopuv(void *data1, void *data2) add_v2_v2(l1->uv, l2->uv); } -static void layerInterp_mloopuv(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mloopuv(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { - MLoopUV *mluv = dest; - float *uv = mluv->uv; + float uv[2]; int i; zero_v2(uv); @@ -793,6 +809,9 @@ static void layerInterp_mloopuv(void **sources, float *weights, madd_v2_v2fl(uv, src->uv, weight); } } + + /* delay writing to the destination incase dest is in sources */ + copy_v2_v2(((MLoopUV *)dest)->uv, uv); } /* origspace is almost exact copy of mloopuv's, keep in sync */ @@ -838,11 +857,10 @@ static void layerAdd_mloop_origspace(void *data1, void *data2) add_v2_v2(l1->uv, l2->uv); } -static void layerInterp_mloop_origspace(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mloop_origspace(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { - OrigSpaceLoop *mluv = dest; - float *uv = mluv->uv; + float uv[2]; int i; zero_v2(uv); @@ -858,16 +876,19 @@ static void layerInterp_mloop_origspace(void **sources, float *weights, } else { for (i = 0; i < count; i++) { - float weight = weights ? weights[i] : 1; + float weight = weights ? weights[i] : 1.0f; OrigSpaceLoop *src = sources[i]; madd_v2_v2fl(uv, src->uv, weight); } } + + /* delay writing to the destination incase dest is in sources */ + copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv); } /* --- end copy */ -static void layerInterp_mcol(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mcol(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { MCol *mc = dest; int i, j, k; @@ -878,7 +899,7 @@ static void layerInterp_mcol(void **sources, float *weights, float b; } col[4] = {{0.0f}}; - float *sub_weight; + const float *sub_weight; if (count <= 0) return; @@ -907,6 +928,7 @@ static void layerInterp_mcol(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ for (j = 0; j < 4; ++j) { /* Subdivide smooth or fractal can cause problems without clamping @@ -946,33 +968,36 @@ static void layerDefault_mcol(void *data, int count) } } -static void layerInterp_bweight(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_bweight(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { - float *f = dest; + float f; float **in = (float **)sources; int i; if (count <= 0) return; - *f = 0.0f; + f = 0.0f; if (weights) { for (i = 0; i < count; ++i) { - *f += *in[i] * weights[i]; + f += *in[i] * weights[i]; } } else { for (i = 0; i < count; ++i) { - *f += *in[i]; + f += *in[i]; } } + + /* delay writing to the destination incase dest is in sources */ + *((float *)dest) = f; } -static void layerInterp_shapekey(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_shapekey(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { - float *co = dest; + float co[3]; float **in = (float **)sources; int i; @@ -990,6 +1015,9 @@ static void layerInterp_shapekey(void **sources, float *weights, add_v3_v3(co, in[i]); } } + + /* delay writing to the destination incase dest is in sources */ + copy_v3_v3((float *)dest, co); } static void layerDefault_mvert_skin(void *data, int count) @@ -1003,8 +1031,8 @@ static void layerDefault_mvert_skin(void *data, int count) } } -static void layerInterp_mvert_skin(void **sources, float *weights, - float *UNUSED(sub_weights), +static void layerInterp_mvert_skin(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { float radius[3], w; @@ -1019,6 +1047,7 @@ static void layerInterp_mvert_skin(void **sources, float *weights, madd_v3_v3fl(radius, vs->radius, w); } + /* delay writing to the destination incase dest is in sources */ vs = dest; copy_v3_v3(vs->radius, radius); vs->flag &= ~MVERT_SKIN_ROOT; @@ -1999,8 +2028,9 @@ void CustomData_interp(const CustomData *source, CustomData *dest, if (dest->layers[dest_i].type == source->layers[src_i].type) { void *src_data = source->layers[src_i].data; - for (j = 0; j < count; ++j) + for (j = 0; j < count; ++j) { sources[j] = (char *)src_data + typeInfo->size * src_indices[j]; + } dest_offset = dest_index * typeInfo->size; @@ -2590,8 +2620,9 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights CustomDataLayer *layer = &data->layers[i]; const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if (typeInfo->interp) { - for (j = 0; j < count; ++j) + for (j = 0; j < count; ++j) { sources[j] = (char *)src_blocks[j] + layer->offset; + } typeInfo->interp(sources, weights, sub_weights, count, (char *)dest_block + layer->offset); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 8db93f8b44a..06807dfcbad 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -3996,7 +3996,7 @@ void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, floa float force_intersect; float temp; - /* project force vector on the plane determined by these two neightbour points + /* project force vector on the plane determined by these two neighbor points * and calculate relative force angle from it*/ cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir); normalize_v3(tangent); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 67e7743c8a4..53c12d32bc1 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -365,7 +365,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short /* initialize replace-flag first */ *replace = 0; - /* sneaky optimisations (don't go through searching process if...): + /* sneaky optimizations (don't go through searching process if...): * - keyframe to be added is to be added out of current bounds * - keyframe to be added would replace one of the existing ones on bounds */ diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 49c3d77a527..0ffd68c9079 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -60,10 +60,8 @@ #include "BKE_curve.h" #include "BKE_displist.h" -static ListBase ttfdata = {NULL, NULL}; /* The vfont code */ - void BKE_vfont_free_data(struct VFont *vfont) { if (vfont->data) { @@ -83,7 +81,10 @@ void BKE_vfont_free_data(struct VFont *vfont) vfont->data = NULL; } - BKE_vfont_tmpfont_remove(vfont); + if (vfont->temp_pf) { + freePackedFile(vfont->temp_pf); /* NULL when the font file can't be found on disk */ + vfont->temp_pf = NULL; + } } void BKE_vfont_free(struct VFont *vf) @@ -91,7 +92,7 @@ void BKE_vfont_free(struct VFont *vf) if (vf == NULL) return; BKE_vfont_free_data(vf); - + if (vf->packedfile) { freePackedFile(vf->packedfile); vf->packedfile = NULL; @@ -128,63 +129,11 @@ static PackedFile *get_builtin_packedfile(void) } } -static void vfont_tmpfont_free(struct TmpFont *tf) -{ - if (tf->pf) { - freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */ - } - MEM_freeN(tf); -} - -void BKE_vfont_free_global_ttf(void) -{ - struct TmpFont *tf, *tf_next; - - for (tf = ttfdata.first; tf; tf = tf_next) { - tf_next = tf->next; - vfont_tmpfont_free(tf); - } - ttfdata.first = ttfdata.last = NULL; -} - -struct TmpFont *BKE_vfont_tmpfont_find(VFont *vfont) -{ - struct TmpFont *tmpfnt = NULL; - - if (vfont == NULL) return NULL; - - /* Try finding the font from font list */ - for (tmpfnt = ttfdata.first; tmpfnt; tmpfnt = tmpfnt->next) { - if (tmpfnt->vfont == vfont) { - break; - } - } - - return tmpfnt; -} - -/* assumes a VFont's tmpfont can't be in the database more then once */ -void BKE_vfont_tmpfont_remove(VFont *vfont) -{ - struct TmpFont *tmpfnt; - - tmpfnt = BKE_vfont_tmpfont_find(vfont); - - if (tmpfnt) { - vfont_tmpfont_free(tmpfnt); - BLI_remlink(&ttfdata, tmpfnt); - } -} - static VFontData *vfont_get_data(Main *bmain, VFont *vfont) { - struct TmpFont *tmpfnt = NULL; - PackedFile *tpf; - - if (vfont == NULL) return NULL; - - /* Try finding the font from font list */ - tmpfnt = BKE_vfont_tmpfont_find(vfont); + if (vfont == NULL) { + return NULL; + } /* And then set the data */ if (!vfont->data) { @@ -198,30 +147,15 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont) pf = vfont->packedfile; /* We need to copy a tmp font to memory unless it is already there */ - if (!tmpfnt) { - tpf = MEM_callocN(sizeof(*tpf), "PackedFile"); - tpf->data = MEM_mallocN(pf->size, "packFile"); - tpf->size = pf->size; - memcpy(tpf->data, pf->data, pf->size); - - /* Add temporary packed file to globals */ - tmpfnt = (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); - tmpfnt->pf = tpf; - tmpfnt->vfont = vfont; - BLI_addtail(&ttfdata, tmpfnt); + if (vfont->temp_pf == NULL) { + vfont->temp_pf = dupPackedFile(pf); } } else { pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id)); - if (!tmpfnt) { - tpf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id)); - - /* Add temporary packed file to globals */ - tmpfnt = (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); - tmpfnt->pf = tpf; - tmpfnt->vfont = vfont; - BLI_addtail(&ttfdata, tmpfnt); + if (vfont->temp_pf == NULL) { + vfont->temp_pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id)); } } if (!pf) { @@ -252,9 +186,8 @@ VFont *BKE_vfont_load(Main *bmain, const char *name) char filename[FILE_MAXFILE]; VFont *vfont = NULL; PackedFile *pf; - PackedFile *tpf = NULL; + PackedFile *temp_pf = NULL; int is_builtin; - struct TmpFont *tmpfnt; if (strcmp(name, FO_BUILTIN_NAME) == 0) { BLI_strncpy(filename, name, sizeof(filename)); @@ -269,7 +202,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name) BLI_splitdirstring(dir, filename); pf = newPackedFile(NULL, name, bmain->name); - tpf = newPackedFile(NULL, name, bmain->name); + temp_pf = newPackedFile(NULL, name, bmain->name); is_builtin = FALSE; } @@ -295,10 +228,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name) /* Do not add FO_BUILTIN_NAME to temporary listbase */ if (strcmp(filename, FO_BUILTIN_NAME)) { - tmpfnt = (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); - tmpfnt->pf = tpf; - tmpfnt->vfont = vfont; - BLI_addtail(&ttfdata, tmpfnt); + vfont->temp_pf = temp_pf; } } @@ -306,8 +236,6 @@ VFont *BKE_vfont_load(Main *bmain, const char *name) if (!vfont || vfont->packedfile != pf) { freePackedFile(pf); } - - //XXX waitcursor(0); } return vfont; @@ -317,14 +245,14 @@ static VFont *which_vfont(Curve *cu, CharInfo *info) { switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) { case CU_CHINFO_BOLD: - if (cu->vfontb) return(cu->vfontb); else return(cu->vfont); + return cu->vfontb ? cu->vfontb : cu->vfont; case CU_CHINFO_ITALIC: - if (cu->vfonti) return(cu->vfonti); else return(cu->vfont); + return cu->vfonti ? cu->vfonti : cu->vfont; case (CU_CHINFO_BOLD | CU_CHINFO_ITALIC): - if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont); + return cu->vfontbi ? cu->vfontbi : cu->vfont; default: - return(cu->vfont); - } + return cu->vfont; + } } VFont *BKE_vfont_builtin_get(void) @@ -344,6 +272,7 @@ static VChar *find_vfont_char(VFontData *vfd, intptr_t character) { VChar *che = NULL; + /* TODO: use ghash */ for (che = vfd->characters.first; che; che = che->next) { if (che->index == character) break; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index b615f8c0d9f..0d9a69008ee 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -167,11 +167,13 @@ static int add_to_group_internal(Group *group, Object *ob) { GroupObject *go; - if (group == NULL || ob == NULL) return 0; + if (group == NULL || ob == NULL) { + return FALSE; + } /* check if the object has been added already */ - for (go = group->gobject.first; go; go = go->next) { - if (go->ob == ob) return 0; + if (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob))) { + return FALSE; } go = MEM_callocN(sizeof(GroupObject), "groupobject"); @@ -179,7 +181,7 @@ static int add_to_group_internal(Group *group, Object *ob) go->ob = ob; - return 1; + return TRUE; } int add_to_group(Group *group, Object *object, Scene *scene, Base *base) @@ -245,15 +247,11 @@ int rem_from_group(Group *group, Object *object, Scene *scene, Base *base) int object_in_group(Object *ob, Group *group) { - GroupObject *go; - - if (group == NULL || ob == NULL) return 0; - - for (go = group->gobject.first; go; go = go->next) { - if (go->ob == ob) - return 1; + if (group == NULL || ob == NULL) { + return FALSE; } - return 0; + + return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL); } Group *find_group(Object *ob, Group *group) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d84c20f7a94..2b2128439c7 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2145,7 +2145,9 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima) void BKE_image_release_renderresult(Scene *scene, Image *ima) { - if (ima->rr) ; + if (ima->rr) { + /* pass */ + } else if (ima->type == IMA_TYPE_R_RESULT) { if (ima->render_slot == ima->last_render_slot) RE_ReleaseResult(RE_GetRender(scene->id.name)); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 3c46e7bcd47..f73fb3879b8 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -19,7 +19,8 @@ * All rights reserved. * * Contributor(s): Blender Foundation, - * Sergey Sharybin + * Sergey Sharybin, + * Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ @@ -41,12 +42,8 @@ #include "DNA_mask_types.h" #include "DNA_node_types.h" -#include "DNA_scene_types.h" -#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_tracking_types.h" #include "DNA_sequence_types.h" #include "BKE_curve.h" @@ -58,7 +55,6 @@ #include "BKE_sequencer.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" -#include "BKE_utildefines.h" static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { @@ -90,7 +86,7 @@ static MaskSplinePoint *mask_spline_point_prev(MaskSpline *spline, MaskSplinePoi } } -static BezTriple *mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) +BezTriple *BKE_mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) { @@ -158,7 +154,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name) mask->masklay_tot++; - masklay->blend = MASK_BLEND_MERGE; + masklay->blend = MASK_BLEND_MERGE_ADD; masklay->alpha = 1.0f; return masklay; @@ -269,586 +265,6 @@ MaskSpline *BKE_mask_spline_add(MaskLayer *masklay) return spline; } -unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) -{ - float max_segment = 0.01f; - unsigned int i, resol = 1; - - if (width != 0 && height != 0) { - if (width >= height) - max_segment = 1.0f / (float) width; - else - max_segment = 1.0f / (float) height; - } - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - BezTriple *bezt, *bezt_next; - float a, b, c, len; - unsigned int cur_resol; - - bezt = &point->bezt; - bezt_next = mask_spline_point_next_bezt(spline, spline->points, point); - - if (bezt_next == NULL) { - break; - } - - a = len_v3v3(bezt->vec[1], bezt->vec[2]); - b = len_v3v3(bezt->vec[2], bezt_next->vec[0]); - c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); - - len = a + b + c; - cur_resol = len / max_segment; - - resol = MAX2(resol, cur_resol); - - if (resol >= MASK_RESOL_MAX) { - break; - } - } - - return CLAMPIS(resol, 1, MASK_RESOL_MAX); -} - -unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) -{ - const float max_segment = 0.005; - unsigned int resol = BKE_mask_spline_resolution(spline, width, height); - float max_jump = 0.0f; - int i; - - /* avoid checking the featrher if we already hit the maximum value */ - if (resol >= MASK_RESOL_MAX) { - return MASK_RESOL_MAX; - } - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - float prev_u, prev_w; - int j; - - prev_u = 0.0f; - prev_w = point->bezt.weight; - - for (j = 0; j < point->tot_uw; j++) { - const float w_diff = (point->uw[j].w - prev_w); - const float u_diff = (point->uw[j].u - prev_u); - - /* avoid divide by zero and very high values, - * though these get clamped eventually */ - if (u_diff > FLT_EPSILON) { - float jump = fabsf(w_diff / u_diff); - - max_jump = MAX2(max_jump, jump); - } - - prev_u = point->uw[j].u; - prev_w = point->uw[j].w; - } - } - - resol += max_jump / max_segment; - - return CLAMPIS(resol, 1, MASK_RESOL_MAX); -} - -int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol) -{ - if (spline->flag & MASK_SPLINE_CYCLIC) { - return spline->tot_point * resol; - } - else { - return ((spline->tot_point - 1) * resol) + 1; - } -} - -float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline, - int *tot_diff_point, - const unsigned int resol - ))[2] -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - MaskSplinePoint *point, *prev; - float (*diff_points)[2], (*fp)[2]; - const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); - int a; - - if (spline->tot_point <= 1) { - /* nothing to differentiate */ - *tot_diff_point = 0; - return NULL; - } - - /* len+1 because of 'forward_diff_bezier' function */ - *tot_diff_point = tot; - diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets"); - - a = spline->tot_point - 1; - if (spline->flag & MASK_SPLINE_CYCLIC) - a++; - - prev = points_array; - point = prev + 1; - - while (a--) { - BezTriple *prevbezt; - BezTriple *bezt; - int j; - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) - point = points_array; - - prevbezt = &prev->bezt; - bezt = &point->bezt; - - for (j = 0; j < 2; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j], - bezt->vec[0][j], bezt->vec[1][j], - &(*fp)[j], resol, 2 * sizeof(float)); - } - - fp += resol; - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { - copy_v2_v2(*fp, bezt->vec[1]); - } - - prev = point; - point++; - } - - return diff_points; -} - -float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, - int *tot_diff_point - ))[2] -{ - int unsigned resol = BKE_mask_spline_resolution(spline, width, height); - - return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol); -} - -float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] -{ - return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point); -} - -/* ** feather points self-intersection collapse routine ** */ - -typedef struct FeatherEdgesBucket { - int tot_segment; - int (*segments)[2]; - int alloc_segment; -} FeatherEdgesBucket; - -static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end) -{ - const int alloc_delta = 256; - - if (bucket->tot_segment >= bucket->alloc_segment) { - if (!bucket->segments) { - bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments"); - } - else { - bucket->segments = MEM_reallocN(bucket->segments, - (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); - } - - bucket->alloc_segment += alloc_delta; - } - - bucket->segments[bucket->tot_segment][0] = start; - bucket->segments[bucket->tot_segment][1] = end; - - bucket->tot_segment++; -} - -static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket, - int cur_a, int cur_b) -{ - int i; - - float *v1 = (float *) feather_points[cur_a]; - float *v2 = (float *) feather_points[cur_b]; - - for (i = 0; i < bucket->tot_segment; i++) { - int check_a = bucket->segments[i][0]; - int check_b = bucket->segments[i][1]; - - float *v3 = (float *) feather_points[check_a]; - float *v4 = (float *) feather_points[check_b]; - - if (check_a >= cur_a - 1 || cur_b == check_a) - continue; - - if (isect_seg_seg_v2(v1, v2, v3, v4)) { - int k; - float p[2]; - float min_a[2], max_a[2]; - float min_b[2], max_b[2]; - - isect_seg_seg_v2_point(v1, v2, v3, v4, p); - - INIT_MINMAX2(min_a, max_a); - INIT_MINMAX2(min_b, max_b); - - /* collapse loop with smaller AABB */ - for (k = 0; k < tot_feather_point; k++) { - if (k >= check_b && k <= cur_a) { - DO_MINMAX2(feather_points[k], min_a, max_a); - } - else { - DO_MINMAX2(feather_points[k], min_b, max_b); - } - } - - if (max_a[0] - min_a[0] < max_b[0] - min_b[0] || - max_a[1] - min_a[1] < max_b[1] - min_b[1]) - { - for (k = check_b; k <= cur_a; k++) { - copy_v2_v2(feather_points[k], p); - } - } - else { - for (k = 0; k <= check_a; k++) { - copy_v2_v2(feather_points[k], p); - } - - if (cur_b != 0) { - for (k = cur_b; k < tot_feather_point; k++) { - copy_v2_v2(feather_points[k], p); - } - } - } - } - } -} - -static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2], - const int buckets_per_side) -{ - int x = (int) ((co[0] - min[0]) * bucket_scale[0]); - int y = (int) ((co[1] - min[1]) * bucket_scale[1]); - - if (x == buckets_per_side) - x--; - - if (y == buckets_per_side) - y--; - - return y * buckets_per_side + x; -} - -static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index, - int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r, - FeatherEdgesBucket **diagonal_bucket_b_r) -{ - int start_bucket_x = start_bucket_index % buckets_per_side; - int start_bucket_y = start_bucket_index / buckets_per_side; - - int end_bucket_x = end_bucket_index % buckets_per_side; - int end_bucket_y = end_bucket_index / buckets_per_side; - - int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x; - int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x; - - *diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index]; - *diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index]; -} - -static void spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], int tot_feather_point) -{ -#define BUCKET_INDEX(co) \ - feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side) - - int buckets_per_side, tot_bucket; - float bucket_size, bucket_scale[2]; - - FeatherEdgesBucket *buckets; - - int i; - float min[2], max[2]; - float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta; - - if (tot_feather_point < 4) { - /* self-intersection works only for quads at least, - * in other cases polygon can't be self-intersecting anyway - */ - - return; - } - - /* find min/max corners of mask to build buckets in that space */ - INIT_MINMAX2(min, max); - - for (i = 0; i < tot_feather_point; i++) { - int next = i + 1; - float delta; - - DO_MINMAX2(feather_points[i], min, max); - - if (next == tot_feather_point) { - if (spline->flag & MASK_SPLINE_CYCLIC) - next = 0; - else - break; - } - - delta = fabsf(feather_points[i][0] - feather_points[next][0]); - if (delta > max_delta_x) - max_delta_x = delta; - - delta = fabsf(feather_points[i][1] - feather_points[next][1]); - if (delta > max_delta_y) - max_delta_y = delta; - } - - /* prevent divisionsby zero by ensuring bounding box is not collapsed */ - if (max[0] - min[0] < FLT_EPSILON) { - max[0] += 0.01f; - min[0] -= 0.01f; - } - - if (max[1] - min[1] < FLT_EPSILON) { - max[1] += 0.01f; - min[1] -= 0.01f; - } - - /* use dynamically calculated buckets per side, so we likely wouldn't - * run into a situation when segment doesn't fit two buckets which is - * pain collecting candidates for intersection - */ - - max_delta_x /= max[0] - min[0]; - max_delta_y /= max[1] - min[1]; - - max_delta = MAX2(max_delta_x, max_delta_y); - - buckets_per_side = MIN2(512, 0.9f / max_delta); - - if (buckets_per_side == 0) { - /* happens when some segment fills the whole bounding box across some of dimension */ - - buckets_per_side = 1; - } - - tot_bucket = buckets_per_side * buckets_per_side; - bucket_size = 1.0f / buckets_per_side; - - /* pre-compute multipliers, to save mathematical operations in loops */ - bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size); - bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size); - - /* fill in buckets' edges */ - buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets"); - - for (i = 0; i < tot_feather_point; i++) { - int start = i, end = i + 1; - int start_bucket_index, end_bucket_index; - - if (end == tot_feather_point) { - if (spline->flag & MASK_SPLINE_CYCLIC) - end = 0; - else - break; - } - - start_bucket_index = BUCKET_INDEX(feather_points[start]); - end_bucket_index = BUCKET_INDEX(feather_points[end]); - - feather_bucket_add_edge(&buckets[start_bucket_index], start, end); - - if (start_bucket_index != end_bucket_index) { - FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; - FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; - - feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, - &diagonal_bucket_a, &diagonal_bucket_b); - - feather_bucket_add_edge(end_bucket, start, end); - feather_bucket_add_edge(diagonal_bucket_a, start, end); - feather_bucket_add_edge(diagonal_bucket_a, start, end); - } - } - - /* check all edges for intersection with edges from their buckets */ - for (i = 0; i < tot_feather_point; i++) { - int cur_a = i, cur_b = i + 1; - int start_bucket_index, end_bucket_index; - - FeatherEdgesBucket *start_bucket; - - if (cur_b == tot_feather_point) - cur_b = 0; - - start_bucket_index = BUCKET_INDEX(feather_points[cur_a]); - end_bucket_index = BUCKET_INDEX(feather_points[cur_b]); - - start_bucket = &buckets[start_bucket_index]; - - feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b); - - if (start_bucket_index != end_bucket_index) { - FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; - FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; - - feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, - &diagonal_bucket_a, &diagonal_bucket_b); - - feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b); - feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b); - feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b); - } - } - - /* free buckets */ - for (i = 0; i < tot_bucket; i++) { - if (buckets[i].segments) - MEM_freeN(buckets[i].segments); - } - - MEM_freeN(buckets); - -#undef BUCKET_INDEX -} - -/** - * values align with #BKE_mask_spline_differentiate_with_resolution_ex - * when \a resol arguments match. - */ -float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline, - int *tot_feather_point, - const unsigned int resol - ))[2] -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - MaskSplinePoint *point, *prev; - float (*feather)[2], (*fp)[2]; - - const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); - int a; - - /* tot+1 because of 'forward_diff_bezier' function */ - feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); - - a = spline->tot_point - 1; - if (spline->flag & MASK_SPLINE_CYCLIC) - a++; - - prev = points_array; - point = prev + 1; - - while (a--) { - /* BezTriple *prevbezt; */ /* UNUSED */ - /* BezTriple *bezt; */ /* UNUSED */ - int j; - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) - point = points_array; - - - /* prevbezt = &prev->bezt; */ - /* bezt = &point->bezt; */ - - for (j = 0; j < resol; j++, fp++) { - float u = (float) j / resol, weight; - float co[2], n[2]; - - /* TODO - these calls all calculate similar things - * could be unified for some speed */ - BKE_mask_point_segment_co(spline, prev, u, co); - BKE_mask_point_normal(spline, prev, u, n); - weight = BKE_mask_point_weight(spline, prev, u); - - madd_v2_v2v2fl(*fp, co, n, weight); - } - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { - float u = 1.0f, weight; - float co[2], n[2]; - - BKE_mask_point_segment_co(spline, prev, u, co); - BKE_mask_point_normal(spline, prev, u, n); - weight = BKE_mask_point_weight(spline, prev, u); - - madd_v2_v2v2fl(*fp, co, n, weight); - } - - prev = point; - point++; - } - - *tot_feather_point = tot; - - if (spline->flag & MASK_SPLINE_NOINTERSECT) - spline_feather_collapse_inner_loops(spline, feather, tot); - - return feather; -} - -float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height, - int *tot_feather_point))[2] -{ - unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); - - return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol); -} - -float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] -{ - return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point); -} - -float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - int i, tot = 0; - float (*feather)[2], (*fp)[2]; - - /* count */ - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &points_array[i]; - - tot += point->tot_uw + 1; - } - - /* create data */ - feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &points_array[i]; - BezTriple *bezt = &point->bezt; - float weight, n[2]; - int j; - - BKE_mask_point_normal(spline, point, 0.0f, n); - weight = BKE_mask_point_weight(spline, point, 0.0f); - - madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); - fp++; - - for (j = 0; j < point->tot_uw; j++) { - float u = point->uw[j].u; - float co[2]; - - BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, u, n); - weight = BKE_mask_point_weight(spline, point, u); - - madd_v2_v2v2fl(*fp, co, n, weight); - fp++; - } - } - - *tot_feather_point = tot; - - return feather; -} - void BKE_mask_point_direction_switch(MaskSplinePoint *point) { const int tot_uw = point->tot_uw; @@ -1067,73 +483,6 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di } } -float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, - int width, int height, - unsigned int *tot_feather_point) -{ - float *feather, *fp; - unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); - unsigned int i; - - feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); - - for (i = 0; i < resol; i++, fp += 2) { - float u = (float)(i % resol) / resol, weight; - float co[2], n[2]; - - BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, u, n); - weight = BKE_mask_point_weight(spline, point, u); - - fp[0] = co[0] + n[0] * weight; - fp[1] = co[1] + n[1] * weight; - } - - *tot_feather_point = resol; - - return feather; -} - -float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point) -{ - return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); -} - -float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, - int width, int height, unsigned int *tot_diff_point) -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - - BezTriple *bezt, *bezt_next; - float *diff_points, *fp; - int j, resol = BKE_mask_spline_resolution(spline, width, height); - - bezt = &point->bezt; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); - - if (!bezt_next) - return NULL; - - /* resol+1 because of 'forward_diff_bezier' function */ - *tot_diff_point = resol + 1; - diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets"); - - for (j = 0; j < 2; j++) { - BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], - bezt_next->vec[0][j], bezt_next->vec[1][j], - fp + j, resol, 2 * sizeof(float)); - } - - copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]); - - return diff_points; -} - -float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point) -{ - return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point); -} - void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2]) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); @@ -1141,7 +490,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2]; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { copy_v2_v2(co, bezt->vec[1]); @@ -1165,7 +514,7 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { BKE_mask_point_handle(point, vec); @@ -1200,7 +549,7 @@ float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, c MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); BezTriple *bezt = &point->bezt, *bezt_next; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { return bezt->weight; @@ -1221,7 +570,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const fl MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); BezTriple *bezt = &point->bezt, *bezt_next; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { return bezt->weight; @@ -1845,17 +1194,6 @@ void BKE_mask_calc_handle_point(MaskSpline *spline, MaskSplinePoint *point) mask_calc_point_handle(point, point_prev, point_next); } -static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist) -{ - if (!equals_v2v2(v2, v1)) { - float nor[2]; - - sub_v2_v2v2(nor, v1, v2); - normalize_v2(nor); - madd_v2_v2v2fl(v1, v2, nor, dist); - } -} - void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u) { /* TODO! - make this interpolate between siblings - not always midpoint! */ @@ -1897,8 +1235,8 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *p length_average /= (float)length_tot; weight_average /= (float)length_tot; - enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); - enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); point->bezt.weight = weight_average; } } @@ -1930,8 +1268,8 @@ void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point, /* preserve length by applying it back */ if (do_recalc_length == FALSE) { - enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); - enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); } } diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c new file mode 100644 index 00000000000..065dc38c81e --- /dev/null +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -0,0 +1,864 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mask_evaluate.c + * \ingroup bke + * + * Functions for evaluating the mask beziers into points for the outline and feather. + */ + +#include <stddef.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_mask_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_movieclip_types.h" +#include "DNA_tracking_types.h" +#include "DNA_sequence_types.h" + +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_mask.h" +#include "BKE_node.h" +#include "BKE_sequencer.h" +#include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_utildefines.h" + + +unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) +{ + float max_segment = 0.01f; + unsigned int i, resol = 1; + + if (width != 0 && height != 0) { + max_segment = 1.0f / (float)maxi(width, height); + } + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + BezTriple *bezt_curr, *bezt_next; + float a, b, c, len; + unsigned int cur_resol; + + bezt_curr = &point->bezt; + bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point); + + if (bezt_next == NULL) { + break; + } + + a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]); + b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]); + c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); + + len = a + b + c; + cur_resol = len / max_segment; + + resol = MAX2(resol, cur_resol); + + if (resol >= MASK_RESOL_MAX) { + break; + } + } + + return CLAMPIS(resol, 1, MASK_RESOL_MAX); +} + +unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) +{ + const float max_segment = 0.005; + unsigned int resol = BKE_mask_spline_resolution(spline, width, height); + float max_jump = 0.0f; + int i; + + /* avoid checking the featrher if we already hit the maximum value */ + if (resol >= MASK_RESOL_MAX) { + return MASK_RESOL_MAX; + } + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + float prev_u, prev_w; + int j; + + prev_u = 0.0f; + prev_w = point->bezt.weight; + + for (j = 0; j < point->tot_uw; j++) { + const float w_diff = (point->uw[j].w - prev_w); + const float u_diff = (point->uw[j].u - prev_u); + + /* avoid divide by zero and very high values, + * though these get clamped eventually */ + if (u_diff > FLT_EPSILON) { + float jump = fabsf(w_diff / u_diff); + + max_jump = MAX2(max_jump, jump); + } + + prev_u = point->uw[j].u; + prev_w = point->uw[j].w; + } + } + + resol += max_jump / max_segment; + + return CLAMPIS(resol, 1, MASK_RESOL_MAX); +} + +int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol) +{ + if (spline->flag & MASK_SPLINE_CYCLIC) { + return spline->tot_point * resol; + } + else { + return ((spline->tot_point - 1) * resol) + 1; + } +} + +float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline, + int *tot_diff_point, + const unsigned int resol + ))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + MaskSplinePoint *point_curr, *point_prev; + float (*diff_points)[2], (*fp)[2]; + const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); + int a; + + if (spline->tot_point <= 1) { + /* nothing to differentiate */ + *tot_diff_point = 0; + return NULL; + } + + /* len+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = tot; + diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + point_prev = points_array; + point_curr = point_prev + 1; + + while (a--) { + BezTriple *bezt_prev; + BezTriple *bezt_curr; + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point_curr = points_array; + + bezt_prev = &point_prev->bezt; + bezt_curr = &point_curr->bezt; + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j], + bezt_curr->vec[0][j], bezt_curr->vec[1][j], + &(*fp)[j], resol, 2 * sizeof(float)); + } + + fp += resol; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + copy_v2_v2(*fp, bezt_curr->vec[1]); + } + + point_prev = point_curr; + point_curr++; + } + + return diff_points; +} + +float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, + int *tot_diff_point + ))[2] +{ + int unsigned resol = BKE_mask_spline_resolution(spline, width, height); + + return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol); +} + +float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] +{ + return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point); +} + +/* ** feather points self-intersection collapse routine ** */ + +typedef struct FeatherEdgesBucket { + int tot_segment; + int (*segments)[2]; + int alloc_segment; +} FeatherEdgesBucket; + +static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end) +{ + const int alloc_delta = 256; + + if (bucket->tot_segment >= bucket->alloc_segment) { + if (!bucket->segments) { + bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments"); + } + else { + bucket->segments = MEM_reallocN(bucket->segments, + (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); + } + + bucket->alloc_segment += alloc_delta; + } + + bucket->segments[bucket->tot_segment][0] = start; + bucket->segments[bucket->tot_segment][1] = end; + + bucket->tot_segment++; +} + +static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket, + int cur_a, int cur_b) +{ + int i; + + float *v1 = (float *) feather_points[cur_a]; + float *v2 = (float *) feather_points[cur_b]; + + for (i = 0; i < bucket->tot_segment; i++) { + int check_a = bucket->segments[i][0]; + int check_b = bucket->segments[i][1]; + + float *v3 = (float *) feather_points[check_a]; + float *v4 = (float *) feather_points[check_b]; + + if (check_a >= cur_a - 1 || cur_b == check_a) + continue; + + if (isect_seg_seg_v2(v1, v2, v3, v4)) { + int k; + float p[2]; + float min_a[2], max_a[2]; + float min_b[2], max_b[2]; + + isect_seg_seg_v2_point(v1, v2, v3, v4, p); + + INIT_MINMAX2(min_a, max_a); + INIT_MINMAX2(min_b, max_b); + + /* collapse loop with smaller AABB */ + for (k = 0; k < tot_feather_point; k++) { + if (k >= check_b && k <= cur_a) { + DO_MINMAX2(feather_points[k], min_a, max_a); + } + else { + DO_MINMAX2(feather_points[k], min_b, max_b); + } + } + + if (max_a[0] - min_a[0] < max_b[0] - min_b[0] || + max_a[1] - min_a[1] < max_b[1] - min_b[1]) + { + for (k = check_b; k <= cur_a; k++) { + copy_v2_v2(feather_points[k], p); + } + } + else { + for (k = 0; k <= check_a; k++) { + copy_v2_v2(feather_points[k], p); + } + + if (cur_b != 0) { + for (k = cur_b; k < tot_feather_point; k++) { + copy_v2_v2(feather_points[k], p); + } + } + } + } + } +} + +static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2], + const int buckets_per_side) +{ + int x = (int) ((co[0] - min[0]) * bucket_scale[0]); + int y = (int) ((co[1] - min[1]) * bucket_scale[1]); + + if (x == buckets_per_side) + x--; + + if (y == buckets_per_side) + y--; + + return y * buckets_per_side + x; +} + +static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index, + int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r, + FeatherEdgesBucket **diagonal_bucket_b_r) +{ + int start_bucket_x = start_bucket_index % buckets_per_side; + int start_bucket_y = start_bucket_index / buckets_per_side; + + int end_bucket_x = end_bucket_index % buckets_per_side; + int end_bucket_y = end_bucket_index / buckets_per_side; + + int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x; + int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x; + + *diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index]; + *diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index]; +} + +void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], const int tot_feather_point) +{ +#define BUCKET_INDEX(co) \ + feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side) + + int buckets_per_side, tot_bucket; + float bucket_size, bucket_scale[2]; + + FeatherEdgesBucket *buckets; + + int i; + float min[2], max[2]; + float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta; + + if (tot_feather_point < 4) { + /* self-intersection works only for quads at least, + * in other cases polygon can't be self-intersecting anyway + */ + + return; + } + + /* find min/max corners of mask to build buckets in that space */ + INIT_MINMAX2(min, max); + + for (i = 0; i < tot_feather_point; i++) { + int next = i + 1; + float delta; + + DO_MINMAX2(feather_points[i], min, max); + + if (next == tot_feather_point) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = 0; + else + break; + } + + delta = fabsf(feather_points[i][0] - feather_points[next][0]); + if (delta > max_delta_x) + max_delta_x = delta; + + delta = fabsf(feather_points[i][1] - feather_points[next][1]); + if (delta > max_delta_y) + max_delta_y = delta; + } + + /* prevent divisionsby zero by ensuring bounding box is not collapsed */ + if (max[0] - min[0] < FLT_EPSILON) { + max[0] += 0.01f; + min[0] -= 0.01f; + } + + if (max[1] - min[1] < FLT_EPSILON) { + max[1] += 0.01f; + min[1] -= 0.01f; + } + + /* use dynamically calculated buckets per side, so we likely wouldn't + * run into a situation when segment doesn't fit two buckets which is + * pain collecting candidates for intersection + */ + + max_delta_x /= max[0] - min[0]; + max_delta_y /= max[1] - min[1]; + + max_delta = MAX2(max_delta_x, max_delta_y); + + buckets_per_side = MIN2(512, 0.9f / max_delta); + + if (buckets_per_side == 0) { + /* happens when some segment fills the whole bounding box across some of dimension */ + + buckets_per_side = 1; + } + + tot_bucket = buckets_per_side * buckets_per_side; + bucket_size = 1.0f / buckets_per_side; + + /* pre-compute multipliers, to save mathematical operations in loops */ + bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size); + bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size); + + /* fill in buckets' edges */ + buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets"); + + for (i = 0; i < tot_feather_point; i++) { + int start = i, end = i + 1; + int start_bucket_index, end_bucket_index; + + if (end == tot_feather_point) { + if (spline->flag & MASK_SPLINE_CYCLIC) + end = 0; + else + break; + } + + start_bucket_index = BUCKET_INDEX(feather_points[start]); + end_bucket_index = BUCKET_INDEX(feather_points[end]); + + feather_bucket_add_edge(&buckets[start_bucket_index], start, end); + + if (start_bucket_index != end_bucket_index) { + FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; + FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; + + feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, + &diagonal_bucket_a, &diagonal_bucket_b); + + feather_bucket_add_edge(end_bucket, start, end); + feather_bucket_add_edge(diagonal_bucket_a, start, end); + feather_bucket_add_edge(diagonal_bucket_a, start, end); + } + } + + /* check all edges for intersection with edges from their buckets */ + for (i = 0; i < tot_feather_point; i++) { + int cur_a = i, cur_b = i + 1; + int start_bucket_index, end_bucket_index; + + FeatherEdgesBucket *start_bucket; + + if (cur_b == tot_feather_point) + cur_b = 0; + + start_bucket_index = BUCKET_INDEX(feather_points[cur_a]); + end_bucket_index = BUCKET_INDEX(feather_points[cur_b]); + + start_bucket = &buckets[start_bucket_index]; + + feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b); + + if (start_bucket_index != end_bucket_index) { + FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; + FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; + + feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, + &diagonal_bucket_a, &diagonal_bucket_b); + + feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b); + feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b); + feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b); + } + } + + /* free buckets */ + for (i = 0; i < tot_bucket; i++) { + if (buckets[i].segments) + MEM_freeN(buckets[i].segments); + } + + MEM_freeN(buckets); + +#undef BUCKET_INDEX +} + +/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */ +static float (*mask_spline_feather_differentiated_points_with_resolution_ex__even(MaskSpline *spline, + int *tot_feather_point, + const unsigned int resol, + const int do_feather_isect + ))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + MaskSplinePoint *point_curr, *point_prev; + float (*feather)[2], (*fp)[2]; + + const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); + int a; + + /* tot+1 because of 'forward_diff_bezier' function */ + feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + point_prev = points_array; + point_curr = point_prev + 1; + + while (a--) { + /* BezTriple *bezt_prev; */ /* UNUSED */ + /* BezTriple *bezt_curr; */ /* UNUSED */ + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point_curr = points_array; + + + /* bezt_prev = &point_prev->bezt; */ + /* bezt_curr = &point_curr->bezt; */ + + for (j = 0; j < resol; j++, fp++) { + float u = (float) j / resol, weight; + float co[2], n[2]; + + /* TODO - these calls all calculate similar things + * could be unified for some speed */ + BKE_mask_point_segment_co(spline, point_prev, u, co); + BKE_mask_point_normal(spline, point_prev, u, n); + weight = BKE_mask_point_weight(spline, point_prev, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + } + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + float u = 1.0f, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point_prev, u, co); + BKE_mask_point_normal(spline, point_prev, u, n); + weight = BKE_mask_point_weight(spline, point_prev, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + } + + point_prev = point_curr; + point_curr++; + } + + *tot_feather_point = tot; + + if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { + BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); + } + + return feather; +} + +/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */ +static float (*mask_spline_feather_differentiated_points_with_resolution_ex__double(MaskSpline *spline, + int *tot_feather_point, + const unsigned int resol, + const int do_feather_isect + ))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + MaskSplinePoint *point_curr, *point_prev; + float (*feather)[2], (*fp)[2]; + const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); + int a; + + if (spline->tot_point <= 1) { + /* nothing to differentiate */ + *tot_feather_point = 0; + return NULL; + } + + /* len+1 because of 'forward_diff_bezier' function */ + *tot_feather_point = tot; + feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + point_prev = points_array; + point_curr = point_prev + 1; + + while (a--) { + BezTriple local_prevbezt; + BezTriple local_bezt; + float point_prev_n[2], point_curr_n[2], tvec[2]; + float weight_prev, weight_curr; + float len_base, len_feather, len_scalar; + + BezTriple *bezt_prev; + BezTriple *bezt_curr; + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point_curr = points_array; + + bezt_prev = &point_prev->bezt; + bezt_curr = &point_curr->bezt; + + /* modified copy for feather */ + local_prevbezt = *bezt_prev; + local_bezt = *bezt_curr; + + bezt_prev = &local_prevbezt; + bezt_curr = &local_bezt; + + /* calc the normals */ + sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]); + normalize_v2(tvec); + point_prev_n[0] = -tvec[1]; + point_prev_n[1] = tvec[0]; + + sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]); + normalize_v2(tvec); + point_curr_n[0] = -tvec[1]; + point_curr_n[1] = tvec[0]; + + weight_prev = bezt_prev->weight; + weight_curr = bezt_curr->weight; + + mul_v2_fl(point_prev_n, weight_prev); + mul_v2_fl(point_curr_n, weight_curr); + + /* before we transform verts */ + len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); + + // add_v2_v2(bezt_prev->vec[0], point_prev_n); // not needed + add_v2_v2(bezt_prev->vec[1], point_prev_n); + add_v2_v2(bezt_prev->vec[2], point_prev_n); + + add_v2_v2(bezt_curr->vec[0], point_curr_n); + add_v2_v2(bezt_curr->vec[1], point_curr_n); + // add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed + + len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); + + /* scale by chane in length */ + len_scalar = len_feather / len_base; + dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1])); + dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1])); + + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j], + bezt_curr->vec[0][j], bezt_curr->vec[1][j], + &(*fp)[j], resol, 2 * sizeof(float)); + } + + + /* scale by the uw's */ + if (point_prev->tot_uw) { + for (j = 0; j < resol; j++, fp++) { + float u = (float) j / resol; + float weight_uw, weight_scalar; + float co[2]; + + /* TODO - these calls all calculate similar things + * could be unified for some speed */ + BKE_mask_point_segment_co(spline, point_prev, u, co); + + weight_uw = BKE_mask_point_weight(spline, point_prev, u); + weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u); + + dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar)); + } + } + else { + fp += resol; + } + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + copy_v2_v2(*fp, bezt_curr->vec[1]); + } + + point_prev = point_curr; + point_curr++; + } + + if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { + BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); + } + + return feather; +} + +/** + * values align with #BKE_mask_spline_differentiate_with_resolution_ex + * when \a resol arguments match. + */ +float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline, + int *tot_feather_point, + const unsigned int resol, + const int do_feather_isect + ))[2] +{ + switch (spline->offset_mode) { + case MASK_SPLINE_OFFSET_EVEN: + return mask_spline_feather_differentiated_points_with_resolution_ex__even(spline, tot_feather_point, resol, do_feather_isect); + break; + case MASK_SPLINE_OFFSET_SMOOTH: + default: + return mask_spline_feather_differentiated_points_with_resolution_ex__double(spline, tot_feather_point, resol, do_feather_isect); + break; + } +} + +float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height, + int *tot_feather_point, const int do_feather_isect))[2] +{ + unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); + + return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol, do_feather_isect); +} + +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] +{ + return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point, TRUE); +} + +float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i, tot = 0; + float (*feather)[2], (*fp)[2]; + + /* count */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + + tot += point->tot_uw + 1; + } + + /* create data */ + feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + BezTriple *bezt = &point->bezt; + float weight, n[2]; + int j; + + BKE_mask_point_normal(spline, point, 0.0f, n); + weight = BKE_mask_point_weight(spline, point, 0.0f); + + madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); + fp++; + + for (j = 0; j < point->tot_uw; j++) { + float u = point->uw[j].u; + float co[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + fp++; + } + } + + *tot_feather_point = tot; + + return feather; +} + +/* *** mask point functions which involve evaluation *** */ +float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, + unsigned int *tot_feather_point) +{ + float *feather, *fp; + unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); + unsigned int i; + + feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); + + for (i = 0; i < resol; i++, fp += 2) { + float u = (float)(i % resol) / resol, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + fp[0] = co[0] + n[0] * weight; + fp[1] = co[1] + n[1] * weight; + } + + *tot_feather_point = resol; + + return feather; +} + +float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point) +{ + return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); +} + +float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, unsigned int *tot_diff_point) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + + BezTriple *bezt, *bezt_next; + float *diff_points, *fp; + int j, resol = BKE_mask_spline_resolution(spline, width, height); + + bezt = &point->bezt; + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); + + if (!bezt_next) + return NULL; + + /* resol+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = resol + 1; + diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets"); + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], + bezt_next->vec[0][j], bezt_next->vec[1][j], + fp + j, resol, 2 * sizeof(float)); + } + + copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]); + + return diff_points; +} + +float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point) +{ + return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point); +} diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 1fde1168999..eb96d6726b9 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -370,8 +370,8 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) { MemArena *arena = BLI_memarena_new(1 << 16, __func__); - const float bucket_dim_x = layer->bounds.xmax - layer->bounds.xmin; - const float bucket_dim_y = layer->bounds.ymax - layer->bounds.ymin; + const float bucket_dim_x = BLI_RCT_SIZE_X(&layer->bounds); + const float bucket_dim_y = BLI_RCT_SIZE_Y(&layer->bounds); layer->buckets_x = (bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL; layer->buckets_y = (bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL; @@ -575,6 +575,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas int tot_diff_point; float (*diff_feather_points)[2]; + float (*diff_feather_points_flip)[2]; int tot_diff_feather_points; const unsigned int resol_a = BKE_mask_spline_resolution(spline, width, height) / 4; @@ -586,7 +587,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas if (do_feather) { diff_feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution_ex( - spline, &tot_diff_feather_points, resol); + spline, &tot_diff_feather_points, resol, FALSE); BLI_assert(diff_feather_points); } else { @@ -649,6 +650,11 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas } if (is_fill) { + /* applt intersections depending on fill settings */ + if (spline->flag & MASK_SPLINE_NOINTERSECT) { + BKE_mask_spline_feather_collapse_inner_loops(spline, diff_feather_points, tot_diff_feather_points); + } + copy_v2_v2(co, diff_points[0]); sf_vert_prev = BLI_scanfill_vert_add(&sf_ctx, co); sf_vert_prev->tmp.u = sf_vert_tot; @@ -710,11 +716,27 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas /* unfilled spline */ if (diff_feather_points) { - float co_diff[3]; + float co_diff[2]; float co_feather[3]; co_feather[2] = 1.0f; + if (spline->flag & MASK_SPLINE_NOINTERSECT) { + diff_feather_points_flip = MEM_mallocN(sizeof(float) * 2 * tot_diff_feather_points, "diff_feather_points_flip"); + + for (j = 0; j < tot_diff_point; j++) { + sub_v2_v2v2(co_diff, diff_points[j], diff_feather_points[j]); + add_v2_v2v2(diff_feather_points_flip[j], diff_points[j], co_diff); + } + + BKE_mask_spline_feather_collapse_inner_loops(spline, diff_feather_points, tot_diff_feather_points); + BKE_mask_spline_feather_collapse_inner_loops(spline, diff_feather_points_flip, tot_diff_feather_points); + } + else { + diff_feather_points_flip = NULL; + } + + open_spline_ranges[open_spline_index].vertex_offset = sf_vert_tot; open_spline_ranges[open_spline_index].vertex_total = tot_diff_point; @@ -738,8 +760,14 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas /* feather vert B */ - sub_v2_v2v2(co_diff, co, co_feather); - add_v2_v2v2(co_feather, co, co_diff); + if (diff_feather_points_flip) { + copy_v2_v2(co_feather, diff_feather_points_flip[j]); + } + else { + sub_v2_v2v2(co_diff, co, co_feather); + add_v2_v2v2(co_feather, co, co_diff); + } + sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather); sf_vert->tmp.u = sf_vert_tot; sf_vert->keyindex = SF_KEYINDEX_TEMP_ID; @@ -752,6 +780,11 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas tot_feather_quads -= 2; } + if (diff_feather_points_flip) { + MEM_freeN(diff_feather_points_flip); + diff_feather_points_flip = NULL; + } + /* cap ends */ /* dummy init value */ @@ -1163,7 +1196,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons BLI_INLINE unsigned int layer_bucket_index_from_xy(MaskRasterLayer *layer, const float xy[2]) { - BLI_assert(BLI_in_rctf_v(&layer->bounds, xy)); + BLI_assert(BLI_rctf_isect_pt_v(&layer->bounds, xy)); return ( (unsigned int)((xy[0] - layer->bounds.xmin) * layer->buckets_xy_scalar[0])) + (((unsigned int)((xy[1] - layer->bounds.ymin) * layer->buckets_xy_scalar[1])) * layer->buckets_x); @@ -1200,7 +1233,7 @@ static float layer_bucket_depth_from_xy(MaskRasterLayer *layer, const float xy[2 float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2]) { /* can't do this because some layers may invert */ - /* if (BLI_in_rctf_v(&mr_handle->bounds, xy)) */ + /* if (BLI_rctf_isect_pt_v(&mr_handle->bounds, xy)) */ const unsigned int layers_tot = mr_handle->layers_tot; unsigned int i; @@ -1213,7 +1246,7 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x float value_layer; /* also used as signal for unused layer (when render is disabled) */ - if (layer->alpha != 0.0f && BLI_in_rctf_v(&layer->bounds, xy)) { + if (layer->alpha != 0.0f && BLI_rctf_isect_pt_v(&layer->bounds, xy)) { value_layer = 1.0f - layer_bucket_depth_from_xy(layer, xy); switch (layer->falloff) { @@ -1249,9 +1282,12 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x } switch (layer->blend) { - case MASK_BLEND_MERGE: + case MASK_BLEND_MERGE_ADD: value += value_layer * (1.0f - value); break; + case MASK_BLEND_MERGE_SUBTRACT: + value -= value_layer * value; + break; case MASK_BLEND_ADD: value += value_layer; break; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 936aac9726d..fc1c5e43cbf 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -80,12 +80,18 @@ void init_def_material(void) /* not material itself */ void BKE_material_free(Material *ma) { + BKE_material_free_ex(ma, TRUE); +} + +/* not material itself */ +void BKE_material_free_ex(Material *ma, int do_id_user) +{ MTex *mtex; int a; for (a = 0; a < MAX_MTEX; a++) { mtex = ma->mtex[a]; - if (mtex && mtex->tex) mtex->tex->id.us--; + if (do_id_user && mtex && mtex->tex) mtex->tex->id.us--; if (mtex) MEM_freeN(mtex); } @@ -101,7 +107,7 @@ void BKE_material_free(Material *ma) /* is no lib link block, but material extension */ if (ma->nodetree) { - ntreeFreeTree(ma->nodetree); + ntreeFreeTree_ex(ma->nodetree, do_id_user); MEM_freeN(ma->nodetree); } @@ -236,7 +242,7 @@ Material *BKE_material_copy(Material *ma) if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview); if (ma->nodetree) { - man->nodetree = ntreeCopyTree(ma->nodetree); /* 0 == full new tree */ + man->nodetree = ntreeCopyTree(ma->nodetree); } man->gpumaterial.first = man->gpumaterial.last = NULL; @@ -808,7 +814,7 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type) *totcolp = act; } - // Determine the object/mesh linking + /* Determine the object/mesh linking */ if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) { /* copy from previous material */ bit = ob->matbits[ob->actcol - 1]; @@ -1484,7 +1490,11 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) } } -/* copy/paste buffer, if we had a propper py api that would be better */ +/** + * \brief copy/paste buffer, if we had a propper py api that would be better + * \note matcopybuf.nodetree does _NOT_ use ID's + * \todo matcopybuf.nodetree's node->id's are NOT validated, this will crash! + */ static Material matcopybuf; static short matcopied = 0; @@ -1512,7 +1522,7 @@ void free_matcopybuf(void) matcopybuf.ramp_spec = NULL; if (matcopybuf.nodetree) { - ntreeFreeTree(matcopybuf.nodetree); + ntreeFreeTree_ex(matcopybuf.nodetree, FALSE); MEM_freeN(matcopybuf.nodetree); matcopybuf.nodetree = NULL; } @@ -1538,7 +1548,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.mtex[a] = MEM_dupallocN(mtex); } } - matcopybuf.nodetree = ntreeCopyTree(ma->nodetree); + matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE); matcopybuf.preview = NULL; matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL; matcopied = 1; @@ -1583,7 +1593,7 @@ void paste_matcopybuf(Material *ma) } } - ma->nodetree = ntreeCopyTree(matcopybuf.nodetree); + ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE); } @@ -1624,7 +1634,7 @@ static void decode_tfaceflag(Material *ma, int flag, int convertall) /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ flag -= 1; - alphablend = flag >> 15; //encoded in the encode_tfaceflag function + alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */ (*game).flag = 0; /* General Material Options */ @@ -2024,8 +2034,7 @@ int do_version_tface(Main *main, int fileload) nowarning = 0; } else - convert_tfacematerial(main, ma); - continue; + convert_tfacematerial(main, ma); continue; } /* no conflicts in this material - 90% of cases diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index fa5304b081a..a92497ffb9d 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -67,12 +67,9 @@ /* Data types */ -typedef struct point { /* a three-dimensional point */ - float x, y, z; /* its coordinates */ -} MB_POINT; - typedef struct vertex { /* surface vertex */ - MB_POINT position, normal; /* position and surface normal */ + float co[3]; /* position and surface normal */ + float no[3]; } VERTEX; typedef struct vertices { /* list of vertices in polygonization */ @@ -82,7 +79,7 @@ typedef struct vertices { /* list of vertices in polygonization */ typedef struct corner { /* corner of a cube */ int i, j, k; /* (i, j, k) is index within lattice */ - float x, y, z, value; /* location and function value */ + float co[3], value; /* location and function value */ struct corner *next; } CORNER; @@ -159,11 +156,11 @@ struct pgn_elements { }; /* Forward declarations */ -static int vertid(CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb); +static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb); static int setcenter(CENTERLIST *table[], int i, int j, int k); static CORNER *setcorner(PROCESS *p, int i, int j, int k); -static void converge(MB_POINT *p1, MB_POINT *p2, float v1, float v2, - float (*function)(float, float, float), MB_POINT *p, MetaBall *mb, int f); +static void converge(const float p1[3], const float p2[3], float v1, float v2, + float (*function)(float, float, float), float p[3], MetaBall *mb, int f); /* Global variables */ @@ -631,77 +628,70 @@ static void calc_mballco(MetaElem *ml, float vec[3]) static float densfunc(MetaElem *ball, float x, float y, float z) { - float dist2 = 0.0, dx, dy, dz; - float vec[3]; - - vec[0] = x; - vec[1] = y; - vec[2] = z; - mul_m4_v3((float (*)[4])ball->imat, vec); - dx = vec[0]; - dy = vec[1]; - dz = vec[2]; - - if (ball->type == MB_BALL) { - } - else if (ball->type == MB_TUBEX) { - if (dx > ball->len) dx -= ball->len; - else if (dx < -ball->len) dx += ball->len; - else dx = 0.0; - } - else if (ball->type == MB_TUBEY) { - if (dy > ball->len) dy -= ball->len; - else if (dy < -ball->len) dy += ball->len; - else dy = 0.0; - } - else if (ball->type == MB_TUBEZ) { - if (dz > ball->len) dz -= ball->len; - else if (dz < -ball->len) dz += ball->len; - else dz = 0.0; - } - else if (ball->type == MB_TUBE) { - if (dx > ball->expx) dx -= ball->expx; - else if (dx < -ball->expx) dx += ball->expx; - else dx = 0.0; - } - else if (ball->type == MB_PLANE) { - if (dx > ball->expx) dx -= ball->expx; - else if (dx < -ball->expx) dx += ball->expx; - else dx = 0.0; - if (dy > ball->expy) dy -= ball->expy; - else if (dy < -ball->expy) dy += ball->expy; - else dy = 0.0; - } - else if (ball->type == MB_ELIPSOID) { - dx *= 1 / ball->expx; - dy *= 1 / ball->expy; - dz *= 1 / ball->expz; - } - else if (ball->type == MB_CUBE) { - if (dx > ball->expx) dx -= ball->expx; - else if (dx < -ball->expx) dx += ball->expx; - else dx = 0.0; - if (dy > ball->expy) dy -= ball->expy; - else if (dy < -ball->expy) dy += ball->expy; - else dy = 0.0; - if (dz > ball->expz) dz -= ball->expz; - else if (dz < -ball->expz) dz += ball->expz; - else dz = 0.0; - } - - dist2 = (dx * dx + dy * dy + dz * dz); - - if (ball->flag & MB_NEGATIVE) { - dist2 = 1.0f - (dist2 / ball->rad2); - if (dist2 < 0.0f) return 0.5f; - - return 0.5f - ball->s * dist2 * dist2 * dist2; + float dist2; + float dvec[3] = {x, y, z}; + + mul_m4_v3((float (*)[4])ball->imat, dvec); + + switch (ball->type) { + case MB_BALL: + /* do nothing */ + break; + case MB_TUBEX: + if (dvec[0] > ball->len) dvec[0] -= ball->len; + else if (dvec[0] < -ball->len) dvec[0] += ball->len; + else dvec[0] = 0.0; + break; + case MB_TUBEY: + if (dvec[1] > ball->len) dvec[1] -= ball->len; + else if (dvec[1] < -ball->len) dvec[1] += ball->len; + else dvec[1] = 0.0; + break; + case MB_TUBEZ: + if (dvec[2] > ball->len) dvec[2] -= ball->len; + else if (dvec[2] < -ball->len) dvec[2] += ball->len; + else dvec[2] = 0.0; + break; + case MB_TUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + break; + case MB_PLANE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + if (dvec[1] > ball->expy) dvec[1] -= ball->expy; + else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; + else dvec[1] = 0.0; + break; + case MB_ELIPSOID: + dvec[0] /= ball->expx; + dvec[1] /= ball->expy; + dvec[2] /= ball->expz; + break; + case MB_CUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + + if (dvec[1] > ball->expy) dvec[1] -= ball->expy; + else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; + else dvec[1] = 0.0; + + if (dvec[2] > ball->expz) dvec[2] -= ball->expz; + else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; + else dvec[2] = 0.0; + break; } - else { - dist2 = 1.0f - (dist2 / ball->rad2); - if (dist2 < 0.0f) return -0.5f; - return ball->s * dist2 * dist2 * dist2 - 0.5f; + dist2 = 1.0f - (len_v3(dvec) / ball->rad2); + + if ((ball->flag & MB_NEGATIVE) == 0) { + return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f; + } + else { + return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2); } } @@ -784,15 +774,12 @@ static float metaball(float x, float y, float z) if (totelem > 1) { node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); if (node) { - ml_p = node->elems.first; - - while (ml_p) { + for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { dens += densfunc(ml_p->ml, x, y, z); - ml_p = ml_p->next; } dens += -0.5f * (metaball_tree->pos - node->pos); - dens += 0.5f * (metaball_tree->neg - node->neg); + dens += 0.5f * (metaball_tree->neg - node->neg); } else { for (a = 0; a < totelem; a++) { @@ -1074,12 +1061,12 @@ static CORNER *setcorner(PROCESS *p, int i, int j, int k) c = (CORNER *) new_pgn_element(sizeof(CORNER)); c->i = i; - c->x = ((float)i - 0.5f) * p->size; + c->co[0] = ((float)i - 0.5f) * p->size; c->j = j; - c->y = ((float)j - 0.5f) * p->size; + c->co[1] = ((float)j - 0.5f) * p->size; c->k = k; - c->z = ((float)k - 0.5f) * p->size; - c->value = p->function(c->x, c->y, c->z); + c->co[2] = ((float)k - 0.5f) * p->size; + c->value = p->function(c->co[0], c->co[1], c->co[2]); c->next = p->corners[index]; p->corners[index] = c; @@ -1204,7 +1191,7 @@ void BKE_mball_cubeTable_free(void) /* setcenter: set (i, j, k) entry of table[] * return 1 if already set; otherwise, set and return 0 */ -static int setcenter(CENTERLIST *table[], int i, int j, int k) +static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) { int index; CENTERLIST *newc, *l, *q; @@ -1324,72 +1311,46 @@ static void addtovertices(VERTICES *vertices, VERTEX v) /* vnormal: compute unit length surface normal at point */ -static void vnormal(MB_POINT *point, PROCESS *p, MB_POINT *v) +static void vnormal(const float point[3], PROCESS *p, float r_no[3]) { float delta = 0.2f * p->delta; - float f = p->function(point->x, point->y, point->z); - - v->x = p->function(point->x + delta, point->y, point->z) - f; - v->y = p->function(point->x, point->y + delta, point->z) - f; - v->z = p->function(point->x, point->y, point->z + delta) - f; - f = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); + float f = p->function(point[0], point[1], point[2]); - if (f != 0.0f) { - v->x /= f; - v->y /= f; - v->z /= f; - } + r_no[0] = p->function(point[0] + delta, point[1], point[2]) - f; + r_no[1] = p->function(point[0], point[1] + delta, point[2]) - f; + r_no[2] = p->function(point[0], point[1], point[2] + delta) - f; + f = normalize_v3(r_no); - if (FALSE) { - MB_POINT temp; + if (0) { + float tvec[3]; delta *= 2.0f; - f = p->function(point->x, point->y, point->z); + f = p->function(point[0], point[1], point[2]); - temp.x = p->function(point->x + delta, point->y, point->z) - f; - temp.y = p->function(point->x, point->y + delta, point->z) - f; - temp.z = p->function(point->x, point->y, point->z + delta) - f; - f = sqrtf(temp.x * temp.x + temp.y * temp.y + temp.z * temp.z); + tvec[0] = p->function(point[0] + delta, point[1], point[2]) - f; + tvec[1] = p->function(point[0], point[1] + delta, point[2]) - f; + tvec[2] = p->function(point[0], point[1], point[2] + delta) - f; - if (f != 0.0f) { - temp.x /= f; - temp.y /= f; - temp.z /= f; - - v->x += temp.x; - v->y += temp.y; - v->z += temp.z; - - f = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); - - if (f != 0.0f) { - v->x /= f; - v->y /= f; - v->z /= f; - } + if (normalize_v3(tvec) != 0.0f) { + add_v3_v3(r_no, tvec); + normalize_v3(r_no); } } - } -static int vertid(CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb) +static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb) { VERTEX v; - MB_POINT a, b; int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); - if (vid != -1) return vid; /* previously computed */ - a.x = c1->x; - a.y = c1->y; - a.z = c1->z; - b.x = c2->x; - b.y = c2->y; - b.z = c2->z; + if (vid != -1) { + return vid; /* previously computed */ + } - converge(&a, &b, c1->value, c2->value, p->function, &v.position, mb, 1); /* position */ - vnormal(&v.position, p, &v.normal); + converge(c1->co, c2->co, c1->value, c2->value, p->function, v.co, mb, 1); /* position */ + vnormal(v.co, p, v.no); addtovertices(&p->vertices, v); /* save vertex */ vid = p->vertices.count - 1; @@ -1403,101 +1364,95 @@ static int vertid(CORNER *c1, CORNER *c2, PROCESS *p, MetaBall *mb) /* converge: from two points of differing sign, converge to zero crossing */ /* watch it: p1 and p2 are used to calculate */ -static void converge(MB_POINT *p1, MB_POINT *p2, float v1, float v2, - float (*function)(float, float, float), MB_POINT *p, MetaBall *mb, int f) +static void converge(const float p1[3], const float p2[3], float v1, float v2, + float (*function)(float, float, float), float p[3], MetaBall *mb, int f) { int i = 0; - MB_POINT pos, neg; + float pos[3], neg[3]; float positive = 0.0f, negative = 0.0f; - float dx = 0.0f, dy = 0.0f, dz = 0.0f; + float dvec[3]; if (v1 < 0) { - pos = *p2; - neg = *p1; + copy_v3_v3(pos, p2); + copy_v3_v3(neg, p1); positive = v2; negative = v1; } else { - pos = *p1; - neg = *p2; + copy_v3_v3(pos, p1); + copy_v3_v3(neg, p2); positive = v1; negative = v2; } - dx = pos.x - neg.x; - dy = pos.y - neg.y; - dz = pos.z - neg.z; + sub_v3_v3v3(dvec, pos, neg); /* Approximation by linear interpolation is faster then binary subdivision, * but it results sometimes (mb->thresh < 0.2) into the strange results */ if ((mb->thresh > 0.2f) && (f == 1)) { - if ((dy == 0.0f) && (dz == 0.0f)) { - p->x = neg.x - negative * dx / (positive - negative); - p->y = neg.y; - p->z = neg.z; + if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { + p[0] = neg[0] - negative * dvec[0] / (positive - negative); + p[1] = neg[1]; + p[2] = neg[2]; return; } - if ((dx == 0.0f) && (dz == 0.0f)) { - p->x = neg.x; - p->y = neg.y - negative * dy / (positive - negative); - p->z = neg.z; + if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { + p[0] = neg[0]; + p[1] = neg[1] - negative * dvec[1] / (positive - negative); + p[2] = neg[2]; return; } - if ((dx == 0.0f) && (dy == 0.0f)) { - p->x = neg.x; - p->y = neg.y; - p->z = neg.z - negative * dz / (positive - negative); + if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { + p[0] = neg[0]; + p[1] = neg[1]; + p[2] = neg[2] - negative * dvec[2] / (positive - negative); return; } } - if ((dy == 0.0f) && (dz == 0.0f)) { - p->y = neg.y; - p->z = neg.z; + if ((dvec[1] == 0.0f) && (dvec[2] == 0.0f)) { + p[1] = neg[1]; + p[2] = neg[2]; while (1) { if (i++ == RES) return; - p->x = 0.5f * (pos.x + neg.x); - if ((function(p->x, p->y, p->z)) > 0.0f) pos.x = p->x; else neg.x = p->x; + p[0] = 0.5f * (pos[0] + neg[0]); + if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; else neg[0] = p[0]; } } - if ((dx == 0.0f) && (dz == 0.0f)) { - p->x = neg.x; - p->z = neg.z; + if ((dvec[0] == 0.0f) && (dvec[2] == 0.0f)) { + p[0] = neg[0]; + p[2] = neg[2]; while (1) { if (i++ == RES) return; - p->y = 0.5f * (pos.y + neg.y); - if ((function(p->x, p->y, p->z)) > 0.0f) pos.y = p->y; else neg.y = p->y; + p[1] = 0.5f * (pos[1] + neg[1]); + if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; else neg[1] = p[1]; } } - - if ((dx == 0.0f) && (dy == 0.0f)) { - p->x = neg.x; - p->y = neg.y; + + if ((dvec[0] == 0.0f) && (dvec[1] == 0.0f)) { + p[0] = neg[0]; + p[1] = neg[1]; while (1) { if (i++ == RES) return; - p->z = 0.5f * (pos.z + neg.z); - if ((function(p->x, p->y, p->z)) > 0.0f) pos.z = p->z; else neg.z = p->z; + p[2] = 0.5f * (pos[2] + neg[2]); + if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; else neg[2] = p[2]; } } /* This is necessary to find start point */ while (1) { - p->x = 0.5f * (pos.x + neg.x); - p->y = 0.5f * (pos.y + neg.y); - p->z = 0.5f * (pos.z + neg.z); - - if (i++ == RES) return; - - if ((function(p->x, p->y, p->z)) > 0.0f) { - pos.x = p->x; - pos.y = p->y; - pos.z = p->z; + mid_v3_v3v3(&p[0], pos, neg); + + if (i++ == RES) { + return; + } + + if ((function(p[0], p[1], p[2])) > 0.0f) { + copy_v3_v3(pos, &p[0]); } else { - neg.x = p->x; - neg.y = p->y; - neg.z = p->z; + copy_v3_v3(neg, &p[0]); } } } @@ -1535,114 +1490,111 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) { - MB_POINT IN, in, OUT, out; /*point;*/ MetaElem *ml; - int i, j, k, c_i, c_j, c_k; - int index[3] = {1, 0, -1}; float f = 0.0f; - float in_v /*, out_v*/; - MB_POINT workp; - float tmp_v, workp_v, max_len, len, dx, dy, dz, nx, ny, nz, MAXN; ml = mainb[a]; - - f = 1 - (mb->thresh / ml->s); + f = 1.0 - (mb->thresh / ml->s); /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be * visible alone ... but still can influence others MetaElements :-) */ if (f > 0.0f) { - OUT.x = IN.x = in.x = 0.0; - OUT.y = IN.y = in.y = 0.0; - OUT.z = IN.z = in.z = 0.0; + float IN[3] = {0.0f}, OUT[3] = {0.0f}, in[3] = {0.0f}, out[3]; + int i, j, k, c_i, c_j, c_k; + int index[3] = {1, 0, -1}; + float in_v /*, out_v*/; + float workp[3]; + float dvec[3]; + float tmp_v, workp_v, max_len, len, nx, ny, nz, MAXN; - calc_mballco(ml, (float *)&in); - in_v = mbproc->function(in.x, in.y, in.z); + calc_mballco(ml, in); + in_v = mbproc->function(in[0], in[1], in[2]); for (i = 0; i < 3; i++) { switch (ml->type) { case MB_BALL: - OUT.x = out.x = IN.x + index[i] * ml->rad; + OUT[0] = out[0] = IN[0] + index[i] * ml->rad; break; case MB_TUBE: case MB_PLANE: case MB_ELIPSOID: case MB_CUBE: - OUT.x = out.x = IN.x + index[i] * (ml->expx + ml->rad); + OUT[0] = out[0] = IN[0] + index[i] * (ml->expx + ml->rad); break; } for (j = 0; j < 3; j++) { switch (ml->type) { case MB_BALL: - OUT.y = out.y = IN.y + index[j] * ml->rad; + OUT[1] = out[1] = IN[1] + index[j] * ml->rad; break; case MB_TUBE: case MB_PLANE: case MB_ELIPSOID: case MB_CUBE: - OUT.y = out.y = IN.y + index[j] * (ml->expy + ml->rad); + OUT[1] = out[1] = IN[1] + index[j] * (ml->expy + ml->rad); break; } for (k = 0; k < 3; k++) { - out.x = OUT.x; - out.y = OUT.y; + out[0] = OUT[0]; + out[1] = OUT[1]; switch (ml->type) { case MB_BALL: case MB_TUBE: case MB_PLANE: - out.z = IN.z + index[k] * ml->rad; + out[2] = IN[2] + index[k] * ml->rad; break; case MB_ELIPSOID: case MB_CUBE: - out.z = IN.z + index[k] * (ml->expz + ml->rad); + out[2] = IN[2] + index[k] * (ml->expz + ml->rad); break; } - calc_mballco(ml, (float *)&out); + calc_mballco(ml, out); - /*out_v = mbproc->function(out.x, out.y, out.z);*/ /*UNUSED*/ + /*out_v = mbproc->function(out[0], out[1], out[2]);*/ /*UNUSED*/ /* find "first points" on Implicit Surface of MetaElemnt ml */ - workp.x = in.x; - workp.y = in.y; - workp.z = in.z; + copy_v3_v3(workp, in); workp_v = in_v; - max_len = sqrtf((out.x - in.x) * (out.x - in.x) + (out.y - in.y) * (out.y - in.y) + (out.z - in.z) * (out.z - in.z)); + max_len = len_v3v3(out, in); - nx = abs((out.x - in.x) / mbproc->size); - ny = abs((out.y - in.y) / mbproc->size); - nz = abs((out.z - in.z) / mbproc->size); + nx = abs((out[0] - in[0]) / mbproc->size); + ny = abs((out[1] - in[1]) / mbproc->size); + nz = abs((out[2] - in[2]) / mbproc->size); MAXN = MAX3(nx, ny, nz); if (MAXN != 0.0f) { - dx = (out.x - in.x) / MAXN; - dy = (out.y - in.y) / MAXN; - dz = (out.z - in.z) / MAXN; + dvec[0] = (out[0] - in[0]) / MAXN; + dvec[1] = (out[1] - in[1]) / MAXN; + dvec[2] = (out[2] - in[2]) / MAXN; len = 0.0; while (len <= max_len) { - workp.x += dx; - workp.y += dy; - workp.z += dz; + workp[0] += dvec[0]; + workp[1] += dvec[1]; + workp[2] += dvec[2]; /* compute value of implicite function */ - tmp_v = mbproc->function(workp.x, workp.y, workp.z); + tmp_v = mbproc->function(workp[0], workp[1], workp[2]); /* add cube to the stack, when value of implicite function crosses zero value */ if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) { /* indexes of CUBE, which includes "first point" */ - c_i = (int)floor(workp.x / mbproc->size); - c_j = (int)floor(workp.y / mbproc->size); - c_k = (int)floor(workp.z / mbproc->size); + c_i = (int)floor(workp[0] / mbproc->size); + c_j = (int)floor(workp[1] / mbproc->size); + c_k = (int)floor(workp[2] / mbproc->size); /* add CUBE (with indexes c_i, c_j, c_k) to the stack, * this cube includes found point of Implicit Surface */ - if (ml->flag & MB_NEGATIVE) - add_cube(mbproc, c_i, c_j, c_k, 2); - else + if ((ml->flag & MB_NEGATIVE) == 0) { add_cube(mbproc, c_i, c_j, c_k, 1); + } + else { + add_cube(mbproc, c_i, c_j, c_k, 2); + } } - len = sqrtf((workp.x - in.x) * (workp.x - in.x) + (workp.y - in.y) * (workp.y - in.y) + (workp.z - in.z) * (workp.z - in.z)); + len = len_v3v3(workp, in); workp_v = tmp_v; } @@ -1928,11 +1880,11 @@ static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) BLI_addtail(&(node->nodes[i]->elems), ml_p); node->count++; - if (ml->flag & MB_NEGATIVE) { - node->nodes[i]->neg++; + if ((ml->flag & MB_NEGATIVE) == 0) { + node->nodes[i]->pos++; } else { - node->nodes[i]->pos++; + node->nodes[i]->neg++; } } @@ -2258,14 +2210,14 @@ static void init_metaball_octal_tree(int depth) ml_p->ml = mainb[a]; BLI_addtail(&node->elems, ml_p); - if (mainb[a]->flag & MB_NEGATIVE) { - /* number of negative MetaElem in scene */ - metaball_tree->neg++; - } - else { + if ((mainb[a]->flag & MB_NEGATIVE) == 0) { /* number of positive MetaElem in scene */ metaball_tree->pos++; } + else { + /* number of negative MetaElem in scene */ + metaball_tree->neg++; + } } /* size of first node */ @@ -2283,7 +2235,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) MetaBall *mb; DispList *dl; int a, nr_cubes; - float *ve, *no, totsize, width; + float *co, *no, totsize, width; mb = ob->data; @@ -2308,11 +2260,11 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) } /* if scene includes more then one MetaElem, then octal tree optimization is used */ - if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1); - if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2); - if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3); - if ((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4); - if (totelem > 1024) init_metaball_octal_tree(5); + if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1); + if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2); + if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3); + if ((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4); + if (totelem > 1024) init_metaball_octal_tree(5); /* don't polygonize metaballs with too high resolution (base mball to small) * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ @@ -2362,6 +2314,8 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) } if (curindex) { + VERTEX *ptr = mbproc.vertices.ptr; + dl = MEM_callocN(sizeof(DispList), "mbaldisp"); BLI_addtail(dispbase, dl); dl->type = DL_INDEX4; @@ -2372,17 +2326,12 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) indices = NULL; a = mbproc.vertices.count; - dl->verts = ve = MEM_mallocN(sizeof(float) * 3 * a, "mballverts"); + dl->verts = co = MEM_mallocN(sizeof(float) * 3 * a, "mballverts"); dl->nors = no = MEM_mallocN(sizeof(float) * 3 * a, "mballnors"); - for (a = 0; a < mbproc.vertices.count; a++, no += 3, ve += 3) { - ve[0] = mbproc.vertices.ptr[a].position.x; - ve[1] = mbproc.vertices.ptr[a].position.y; - ve[2] = mbproc.vertices.ptr[a].position.z; - - no[0] = mbproc.vertices.ptr[a].normal.x; - no[1] = mbproc.vertices.ptr[a].normal.y; - no[2] = mbproc.vertices.ptr[a].normal.z; + for (a = 0; a < mbproc.vertices.count; ptr++, a++, no += 3, co += 3) { + copy_v3_v3(co, ptr->co); + copy_v3_v3(no, ptr->no); } } @@ -2403,29 +2352,30 @@ int BKE_mball_minmax(MetaBall *mb, float min[3], float max[3]) return (mb->elems.first != NULL); } -int BKE_mball_center_median(MetaBall *mb, float cent[3]) +int BKE_mball_center_median(MetaBall *mb, float r_cent[3]) { MetaElem *ml; int total = 0; - zero_v3(cent); + zero_v3(r_cent); for (ml = mb->elems.first; ml; ml = ml->next) { - add_v3_v3(cent, &ml->x); + add_v3_v3(r_cent, &ml->x); } - if (total) - mul_v3_fl(cent, 1.0f / (float)total); + if (total) { + mul_v3_fl(r_cent, 1.0f / (float)total); + } return (total != 0); } -int BKE_mball_center_bounds(MetaBall *mb, float cent[3]) +int BKE_mball_center_bounds(MetaBall *mb, float r_cent[3]) { float min[3], max[3]; if (BKE_mball_minmax(mb, min, max)) { - mid_v3_v3v3(cent, min, max); + mid_v3_v3v3(r_cent, min, max); return 1; } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index f5ae3c7da2b..8c3ec7e2e40 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2702,13 +2702,13 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, #endif { /* sort loop indices to ensure winding is correct */ - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); - if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); - if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); } /* end abusing the edcode */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d62b03b5060..9590160c8f3 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -764,7 +764,7 @@ void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp) } /* Add the given NLA-Strip to the given Meta-Strip, assuming that the - * strip isn't attached to anyy list of strips + * strip isn't attached to any list of strips */ short BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 7cee9626c3f..c283db94103 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -671,7 +671,7 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype) * copying for internal use (threads for eg), where you wont want it to modify the * scene data. */ -static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_extern) +static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern) { bNodeTree *newtree; bNode *node /*, *nnode */ /* UNUSED */, *last; @@ -702,6 +702,11 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e last = ntree->nodes.last; for (node = ntree->nodes.first; node; node = node->next) { + /* ntreeUserDecrefID inline */ + if (do_id_user) { + id_us_plus(node->id); + } + if (do_make_extern) { id_lib_extern(node->id); } @@ -751,22 +756,56 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e return newtree; } +bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user) +{ + return ntreeCopyTree_internal(ntree, do_id_user, TRUE); +} bNodeTree *ntreeCopyTree(bNodeTree *ntree) { - return ntreeCopyTree_internal(ntree, TRUE); + return ntreeCopyTree_ex(ntree, TRUE); } /* use when duplicating scenes */ -void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) +void ntreeSwitchID_ex(bNodeTree *ntree, ID *id_from, ID *id_to, const short do_id_user) { bNode *node; + + if (id_from == id_to) { + /* should never happen but may as well skip if it does */ + return; + } + /* for scene duplication only */ for (node = ntree->nodes.first; node; node = node->next) { if (node->id == id_from) { + if (do_id_user) { + id_us_min(id_from); + id_us_plus(id_to); + } + node->id = id_to; } } } +void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) +{ + ntreeSwitchID_ex(ntree, id_from, id_to, TRUE); +} + +void ntreeUserIncrefID(bNodeTree *ntree) +{ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + id_us_plus(node->id); + } +} +void ntreeUserDecrefID(bNodeTree *ntree) +{ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + id_us_min(node->id); + } +} /* *************** preview *********** */ /* if node->preview, then we assume the rect to exist */ @@ -913,6 +952,7 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent) } } +/** \note caller needs to manage node->id user */ void nodeFreeNode(bNodeTree *ntree, bNode *node) { bNodeSocket *sock, *nextsock; @@ -956,7 +996,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) } /* do not free ntree itself here, BKE_libblock_free calls this function too */ -void ntreeFreeTree(bNodeTree *ntree) +void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) { bNode *node, *next; bNodeSocket *sock; @@ -990,6 +1030,12 @@ void ntreeFreeTree(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = next) { next = node->next; + + /* ntreeUserIncrefID inline */ + if (do_id_user) { + id_us_min(node->id); + } + nodeFreeNode(ntree, node); } @@ -1000,6 +1046,11 @@ void ntreeFreeTree(bNodeTree *ntree) node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&ntree->outputs); } +/* same as ntreeFreeTree_ex but always manage users */ +void ntreeFreeTree(bNodeTree *ntree) +{ + ntreeFreeTree_ex(ntree, TRUE); +} void ntreeFreeCache(bNodeTree *ntree) { @@ -1188,7 +1239,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } /* node copy func */ - ltree = ntreeCopyTree_internal(ntree, FALSE); + ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE); if (adt) { AnimData *ladt = BKE_animdata_from_id(<ree->id); @@ -1248,7 +1299,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) if (ntreetype->local_merge) ntreetype->local_merge(localtree, ntree); - ntreeFreeTree(localtree); + ntreeFreeTree_ex(localtree, FALSE); MEM_freeN(localtree); } @@ -1425,13 +1476,37 @@ void nodeSocketSetType(bNodeSocket *sock, int type) /* ************** Node Clipboard *********** */ +#define USE_NODE_CB_VALIDATE + +#ifdef USE_NODE_CB_VALIDATE +/** + * This data structure is to validate the node on creation, + * otherwise we may reference missing data. + * + * Currently its only used for ID's, but nodes may one day + * reference other pointers which need validation. + */ +typedef struct bNodeClipboardExtraInfo { + struct bNodeClipboardExtraInfo *next, *prev; + ID *id; + char id_name[MAX_ID_NAME]; + char library_name[FILE_MAX]; +} bNodeClipboardExtraInfo; +#endif /* USE_NODE_CB_VALIDATE */ + + typedef struct bNodeClipboard { ListBase nodes; + +#ifdef USE_NODE_CB_VALIDATE + ListBase nodes_extra_info; +#endif + ListBase links; int type; } bNodeClipboard; -bNodeClipboard node_clipboard; +bNodeClipboard node_clipboard = {{0}}; void BKE_node_clipboard_init(struct bNodeTree *ntree) { @@ -1454,11 +1529,83 @@ void BKE_node_clipboard_clear(void) nodeFreeNode(NULL, node); } node_clipboard.nodes.first = node_clipboard.nodes.last = NULL; + +#ifdef USE_NODE_CB_VALIDATE + BLI_freelistN(&node_clipboard.nodes_extra_info); +#endif +} + +/* return FALSE when one or more ID's are lost */ +int BKE_node_clipboard_validate(void) +{ + int ok = TRUE; + +#ifdef USE_NODE_CB_VALIDATE + bNodeClipboardExtraInfo *node_info; + bNode *node; + + + /* lists must be aligned */ + BLI_assert(BLI_countlist(&node_clipboard.nodes) == + BLI_countlist(&node_clipboard.nodes_extra_info)); + + for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first; + node; + node = node->next, node_info = node_info->next) + { + /* validate the node against the stored node info */ + + /* re-assign each loop since we may clear, + * open a new file where the ID is valid, and paste again */ + node->id = node_info->id; + + /* currently only validate the ID */ + if (node->id) { + ListBase *lb = which_libbase(G.main, GS(node_info->id_name)); + BLI_assert(lb != NULL); + + if (BLI_findindex(lb, node_info->id) == -1) { + /* may assign NULL */ + node->id = BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2); + + if (node->id == NULL) { + ok = FALSE; + } + } + } + } +#endif /* USE_NODE_CB_VALIDATE */ + + return ok; } void BKE_node_clipboard_add_node(bNode *node) { +#ifdef USE_NODE_CB_VALIDATE + /* add extra info */ + bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo)); + + node_info->id = node->id; + if (node->id) { + BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name)); + if (node->id->lib) { + BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name)); + } + else { + node_info->library_name[0] = '\0'; + } + } + else { + node_info->id_name[0] = '\0'; + node_info->library_name[0] = '\0'; + } + BLI_addtail(&node_clipboard.nodes_extra_info, node_info); + /* end extra info */ +#endif /* USE_NODE_CB_VALIDATE */ + + /* add node */ BLI_addtail(&node_clipboard.nodes, node); + } void BKE_node_clipboard_add_link(bNodeLink *link) @@ -1992,6 +2139,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_vecblur(ttype); register_node_type_cmp_dilateerode(ttype); register_node_type_cmp_inpaint(ttype); + register_node_type_cmp_despeckle(ttype); register_node_type_cmp_defocus(ttype); register_node_type_cmp_valtorgb(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index bc6cdc949eb..5bb0e0929ff 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1524,7 +1524,7 @@ void BKE_object_mat3_to_rot(Object *ob, float mat[][3], short use_compat) /* end drot correction */ if (use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, tmat); - else mat3_to_eulO(ob->rot, ob->rotmode, tmat); + else mat3_to_eulO(ob->rot, ob->rotmode, tmat); } } } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index f115a41d419..9787a5025f7 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -158,7 +158,17 @@ void freePackedFile(PackedFile *pf) else printf("freePackedFile: Trying to free a NULL pointer\n"); } - + +PackedFile *dupPackedFile(const PackedFile *pf_src) +{ + PackedFile *pf_dst; + + pf_dst = MEM_dupallocN(pf_src); + pf_dst->data = MEM_dupallocN(pf_src->data); + + return pf_dst; +} + PackedFile *newPackedFileMemory(void *mem, int memlen) { PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index e097a54c478..66647a994bc 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -155,7 +155,8 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if (sce->nodetree) { - scen->nodetree = ntreeCopyTree(sce->nodetree); /* copies actions */ + /* ID's are managed on both copy and switch */ + scen->nodetree = ntreeCopyTree(sce->nodetree); ntreeSwitchID(scen->nodetree, &sce->id, &scen->id); } @@ -557,14 +558,7 @@ Scene *BKE_scene_add(const char *name) Base *BKE_scene_base_find(Scene *scene, Object *ob) { - Base *base; - - base = scene->base.first; - while (base) { - if (base->object == ob) return base; - base = base->next; - } - return NULL; + return BLI_findptr(&scene->base, ob, offsetof(Base, object)); } void BKE_scene_set_background(Main *bmain, Scene *scene) @@ -589,10 +583,10 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) /* group flags again */ for (group = bmain->group.first; group; group = group->id.next) { - go = group->gobject.first; - while (go) { - if (go->ob) go->ob->flag |= OB_FROMGROUP; - go = go->next; + for (go = group->gobject.first; go; go = go->next) { + if (go->ob) { + go->ob->flag |= OB_FROMGROUP; + } } } diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index 387ec67eb1c..e3f0226c863 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -37,8 +37,11 @@ #include "BKE_sequencer.h" #include "IMB_moviecache.h" +#include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "BLI_listbase.h" + typedef struct SeqCacheKey { struct Sequence *seq; SeqRenderData context; @@ -46,7 +49,25 @@ typedef struct SeqCacheKey { seq_stripelem_ibuf_t type; } SeqCacheKey; +typedef struct SeqPreprocessCacheElem { + struct SeqPreprocessCacheElem *next, *prev; + + struct Sequence *seq; + SeqRenderData context; + seq_stripelem_ibuf_t type; + + ImBuf *ibuf; +} SeqPreprocessCacheElem; + +typedef struct SeqPreprocessCache { + int cfra; + ListBase elems; +} SeqPreprocessCache; + static struct MovieCache *moviecache = NULL; +static struct SeqPreprocessCache *preprocess_cache = NULL; + +static void preprocessed_cache_destruct(void); static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b) { @@ -160,6 +181,8 @@ void BKE_sequencer_cache_destruct(void) { if (moviecache) IMB_moviecache_free(moviecache); + + preprocessed_cache_destruct(); } void BKE_sequencer_cache_cleanup(void) @@ -168,6 +191,8 @@ void BKE_sequencer_cache_cleanup(void) IMB_moviecache_free(moviecache); moviecache = IMB_moviecache_create("seqcache", sizeof(SeqCacheKey), seqcache_hashhash, seqcache_hashcmp); } + + BKE_sequencer_preprocessed_cache_cleanup(); } static int seqcache_key_check_seq(void *userkey, void *userdata) @@ -219,3 +244,100 @@ void BKE_sequencer_cache_put(SeqRenderData context, Sequence *seq, float cfra, s IMB_moviecache_put(moviecache, &key, i); } + +void BKE_sequencer_preprocessed_cache_cleanup(void) +{ + SeqPreprocessCacheElem *elem; + + if (!preprocess_cache) + return; + + for (elem = preprocess_cache->elems.first; elem; elem = elem->next) { + IMB_freeImBuf(elem->ibuf); + } + BLI_freelistN(&preprocess_cache->elems); + + preprocess_cache->elems.first = preprocess_cache->elems.last = NULL; +} + +static void preprocessed_cache_destruct(void) +{ + if (!preprocess_cache) + return; + + BKE_sequencer_preprocessed_cache_cleanup(); + + MEM_freeN(preprocess_cache); + preprocess_cache = NULL; +} + +ImBuf *BKE_sequencer_preprocessed_cache_get(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type) +{ + SeqPreprocessCacheElem *elem; + + if (!preprocess_cache) + return NULL; + + if (preprocess_cache->cfra != cfra) + return NULL; + + for (elem = preprocess_cache->elems.first; elem; elem = elem->next) { + if (elem->seq != seq) + continue; + + if (elem->type != type) + continue; + + if (seq_cmp_render_data(&elem->context, &context) != 0) + continue; + + IMB_refImBuf(elem->ibuf); + return elem->ibuf; + } + + return NULL; +} + +void BKE_sequencer_preprocessed_cache_put(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *ibuf) +{ + SeqPreprocessCacheElem *elem; + + if (!preprocess_cache) { + preprocess_cache = MEM_callocN(sizeof(SeqPreprocessCache), "sequencer preprocessed cache"); + } + else { + if (preprocess_cache->cfra != cfra) + BKE_sequencer_preprocessed_cache_cleanup(); + } + + elem = MEM_callocN(sizeof(SeqPreprocessCacheElem), "sequencer preprocessed cache element"); + + elem->seq = seq; + elem->type = type; + elem->context = context; + elem->ibuf = ibuf; + + preprocess_cache->cfra = cfra; + + IMB_refImBuf(ibuf); + + BLI_addtail(&preprocess_cache->elems, elem); +} + +void BKE_sequencer_preprocessed_cache_cleanup_sequence(Sequence *seq) +{ + SeqPreprocessCacheElem *elem, *elem_next; + + if (!preprocess_cache) + return; + + for (elem = preprocess_cache->elems.first; elem; elem = elem_next) { + elem_next = elem->next; + + if (elem->seq == seq) { + IMB_freeImBuf(elem->ibuf); + + BLI_freelinkN(&preprocess_cache->elems, elem); + } + } +} diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 87906337ca2..d137393e698 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -56,7 +56,7 @@ #include "RNA_access.h" -static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, +static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1, unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out) { @@ -72,7 +72,7 @@ static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ib *rect3 = (unsigned char*) ibuf3->rect + offset; } -static void slize_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, +static void slice_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, const ImBuf *ibuf3, const ImBuf *out, int start_line, float **rect1, float **rect2, float **rect3, float **rect_out) { @@ -286,14 +286,14 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaover_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -448,14 +448,14 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaunder_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -558,14 +558,14 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_cross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -807,14 +807,14 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_gammacross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_gammacross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } @@ -913,14 +913,14 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_add_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_add_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } @@ -1017,14 +1017,14 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_sub_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -1214,14 +1214,14 @@ static void do_mul_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_mul_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_mul_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } @@ -2748,7 +2748,7 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out); do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out); @@ -2756,7 +2756,7 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out); do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out); diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c new file mode 100644 index 00000000000..70f27db0f74 --- /dev/null +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -0,0 +1,651 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/seqmodifier.c + * \ingroup bke + */ + +#include <stddef.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "DNA_sequence_types.h" + +#include "BKE_colortools.h" +#include "BKE_sequencer.h" +#include "BKE_utildefines.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES]; +static int modifierTypesInit = FALSE; + +/*********************** Modifiers *************************/ + +typedef void (*modifier_apply_threaded_cb) (int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v); + +typedef struct ModifierInitData { + ImBuf *ibuf; + ImBuf *mask; + void *user_data; + + modifier_apply_threaded_cb apply_callback; +} ModifierInitData; + +typedef struct ModifierThread { + int width, height; + + unsigned char *rect, *mask_rect; + float *rect_float, *mask_rect_float; + + void *user_data; + + modifier_apply_threaded_cb apply_callback; +} ModifierThread; + + +static ImBuf *modifier_mask_get(SequenceModifierData *smd, SeqRenderData context, int cfra, int make_float) +{ + return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, make_float); +} + +static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +{ + ModifierThread *handle = (ModifierThread *) handle_v; + ModifierInitData *init_data = (ModifierInitData *) init_data_v; + ImBuf *ibuf = init_data->ibuf; + ImBuf *mask = init_data->mask; + + int offset = 4 * start_line * ibuf->x; + + memset(handle, 0, sizeof(ModifierThread)); + + handle->width = ibuf->x; + handle->height = tot_line; + handle->apply_callback = init_data->apply_callback; + handle->user_data = init_data->user_data; + + if (ibuf->rect) + handle->rect = (unsigned char *) ibuf->rect + offset; + + if (ibuf->rect_float) + handle->rect_float = ibuf->rect_float + offset; + + if (mask) { + if (mask->rect) + handle->mask_rect = (unsigned char *) mask->rect + offset; + + if (mask->rect_float) + handle->mask_rect_float = mask->rect_float + offset; + } + else { + handle->mask_rect = NULL; + handle->mask_rect_float = NULL; + } +} + +static void *modifier_do_thread(void *thread_data_v) +{ + ModifierThread *td = (ModifierThread *) thread_data_v; + + td->apply_callback(td->width, td->height, td->rect, td->rect_float, td->mask_rect, td->mask_rect_float, td->user_data); + + return NULL; +} + +static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_threaded_cb apply_callback, void *user_data) +{ + ModifierInitData init_data; + + init_data.ibuf = ibuf; + init_data.mask = mask; + init_data.user_data = user_data; + + init_data.apply_callback = apply_callback; + + IMB_processor_apply_threaded(ibuf->y, sizeof(ModifierThread), &init_data, + modifier_init_handle, modifier_do_thread); +} + +/* **** Color Balance Modifier **** */ + +void colorBalance_init_data(SequenceModifierData *smd) +{ + ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; + int c; + + cbmd->color_multiply = 1.0f; + + for (c = 0; c < 3; c++) { + cbmd->color_balance.lift[c] = 1.0f; + cbmd->color_balance.gamma[c] = 1.0f; + cbmd->color_balance.gain[c] = 1.0f; + } +} + +ImBuf *colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +{ + ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; + ImBuf *ibuf_new = IMB_dupImBuf(ibuf); + + BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf_new, cbmd->color_multiply, FALSE, mask); + + return ibuf_new; +} + +static SequenceModifierTypeInfo seqModifier_ColorBalance = { + "Color Balance", /* name */ + "ColorBalanceModifierData", /* struct_name */ + sizeof(ColorBalanceModifierData), /* struct_size */ + colorBalance_init_data, /* init_data */ + NULL, /* free_data */ + NULL, /* copy_data */ + colorBalance_apply /* apply */ +}; + +/* **** Curves Modifier **** */ + +void curves_init_data(SequenceModifierData *smd) +{ + CurvesModifierData *cmd = (CurvesModifierData *) smd; + + curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f); +} + +void curves_free_data(SequenceModifierData *smd) +{ + CurvesModifierData *cmd = (CurvesModifierData *) smd; + + curvemapping_free_data(&cmd->curve_mapping); +} + +void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) +{ + CurvesModifierData *cmd = (CurvesModifierData *) smd; + CurvesModifierData *cmd_target = (CurvesModifierData *) target; + + curvemapping_copy_data(&cmd_target->curve_mapping, &cmd->curve_mapping); +} + +void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) +{ + CurveMapping *curve_mapping = (CurveMapping *) data_v; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + int pixel_index = (y * width + x) * 4; + + if (rect_float) { + float *pixel = rect_float + pixel_index; + float result[3]; + + curvemapping_evaluate_premulRGBF(curve_mapping, result, pixel); + + if (mask_rect_float) { + float *m = mask_rect_float + pixel_index; + + pixel[0] = pixel[0] * (1.0f - m[0]) + result[0] * m[0]; + pixel[1] = pixel[1] * (1.0f - m[1]) + result[1] * m[1]; + pixel[2] = pixel[2] * (1.0f - m[2]) + result[2] * m[2]; + } + else { + pixel[0] = result[0]; + pixel[1] = result[1]; + pixel[2] = result[2]; + } + } + if (rect) { + unsigned char *pixel = rect + pixel_index; + unsigned char result[3]; + + curvemapping_evaluate_premulRGB(curve_mapping, result, pixel); + + if (mask_rect) { + float t[3]; + + rgb_uchar_to_float(t, mask_rect + pixel_index); + + pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0]; + pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1]; + pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2]; + } + else { + pixel[0] = result[0]; + pixel[1] = result[1]; + pixel[2] = result[2]; + } + } + } + } +} + +ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +{ + CurvesModifierData *cmd = (CurvesModifierData *) smd; + ImBuf *ibuf_new = IMB_dupImBuf(ibuf); + + float black[3] = {0.0f, 0.0f, 0.0f}; + float white[3] = {1.0f, 1.0f, 1.0f}; + + curvemapping_initialize(&cmd->curve_mapping); + + curvemapping_premultiply(&cmd->curve_mapping, 0); + curvemapping_set_black_white(&cmd->curve_mapping, black, white); + + modifier_apply_threaded(ibuf_new, mask, curves_apply_threaded, &cmd->curve_mapping); + + curvemapping_premultiply(&cmd->curve_mapping, 1); + + return ibuf_new; +} + +static SequenceModifierTypeInfo seqModifier_Curves = { + "Curves", /* name */ + "CurvesModifierData", /* struct_name */ + sizeof(CurvesModifierData), /* struct_size */ + curves_init_data, /* init_data */ + curves_free_data, /* free_data */ + curves_copy_data, /* copy_data */ + curves_apply /* apply */ +}; + +/* **** Hue Correct Modifier **** */ + +void hue_correct_init_data(SequenceModifierData *smd) +{ + HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; + int c; + + curvemapping_set_defaults(&hcmd->curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f); + hcmd->curve_mapping.preset = CURVE_PRESET_MID9; + + for (c = 0; c < 3; c++) { + CurveMap *cuma = &hcmd->curve_mapping.cm[c]; + + curvemap_reset(cuma, &hcmd->curve_mapping.clipr, hcmd->curve_mapping.preset, CURVEMAP_SLOPE_POSITIVE); + } + + /* default to showing Saturation */ + hcmd->curve_mapping.cur = 1; +} + +void hue_correct_free_data(SequenceModifierData *smd) +{ + HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; + + curvemapping_free_data(&hcmd->curve_mapping); +} + +void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd) +{ + HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; + HueCorrectModifierData *hcmd_target = (HueCorrectModifierData *) target; + + curvemapping_copy_data(&hcmd_target->curve_mapping, &hcmd->curve_mapping); +} + +void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) +{ + CurveMapping *curve_mapping = (CurveMapping *) data_v; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + int pixel_index = (y * width + x) * 4; + float pixel[3], result[3], mask[3] = {1.0f, 1.0f, 1.0f}; + float hsv[3], f; + + if (rect_float) + copy_v3_v3(pixel, rect_float + pixel_index); + else + rgb_uchar_to_float(pixel, rect + pixel_index); + + rgb_to_hsv(pixel[0], pixel[1], pixel[2], hsv, hsv + 1, hsv + 2); + + /* adjust hue, scaling returned default 0.5 up to 1 */ + f = curvemapping_evaluateF(curve_mapping, 0, hsv[0]); + hsv[0] += f - 0.5f; + + /* adjust saturation, scaling returned default 0.5 up to 1 */ + f = curvemapping_evaluateF(curve_mapping, 1, hsv[0]); + hsv[1] *= (f * 2.0f); + + /* adjust value, scaling returned default 0.5 up to 1 */ + f = curvemapping_evaluateF(curve_mapping, 2, hsv[0]); + hsv[2] *= (f * 2.f); + + hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ + CLAMP(hsv[1], 0.0f, 1.0f); + + /* convert back to rgb */ + hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2); + + if (mask_rect_float) + copy_v3_v3(mask, mask_rect_float + pixel_index); + else if (mask_rect) + rgb_uchar_to_float(mask, mask_rect + pixel_index); + + result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0]; + result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1]; + result[2] = pixel[2] * (1.0f - mask[2]) + result[2] * mask[2]; + + if (rect_float) + copy_v3_v3(rect_float + pixel_index, result); + else + rgb_float_to_uchar(rect + pixel_index, result); + } + } +} + +ImBuf *hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +{ + HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; + ImBuf *ibuf_new = IMB_dupImBuf(ibuf); + + curvemapping_initialize(&hcmd->curve_mapping); + + modifier_apply_threaded(ibuf_new, mask, hue_correct_apply_threaded, &hcmd->curve_mapping); + + return ibuf_new; +} + +static SequenceModifierTypeInfo seqModifier_HueCorrect = { + "Hue Correct", /* name */ + "HueCorrectModifierData", /* struct_name */ + sizeof(HueCorrectModifierData), /* struct_size */ + hue_correct_init_data, /* init_data */ + hue_correct_free_data, /* free_data */ + hue_correct_copy_data, /* copy_data */ + hue_correct_apply /* apply */ +}; + +/* **** Bright/Contrast Modifier **** */ + +typedef struct BrightContrastThreadData { + float bright; + float contrast; +} BrightContrastThreadData; + +void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) +{ + BrightContrastThreadData *data = (BrightContrastThreadData *) data_v; + int x, y; + + float i; + int c; + float a, b, v; + float brightness = data->bright / 100.0f; + float contrast = data->contrast; + float delta = contrast / 200.0f; + + a = 1.0f - delta * 2.0f; + /* + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + if (contrast > 0) { + a = 1.0f / a; + b = a * (brightness - delta); + } + else { + delta *= -1; + b = a * (brightness + delta); + } + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + int pixel_index = (y * width + x) * 4; + + if (rect) { + unsigned char *pixel = rect + pixel_index; + + for (c = 0; c < 3; c++) { + i = pixel[c]; + v = a * i + b; + + if (mask_rect) { + unsigned char *m = mask_rect + pixel_index; + float t = (float) m[c] / 255.0f; + + pixel[c] = pixel[c] * (1.0f - t) + v * t; + } + else + pixel[c] = v; + } + } + else if (rect_float) { + float *pixel = rect_float + pixel_index; + + for (c = 0; c < 3; c++) { + i = pixel[c]; + v = a * i + b; + + if (mask_rect_float) { + float *m = mask_rect_float + pixel_index; + + pixel[c] = pixel[c] * (1.0f - m[c]) + v * m[c]; + } + else + pixel[c] = v; + } + } + } + } +} + +ImBuf *brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +{ + BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd; + BrightContrastThreadData data; + ImBuf *ibuf_new = IMB_dupImBuf(ibuf); + + data.bright = bcmd->bright; + data.contrast = bcmd->contrast; + + modifier_apply_threaded(ibuf_new, mask, brightcontrast_apply_threaded, &data); + + return ibuf_new; +} + +static SequenceModifierTypeInfo seqModifier_BrightContrast = { + "Bright/Contrast", /* name */ + "BrightContrastModifierData", /* struct_name */ + sizeof(BrightContrastModifierData), /* struct_size */ + NULL, /* init_data */ + NULL, /* free_data */ + NULL, /* copy_data */ + brightcontrast_apply /* apply */ +}; + +/*********************** Modifier functions *************************/ + +static void sequence_modifier_type_info_init(void) +{ +#define INIT_TYPE(typeName) (modifiersTypes[seqModifierType_##typeName] = &seqModifier_##typeName) + + INIT_TYPE(ColorBalance); + INIT_TYPE(Curves); + INIT_TYPE(HueCorrect); + INIT_TYPE(BrightContrast); + +#undef INIT_TYPE +} + +SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type) +{ + if (!modifierTypesInit) { + sequence_modifier_type_info_init(); + modifierTypesInit = TRUE; + } + + return modifiersTypes[type]; +} + +SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type) +{ + SequenceModifierData *smd; + SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type); + + smd = MEM_callocN(smti->struct_size, "sequence modifier"); + + smd->type = type; + smd->flag |= SEQUENCE_MODIFIER_EXPANDED; + + if (!name || !name[0]) + BLI_strncpy(smd->name, smti->name, sizeof(smd->name)); + else + BLI_strncpy(smd->name, name, sizeof(smd->name)); + + BLI_addtail(&seq->modifiers, smd); + + BKE_sequence_modifier_unique_name(seq, smd); + + if (smti->init_data) + smti->init_data(smd); + + return smd; +} + +int BKE_sequence_modifier_remove(Sequence *seq, SequenceModifierData *smd) +{ + if (BLI_findindex(&seq->modifiers, smd) == -1) + return FALSE; + + BLI_remlink(&seq->modifiers, smd); + BKE_sequence_modifier_free(smd); + + return TRUE; +} + +void BKE_sequence_modifier_clear(Sequence *seq) +{ + SequenceModifierData *smd, *smd_next; + + for (smd = seq->modifiers.first; smd; smd = smd_next) { + smd_next = smd->next; + BKE_sequence_modifier_free(smd); + } + + seq->modifiers.first = seq->modifiers.last = NULL; +} + +void BKE_sequence_modifier_free(SequenceModifierData *smd) +{ + SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + + if (smti && smti->free_data) { + smti->free_data(smd); + } + + MEM_freeN(smd); +} + +void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd) +{ + SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + + BLI_uniquename(&seq->modifiers, smd, smti->name, '.', offsetof(SequenceModifierData, name), sizeof(smd->name)); +} + +SequenceModifierData *BKE_sequence_modifier_find_by_name(Sequence *seq, char *name) +{ + return BLI_findstring(&(seq->modifiers), name, offsetof(SequenceModifierData, name)); +} + +ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, ImBuf *ibuf, int cfra) +{ + SequenceModifierData *smd; + ImBuf *processed_ibuf = ibuf; + + for (smd = seq->modifiers.first; smd; smd = smd->next) { + SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + ImBuf *ibuf_new; + + /* could happen if modifier is being removed or not exists in current version of blender */ + if (!smti) + continue; + + /* modifier is muted, do nothing */ + if (smd->flag & SEQUENCE_MODIFIER_MUTE) + continue; + + if (smti->apply) { + ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL); + + if (processed_ibuf == ibuf) + processed_ibuf = IMB_dupImBuf(ibuf); + + ibuf_new = smti->apply(smd, processed_ibuf, mask); + + if (ibuf_new != processed_ibuf) { + IMB_freeImBuf(processed_ibuf); + processed_ibuf = ibuf_new; + } + + if (mask) + IMB_freeImBuf(mask); + } + } + + return processed_ibuf; +} + +void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq) +{ + SequenceModifierData *smd; + + for (smd = seq->modifiers.first; smd; smd = smd->next) { + SequenceModifierData *smdn; + SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + + smdn = MEM_dupallocN(smd); + + if (smti && smti->copy_data) + smti->copy_data(smdn, smd); + + smdn->next = smdn->prev = NULL; + BLI_addtail(&seqn->modifiers, smdn); + } +} + +int BKE_sequence_supports_modifiers(Sequence *seq) +{ + return !ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD); +} diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 9625fad69a6..8aab622148b 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -83,6 +83,7 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown); static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra); static void seq_free_animdata(Scene *scene, Sequence *seq); +static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short make_float); /* **** XXX ******** */ #define SELECT 1 @@ -203,7 +204,13 @@ void BKE_sequence_free(Scene *scene, Sequence *seq) seq_free_animdata(scene, seq); } - BKE_sequencer_cache_cleanup_sequence(seq); + /* free modifiers */ + BKE_sequence_modifier_clear(seq); + + /* free cached data used by this strip, + * also invalidate cache for all dependent sequences + */ + BKE_sequence_invalidate_cache(scene, seq); MEM_freeN(seq); } @@ -1432,7 +1439,7 @@ static void make_cb_table_float(float lift, float gain, float gamma, } } -static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul) +static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul) { unsigned char cb_tab[3][256]; int c; @@ -1440,7 +1447,7 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned unsigned char *e = p + width * 4 * height; unsigned char *m = mask_rect; - StripColorBalance cb = calc_cb(seq->strip->color_balance); + StripColorBalance cb = calc_cb(cb_); for (c = 0; c < 3; c++) { make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul); @@ -1466,7 +1473,7 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned } } -static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul) +static void color_balance_byte_float(StripColorBalance *cb_, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul) { float cb_tab[4][256]; int c, i; @@ -1478,7 +1485,7 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float * o = rect_float; - cb = calc_cb(seq->strip->color_balance); + cb = calc_cb(cb_); for (c = 0; c < 3; c++) { make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul); @@ -1510,12 +1517,12 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float * } } -static void color_balance_float_float(Sequence *seq, float *rect_float, float *mask_rect_float, int width, int height, float mul) +static void color_balance_float_float(StripColorBalance *cb_, float *rect_float, float *mask_rect_float, int width, int height, float mul) { float *p = rect_float; float *e = rect_float + width * 4 * height; float *m = mask_rect_float; - StripColorBalance cb = calc_cb(seq->strip->color_balance); + StripColorBalance cb = calc_cb(cb_); while (p < e) { int c; @@ -1535,20 +1542,23 @@ static void color_balance_float_float(Sequence *seq, float *rect_float, float *m } typedef struct ColorBalanceInitData { - Sequence *seq; + StripColorBalance *cb; ImBuf *ibuf; float mul; ImBuf *mask; + short make_float; } ColorBalanceInitData; typedef struct ColorBalanceThread { - Sequence *seq; + StripColorBalance *cb; float mul; int width, height; unsigned char *rect, *mask_rect; float *rect_float, *mask_rect_float; + + short make_float; } ColorBalanceThread; static void color_balance_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -1562,10 +1572,11 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li memset(handle, 0, sizeof(ColorBalanceThread)); - handle->seq = init_data->seq; + handle->cb = init_data->cb; handle->mul = init_data->mul; handle->width = ibuf->x; handle->height = tot_line; + handle->make_float = init_data->make_float; if (ibuf->rect) handle->rect = (unsigned char *) ibuf->rect + offset; @@ -1589,7 +1600,7 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li static void *color_balance_do_thread(void *thread_data_v) { ColorBalanceThread *thread_data = (ColorBalanceThread *) thread_data_v; - Sequence *seq = thread_data->seq; + StripColorBalance *cb = thread_data->cb; int width = thread_data->width, height = thread_data->height; unsigned char *rect = thread_data->rect; unsigned char *mask_rect = thread_data->mask_rect; @@ -1598,48 +1609,56 @@ static void *color_balance_do_thread(void *thread_data_v) float mul = thread_data->mul; if (rect_float) { - color_balance_float_float(seq, rect_float, mask_rect_float, width, height, mul); + color_balance_float_float(cb, rect_float, mask_rect_float, width, height, mul); } - else if (seq->flag & SEQ_MAKE_FLOAT) { - color_balance_byte_float(seq, rect, rect_float, mask_rect, width, height, mul); + else if (thread_data->make_float) { + color_balance_byte_float(cb, rect, rect_float, mask_rect, width, height, mul); } else { - color_balance_byte_byte(seq, rect, mask_rect, width, height, mul); + color_balance_byte_byte(cb, rect, mask_rect, width, height, mul); } return NULL; } -static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra) +ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, int cfra, int make_float) +{ + ImBuf *mask_input = NULL; + + if (mask_input_type == SEQUENCE_MASK_INPUT_STRIP) { + if (mask_sequence) { + mask_input = seq_render_strip(context, mask_sequence, cfra); + + if (make_float) { + if (!mask_input->rect_float) + IMB_float_from_rect(mask_input); + } + else { + if (!mask_input->rect) + IMB_rect_from_float(mask_input); + } + } + } + else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) { + mask_input = seq_render_mask(context, mask_id, cfra, make_float); + } + + return mask_input; +} + +void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float mul, short make_float, ImBuf *mask_input) { ColorBalanceInitData init_data; - if (!ibuf->rect_float && seq->flag & SEQ_MAKE_FLOAT) + if (!ibuf->rect_float && make_float) imb_addrectfloatImBuf(ibuf); - init_data.seq = seq; + init_data.cb = cb; init_data.ibuf = ibuf; init_data.mul = mul; init_data.mask = NULL; - - if (seq->mask_sequence) { - if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) { - ImBuf *mask = seq_render_strip(context, seq->mask_sequence, cfra); - - if (mask) { - if (ibuf->rect_float) { - if (!mask->rect_float) - IMB_float_from_rect(mask); - } - else { - if (!mask->rect) - IMB_rect_from_float(mask); - } - - init_data.mask = mask; - } - } - } + init_data.make_float = make_float; + init_data.mask = mask_input; IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data, color_balance_init_handle, color_balance_do_thread); @@ -1650,9 +1669,26 @@ static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, flo */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); +} - if (init_data.mask) - IMB_freeImBuf(init_data.mask); +static void sequence_color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra) +{ + StripColorBalance *cb = seq->strip->color_balance; + ImBuf *mask_input = NULL; + short make_float = seq->flag & SEQ_MAKE_FLOAT; + + if (seq->mask_sequence) { + if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) { + int make_float = ibuf->rect_float != NULL; + + mask_input = BKE_sequencer_render_mask_input(context, SEQUENCE_MASK_INPUT_STRIP, seq->mask_sequence, NULL, cfra, make_float); + } + } + + BKE_sequencer_color_balance_apply(cb, ibuf, mul, make_float, mask_input); + + if (mask_input) + IMB_freeImBuf(mask_input); } /* @@ -1696,6 +1732,10 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen if (seq->sat != 1.0f) { return TRUE; } + + if (seq->modifiers.first) { + return TRUE; + } return FALSE; } @@ -1795,7 +1835,7 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, } if (seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { - color_balance(context, seq, ibuf, mul, cfra); + sequence_color_balance(context, seq, ibuf, mul, cfra); mul = 1.0; } @@ -1818,7 +1858,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, } } - if (ibuf->x != context.rectx || ibuf->y != context.recty) { if (context.scene->r.mode & R_OSA) { IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty); @@ -1827,6 +1866,16 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty); } } + + if (seq->modifiers.first) { + ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra); + + if (ibuf_new != ibuf) { + IMB_freeImBuf(ibuf); + ibuf = ibuf_new; + } + } + return ibuf; } @@ -2098,23 +2147,23 @@ static ImBuf *seq_render_movieclip_strip(SeqRenderData context, Sequence *seq, f } -static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float nr) +static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short make_float) { /* TODO - add option to rasterize to alpha imbuf? */ ImBuf *ibuf = NULL; float *maskbuf; int i; - if (!seq->mask) { + if (!mask) { return NULL; } else { Mask *mask_temp; MaskRasterHandle *mr_handle; - mask_temp = BKE_mask_copy_nolib(seq->mask); + mask_temp = BKE_mask_copy_nolib(mask); - BKE_mask_evaluate(mask_temp, seq->mask->sfra + nr, TRUE); + BKE_mask_evaluate(mask_temp, mask->sfra + nr, TRUE); maskbuf = MEM_mallocN(sizeof(float) * context.rectx * context.recty, __func__); @@ -2131,7 +2180,7 @@ static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float } - if (seq->flag & SEQ_MAKE_FLOAT) { + if (make_float) { /* pixels */ float *fp_src; float *fp_dst; @@ -2173,6 +2222,13 @@ static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float return ibuf; } +static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float nr) +{ + short make_float = seq->flag & SEQ_MAKE_FLOAT; + + return seq_render_mask(context, seq->mask, nr, make_float); +} + static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float nr) { ImBuf *ibuf = NULL; @@ -2328,160 +2384,146 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float return ibuf; } -static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) +static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, float cfra) { ImBuf *ibuf = NULL; - char name[FILE_MAX]; - int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); - int is_proxy_image = FALSE; float nr = give_stripelem_index(seq, cfra); - /* all effects are handled similarly with the exception of speed effect */ int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; - int is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); - - ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); - - /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, - * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */ - if (ibuf) - use_preprocess = FALSE; - - if (ibuf == NULL) - ibuf = copy_from_ibuf_still(context, seq, nr); - - /* MOVIECLIPs have their own proxy management */ - if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { - ibuf = seq_proxy_fetch(context, seq, cfra); - is_proxy_image = (ibuf != NULL); - } + int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + char name[FILE_MAX]; - if (ibuf == NULL) switch (type) { - case SEQ_TYPE_META: - { - ImBuf *meta_ibuf = NULL; + switch (type) { + case SEQ_TYPE_META: + { + ImBuf *meta_ibuf = NULL; - if (seq->seqbase.first) - meta_ibuf = seq_render_strip_stack( - context, &seq->seqbase, - seq->start + nr, 0); + if (seq->seqbase.first) + meta_ibuf = seq_render_strip_stack(context, &seq->seqbase, seq->start + nr, 0); - if (meta_ibuf) { - ibuf = meta_ibuf; - if (ibuf && use_preprocess) { - ImBuf *i = IMB_dupImBuf(ibuf); + if (meta_ibuf) { + ibuf = meta_ibuf; + if (ibuf && use_preprocess) { + ImBuf *i = IMB_dupImBuf(ibuf); - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); - ibuf = i; - } + ibuf = i; } - - break; } - case SEQ_TYPE_SPEED: - { - ImBuf *child_ibuf = NULL; - float f_cfra; - SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; + break; + } - BKE_sequence_effect_speed_rebuild_map(context.scene, seq, 0); + case SEQ_TYPE_SPEED: + { + ImBuf *child_ibuf = NULL; - /* weeek! */ - f_cfra = seq->start + s->frameMap[(int)nr]; + float f_cfra; + SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; - child_ibuf = seq_render_strip(context, seq->seq1, f_cfra); + BKE_sequence_effect_speed_rebuild_map(context.scene, seq, 0); - if (child_ibuf) { - ibuf = child_ibuf; - if (ibuf && use_preprocess) { - ImBuf *i = IMB_dupImBuf(ibuf); + /* weeek! */ + f_cfra = seq->start + s->frameMap[(int)nr]; - IMB_freeImBuf(ibuf); + child_ibuf = seq_render_strip(context, seq->seq1, f_cfra); - ibuf = i; - } + if (child_ibuf) { + ibuf = child_ibuf; + if (ibuf && use_preprocess) { + ImBuf *i = IMB_dupImBuf(ibuf); + + IMB_freeImBuf(ibuf); + + ibuf = i; } - break; - } - case SEQ_TYPE_EFFECT: - { - ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr); - break; } - case SEQ_TYPE_IMAGE: - { - StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); + break; + } - if (s_elem) { - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); - BLI_path_abs(name, G.main->name); - } + case SEQ_TYPE_EFFECT: + { + ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr); + break; + } - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) { - /* we don't need both (speed reasons)! */ - if (ibuf->rect_float && ibuf->rect) - imb_freerectImBuf(ibuf); + case SEQ_TYPE_IMAGE: + { + StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); - /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - IMB_convert_profile(ibuf, IB_PROFILE_NONE); + if (s_elem) { + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); + BLI_path_abs(name, G.main->name); + } - copy_to_ibuf_still(context, seq, nr, ibuf); + if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) { + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); - s_elem->orig_width = ibuf->x; - s_elem->orig_height = ibuf->y; - } - break; + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + if (ibuf->profile == IB_PROFILE_LINEAR_RGB) + IMB_convert_profile(ibuf, IB_PROFILE_NONE); + + copy_to_ibuf_still(context, seq, nr, ibuf); + + s_elem->orig_width = ibuf->x; + s_elem->orig_height = ibuf->y; } - case SEQ_TYPE_MOVIE: - { - seq_open_anim_file(seq); + break; + } - if (seq->anim) { - IMB_anim_set_preseek(seq->anim, seq->anim_preseek); + case SEQ_TYPE_MOVIE: + { + seq_open_anim_file(seq); - ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs, - seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, - seq_rendersize_to_proxysize(context.preview_render_size)); + if (seq->anim) { + IMB_anim_set_preseek(seq->anim, seq->anim_preseek); - /* we don't need both (speed reasons)! */ - if (ibuf && ibuf->rect_float && ibuf->rect) - imb_freerectImBuf(ibuf); - if (ibuf) { - seq->strip->stripdata->orig_width = ibuf->x; - seq->strip->stripdata->orig_height = ibuf->y; - } + ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs, + seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, + seq_rendersize_to_proxysize(context.preview_render_size)); + + /* we don't need both (speed reasons)! */ + if (ibuf && ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); + if (ibuf) { + seq->strip->stripdata->orig_width = ibuf->x; + seq->strip->stripdata->orig_height = ibuf->y; } - copy_to_ibuf_still(context, seq, nr, ibuf); - break; } - case SEQ_TYPE_SCENE: - { - /* scene can be NULL after deletions */ - ibuf = seq_render_scene_strip(context, seq, nr); + copy_to_ibuf_still(context, seq, nr, ibuf); + break; + } - /* Scene strips update all animation, so we need to restore original state.*/ - BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra); + case SEQ_TYPE_SCENE: + { + /* scene can be NULL after deletions */ + ibuf = seq_render_scene_strip(context, seq, nr); - copy_to_ibuf_still(context, seq, nr, ibuf); - break; - } - case SEQ_TYPE_MOVIECLIP: - { - ibuf = seq_render_movieclip_strip(context, seq, nr); + /* Scene strips update all animation, so we need to restore original state.*/ + BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra); - if (ibuf && use_preprocess) { - ImBuf *i = IMB_dupImBuf(ibuf); + copy_to_ibuf_still(context, seq, nr, ibuf); + break; + } - IMB_freeImBuf(ibuf); + case SEQ_TYPE_MOVIECLIP: + { + ibuf = seq_render_movieclip_strip(context, seq, nr); - ibuf = i; - } + if (ibuf && use_preprocess) { + ImBuf *i = IMB_dupImBuf(ibuf); - copy_to_ibuf_still(context, seq, nr, ibuf); - break; + IMB_freeImBuf(ibuf); + + ibuf = i; } + + copy_to_ibuf_still(context, seq, nr, ibuf); + break; + } + case SEQ_TYPE_MASK: { /* ibuf is alwats new */ @@ -2492,6 +2534,47 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) } } + return ibuf; +} + +static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) +{ + ImBuf *ibuf = NULL; + int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + int is_proxy_image = FALSE; + float nr = give_stripelem_index(seq, cfra); + /* all effects are handled similarly with the exception of speed effect */ + int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; + int is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); + + ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + + /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, + * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */ + if (ibuf) + use_preprocess = FALSE; + + if (ibuf == NULL) + ibuf = copy_from_ibuf_still(context, seq, nr); + + if (ibuf == NULL) { + ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + + if (ibuf == NULL) { + /* MOVIECLIPs have their own proxy management */ + if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { + ibuf = seq_proxy_fetch(context, seq, cfra); + is_proxy_image = (ibuf != NULL); + } + + if (ibuf == NULL) + ibuf = do_render_strip_uncached(context, seq, cfra); + + if (ibuf) + BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + } + } + if (ibuf == NULL) ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); @@ -2855,6 +2938,9 @@ static void free_anim_seq(Sequence *seq) /* check whether sequence cur depends on seq */ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) { + if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq) + return TRUE; + /* sequences are not intersecting in time, assume no dependency exists between them */ if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp) return FALSE; @@ -2876,7 +2962,7 @@ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) return TRUE; } -void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) +static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_preprocess) { Editing *ed = scene->ed; Sequence *cur; @@ -2884,18 +2970,33 @@ void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) /* invalidate cache for current sequence */ BKE_sequencer_cache_cleanup_sequence(seq); + if (invalidate_preprocess) + BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); + /* invalidate cache for all dependent sequences */ SEQ_BEGIN (ed, cur) { if (cur == seq) continue; - if (BKE_sequence_check_depend(seq, cur)) + if (BKE_sequence_check_depend(seq, cur)) { BKE_sequencer_cache_cleanup_sequence(cur); + BKE_sequencer_preprocessed_cache_cleanup_sequence(cur); + } } SEQ_END } +void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) +{ + sequence_invalidate_cache(scene, seq, TRUE); +} + +void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq) +{ + sequence_invalidate_cache(scene, seq, FALSE); +} + void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int check_mem_usage, int keep_file_handles) { Sequence *seq; @@ -3531,8 +3632,8 @@ int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity); - SWAP(void *, seq_a->prev, seq_b->prev); - SWAP(void *, seq_a->next, seq_b->next); + SWAP(Sequence *, seq_a->prev, seq_b->prev); + SWAP(Sequence *, seq_a->next, seq_b->next); SWAP(int, seq_a->start, seq_b->start); SWAP(int, seq_a->startofs, seq_b->startofs); SWAP(int, seq_a->endofs, seq_b->endofs); @@ -3941,6 +4042,12 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->color_balance = MEM_dupallocN(seq->strip->color_balance); } + if (seqn->modifiers.first) { + seqn->modifiers.first = seqn->modifiers.last = NULL; + + BKE_sequence_modifier_list_copy(seqn, seq); + } + if (seq->type == SEQ_TYPE_META) { seqn->strip->stripdata = NULL; @@ -4060,3 +4167,4 @@ int BKE_seqence_is_valid_check(Sequence *seq) return TRUE; } + diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 14360297ec0..2462de07a18 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -774,37 +774,37 @@ void sound_force_device(int UNUSED(device)) {} void sound_init_once(void) {} void sound_init(struct Main *UNUSED(bmain)) {} void sound_exit(void) {} -void sound_cache(struct bSound* UNUSED(sound)) { } -void sound_delete_cache(struct bSound* UNUSED(sound)) {} -void sound_load(struct Main *UNUSED(bmain), struct bSound* UNUSED(sound)) {} +void sound_cache(struct bSound *UNUSED(sound)) { } +void sound_delete_cache(struct bSound *UNUSED(sound)) {} +void sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {} void sound_create_scene(struct Scene *UNUSED(scene)) {} void sound_destroy_scene(struct Scene *UNUSED(scene)) {} void sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {} -void* sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } -void* sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence)) { return NULL; } -void* sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } -void* sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence)) { return NULL; } -void sound_remove_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle)) {} -void sound_mute_scene_sound(void* UNUSED(handle), char UNUSED(mute)) {} -void sound_move_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) {} +void *sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } +void *sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; } +void *sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } +void *sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; } +void sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {} +void sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {} +void sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) {} void sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {} void sound_play_scene(struct Scene *UNUSED(scene)) {} void sound_stop_scene(struct Scene *UNUSED(scene)) {} void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; } int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; } -int sound_read_sound_buffer(struct bSound* UNUSED(sound), float* UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; } -void sound_read_waveform(struct bSound* sound) { (void)sound; } +int sound_read_sound_buffer(struct bSound *UNUSED(sound), float *UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; } +void sound_read_waveform(struct bSound *sound) { (void)sound; } void sound_init_main(struct Main *bmain) { (void)bmain; } void sound_set_cfra(int cfra) { (void)cfra; } -void sound_update_sequencer(struct Main* main, struct bSound* sound) { (void)main; (void)sound; } -void sound_update_scene(struct Scene* scene) { (void)scene; } -void sound_update_scene_sound(void* handle, struct bSound* sound) { (void)handle; (void)sound; } +void sound_update_sequencer(struct Main *main, struct bSound *sound) { (void)main; (void)sound; } +void sound_update_scene(struct Scene *scene) { (void)scene; } +void sound_update_scene_sound(void *handle, struct bSound *sound) { (void)handle; (void)sound; } void sound_update_scene_listener(struct Scene *scene) { (void)scene; } void sound_update_fps(struct Scene *scene) { (void)scene; } -void sound_set_scene_sound_volume(void* handle, float volume, char animated) { (void)handle; (void)volume; (void)animated; } -void sound_set_scene_sound_pan(void* handle, float pan, char animated) { (void)handle; (void)pan; (void)animated; } +void sound_set_scene_sound_volume(void *handle, float volume, char animated) { (void)handle; (void)volume; (void)animated; } +void sound_set_scene_sound_pan(void *handle, float pan, char animated) { (void)handle; (void)pan; (void)animated; } void sound_set_scene_volume(struct Scene *scene, float volume) { (void)scene; (void)volume; } -void sound_set_scene_sound_pitch(void* handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; } -float sound_get_length(struct bSound* sound) { (void)sound; return 0; } +void sound_set_scene_sound_pitch(void *handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; } +float sound_get_length(struct bSound *sound) { (void)sound; return 0; } #endif // WITH_AUDASPACE diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index a7171caaf8c..5c8192b2a62 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -113,7 +113,8 @@ typedef enum { CCG_USE_ARENA = 2, CCG_CALC_NORMALS = 4, /* add an extra four bytes for a mask layer */ - CCG_ALLOC_MASK = 8 + CCG_ALLOC_MASK = 8, + CCG_SIMPLE_SUBDIV = 16 } CCGFlags; static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, @@ -133,7 +134,10 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL); - if (oldUseAging != useAging) { + if ((oldUseAging != useAging) || + (ccgSubSurf_getSimpleSubdiv(prevSS) != + !!(flags & CCG_SIMPLE_SUBDIV))) + { ccgSubSurf_free(prevSS); } else { @@ -156,6 +160,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, ifc.vertDataSize += sizeof(float) * 3; if (flags & CCG_ALLOC_MASK) ifc.vertDataSize += sizeof(float); + ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV); if (useArena) { CCGAllocatorIFC allocatorIFC; @@ -1463,9 +1468,9 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) } static void ccgDM_foreachMappedVert( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), - void *userData) + DerivedMesh *dm, + void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), + void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGVertIterator *vi; @@ -1485,9 +1490,9 @@ static void ccgDM_foreachMappedVert( } static void ccgDM_foreachMappedEdge( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), - void *userData) + DerivedMesh *dm, + void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), + void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; @@ -2487,9 +2492,9 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, } static void ccgDM_foreachMappedFaceCenter( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float co[3], const float no[3]), - void *userData) + DerivedMesh *dm, + void (*func)(void *userData, int index, const float co[3], const float no[3]), + void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; @@ -3474,7 +3479,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( float (*vertCos)[3], SubsurfFlags flags) { - int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF; + int useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV : 0; CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); @@ -3483,7 +3488,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( if (flags & SUBSURF_FOR_EDIT_MODE) { int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels; - smd->emCache = _getSubSurf(smd->emCache, levels, 3, useAging | CCG_CALC_NORMALS); + smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS); ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple); result = getCCGDerivedMesh(smd->emCache, @@ -3498,7 +3503,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( if (levels == 0) return dm; - ss = _getSubSurf(NULL, levels, 3, CCG_USE_ARENA | CCG_CALC_NORMALS); + ss = _getSubSurf(NULL, levels, 3, useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); @@ -3529,7 +3534,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( } if (useIncremental && (flags & SUBSURF_IS_FINAL_CALC)) { - smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useAging | CCG_CALC_NORMALS); + smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); @@ -3538,7 +3543,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( useSubsurfUv, dm); } else { - CCGFlags ccg_flags = CCG_USE_ARENA | CCG_CALC_NORMALS; + CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS; if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) { ccgSubSurf_free(smd->mCache); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 5bad69c2e8d..2f54fe6cebd 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -1292,7 +1292,7 @@ PointDensity *BKE_add_pointdensity(void) pd->falloff_curve->preset = CURVE_PRESET_LINE; pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; curvemap_reset(pd->falloff_curve->cm, &pd->falloff_curve->clipr, pd->falloff_curve->preset, CURVEMAP_SLOPE_POSITIVE); - curvemapping_changed(pd->falloff_curve, 0); + curvemapping_changed(pd->falloff_curve, FALSE); return pd; } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 303098ea0bd..dd71e43182e 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -128,8 +128,9 @@ World *BKE_world_copy(World *wrld) } } - if (wrld->nodetree) + if (wrld->nodetree) { wrldn->nodetree = ntreeCopyTree(wrld->nodetree); + } if (wrld->preview) wrldn->preview = BKE_previewimg_copy(wrld->preview); diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index f22fd74baf4..3526058e12b 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -69,8 +69,6 @@ #include "ffmpeg_compat.h" -extern void do_init_ffmpeg(void); - static int ffmpeg_type = 0; static int ffmpeg_codec = CODEC_ID_MPEG4; static int ffmpeg_audio_codec = CODEC_ID_NONE; @@ -101,6 +99,8 @@ static AUD_Device *audio_mixdown_device = 0; #define FFMPEG_AUTOSPLIT_SIZE 2000000000 +#define PRINT if (G.debug & G_DEBUG_FFMPEG) printf + /* Delete a picture buffer */ static void delete_picture(AVFrame *f) @@ -125,9 +125,7 @@ static int write_audio_frame(void) AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples); audio_time += (double) audio_input_samples / (double) c->sample_rate; - pkt.size = avcodec_encode_audio(c, audio_output_buffer, - audio_outbuf_size, - (short *)audio_input_buffer); + pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer); if (pkt.size < 0) { // XXX error("Error writing audio packet"); @@ -137,9 +135,8 @@ static int write_audio_frame(void) pkt.data = audio_output_buffer; if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) { - pkt.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, audio_stream->time_base); - fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts); + pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base); + PRINT("Audio Frame PTS: %d\n", (int) pkt.pts); } pkt.stream_index = audio_stream->index; @@ -189,8 +186,7 @@ static const char **get_file_extensions(int format) return rv; } case FFMPEG_MPEG2: { - static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", - NULL }; + static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", NULL }; return rv; } case FFMPEG_MPEG4: { @@ -254,21 +250,18 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0); } - outsize = avcodec_encode_video(c, video_buffer, video_buffersize, - frame); + outsize = avcodec_encode_video(c, video_buffer, video_buffersize, frame); if (outsize > 0) { AVPacket packet; av_init_packet(&packet); if (c->coded_frame->pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, - video_stream->time_base); - fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base); + PRINT("Video Frame PTS: %d\n", (int)packet.pts); } else { - fprintf(stderr, "Video Frame PTS: not set\n"); + PRINT("Video Frame PTS: not set\n"); } if (c->coded_frame->key_frame) packet.flags |= AV_PKT_FLAG_KEY; @@ -364,7 +357,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) char *param; const AVOption *rv = NULL; - fprintf(stderr, "FFMPEG expert option: %s: ", prop->name); + PRINT("FFMPEG expert option: %s: ", prop->name); BLI_strncpy(name, prop->name, sizeof(name)); @@ -376,15 +369,15 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) switch (prop->type) { case IDP_STRING: - fprintf(stderr, "%s.\n", IDP_String(prop)); + PRINT("%s.\n", IDP_String(prop)); av_set_string3(c, prop->name, IDP_String(prop), 1, &rv); break; case IDP_FLOAT: - fprintf(stderr, "%g.\n", IDP_Float(prop)); + PRINT("%g.\n", IDP_Float(prop)); rv = av_set_double(c, prop->name, IDP_Float(prop)); break; case IDP_INT: - fprintf(stderr, "%d.\n", IDP_Int(prop)); + PRINT("%d.\n", IDP_Int(prop)); if (param) { if (IDP_Int(prop)) { @@ -401,8 +394,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) } if (!rv) { - fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n", - prop->name); + PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name); } } @@ -446,11 +438,14 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char /* prepare a video stream for the output file */ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of, - int rectx, int recty) + int rectx, int recty, char *error, int error_size) { AVStream *st; AVCodecContext *c; AVCodec *codec; + + error[0] = '\0'; + st = av_new_stream(of, 0); if (!st) return NULL; @@ -460,7 +455,6 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->codec_id = codec_id; c->codec_type = AVMEDIA_TYPE_VIDEO; - /* Get some values from the current render settings */ c->width = rectx; @@ -492,7 +486,8 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->me_method = ME_EPZS; codec = avcodec_find_encoder(c->codec_id); - if (!codec) return NULL; + if (!codec) + return NULL; /* Be sure to use the correct pixel format(e.g. RGB, YUV) */ @@ -547,27 +542,25 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex // || !strcmp(of->oformat->name, "3gp") ) { - fprintf(stderr, "Using global header\n"); + PRINT("Using global header\n"); c->flags |= CODEC_FLAG_GLOBAL_HEADER; } /* Determine whether we are encoding interlaced material or not */ if (rd->mode & R_FIELDS) { - fprintf(stderr, "Encoding interlaced video\n"); + PRINT("Encoding interlaced video\n"); c->flags |= CODEC_FLAG_INTERLACED_DCT; c->flags |= CODEC_FLAG_INTERLACED_ME; } /* xasp & yasp got float lately... */ - st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q( - ((double) rd->xasp / (double) rd->yasp), 255); + st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255); set_ffmpeg_properties(rd, c, "video"); if (avcodec_open(c, codec) < 0) { - // - //XXX error("Couldn't initialize codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -584,16 +577,11 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex else video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height); - video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t), - "FFMPEG video buffer"); + video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t), "FFMPEG video buffer"); current_frame = alloc_picture(c->pix_fmt, c->width, c->height); - img_convert_ctx = sws_getContext(c->width, c->height, - PIX_FMT_BGR32, - c->width, c->height, - c->pix_fmt, - SWS_BICUBIC, + img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); return st; } @@ -645,11 +633,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4; } - audio_output_buffer = (uint8_t *)av_malloc( - audio_outbuf_size); + audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - audio_input_buffer = (uint8_t *)av_malloc( - audio_input_samples * c->channels * sizeof(int16_t)); + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); audio_time = 0.0f; @@ -672,7 +658,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report AVFormatContext *of; AVOutputFormat *fmt; AVDictionary *opts = NULL; - char name[256]; + char name[256], error[1024]; const char **exts; ffmpeg_type = rd->ffcodecdata.type; @@ -681,14 +667,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; ffmpeg_gop_size = rd->ffcodecdata.gop_size; - ffmpeg_autosplit = rd->ffcodecdata.flags - & FFMPEG_AUTOSPLIT_OUTPUT; + ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; - do_init_ffmpeg(); - /* Determine the correct filename */ BKE_ffmpeg_filepath_get(name, rd); - fprintf(stderr, "Starting output to %s(ffmpeg)...\n" + PRINT("Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" " gop_size=%d, autosplit=%d\n" @@ -793,10 +776,14 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (fmt->video_codec != CODEC_ID_NONE) { - video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); - printf("alloc video stream %p\n", video_stream); + video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error)); + PRINT("alloc video stream %p\n", video_stream); if (!video_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + if (error[0]) + BKE_report(reports, RPT_ERROR, error); + else + BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + av_dict_free(&opts); return 0; } @@ -867,13 +854,11 @@ void flush_ffmpeg(void) break; } if (c->coded_frame->pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, - video_stream->time_base); - fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base); + PRINT("Video Frame PTS: %d\n", (int) packet.pts); } else { - fprintf(stderr, "Video Frame PTS: not set\n"); + PRINT("Video Frame PTS: not set\n"); } if (c->coded_frame->key_frame) { packet.flags |= AV_PKT_FLAG_KEY; @@ -916,8 +901,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd) } while (*fe) { - if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), - *fe) == 0) + if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) { break; } @@ -983,9 +967,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i AVFrame *avframe; int success = 1; - fprintf(stderr, "Writing frame %i, " - "render width=%d, render height=%d\n", frame, - rectx, recty); + PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, rectx, recty); // why is this done before writing the video frame and again at end_ffmpeg? // write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); @@ -1013,7 +995,7 @@ void BKE_ffmpeg_end(void) { unsigned int i; - fprintf(stderr, "Closing ffmpeg...\n"); + PRINT("Closing ffmpeg...\n"); #if 0 if (audio_stream) { /* SEE UPPER */ @@ -1029,7 +1011,7 @@ void BKE_ffmpeg_end(void) #endif if (video_stream && video_stream->codec) { - fprintf(stderr, "Flushing delayed frames...\n"); + PRINT("Flushing delayed frames...\n"); flush_ffmpeg(); } @@ -1041,7 +1023,7 @@ void BKE_ffmpeg_end(void) if (video_stream && video_stream->codec) { avcodec_close(video_stream->codec); - printf("zero video stream %p\n", video_stream); + PRINT("zero video stream %p\n", video_stream); video_stream = 0; } @@ -1142,8 +1124,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in BLI_strncpy(name, o->name, sizeof(name)); } - fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n", - type, parent_index, opt_index, name); + PRINT("ffmpeg_property_add: %s %d %d %s\n", type, parent_index, opt_index, name); prop = IDP_GetPropertyFromGroup(group, name); if (prop) { @@ -1181,8 +1162,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in /* not all versions of ffmpeg include that, so here we go ... */ -static const AVOption *my_av_find_opt(void *v, const char *name, - const char *unit, int mask, int flags) +static const AVOption *my_av_find_opt(void *v, const char *name, const char *unit, int mask, int flags) { AVClass *c = *(AVClass **)v; const AVOption *o = c->option; @@ -1235,14 +1215,11 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { p = my_av_find_opt(&c, param, o->unit, 0, 0); if (p) { - prop = BKE_ffmpeg_property_add(rd, - (char *) type, p - c.av_class->option, - o - c.av_class->option); + prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option); } } else { - prop = BKE_ffmpeg_property_add(rd, - (char *) type, o - c.av_class->option, 0); + prop = BKE_ffmpeg_property_add(rd, (char *) type, o - c.av_class->option, 0); } @@ -1316,12 +1293,10 @@ static void ffmpeg_set_expert_options(RenderData *rd) if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) BKE_ffmpeg_property_add_string(rd, "video", "cqp:0"); } -#if 0 /* disabled for after release */ else if (codec_id == CODEC_ID_DNXHD) { if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) - ffmpeg_property_add_string(rd, "video", "mbd:rd"); + BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd"); } -#endif } void BKE_ffmpeg_preset_set(RenderData *rd, int preset) |