diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-02-24 07:39:20 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-02-24 07:39:20 +0400 |
commit | d120ec146d3c28b7243371b0de1edf4ba590470c (patch) | |
tree | a05f182978c6007bb9193f6ad0b4f2b210394ee8 /source/blender/blenkernel/intern | |
parent | 3df023ae82eef0ea105dc61c9730af87b59a07d1 (diff) | |
parent | 93c3593d825aafe30aaf051182e50bde4c6084dd (diff) |
Merged changes in the trunk up to revision 54802.
Diffstat (limited to 'source/blender/blenkernel/intern')
24 files changed, 621 insertions, 281 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 8e740075bc6..6b3c95a5cd3 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1017,8 +1017,12 @@ void weight_to_rgb(float r_rgb[3], const float weight) /* draw_flag's for calc_weightpaint_vert_color */ enum { - CALC_WP_MULTIPAINT = (1 << 0), - CALC_WP_AUTO_NORMALIZE = (1 << 1) + /* only one of these should be set, keep first (for easy bit-shifting) */ + CALC_WP_GROUP_USER_ACTIVE = (1 << 1), + CALC_WP_GROUP_USER_ALL = (1 << 2), + + CALC_WP_MULTIPAINT = (1 << 3), + CALC_WP_AUTO_NORMALIZE = (1 << 4) }; static void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const float input) @@ -1050,7 +1054,7 @@ static void calc_weightpaint_vert_color( { float input = 0.0f; - int make_black = FALSE; + bool make_black = false; if ((defbase_sel_tot > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { int was_a_nonzero = FALSE; @@ -1072,7 +1076,7 @@ static void calc_weightpaint_vert_color( /* make it black if the selected groups have no weight on a vertex */ if (was_a_nonzero == FALSE) { - make_black = TRUE; + make_black = true; } else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) { input /= defbase_sel_tot; /* get the average */ @@ -1081,6 +1085,17 @@ static void calc_weightpaint_vert_color( else { /* default, non tricky behavior */ input = defvert_find_weight(dv, defbase_act); + + if (draw_flag & CALC_WP_GROUP_USER_ACTIVE) { + if (input == 0.0f) { + make_black = true; + } + } + else if (draw_flag & CALC_WP_GROUP_USER_ALL) { + if (input == 0.0f) { + make_black = defvert_is_weight_zero(dv, defbase_tot); + } + } } if (make_black) { /* TODO, theme color */ @@ -1138,7 +1153,12 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i } else { int col_i; - weightpaint_color((unsigned char *)&col_i, coba, 0.0f); + if (draw_flag & (CALC_WP_GROUP_USER_ACTIVE | CALC_WP_GROUP_USER_ALL)) { + col_i = 0; + } + else { + weightpaint_color((unsigned char *)&col_i, coba, 0.0f); + } fill_vn_i((int *)wtcol_v, numVerts, col_i); } @@ -1354,8 +1374,11 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; int sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm); - const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | + const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : + /* CALC_WP_GROUP_USER_ACTIVE or CALC_WP_GROUP_USER_ALL*/ + (1 << scene->toolsettings->weightuser)) | (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); + /* Generic preview only in object mode! */ const int do_mod_mcol = (ob->mode == OB_MODE_OBJECT); #if 0 /* XXX Will re-enable this when we have global mod stack options. */ @@ -2720,7 +2743,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, a = attribs->tottface++; attribs->tface[a].array = tfdata->layers[layer].data; - attribs->tface[a].em_offset = tfdata->layers[layer].offset; + attribs->tface[a].em_offset = ldata->layers[layer].offset; attribs->tface[a].gl_index = gattribs->layer[b].glindex; attribs->tface[a].gl_texco = gattribs->layer[b].gltexco; } @@ -2757,7 +2780,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, a = attribs->totmcol++; attribs->mcol[a].array = tfdata->layers[layer].data; - attribs->mcol[a].em_offset = tfdata->layers[layer].offset; + /* odd, store the offset for a different layer type here, but editmode draw code expects it */ + attribs->mcol[a].em_offset = ldata->layers[layer].offset; attribs->mcol[a].gl_index = gattribs->layer[b].glindex; } } @@ -2773,6 +2797,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, a = attribs->totmcol++; attribs->mcol[a].array = tfdata->layers[layer].data; + /* odd, store the offset for a different layer type here, but editmode draw code expects it */ attribs->mcol[a].em_offset = tfdata->layers[layer].offset; attribs->mcol[a].gl_index = gattribs->layer[b].glindex; } diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index a6b3008e00a..4eb26e81ae2 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -69,7 +69,6 @@ #include "BKE_depsgraph.h" #include "BKE_anim.h" #include "BKE_report.h" -#include "BKE_rigidbody.h" // XXX bad level call... @@ -320,46 +319,45 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) } /* "brew me a list that's sorted a bit faster now depsy" */ - DAG_scene_sort(G.main, scene); + DAG_scene_relations_rebuild(G.main, scene); } /* update scene for current frame */ static void motionpaths_calc_update_scene(Scene *scene) { #if 1 // 'production' optimizations always on - Base *base, *last = NULL; - float ctime = BKE_scene_frame_get(scene); - - /* only stuff that moves or needs display still */ - DAG_scene_update_flags(G.main, scene, scene->lay, TRUE); - - /* find the last object with the tag - * - all those afterwards are assumed to not be relevant for our calculations - */ - /* optimize further by moving out... */ - for (base = scene->base.first; base; base = base->next) { - if (base->object->flag & BA_TEMP_TAG) - last = base; + + /* rigid body simulation needs complete update to work correctly for now */ + /* RB_TODO investigate if we could avoid updating everything */ + if (BKE_scene_check_rigidbody_active(scene)) { + BKE_scene_update_for_newframe(G.main, scene, scene->lay); } - - /* run rigidbody sim - * NOTE: keep in sync with BKE_scene_update_for_newframe() in scene.c - */ - // XXX: this position may still change, objects not being updated correctly before simulation is run - // NOTE: current position is so that rigidbody sim affects other objects - if (BKE_scene_check_rigidbody_active(scene)) - BKE_rigidbody_do_simulation(scene, ctime); - - /* perform updates for tagged objects */ - /* XXX: this will break if rigs depend on scene or other data that - * is animated but not attached to/updatable from objects */ - for (base = scene->base.first; base; base = base->next) { - /* update this object */ - BKE_object_handle_update(scene, base->object); + else { /* otherwise we can optimize by restricting updates */ + Base *base, *last = NULL; + + /* only stuff that moves or needs display still */ + DAG_scene_update_flags(G.main, scene, scene->lay, TRUE); - /* if this is the last one we need to update, let's stop to save some time */ - if (base == last) - break; + /* find the last object with the tag + * - all those afterwards are assumed to not be relevant for our calculations + */ + /* optimize further by moving out... */ + for (base = scene->base.first; base; base = base->next) { + if (base->object->flag & BA_TEMP_TAG) + last = base; + } + + /* perform updates for tagged objects */ + /* XXX: this will break if rigs depend on scene or other data that + * is animated but not attached to/updatable from objects */ + for (base = scene->base.first; base; base = base->next) { + /* update this object */ + BKE_object_handle_update(scene, base->object); + + /* if this is the last one we need to update, let's stop to save some time */ + if (base == last) + break; + } } #else // original, 'always correct' version /* do all updates diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index fb2d1a3aaf7..be316197078 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -1000,8 +1000,7 @@ int BKE_copybuffer_paste(bContext *C, char *libname, ReportList *reports) flag_all_listbases_ids(LIB_PRE_EXISTING, 0); /* recreate dependency graph to include new objects */ - DAG_scene_sort(bmain, scene); - DAG_ids_flush_update(bmain, 0); + DAG_relations_tag_update(bmain); BLO_blendhandle_close(bh); /* remove library... */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 1a25def3829..48ad3f51389 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4261,7 +4261,7 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isRe /* Free data of a specific constraint if it has any info. * be sure to run BIK_clear_data() when freeing an IK constraint, - * unless DAG_scene_sort is called. + * unless DAG_relations_tag_update is called. */ void BKE_free_constraint_data(bConstraint *con) { diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index a45afa5e69a..a9e3d52f223 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -48,6 +48,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" @@ -851,7 +853,7 @@ void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg) const char *CTX_wm_operator_poll_msg_get(bContext *C) { - return C->wm.operator_poll_msg; + return IFACE_(C->wm.operator_poll_msg); } /* data context */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 7d6212f8760..2da75ec64be 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -2202,6 +2202,70 @@ static void make_bevel_list_segment_3D(BevList *bl) copy_qt_qt(bevp2->quat, bevp1->quat); } +/* only for 2 points */ +static void make_bevel_list_segment_2D(BevList *bl) +{ + BevPoint *bevp2 = (BevPoint *)(bl + 1); + BevPoint *bevp1 = bevp2 + 1; + + const float x1 = bevp1->vec[0] - bevp2->vec[0]; + const float y1 = bevp1->vec[1] - bevp2->vec[1]; + + calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); + bevp2->sina = bevp1->sina; + bevp2->cosa = bevp1->cosa; + + /* fill in dir & quat */ + make_bevel_list_segment_3D(bl); +} + +static void make_bevel_list_2D(BevList *bl) +{ + /* note: bevp->dir and bevp->quat are not needed for beveling but are + * used when making a path from a 2D curve, therefor they need to be set - Campbell */ + + BevPoint *bevp2 = (BevPoint *)(bl + 1); + BevPoint *bevp1 = bevp2 + (bl->nr - 1); + BevPoint *bevp0 = bevp1 - 1; + int nr; + + nr = bl->nr; + while (nr--) { + const float x1 = bevp1->vec[0] - bevp0->vec[0]; + const float x2 = bevp1->vec[0] - bevp2->vec[0]; + const float y1 = bevp1->vec[1] - bevp0->vec[1]; + const float y2 = bevp1->vec[1] - bevp2->vec[1]; + + calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); + + /* from: make_bevel_list_3D_zup, could call but avoid a second loop. + * no need for tricky tilt calculation as with 3D curves */ + bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec); + vec_to_quat(bevp1->quat, bevp1->dir, 5, 1); + /* done with inline make_bevel_list_3D_zup */ + + bevp0 = bevp1; + bevp1 = bevp2; + bevp2++; + } + + /* correct non-cyclic cases */ + if (bl->poly == -1) { + BevPoint *bevp = (BevPoint *)(bl + 1); + bevp1 = bevp + 1; + bevp->sina = bevp1->sina; + bevp->cosa = bevp1->cosa; + bevp = (BevPoint *)(bl + 1); + bevp += (bl->nr - 1); + bevp1 = bevp - 1; + bevp->sina = bevp1->sina; + bevp->cosa = bevp1->cosa; + + /* correct for the dir/quat, see above why its needed */ + bevel_list_cyclic_fix_3D(bl); + } +} + void BKE_curve_bevelList_make(Object *ob) { /* @@ -2216,7 +2280,7 @@ void BKE_curve_bevelList_make(Object *ob) BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; - float min, inp, x1, x2, y1, y2; + float min, inp; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu = 0, len = 0; int do_tilt, do_radius, do_weight; @@ -2534,76 +2598,22 @@ void BKE_curve_bevelList_make(Object *ob) /* STEP 4: 2D-COSINES or 3D ORIENTATION */ if ((cu->flag & CU_3D) == 0) { - /* note: bevp->dir and bevp->quat are not needed for beveling but are - * used when making a path from a 2D curve, therefor they need to be set - Campbell */ - bl = cu->bev.first; - while (bl) { - + /* 2D Curves */ + for (bl = cu->bev.first; bl; bl = bl->next) { if (bl->nr < 2) { /* do nothing */ } else if (bl->nr == 2) { /* 2 pnt, treat separate */ - bevp2 = (BevPoint *)(bl + 1); - bevp1 = bevp2 + 1; - - x1 = bevp1->vec[0] - bevp2->vec[0]; - y1 = bevp1->vec[1] - bevp2->vec[1]; - - calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); - bevp2->sina = bevp1->sina; - bevp2->cosa = bevp1->cosa; - - /* fill in dir & quat */ - make_bevel_list_segment_3D(bl); + make_bevel_list_segment_2D(bl); } else { - bevp2 = (BevPoint *)(bl + 1); - bevp1 = bevp2 + (bl->nr - 1); - bevp0 = bevp1 - 1; - - nr = bl->nr; - while (nr--) { - x1 = bevp1->vec[0] - bevp0->vec[0]; - x2 = bevp1->vec[0] - bevp2->vec[0]; - y1 = bevp1->vec[1] - bevp0->vec[1]; - y2 = bevp1->vec[1] - bevp2->vec[1]; - - calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); - - /* from: make_bevel_list_3D_zup, could call but avoid a second loop. - * no need for tricky tilt calculation as with 3D curves */ - bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec); - vec_to_quat(bevp1->quat, bevp1->dir, 5, 1); - /* done with inline make_bevel_list_3D_zup */ - - bevp0 = bevp1; - bevp1 = bevp2; - bevp2++; - } - - /* correct non-cyclic cases */ - if (bl->poly == -1) { - bevp = (BevPoint *)(bl + 1); - bevp1 = bevp + 1; - bevp->sina = bevp1->sina; - bevp->cosa = bevp1->cosa; - bevp = (BevPoint *)(bl + 1); - bevp += (bl->nr - 1); - bevp1 = bevp - 1; - bevp->sina = bevp1->sina; - bevp->cosa = bevp1->cosa; - - /* correct for the dir/quat, see above why its needed */ - bevel_list_cyclic_fix_3D(bl); - } + make_bevel_list_2D(bl); } - bl = bl->next; } } - else { /* 3D Curves */ - bl = cu->bev.first; - while (bl) { - + else { + /* 3D Curves */ + for (bl = cu->bev.first; bl; bl = bl->next) { if (bl->nr < 2) { /* do nothing */ } @@ -2613,7 +2623,6 @@ void BKE_curve_bevelList_make(Object *ob) else { make_bevel_list_3D(bl, (int)(resolu * cu->twist_smooth), cu->twist_mode); } - bl = bl->next; } } } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index de15100de0b..439180e8d76 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -41,14 +41,13 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BKE_deform.h" - #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_deform.h" /* own include */ void defgroup_copy_list(ListBase *outbase, ListBase *inbase) { @@ -787,6 +786,24 @@ int defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b) return -1; } +/** + * return true if has no weights + */ +bool defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_tot) +{ + MDeformWeight *dw = dvert->dw; + unsigned int i; + for (i = dvert->totweight; i != 0; i--, dw++) { + if (dw->weight != 0.0f) { + /* check the group is in-range, happens on rare situations */ + if (LIKELY(dw->def_nr < defgroup_tot)) { + return false; + } + } + } + return true; +} + /* -------------------------------------------------------------------- */ /* Defvert Array functions */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 99d0c5ed964..8c55ad02dc6 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -837,7 +837,6 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) DagAdjList *itA; dag = sce->theDag; - sce->dagisvalid = 1; if (dag) free_forest(dag); else { @@ -1846,8 +1845,18 @@ static void scene_sort_groups(Main *bmain, Scene *sce) } } +/* free the depency graph */ +static void dag_scene_free(Scene *sce) +{ + if (sce->theDag) { + free_forest(sce->theDag); + MEM_freeN(sce->theDag); + sce->theDag = NULL; + } +} + /* sort the base list on dependency order */ -void DAG_scene_sort(Main *bmain, Scene *sce) +static void dag_scene_build(Main *bmain, Scene *sce) { DagNode *node, *rootnode; DagNodeQueue *nqueue; @@ -1856,7 +1865,7 @@ void DAG_scene_sort(Main *bmain, Scene *sce) int skip = 0; ListBase tempbase; Base *base; - + tempbase.first = tempbase.last = NULL; build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA); @@ -1936,10 +1945,34 @@ void DAG_scene_sort(Main *bmain, Scene *sce) printf(" %s\n", base->object->id.name); } } + /* temporal...? */ sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ } +/* clear all dependency graphs */ +void DAG_relations_tag_update(Main *bmain) +{ + Scene *sce; + + for (sce = bmain->scene.first; sce; sce = sce->id.next) + dag_scene_free(sce); +} + +/* rebuild dependency graph only for a given scene */ +void DAG_scene_relations_rebuild(Main *bmain, Scene *sce) +{ + dag_scene_free(sce); + DAG_scene_relations_update(bmain, sce); +} + +/* create dependency graph if it was cleared or didn't exist yet */ +void DAG_scene_relations_update(Main *bmain, Scene *sce) +{ + if (!sce->theDag) + dag_scene_build(bmain, sce); +} + static void lib_id_recalc_tag(Main *bmain, ID *id) { id->flag |= LIB_ID_RECALC; @@ -2177,7 +2210,7 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho if (sce->theDag == NULL) { printf("DAG zero... not allowed to happen!\n"); - DAG_scene_sort(bmain, sce); + DAG_scene_relations_update(bmain, sce); } firstnode = sce->theDag->DagNode.first; /* always scene node */ @@ -2545,20 +2578,6 @@ static void dag_current_scene_layers(Main *bmain, ListBase *lb) } } -void DAG_ids_flush_update(Main *bmain, int time) -{ - ListBase listbase; - DagSceneLayer *dsl; - - /* get list of visible scenes and layers */ - dag_current_scene_layers(bmain, &listbase); - - for (dsl = listbase.first; dsl; dsl = dsl->next) - DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, time); - - BLI_freelistN(&listbase); -} - void DAG_on_visible_update(Main *bmain, const short do_time) { ListBase listbase; @@ -2895,12 +2914,10 @@ void DAG_ids_clear_recalc(Main *bmain) memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); } -void DAG_id_tag_update(ID *id, short flag) +void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) { - Main *bmain = G.main; - if (id == NULL) return; - + /* tag ID for update */ if (flag) { if (flag & OB_RECALC_OB) @@ -2955,6 +2972,11 @@ void DAG_id_tag_update(ID *id, short flag) } } +void DAG_id_tag_update(ID *id, short flag) +{ + DAG_id_tag_update_ex(G.main, id, flag); +} + void DAG_id_type_tag(Main *bmain, short idtype) { if (idtype == ID_NT) { @@ -3169,7 +3191,7 @@ void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob) } else { printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name + 2); - DAG_scene_sort(bmain, scene); + DAG_scene_relations_rebuild(bmain, scene); } dag_print_dependencies = 0; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index d652b97e2fa..11c05772962 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -997,6 +997,43 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); } +/** + * \note + * + * For UV's: + * const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); + * + * This is intentionally different to calling: + * CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i); + * + * ... because the material may use layer names to select different UV's + * see: [#34378] + */ +static void emdm_pass_attrib_vertex_glsl(DMVertexAttribs *attribs, BMLoop *loop, int index_in_face) +{ + BMVert *eve = loop->v; + int i; + + if (attribs->totorco) { + const float *orco = attribs->orco.array[BM_elem_index_get(eve)]; + glVertexAttrib3fvARB(attribs->orco.gl_index, orco); + } + for (i = 0; i < attribs->tottface; i++) { + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); + glVertexAttrib2fvARB(attribs->tface[i].gl_index, luv->uv); + } + for (i = 0; i < attribs->totmcol; i++) { + const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset); + GLubyte col[4]; + col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; + glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col); + } + if (attribs->tottang) { + const float *tang = attribs->tang.array[i * 4 + index_in_face]; + glVertexAttrib3fvARB(attribs->tang.gl_index, tang); + } +} + static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial, DMSetDrawOptions setDrawOptions, @@ -1012,7 +1049,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, DMVertexAttribs attribs; GPUVertexAttribs gattribs; - int i, b, matnr, new_matnr, do_draw; + int i, matnr, new_matnr, do_draw; do_draw = FALSE; matnr = -1; @@ -1023,30 +1060,6 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, glShadeModel(GL_SMOOTH); BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); -#define PASSATTRIB(loop, eve, vert) { \ - if (attribs.totorco) { \ - float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \ - glVertexAttrib3fvARB(attribs.orco.gl_index, orco); \ - } \ - for (b = 0; b < attribs.tottface; b++) { \ - MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \ - CD_MLOOPUV, b); \ - glVertexAttrib2fvARB(attribs.tface[b].gl_index, _luv->uv); \ - } \ - for (b = 0; b < attribs.totmcol; b++) { \ - MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \ - CD_MLOOPCOL, b); \ - GLubyte _col[4]; \ - _col[0] = _cp->b; _col[1] = _cp->g; _col[2] = _cp->r; _col[3] = _cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].gl_index, _col); \ - } \ - if (attribs.tottang) { \ - float *tang = attribs.tang.array[i * 4 + vert]; \ - glVertexAttrib3fvARB(attribs.tang.gl_index, tang); \ - } \ - } (void)0 - - for (i = 0, ltri = em->looptris[0]; i < em->tottri; i++, ltri += 3) { int drawSmooth; @@ -1069,20 +1082,20 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]); else glNormal3fv(efa->no); - PASSATTRIB(ltri[0], ltri[0]->v, 0); + emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0); if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); else glVertex3fv(ltri[0]->v->co); - PASSATTRIB(ltri[1], ltri[1]->v, 1); + emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1); if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); else glVertex3fv(ltri[1]->v->co); - PASSATTRIB(ltri[2], ltri[2]->v, 2); + emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2); if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); else glVertex3fv(ltri[2]->v->co); } else { - PASSATTRIB(ltri[0], ltri[0]->v, 0); + emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0); if (vertexCos) { glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); @@ -1092,7 +1105,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, glVertex3fv(ltri[0]->v->co); } - PASSATTRIB(ltri[1], ltri[1]->v, 1); + emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1); if (vertexCos) { glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); @@ -1102,7 +1115,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, glVertex3fv(ltri[1]->v->co); } - PASSATTRIB(ltri[2], ltri[2]->v, 2); + emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2); if (vertexCos) { glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); @@ -1115,7 +1128,6 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, glEnd(); } } -#undef PASSATTRIB } static void emDM_drawFacesGLSL(DerivedMesh *dm, @@ -1124,6 +1136,38 @@ static void emDM_drawFacesGLSL(DerivedMesh *dm, dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); } +/* emdm_pass_attrib_vertex_glsl's note about em_offset use applies here */ +static void emdm_pass_attrib_vertex_mat(DMVertexAttribs *attribs, BMLoop *loop, int index_in_face) +{ + BMVert *eve = loop->v; + int i; + + if (attribs->totorco) { + float *orco = attribs->orco.array[BM_elem_index_get(eve)]; + if (attribs->orco.gl_texco) + glTexCoord3fv(orco); + else + glVertexAttrib3fvARB(attribs->orco.gl_index, orco); + } + for (i = 0; i < attribs->tottface; i++) { + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); + if (attribs->tface[i].gl_texco) + glTexCoord2fv(luv->uv); + else + glVertexAttrib2fvARB(attribs->tface[i].gl_index, luv->uv); + } + for (i = 0; i < attribs->totmcol; i++) { + const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset); + GLubyte col[4]; + col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; + glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col); + } + if (attribs->tottang) { + float *tang = attribs->tang.array[i * 4 + index_in_face]; + glVertexAttrib4fvARB(attribs->tang.gl_index, tang); + } +} + static void emDM_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) @@ -1137,7 +1181,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm, BMLoop **ltri; DMVertexAttribs attribs = {{{0}}}; GPUVertexAttribs gattribs; - int i, b, matnr, new_matnr; + int i, matnr, new_matnr; matnr = -1; @@ -1146,35 +1190,6 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm, BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); -#define PASSATTRIB(loop, eve, vert) { \ - if (attribs.totorco) { \ - float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \ - if (attribs.orco.gl_texco) \ - glTexCoord3fv(orco); \ - else \ - glVertexAttrib3fvARB(attribs.orco.gl_index, orco); \ - } \ - for (b = 0; b < attribs.tottface; b++) { \ - MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \ - CD_MLOOPUV, b); \ - if (attribs.tface[b].gl_texco) \ - glTexCoord2fv(_luv->uv); \ - else \ - glVertexAttrib2fvARB(attribs.tface[b].gl_index, _luv->uv); \ - } \ - for (b = 0; b < attribs.totmcol; b++) { \ - MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \ - CD_MLOOPCOL, b); \ - GLubyte _col[4]; \ - _col[0] = _cp->b; _col[1] = _cp->g; _col[2] = _cp->r; _col[3] = _cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].gl_index, _col); \ - } \ - if (attribs.tottang) { \ - float *tang = attribs.tang.array[i * 4 + vert]; \ - glVertexAttrib4fvARB(attribs.tang.gl_index, tang); \ - } \ - } (void)0 - for (i = 0, ltri = em->looptris[0]; i < em->tottri; i++, ltri += 3) { int drawSmooth; @@ -1198,21 +1213,21 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm, if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]); else glNormal3fv(efa->no); - PASSATTRIB(ltri[0], ltri[0]->v, 0); + emdm_pass_attrib_vertex_mat(&attribs, ltri[0], 0); if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); else glVertex3fv(ltri[0]->v->co); - PASSATTRIB(ltri[1], ltri[1]->v, 1); + emdm_pass_attrib_vertex_mat(&attribs, ltri[1], 1); if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); else glVertex3fv(ltri[1]->v->co); - PASSATTRIB(ltri[2], ltri[2]->v, 2); + emdm_pass_attrib_vertex_mat(&attribs, ltri[2], 2); if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); else glVertex3fv(ltri[2]->v->co); } else { - PASSATTRIB(ltri[0], ltri[0]->v, 0); + emdm_pass_attrib_vertex_mat(&attribs, ltri[0], 0); if (vertexCos) { glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); @@ -1222,7 +1237,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm, glVertex3fv(ltri[0]->v->co); } - PASSATTRIB(ltri[1], ltri[1]->v, 1); + emdm_pass_attrib_vertex_mat(&attribs, ltri[1], 1); if (vertexCos) { glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); @@ -1232,7 +1247,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm, glVertex3fv(ltri[1]->v->co); } - PASSATTRIB(ltri[2], ltri[2]->v, 2); + emdm_pass_attrib_vertex_mat(&attribs, ltri[2], 2); if (vertexCos) { glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); @@ -1244,7 +1259,6 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm, } glEnd(); } -#undef PASSATTRIB } static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 9fdf51ceba9..19ef1e3971d 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -454,7 +454,7 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src) if (strcmp(loop->name, prop->name) == 0) { IDProperty *copy = IDP_CopyProperty(prop); - BLI_insertlink(&dest->data.group, loop, copy); + BLI_insertlinkafter(&dest->data.group, loop, copy); BLI_remlink(&dest->data.group, loop); IDP_FreeProperty(loop); @@ -479,7 +479,7 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) { IDProperty *loop; if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) { - BLI_insertlink(&group->data.group, loop, prop); + BLI_insertlinkafter(&group->data.group, loop, prop); BLI_remlink(&group->data.group, loop); IDP_FreeProperty(loop); @@ -532,7 +532,7 @@ int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew) { if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) { group->len++; - BLI_insertlink(&group->data.group, previous, pnew); + BLI_insertlinkafter(&group->data.group, previous, pnew); return 1; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index de85cb54cfd..3655afdf088 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -571,6 +571,20 @@ static void image_init_color_management(Image *ima) } } +void BKE_image_alpha_mode_from_extension(Image *image) +{ + if (BLI_testextensie(image->name, ".exr") || + BLI_testextensie(image->name, ".cin") || + BLI_testextensie(image->name, ".dpx") || + BLI_testextensie(image->name, ".hdr")) + { + image->alpha_mode = IMA_ALPHA_PREMUL; + } + else { + image->alpha_mode = IMA_ALPHA_STRAIGHT; + } +} + Image *BKE_image_load(Main *bmain, const char *filepath) { Image *ima; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index cb0a11a16e0..f3dc391738e 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -246,7 +246,7 @@ void BKE_key_sort(Key *key) /* find the right location and insert before */ for (kb2 = key->block.first; kb2; kb2 = kb2->next) { if (kb2->pos > kb->pos) { - BLI_insertlink(&key->block, kb2->prev, kb); + BLI_insertlinkafter(&key->block, kb2->prev, kb); break; } } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 943d9e9452a..eceac61ddb6 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -216,7 +216,7 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, colorspace = clip->colorspace_settings.name; } - loadflag = IB_rect | IB_multilayer; + loadflag = IB_rect | IB_multilayer | IB_alphamode_detect; /* read ibuf */ ibuf = IMB_loadiffname(name, loadflag, colorspace); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 97bee320ecb..86fe47268d6 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2028,9 +2028,8 @@ void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char ntype->update_internal_links = ttype->update_internal_links; /* default size values */ - ntype->width = 140; - ntype->minwidth = 100; - ntype->maxwidth = 320; + node_type_size_preset(ntype, NODE_SIZE_DEFAULT); + ntype->height = 100; ntype->minheight = 30; ntype->maxheight = FLT_MAX; @@ -2062,6 +2061,21 @@ void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwid ntype->maxwidth = maxwidth; } +void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size) +{ + switch (size) { + case NODE_SIZE_DEFAULT: + node_type_size(ntype, 140, 100, 320); + break; + case NODE_SIZE_SMALL: + node_type_size(ntype, 100, 80, 320); + break; + case NODE_SIZE_LARGE: + node_type_size(ntype, 140, 120, 500); + break; + } +} + void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *)) { if (storagename) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 119dc8c7d11..5cea2c9fe0e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -74,6 +74,7 @@ #include "BKE_bullet.h" #include "BKE_colortools.h" #include "BKE_deform.h" +#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_animsys.h" #include "BKE_anim.h" @@ -410,7 +411,8 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec if (*obpoin == unlinkOb) { *obpoin = NULL; - ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; // XXX: should this just be OB_RECALC_DATA? + // XXX: should this just be OB_RECALC_DATA? + DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } } @@ -444,14 +446,14 @@ void BKE_object_unlink(Object *ob) obt->proxy = NULL; if (obt->proxy_from == ob) { obt->proxy_from = NULL; - obt->recalc |= OB_RECALC_OB; + DAG_id_tag_update(&obt->id, OB_RECALC_OB); } if (obt->proxy_group == ob) obt->proxy_group = NULL; if (obt->parent == ob) { obt->parent = NULL; - obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob); @@ -461,15 +463,15 @@ void BKE_object_unlink(Object *ob) if (cu->bevobj == ob) { cu->bevobj = NULL; - obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } if (cu->taperobj == ob) { cu->taperobj = NULL; - obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } if (cu->textoncurve == ob) { cu->textoncurve = NULL; - obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } } else if (obt->type == OB_ARMATURE && obt->pose) { @@ -487,7 +489,7 @@ void BKE_object_unlink(Object *ob) if (ct->tar == ob) { ct->tar = NULL; ct->subtarget[0] = '\0'; - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); } } @@ -501,7 +503,7 @@ void BKE_object_unlink(Object *ob) } else if (ELEM(OB_MBALL, ob->type, obt->type)) { if (BKE_mball_is_basis_for(obt, ob)) - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); } sca_remove_ob_poin(obt, ob); @@ -518,7 +520,7 @@ void BKE_object_unlink(Object *ob) if (ct->tar == ob) { ct->tar = NULL; ct->subtarget[0] = '\0'; - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); } } @@ -530,12 +532,12 @@ void BKE_object_unlink(Object *ob) /* object is deflector or field */ if (ob->pd) { if (obt->soft) - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); /* cloth */ for (md = obt->modifiers.first; md; md = md->next) if (md->type == eModifierType_Cloth) - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); } /* strips */ @@ -564,14 +566,14 @@ void BKE_object_unlink(Object *ob) for (; pt; pt = pt->next) { if (pt->ob == ob) { pt->ob = NULL; - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); break; } } if (tpsys->target_ob == ob) { tpsys->target_ob = NULL; - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); } if (tpsys->part->dup_ob == ob) @@ -606,7 +608,7 @@ void BKE_object_unlink(Object *ob) } } if (ob->pd) - obt->recalc |= OB_RECALC_DATA; + DAG_id_tag_update(&obt->id, OB_RECALC_DATA); } obt = obt->id.next; @@ -984,7 +986,7 @@ Object *BKE_object_add(struct Scene *scene, int type) base = BKE_scene_base_add(scene, ob); BKE_scene_base_deselect_all(scene); BKE_scene_base_select(scene, base); - ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); return ob; } @@ -1494,7 +1496,8 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) ob->proxy_group = gob; id_lib_extern(&target->id); - ob->recalc = target->recalc = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DAG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* copy transform * - gob means this proxy comes from a group, just apply the matrix @@ -2132,7 +2135,8 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[ } /* note, scene is the active scene while actual_scene is the scene the object resides in */ -void BKE_object_where_is_calc_time_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob, float ctime) +void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime, + RigidBodyWorld *rbw) { if (ob == NULL) return; @@ -2158,6 +2162,8 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, RigidBodyWorld *rbw, Object BKE_object_to_mat4(ob, ob->obmat); } + /* try to fall back to the scene rigid body world if none given */ + rbw = rbw ? rbw : scene->rigidbody_world; /* read values pushed into RBO from sim/cache... */ BKE_rigidbody_sync_transforms(rbw, ob, ctime); @@ -2177,7 +2183,7 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, RigidBodyWorld *rbw, Object void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) { - BKE_object_where_is_calc_time_ex(scene, NULL, ob, ctime); + BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL); } /* get object transformation matrix without recalculating dependencies and @@ -2203,17 +2209,17 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4]) void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob) { - BKE_object_where_is_calc_time_ex(scene, rbw, ob, BKE_scene_frame_get(scene)); + BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw); } void BKE_object_where_is_calc(Scene *scene, Object *ob) { - BKE_object_where_is_calc_time_ex(scene, NULL, ob, BKE_scene_frame_get(scene)); + BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL); } -void BKE_object_where_is_calc_simul(Scene *scene, Object *ob) /* was written for the old game engine (until 2.04) */ /* It seems that this function is only called * for a lamp that is the child of another object */ +void BKE_object_where_is_calc_simul(Scene *scene, Object *ob) { Object *par; float *fp1, *fp2; @@ -2644,7 +2650,8 @@ int BKE_object_parent_loop_check(const Object *par, const Object *ob) /* the main object update call, for object matrix, constraints, keys and displist (modifiers) */ /* requires flags to be set! */ /* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */ -void BKE_object_handle_update_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob) +void BKE_object_handle_update_ex(Scene *scene, Object *ob, + RigidBodyWorld *rbw) { if (ob->recalc & OB_RECALC_ALL) { /* speed optimization for animation lookups */ @@ -2846,7 +2853,7 @@ void BKE_object_handle_update_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob) */ void BKE_object_handle_update(Scene *scene, Object *ob) { - BKE_object_handle_update_ex(scene, NULL, ob); + BKE_object_handle_update_ex(scene, ob, NULL); } void BKE_object_sculpt_modifiers_changed(Object *ob) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index c01ea4e518d..f90fde983aa 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3509,12 +3509,12 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->flag = PSYS_ENABLED | PSYS_CURRENT; psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1); - DAG_scene_sort(G.main, scene); + DAG_relations_tag_update(G.main); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); return md; } -void object_remove_particle_system(Scene *scene, Object *ob) +void object_remove_particle_system(Scene *UNUSED(scene), Object *ob) { ParticleSystem *psys = psys_get_current(ob); ParticleSystemModifierData *psmd; @@ -3552,7 +3552,7 @@ void object_remove_particle_system(Scene *scene, Object *ob) else ob->mode &= ~OB_MODE_PARTICLE_EDIT; - DAG_scene_sort(G.main, scene); + DAG_relations_tag_update(G.main); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } static void default_particle_settings(ParticleSettings *part) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 6e4937d11ec..3efe25794e1 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3028,13 +3028,20 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f normalize_qt(pa->state.rot); } -/************************************************/ -/* Collisions */ -/************************************************/ +/************************************************ + * Collisions + * + * The algorithm is roughly: + * 1. Use a BVH tree to search for faces that a particle may collide with. + * 2. Use Newton's method to find the exact time at which the collision occurs. + * http://en.wikipedia.org/wiki/Newton's_method + * + ************************************************/ #define COLLISION_MAX_COLLISIONS 10 #define COLLISION_MIN_RADIUS 0.001f #define COLLISION_MIN_DISTANCE 0.0001f #define COLLISION_ZERO 0.00001f +#define COLLISION_INIT_STEP 0.00008f typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor); static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor) { @@ -3189,16 +3196,20 @@ static void collision_point_on_surface(float p[3], ParticleCollisionElement *pce /* find first root in range [0-1] starting from 0 */ static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func) { - float t0, t1, d0, d1, dd, n[3]; + float t0, t1, dt_init, d0, d1, dd, n[3]; int iter; pce->inv_nor = -1; + /* Initial step size should be small, but not too small or floating point + * precision errors will appear. - z0r */ + dt_init = COLLISION_INIT_STEP * col->inv_total_time; + /* start from the beginning */ t0 = 0.f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co1, radius, pce, n); - t1 = 0.001f; + t1 = dt_init; d1 = 0.f; for (iter=0; iter<10; iter++) {//, itersum++) { @@ -3208,11 +3219,6 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part d1 = distance_func(pce->p, radius, pce, n); - /* no movement, so no collision */ - if (d1 == d0) { - return -1.f; - } - /* particle already inside face, so report collision */ if (iter == 0 && d0 < 0.f && d0 > -radius) { copy_v3_v3(pce->p, col->co1); @@ -3220,7 +3226,24 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part pce->inside = 1; return 0.f; } - + + /* Zero gradient (no movement relative to element). Can't step from + * here. */ + if (d1 == d0) { + /* If first iteration, try from other end where the gradient may be + * greater. Note: code duplicated below. */ + if (iter == 0) { + t0 = 1.f; + collision_interpolate_element(pce, t0, col->f, col); + d0 = distance_func(col->co2, radius, pce, n); + t1 = 1.0f - dt_init; + d1 = 0.f; + continue; + } + else + return -1.f; + } + dd = (t1-t0)/(d1-d0); t0 = t1; @@ -3228,14 +3251,14 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part t1 -= d1*dd; - /* particle movin away from plane could also mean a strangely rotating face, so check from end */ + /* Particle moving away from plane could also mean a strangely rotating + * face, so check from end. Note: code duplicated above. */ if (iter == 0 && t1 < 0.f) { t0 = 1.f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co2, radius, pce, n); - t1 = 0.999f; + t1 = 1.0f - dt_init; d1 = 0.f; - continue; } else if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f)) @@ -3683,6 +3706,7 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa memset(&col, 0, sizeof(ParticleCollision)); col.total_time = timestep * dfra; + col.inv_total_time = 1.0f/col.total_time; col.inv_timestep = 1.0f/timestep; col.cfra = cfra; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 4302032ade1..27c5e03132e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -52,6 +52,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "PIL_time.h" #include "WM_api.h" @@ -3505,11 +3507,11 @@ void BKE_ptcache_update_info(PTCacheID *pid) /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) - BLI_snprintf(cache->info, sizeof(cache->info), "%i frames found!", totframes); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i frames found!"), totframes); else if (totframes && cache->totpoint) - BLI_snprintf(cache->info, sizeof(cache->info), "%i points found!", cache->totpoint); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i points found!"), cache->totpoint); else - BLI_snprintf(cache->info, sizeof(cache->info), "No valid data to read!"); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("No valid data to read!")); return; } @@ -3518,9 +3520,9 @@ void BKE_ptcache_update_info(PTCacheID *pid) int totpoint = pid->totpoint(pid->calldata, 0); if (cache->totpoint > totpoint) - BLI_snprintf(mem_info, sizeof(mem_info), "%i cells + High Resolution cached", totpoint); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells + High Resolution cached"), totpoint); else - BLI_snprintf(mem_info, sizeof(mem_info), "%i cells cached", totpoint); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells cached"), totpoint); } else { int cfra = cache->startframe; @@ -3530,7 +3532,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - BLI_snprintf(mem_info, sizeof(mem_info), "%i frames on disk", totframes); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames on disk"), totframes); } } else { @@ -3554,17 +3556,18 @@ void BKE_ptcache_update_info(PTCacheID *pid) mb = (bytes > 1024.0f * 1024.0f); - BLI_snprintf(mem_info, sizeof(mem_info), "%i frames in memory (%.1f %s)", + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"), totframes, bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), - mb ? "Mb" : "kb"); + mb ? IFACE_("Mb") : IFACE_("kb")); } if (cache->flag & PTCACHE_OUTDATED) { - BLI_snprintf(cache->info, sizeof(cache->info), "%s, cache is outdated!", mem_info); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, cache is outdated!"), mem_info); } else if (cache->flag & PTCACHE_FRAMES_SKIPPED) { - BLI_snprintf(cache->info, sizeof(cache->info), "%s, not exact since frame %i.", mem_info, cache->last_exact); + BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, not exact since frame %i."), + mem_info, cache->last_exact); } else { BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info); @@ -3586,4 +3589,3 @@ void BKE_ptcache_invalidate(PointCache *cache) cache->last_exact = MIN2(cache->startframe, 0); } } - diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 26f0c25617f..4c6bae122cd 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -633,8 +633,18 @@ void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, shor else RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f); break; + case RBC_TYPE_MOTOR: + rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2); + + RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG); + RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, rbc->motor_ang_max_impulse); + RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, rbc->motor_ang_target_velocity); + break; } } + else { /* can't create constraint without both rigid bodies */ + return; + } RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED); @@ -813,6 +823,11 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty rbc->spring_stiffness_y = 10.0f; rbc->spring_stiffness_z = 10.0f; + rbc->motor_lin_max_impulse = 1.0f; + rbc->motor_lin_target_velocity = 1.0f; + rbc->motor_ang_max_impulse = 1.0f; + rbc->motor_ang_target_velocity = 1.0f; + /* flag cache as outdated */ BKE_rigidbody_cache_reset(rbw); @@ -1259,7 +1274,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } /* advance simulation, we can only step one frame forward */ - if (ctime == rbw->ltime + 1) { + if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) { /* write cache for first frame when on second frame */ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { BKE_ptcache_write(&pid, startframe); @@ -1308,7 +1323,7 @@ struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, s struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; } void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {} void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} -void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) {} +void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {} void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index eb4e0d9c679..6433b73fda0 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -734,7 +734,7 @@ void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up) } if (tmp) { BLI_remlink(&ob->sensors, sens); - BLI_insertlink(&ob->sensors, tmp, sens); + BLI_insertlinkafter(&ob->sensors, tmp, sens); } } } @@ -778,7 +778,7 @@ void sca_move_controller(bController *cont_to_move, Object *ob, int move_up) tmp = tmp->next; } BLI_remlink(&ob->controllers, cont); - BLI_insertlink(&ob->controllers, tmp, cont); + BLI_insertlinkafter(&ob->controllers, tmp, cont); } } @@ -818,7 +818,7 @@ void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up) } if (tmp) { BLI_remlink(&ob->actuators, act); - BLI_insertlink(&ob->actuators, tmp, act); + BLI_insertlinkafter(&ob->actuators, tmp, act); } } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9934d9b6e9a..e1e4563e89f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -177,6 +177,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) scen->obedit = NULL; scen->stats = NULL; scen->fps_info = NULL; + scen->rigidbody_world = NULL; /* RB_TODO figure out a way of copying the rigid body world */ BLI_duplicatelist(&(scen->markers), &(sce->markers)); BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); @@ -404,7 +405,7 @@ void BKE_scene_free(Scene *sce) BKE_color_managed_view_settings_free(&sce->view_settings); } -static Scene *scene_add(Main *bmain, const char *name) +Scene *BKE_scene_add(Main *bmain, const char *name) { Scene *sce; ParticleEditSettings *pset; @@ -639,11 +640,6 @@ static Scene *scene_add(Main *bmain, const char *name) return sce; } -Scene *BKE_scene_add(Main *bmain, const char *name) -{ - return scene_add(bmain, name); -} - Base *BKE_scene_base_find(Scene *scene, Object *ob) { return BLI_findptr(&scene->base, ob, offsetof(Base, object)); @@ -679,12 +675,11 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) } /* sort baselist */ - DAG_scene_sort(bmain, scene); + DAG_scene_relations_rebuild(bmain, scene); /* ensure dags are built for sets */ - for (sce = scene->set; sce; sce = sce->set) - if (sce->theDag == NULL) - DAG_scene_sort(bmain, sce); + for (sce = scene; sce; sce = sce->set) + DAG_scene_relations_update(bmain, sce); /* copy layers and flags from bases to objects */ for (base = scene->base.first; base; base = base->next) { @@ -1155,7 +1150,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; - BKE_object_handle_update_ex(scene_parent, scene->rigidbody_world, ob); + BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world); if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); @@ -1180,9 +1175,15 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen /* this is called in main loop, doing tagged updates before redraw */ void BKE_scene_update_tagged(Main *bmain, Scene *scene) { + Scene *sce_iter; + /* keep this first */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE); + /* (re-)build dependency graph if needed */ + for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) + DAG_scene_relations_update(bmain, sce_iter); + /* flush recalc flags to dependencies */ DAG_ids_flush_tagged(bmain); @@ -1233,10 +1234,8 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) /* clear animation overrides */ /* XXX TODO... */ - for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set) { - if (sce_iter->theDag == NULL) - DAG_scene_sort(bmain, sce_iter); - } + for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set) + DAG_scene_relations_update(bmain, sce_iter); /* flush recalc flags to dependencies, if we were only changing a frame * this would not be necessary, but if a user or a script has modified diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 45393726add..68618287546 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3955,6 +3955,24 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine) return seq; } +void BKE_sequence_alpha_mode_from_extension(Sequence *seq) +{ + if (seq->strip && seq->strip->stripdata) { + char *name = seq->strip->stripdata->name; + + if (BLI_testextensie(name, ".exr") || + BLI_testextensie(name, ".cin") || + BLI_testextensie(name, ".dpx") || + BLI_testextensie(name, ".hdr")) + { + seq->alpha_mode = IMA_ALPHA_PREMUL; + } + else { + seq->alpha_mode = IMA_ALPHA_STRAIGHT; + } + } +} + void BKE_sequence_init_colorspace(Sequence *seq) { if (seq->strip && seq->strip->stripdata) { diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 86e7a152a4a..74c0a76f82d 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2938,6 +2938,18 @@ int text_check_identifier_nodigit(const char ch) return 0; } +#ifndef WITH_PYTHON +int text_check_identifier_unicode(const unsigned int ch) +{ + return (ch < 255 && text_check_identifier((char)ch)); +} + +int text_check_identifier_nodigit_unicode(const unsigned int ch) +{ + return (ch < 255 && text_check_identifier_nodigit((char)ch)); +} +#endif /* WITH_PYTHON */ + int text_check_whitespace(const char ch) { if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 8b81e474e76..1a7458f531c 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -141,8 +141,10 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) } BLI_freelistN(&dopesheet->channels); + BLI_freelistN(&dopesheet->coverage_segments); dopesheet->channels.first = dopesheet->channels.last = NULL; + dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL; dopesheet->tot_channel = 0; } @@ -1605,6 +1607,67 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali calibration_height, overscan, FALSE); } +void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2]) +{ + int a; + float pos[2], warped_pos[2]; + const int coord_delta = 5; + + delta[0] = delta[1] = -FLT_MAX; + + for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) { + if (a > rect->xmax) + a = rect->xmax; + + /* bottom edge */ + pos[0] = a; + pos[1] = rect->ymin; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + /* top edge */ + pos[0] = a; + pos[1] = rect->ymax; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + if (a >= rect->xmax) + break; + } + + for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) { + if (a > rect->ymax) + a = rect->ymax; + + /* left edge */ + pos[0] = rect->xmin; + pos[1] = a; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + /* right edge */ + pos[0] = rect->xmax; + pos[1] = a; + + BKE_tracking_undistort_v2(tracking, pos, warped_pos); + + delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + + if (a >= rect->ymax) + break; + } +} + /*********************** Image sampling *************************/ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) @@ -3723,6 +3786,88 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, in } } +static int coverage_from_count(int count) +{ + if (count < 8) + return TRACKING_COVERAGE_BAD; + else if (count < 16) + return TRACKING_COVERAGE_ACCEPTABLE; + return TRACKING_COVERAGE_OK; +} + +static void tracking_dopesheet_calc_coverage(MovieTracking *tracking) +{ + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track; + int frames, start_frame = INT_MAX, end_frame = -INT_MAX; + int *per_frame_counter; + int prev_coverage, last_segment_frame; + int i; + + /* find frame boundaries */ + for (track = tracksbase->first; track; track = track->next) { + start_frame = min_ii(start_frame, track->markers[0].framenr); + end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr); + } + + frames = end_frame - start_frame + 1; + + /* this is a per-frame counter of markers (how many markers belongs to the same frame) */ + per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter"); + + /* find per-frame markers count */ + for (track = tracksbase->first; track; track = track->next) { + int i; + + for (i = 0; i < track->markersnr; i++) { + MovieTrackingMarker *marker = &track->markers[i]; + + /* TODO: perhaps we need to add check for non-single-frame track here */ + if ((marker->flag & MARKER_DISABLED) == 0) + per_frame_counter[marker->framenr - start_frame]++; + } + } + + /* convert markers count to coverage and detect segments with the same coverage */ + prev_coverage = coverage_from_count(per_frame_counter[0]); + last_segment_frame = start_frame; + + /* means only disabled tracks in the beginning, could be ignored */ + if (!per_frame_counter[0]) + prev_coverage = TRACKING_COVERAGE_OK; + + for (i = 1; i < frames; i++) { + int coverage = coverage_from_count(per_frame_counter[i]); + + /* means only disabled tracks in the end, could be ignored */ + if (i == frames - 1 && !per_frame_counter[i]) + coverage = TRACKING_COVERAGE_OK; + + if (coverage != prev_coverage || i == frames - 1) { + MovieTrackingDopesheetCoverageSegment *coverage_segment; + int end_segment_frame = i - 1 + start_frame; + + if (end_segment_frame == last_segment_frame) + end_segment_frame++; + + coverage_segment = MEM_callocN(sizeof(MovieTrackingDopesheetCoverageSegment), "tracking coverage segment"); + coverage_segment->coverage = prev_coverage; + coverage_segment->start_frame = last_segment_frame; + coverage_segment->end_frame = end_segment_frame; + + BLI_addtail(&dopesheet->coverage_segments, coverage_segment); + + last_segment_frame = end_segment_frame; + } + + prev_coverage = coverage; + } + + MEM_freeN(per_frame_counter); +} + void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking) { MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; @@ -3750,6 +3895,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking) reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + /* channels */ for (track = tracksbase->first; track; track = track->next) { MovieTrackingDopesheetChannel *channel; @@ -3777,5 +3923,8 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking) tracking_dopesheet_sort(tracking, sort_method, inverse); + /* frame coverage */ + tracking_dopesheet_calc_coverage(tracking); + dopesheet->ok = TRUE; } |