diff options
Diffstat (limited to 'source/blender/blenkernel/intern/scene.c')
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 807 |
1 files changed, 683 insertions, 124 deletions
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b6fc44ec016..1ccc213006a 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -58,21 +58,25 @@ #include "BLI_threads.h" #include "BLI_task.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_armature.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_editmesh.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" #include "BKE_global.h" +#include "BKE_gpencil.h" #include "BKE_group.h" +#include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_library.h" +#include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_node.h" @@ -80,27 +84,37 @@ #include "BKE_paint.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_unit.h" #include "BKE_world.h" +#ifdef WITH_OPENSUBDIV +# include "BKE_modifier.h" +# include "CCGSubSurf.h" +#endif + +#include "DEG_depsgraph.h" + #include "RE_engine.h" #include "PIL_time.h" #include "IMB_colormanagement.h" +#include "IMB_imbuf.h" #include "bmesh.h" -//XXX #include "BIF_previewrender.h" -//XXX #include "BIF_editseq.h" - #ifdef WIN32 #else # include <sys/time.h> #endif +const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER"; +const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME"; +const char *RE_engine_id_CYCLES = "CYCLES"; + void free_avicodecdata(AviCodecData *acd) { if (acd) { @@ -150,18 +164,21 @@ Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; SceneRenderLayer *srl, *new_srl; + FreestyleLineSet *lineset; ToolSettings *ts; Base *base, *obase; if (type == SCE_COPY_EMPTY) { - ListBase lb; + ListBase rl, rv; /* XXX. main should become an arg */ scen = BKE_scene_add(G.main, sce->id.name + 2); - lb = scen->r.layers; + rl = scen->r.layers; + rv = scen->r.views; scen->r = sce->r; - scen->r.layers = lb; + scen->r.layers = rl; scen->r.actlay = 0; + scen->r.views = rv; scen->unit = sce->unit; scen->physics_settings = sce->physics_settings; scen->gm = sce->gm; @@ -184,6 +201,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) scen->ed = NULL; scen->theDag = NULL; + scen->depsgraph = NULL; scen->obedit = NULL; scen->stats = NULL; scen->fps_info = NULL; @@ -194,6 +212,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) BLI_duplicatelist(&(scen->markers), &(sce->markers)); BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers)); + BLI_duplicatelist(&(scen->r.views), &(sce->r.views)); BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if (sce->nodetree) { @@ -221,7 +240,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) sizeof(scen->sequencer_colorspace_settings.name)); /* copy action and remove animation used by sequencer */ - BKE_copy_animdata_id_action(&scen->id); + BKE_animdata_copy_id_action(&scen->id); if (type != SCE_COPY_FULL) remove_sequencer_fcurves(scen); @@ -230,6 +249,14 @@ Scene *BKE_scene_copy(Scene *sce, int type) new_srl = scen->r.layers.first; for (srl = sce->r.layers.first; srl; srl = srl->next) { BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig); + if (type == SCE_COPY_FULL) { + for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + if (lineset->linestyle) { + id_us_plus((ID *)lineset->linestyle); + lineset->linestyle = BKE_linestyle_copy(G.main, lineset->linestyle); + } + } + } new_srl = new_srl->next; } } @@ -290,14 +317,14 @@ Scene *BKE_scene_copy(Scene *sce, int type) } /* before scene copy */ - sound_create_scene(scen); + BKE_sound_create_scene(scen); /* world */ if (type == SCE_COPY_FULL) { if (scen->world) { id_us_plus((ID *)scen->world); scen->world = BKE_world_copy(scen->world); - BKE_copy_animdata_id_action((ID *)scen->world); + BKE_animdata_copy_id_action((ID *)scen->world); } if (sce->ed) { @@ -306,6 +333,23 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL); } } + + /* grease pencil */ + if (scen->gpd) { + if (type == SCE_COPY_FULL) { + scen->gpd = gpencil_data_duplicate(scen->gpd, false); + } + else if (type == SCE_COPY_EMPTY) { + scen->gpd = NULL; + } + else { + id_us_plus((ID *)scen->gpd); + } + } + + if (sce->preview) { + scen->preview = BKE_previewimg_copy(sce->preview); + } return scen; } @@ -345,7 +389,7 @@ void BKE_scene_free(Scene *sce) BLI_freelistN(&sce->base); BKE_sequencer_editing_free(sce); - BKE_free_animdata((ID *)sce); + BKE_animdata_free((ID *)sce); BKE_keyingsets_free(&sce->keyingsets); if (sce->rigidbody_world) @@ -374,6 +418,7 @@ void BKE_scene_free(Scene *sce) BLI_freelistN(&sce->markers); BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); + BLI_freelistN(&sce->r.views); if (sce->toolsettings) { if (sce->toolsettings->vpaint) { @@ -399,6 +444,8 @@ void BKE_scene_free(Scene *sce) } DAG_scene_free(sce); + if (sce->depsgraph) + DEG_graph_free(sce->depsgraph); if (sce->nodetree) { ntreeFreeTree(sce->nodetree); @@ -410,9 +457,11 @@ void BKE_scene_free(Scene *sce) if (sce->fps_info) MEM_freeN(sce->fps_info); - sound_destroy_scene(sce); + BKE_sound_destroy_scene(sce); BKE_color_managed_view_settings_free(&sce->view_settings); + + BKE_previewimg_free(&sce->preview); } Scene *BKE_scene_add(Main *bmain, const char *name) @@ -421,6 +470,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) ParticleEditSettings *pset; int a; const char *colorspace_name; + SceneRenderView *srv; sce = BKE_libblock_alloc(bmain, ID_SCE, name); sce->lay = sce->layact = 1; @@ -526,6 +576,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct"); sce->toolsettings->doublimit = 0.001; + sce->toolsettings->vgroup_weight = 1.0f; sce->toolsettings->uvcalc_margin = 0.001f; sce->toolsettings->unwrapper = 1; sce->toolsettings->select_thresh = 0.01f; @@ -598,7 +649,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.ffcodecdata.audio_bitrate = 192; sce->r.ffcodecdata.audio_channels = 2; - BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine)); + BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine)); sce->audio.distance_model = 2.0f; sce->audio.doppler_factor = 1.0f; @@ -612,7 +663,16 @@ Scene *BKE_scene_add(Main *bmain, const char *name) /* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */ BKE_scene_add_render_layer(sce, NULL); - + + /* multiview - stereo */ + BKE_scene_add_render_view(sce, STEREO_LEFT_NAME); + srv = sce->r.views.first; + BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix)); + + BKE_scene_add_render_view(sce, STEREO_RIGHT_NAME); + srv = sce->r.views.last; + BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); + /* game data */ sce->gm.stereoflag = STEREO_NOSTEREO; sce->gm.stereomode = STEREO_ANAGLYPH; @@ -649,7 +709,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->gm.recastData.cellsize = 0.3f; sce->gm.recastData.cellheight = 0.2f; - sce->gm.recastData.agentmaxslope = M_PI / 2; + sce->gm.recastData.agentmaxslope = M_PI_4; sce->gm.recastData.agentmaxclimb = 0.9f; sce->gm.recastData.agentheight = 2.0f; sce->gm.recastData.agentradius = 0.6f; @@ -661,9 +721,12 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->gm.recastData.detailsampledist = 6.0f; sce->gm.recastData.detailsamplemaxerror = 1.0f; + sce->gm.lodflag = SCE_LOD_USE_HYST; + sce->gm.scehysteresis = 10; + sce->gm.exitkey = 218; // Blender key code for ESC - sound_create_scene(sce); + BKE_sound_create_scene(sce); /* color management */ colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER); @@ -673,14 +736,40 @@ Scene *BKE_scene_add(Main *bmain, const char *name) BLI_strncpy(sce->sequencer_colorspace_settings.name, colorspace_name, sizeof(sce->sequencer_colorspace_settings.name)); + /* Safe Areas */ + copy_v2_fl2(sce->safe_areas.title, 3.5f / 100.0f, 3.5f / 100.0f); + copy_v2_fl2(sce->safe_areas.action, 10.0f / 100.0f, 5.0f / 100.0f); + copy_v2_fl2(sce->safe_areas.title_center, 17.5f / 100.0f, 5.0f / 100.0f); + copy_v2_fl2(sce->safe_areas.action_center, 15.0f / 100.0f, 5.0f / 100.0f); + + sce->preview = NULL; + return sce; } +Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) +{ + Base *base; + + for (base = scene->base.first; base; base = base->next) { + if (STREQ(base->object->id.name + 2, name)) { + break; + } + } + + return base; +} + Base *BKE_scene_base_find(Scene *scene, Object *ob) { return BLI_findptr(&scene->base, ob, offsetof(Base, object)); } +/** + * Sets the active scene, mainly used when running in background mode (``--scene`` command line argument). + * This is also called to set the scene directly, bypassing windowing code. + * Otherwise #ED_screen_set_scene is used when changing scenes by the user. + */ void BKE_scene_set_background(Main *bmain, Scene *scene) { Scene *sce; @@ -745,33 +834,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) return NULL; } -static void scene_unlink_space_node(SpaceNode *snode, Scene *sce) -{ - if (snode->id == &sce->id) { - /* nasty DNA logic for SpaceNode: - * ideally should be handled by editor code, but would be bad level call - */ - bNodeTreePath *path, *path_next; - for (path = snode->treepath.first; path; path = path_next) { - path_next = path->next; - MEM_freeN(path); - } - BLI_listbase_clear(&snode->treepath); - - snode->id = NULL; - snode->from = NULL; - snode->nodetree = NULL; - snode->edittree = NULL; - } -} - -static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce) -{ - if (sbuts->pinid == &sce->id) { - sbuts->pinid = NULL; - } -} - void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) { Scene *sce1; @@ -796,24 +858,11 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) /* all screens */ for (screen = bmain->screen.first; screen; screen = screen->id.next) { - ScrArea *area; - - if (screen->scene == sce) + if (screen->scene == sce) { screen->scene = newsce; - - for (area = screen->areabase.first; area; area = area->next) { - SpaceLink *space_link; - for (space_link = area->spacedata.first; space_link; space_link = space_link->next) { - switch (space_link->spacetype) { - case SPACE_NODE: - scene_unlink_space_node((SpaceNode *)space_link, sce); - break; - case SPACE_BUTS: - scene_unlink_space_buts((SpaceButs *)space_link, sce); - break; - } - } } + + /* editors are handled by WM_main_remove_editor_id_reference */ } BKE_libblock_free(bmain, sce); @@ -1095,39 +1144,36 @@ void BKE_scene_base_select(Scene *sce, Base *selbase) } /* checks for cycle, returns 1 if it's all OK */ -int BKE_scene_validate_setscene(Main *bmain, Scene *sce) +bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) { - Scene *scene; + Scene *sce_iter; int a, totscene; + + if (sce->set == NULL) return true; + totscene = BLI_listbase_count(&bmain->scene); - if (sce->set == NULL) return 1; - - totscene = 0; - for (scene = bmain->scene.first; scene; scene = scene->id.next) - totscene++; - - for (a = 0, scene = sce; scene->set; scene = scene->set, a++) { + for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) { /* more iterations than scenes means we have a cycle */ if (a > totscene) { /* the tested scene gets zero'ed, that's typically current scene */ sce->set = NULL; - return 0; + return false; } } - return 1; + return true; } /* This function is needed to cope with fractional frames - including two Blender rendering features * mblur (motion blur that renders 'subframes' and blurs them together), and fields rendering. */ -float BKE_scene_frame_get(Scene *scene) +float BKE_scene_frame_get(const Scene *scene) { return BKE_scene_frame_get_from_ctime(scene, scene->r.cfra); } /* This function is used to obtain arbitrary fractional frames */ -float BKE_scene_frame_get_from_ctime(Scene *scene, const float frame) +float BKE_scene_frame_get_from_ctime(const Scene *scene, const float frame) { float ctime = frame; ctime += scene->r.subframe; @@ -1146,6 +1192,7 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra) scene->r.cfra = (int)intpart; } +#ifdef WITH_LEGACY_DEPSGRAPH /* drivers support/hacks * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render * - these are always run since the depsgraph can't handle non-object data @@ -1245,9 +1292,38 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen } } } +} +#endif /* WITH_LEGACY_DEPSGRAPH */ +/* That's like really a bummer, because currently animation data for armatures + * might want to use pose, and pose might be missing on the object. + * This happens when changing visible layers, which leads to situations when + * pose is missing or marked for recalc, animation will change it and then + * object update will restore the pose. + * + * This could be solved by the new dependency graph, but for until then we'll + * do an extra pass on the objects to ensure it's all fine. + */ +#define POSE_ANIMATION_WORKAROUND + +#ifdef POSE_ANIMATION_WORKAROUND +static void scene_armature_depsgraph_workaround(Main *bmain) +{ + Object *ob; + if (BLI_listbase_is_empty(&bmain->armature) || !DAG_id_type_tagged(bmain, ID_OB)) { + return; + } + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->type == OB_ARMATURE && ob->adt && ob->adt->recalc & ADT_RECALC_ANIM) { + if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { + BKE_pose_rebuild(ob, ob->data); + } + } + } } +#endif +#ifdef WITH_LEGACY_DEPSGRAPH static void scene_rebuild_rbw_recursive(Scene *scene, float ctime) { if (scene->set) @@ -1265,12 +1341,18 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime) if (BKE_scene_check_rigidbody_active(scene)) BKE_rigidbody_do_simulation(scene, ctime); } +#endif /* Used to visualize CPU threads activity during threaded object update, * would pollute STDERR with whole bunch of timing information which then * could be parsed and nicely visualized. */ -#undef DETAILED_ANALYSIS_OUTPUT +#ifdef WITH_LEGACY_DEPSGRAPH +# undef DETAILED_ANALYSIS_OUTPUT +#else +/* ALWAYS KEEY DISABLED! */ +# undef DETAILED_ANALYSIS_OUTPUT +#endif /* Mballs evaluation uses BKE_scene_base_iter_next which calls * duplilist for all objects in the scene. This leads to conflict @@ -1278,10 +1360,16 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime) * * Ideally Mballs shouldn't do such an iteration and use DAG * queries instead. For the time being we've got new DAG - * let's keep it simple and update mballs in a ingle thread. + * let's keep it simple and update mballs in a single thread. */ #define MBALL_SINGLETHREAD_HACK +/* Need this because CCFDM holds some OpenGL resources. */ +#ifdef WITH_OPENSUBDIV +# define OPENSUBDIV_GL_WORKAROUND +#endif + +#ifdef WITH_LEGACY_DEPSGRAPH typedef struct StatisicsEntry { struct StatisicsEntry *next, *prev; Object *object; @@ -1296,13 +1384,13 @@ typedef struct ThreadedObjectUpdateState { Scene *scene_parent; double base_time; - /* Execution statistics */ - ListBase statistics[BLENDER_MAX_THREADS]; - bool has_updated_objects; - #ifdef MBALL_SINGLETHREAD_HACK bool has_mballs; #endif + + /* Execution statistics */ + bool has_updated_objects; + ListBase *statistics; } ThreadedObjectUpdateState; static void scene_update_object_add_task(void *node, void *user_data); @@ -1371,6 +1459,8 @@ static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadi if (add_to_stats) { StatisicsEntry *entry; + BLI_assert(threadid < BLI_pool_get_num_threads(pool)); + entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics"); entry->object = object; entry->start_time = start_time; @@ -1400,6 +1490,7 @@ static void scene_update_object_add_task(void *node, void *user_data) static void print_threads_statistics(ThreadedObjectUpdateState *state) { int i, tot_thread; + double finish_time; if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) { return; @@ -1425,6 +1516,7 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) } } #else + finish_time = PIL_check_seconds_timer(); tot_thread = BLI_system_thread_count(); for (i = 0; i < tot_thread; i++) { @@ -1454,6 +1546,9 @@ static void print_threads_statistics(ThreadedObjectUpdateState *state) BLI_freelistN(&state->statistics[i]); } + if (state->has_updated_objects) { + printf("Scene update in %f sec\n", finish_time - state->base_time); + } #endif } @@ -1475,6 +1570,47 @@ static bool scene_need_update_objects(Main *bmain) DAG_id_type_tagged(bmain, ID_AR); /* Armature */ } +#ifdef OPENSUBDIV_GL_WORKAROUND +/* CCG DrivedMesh currently hold some OpenGL handles, which could only be + * released from the main thread. + * + * Ideally we need to use gpu_buffer_free, but it's a bit tricky because + * some buffers are only accessible from OpenSubdiv side. + */ +static void scene_free_unused_opensubdiv_cache(Scene *scene) +{ + Base *base; + for (base = scene->base.first; base; base = base->next) { + Object *object = base->object; + if (object->type == OB_MESH && object->recalc & OB_RECALC_DATA) { + ModifierData *md = object->modifiers.last; + if (md != NULL && md->type == eModifierType_Subsurf) { + SubsurfModifierData *smd = (SubsurfModifierData *) md; + bool object_in_editmode = object->mode == OB_MODE_EDIT; + if (!smd->use_opensubdiv || + DAG_get_eval_flags_for_object(scene, object) & DAG_EVAL_NEED_CPU) + { + if (smd->mCache != NULL) { + ccgSubSurf_free_osd_mesh(smd->mCache); + } + if (smd->emCache != NULL) { + ccgSubSurf_free_osd_mesh(smd->emCache); + } + } + if (object_in_editmode && smd->mCache != NULL) { + ccgSubSurf_free(smd->mCache); + smd->mCache = NULL; + } + if (!object_in_editmode && smd->emCache != NULL) { + ccgSubSurf_free(smd->emCache); + smd->emCache = NULL; + } + } + } + } +} +#endif + static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent) { TaskScheduler *task_scheduler = BLI_task_scheduler_get(); @@ -1493,13 +1629,19 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene return; } +#ifdef OPENSUBDIV_GL_WORKAROUND + scene_free_unused_opensubdiv_cache(scene); +#endif + state.eval_ctx = eval_ctx; state.scene = scene; state.scene_parent = scene_parent; /* Those are only needed when blender is run with --debug argument. */ if (G.debug & G_DEBUG_DEPSGRAPH) { - memset(state.statistics, 0, sizeof(state.statistics)); + const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler); + state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics), + "scene update objects stats"); state.has_updated_objects = false; state.base_time = PIL_check_seconds_timer(); } @@ -1509,6 +1651,9 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene #endif task_pool = BLI_task_pool_create(task_scheduler, &state); + if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { + BLI_pool_set_num_threads(task_pool, 1); + } DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool); BLI_task_pool_work_and_wait(task_pool); @@ -1516,6 +1661,7 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene if (G.debug & G_DEBUG_DEPSGRAPH) { print_threads_statistics(&state); + MEM_freeN(state.statistics); } /* We do single thread pass to update all the objects which are in cyclic dependency. @@ -1561,6 +1707,7 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma BKE_mask_update_scene(bmain, scene); } +#endif /* WITH_LEGACY_DEPSGRAPH */ static bool check_rendered_viewport_visible(Main *bmain) { @@ -1596,9 +1743,9 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) Object *obedit = scene->obedit; if (obedit) { Mesh *mesh = obedit->data; - /* TODO(sergey): Check object recalc flags as well? */ if ((obedit->type == OB_MESH) && - (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA))) + ((obedit->id.flag & LIB_ID_RECALC_ALL) || + (mesh->id.flag & LIB_ID_RECALC_ALL))) { if (check_rendered_viewport_visible(bmain)) { BMesh *bm = mesh->edit_btmesh->bm; @@ -1612,13 +1759,26 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene) { Scene *sce_iter; - +#ifdef WITH_LEGACY_DEPSGRAPH + bool use_new_eval = !DEG_depsgraph_use_legacy(); +#endif + /* 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) + for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) { DAG_scene_relations_update(bmain, sce_iter); + /* Uncomment this to check if graph was properly tagged for update. */ +#if 0 +#ifdef WITH_LEGACY_DEPSGRAPH + if (use_new_eval) +#endif + { + DAG_scene_relations_validate(bmain, sce_iter); + } +#endif + } /* flush editing data if needed */ prepare_mesh_for_viewport_render(bmain, scene); @@ -1639,9 +1799,25 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc * * in the future this should handle updates for all datablocks, not * only objects and scenes. - brecht */ - scene_update_tagged_recursive(eval_ctx, bmain, scene, scene); +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + scene_update_tagged_recursive(eval_ctx, bmain, scene, scene); + } + else +#endif + { +#ifdef OPENSUBDIV_GL_WORKAROUND + if (DEG_needs_eval(scene->depsgraph)) { + scene_free_unused_opensubdiv_cache(scene); + } +#endif + DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene); + /* TODO(sergey): This is to beocme a node in new depsgraph. */ + BKE_mask_update_scene(bmain, scene); + } + /* update sound system animation (TODO, move to depsgraph) */ - sound_update_scene(bmain, scene); + BKE_sound_update_scene(bmain, scene); /* extra call here to recalc scene animation (for sequencer) */ { @@ -1657,7 +1833,8 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc * Need to do this so changing material settings from the graph/dopesheet * will update stuff in the viewport. */ - if (DAG_id_type_tagged(bmain, ID_MA)) { +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) { Material *material; float ctime = BKE_scene_frame_get(scene); @@ -1672,7 +1849,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc } /* Also do the same for node trees. */ - if (DAG_id_type_tagged(bmain, ID_NT)) { + if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) { float ctime = BKE_scene_frame_get(scene); FOREACH_NODETREE(bmain, ntree, id) @@ -1683,9 +1860,12 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc } FOREACH_NODETREE_END } +#endif /* notify editors and python about recalc */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST); + + /* Inform editors about possible changes. */ DAG_ids_check_recalc(bmain, scene, false); /* clear recalc flags */ @@ -1705,6 +1885,14 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, #ifdef DETAILED_ANALYSIS_OUTPUT double start_time = PIL_check_seconds_timer(); #endif +#ifdef WITH_LEGACY_DEPSGRAPH + bool use_new_eval = !DEG_depsgraph_use_legacy(); +#else + /* TODO(sergey): Pass to evaluation routines instead of storing layer in the graph? */ + (void) do_invisible_flush; +#endif + + DAG_editors_update_pre(bmain, sce, true); /* keep this first */ BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE); @@ -1714,13 +1902,17 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, * call this at the start so modifiers with textures don't lag 1 frame */ BKE_image_update_frame(bmain, sce->r.cfra); +#ifdef WITH_LEGACY_DEPSGRAPH /* rebuild rigid body worlds before doing the actual frame update * this needs to be done on start frame but animation playback usually starts one frame later * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive */ - scene_rebuild_rbw_recursive(sce, ctime); - - sound_set_cfra(sce->r.cfra); + if (!use_new_eval) { + scene_rebuild_rbw_recursive(sce, ctime); + } +#endif + + BKE_sound_set_cfra(sce->r.cfra); /* clear animation overrides */ /* XXX TODO... */ @@ -1728,25 +1920,37 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, 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 - * some datablock before BKE_scene_update_tagged was called, we need the flush */ - DAG_ids_flush_tagged(bmain); +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + /* 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 + * some datablock before BKE_scene_update_tagged was called, we need the flush */ + DAG_ids_flush_tagged(bmain); - /* Following 2 functions are recursive - * so don't call within 'scene_update_tagged_recursive' */ - DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still + /* Following 2 functions are recursive + * so don't call within 'scene_update_tagged_recursive' */ + DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still + } +#endif BKE_mask_evaluate_all_masks(bmain, ctime, true); +#ifdef POSE_ANIMATION_WORKAROUND + scene_armature_depsgraph_workaround(bmain); +#endif + /* All 'standard' (i.e. without any dependencies) animation is handled here, * with an 'local' to 'macro' order of evaluation. This should ensure that * settings stored nestled within a hierarchy (i.e. settings in a Texture block * can be overridden by settings from Scene, which owns the Texture through a hierarchy * such as Scene->World->MTex/Texture) can still get correctly overridden. */ - BKE_animsys_evaluate_all_animation(bmain, sce, ctime); - /*...done with recursive funcs */ +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + BKE_animsys_evaluate_all_animation(bmain, sce, ctime); + /*...done with recursive funcs */ + } +#endif /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later * when trying to find materials with drivers that need evaluating [#32017] @@ -1756,19 +1960,38 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, /* run rigidbody sim */ /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */ - scene_do_rb_simulation_recursive(sce, ctime); - +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + scene_do_rb_simulation_recursive(sce, ctime); + } +#endif + /* BKE_object_handle_update() on all objects, groups and sets */ - scene_update_tagged_recursive(eval_ctx, bmain, sce, sce); +#ifdef WITH_LEGACY_DEPSGRAPH + if (use_new_eval) { + DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay); + } + else { + scene_update_tagged_recursive(eval_ctx, bmain, sce, sce); + } +#else + DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay); +#endif + /* update sound system animation (TODO, move to depsgraph) */ - sound_update_scene(bmain, sce); + BKE_sound_update_scene(bmain, sce); - scene_depsgraph_hack(eval_ctx, sce, sce); +#ifdef WITH_LEGACY_DEPSGRAPH + if (!use_new_eval) { + scene_depsgraph_hack(eval_ctx, sce, sce); + } +#endif /* notify editors and python about recalc */ BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST); BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST); + /* Inform editors about possible changes. */ DAG_ids_check_recalc(bmain, sce, true); /* clear recalc flags */ @@ -1808,13 +2031,13 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * Scene *sce; if (act == -1) { - return 0; + return false; } else if ( (scene->r.layers.first == scene->r.layers.last) && (scene->r.layers.first == srl)) { /* ensure 1 layer is kept */ - return 0; + return false; } BLI_remlink(&scene->r.layers, srl); @@ -1836,28 +2059,74 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * } } - return 1; + return true; +} + +/* return default view */ +SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name) +{ + SceneRenderView *srv; + + if (!name) + name = DATA_("RenderView"); + + srv = MEM_callocN(sizeof(SceneRenderView), "new render view"); + BLI_strncpy(srv->name, name, sizeof(srv->name)); + BLI_uniquename(&sce->r.views, srv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(srv->name)); + BLI_addtail(&sce->r.views, srv); + + return srv; +} + +bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv) +{ + const int act = BLI_findindex(&scene->r.views, srv); + + if (act == -1) { + return false; + } + else if (scene->r.views.first == scene->r.views.last) { + /* ensure 1 view is kept */ + return false; + } + + BLI_remlink(&scene->r.views, srv); + MEM_freeN(srv); + + scene->r.actview = 0; + + return true; } /* render simplification */ -int get_render_subsurf_level(RenderData *r, int lvl) +int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render) { - if (r->mode & R_SIMPLIFY) - return min_ii(r->simplify_subsurf, lvl); - else + if (r->mode & R_SIMPLIFY) { + if (for_render) + return min_ii(r->simplify_subsurf_render, lvl); + else + return min_ii(r->simplify_subsurf, lvl); + } + else { return lvl; + } } -int get_render_child_particle_number(RenderData *r, int num) +int get_render_child_particle_number(const RenderData *r, int num, bool for_render) { - if (r->mode & R_SIMPLIFY) - return (int)(r->simplify_particles * num); - else + if (r->mode & R_SIMPLIFY) { + if (for_render) + return (int)(r->simplify_particles_render * num); + else + return (int)(r->simplify_particles * num); + } + else { return num; + } } -int get_render_shadow_samples(RenderData *r, int samples) +int get_render_shadow_samples(const RenderData *r, int samples) { if ((r->mode & R_SIMPLIFY) && samples > 0) return min_ii(r->simplify_shadowsamples, samples); @@ -1865,7 +2134,7 @@ int get_render_shadow_samples(RenderData *r, int samples) return samples; } -float get_render_aosss_error(RenderData *r, float error) +float get_render_aosss_error(const RenderData *r, float error) { if (r->mode & R_SIMPLIFY) return ((1.0f - r->simplify_aosss) * 10.0f + 1.0f) * error; @@ -1897,17 +2166,27 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) return NULL; } -bool BKE_scene_use_new_shading_nodes(Scene *scene) +bool BKE_scene_use_new_shading_nodes(const Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); + const RenderEngineType *type = RE_engines_find(scene->r.engine); return (type && type->flag & RE_USE_SHADING_NODES); } -bool BKE_scene_uses_blender_internal(struct Scene *scene) +bool BKE_scene_use_shading_nodes_custom(Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->r.engine); + return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM); +} + +bool BKE_scene_uses_blender_internal(const Scene *scene) { - return strcmp("BLENDER_RENDER", scene->r.engine) == 0; + return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER); } +bool BKE_scene_uses_blender_game(const Scene *scene) +{ + return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME); +} void BKE_scene_base_flag_to_objects(struct Scene *scene) { @@ -1949,7 +2228,7 @@ void BKE_scene_disable_color_management(Scene *scene) bool BKE_scene_check_color_management_enabled(const Scene *scene) { - return strcmp(scene->display_settings.display_device, "None") != 0; + return !STREQ(scene->display_settings.display_device, "None"); } bool BKE_scene_check_rigidbody_active(const Scene *scene) @@ -1994,15 +2273,295 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl switch (unit_type) { case B_UNIT_LENGTH: return value * (double)unit->scale_length; - case B_UNIT_CAMERA: - return value * (double)unit->scale_length; case B_UNIT_AREA: return value * pow(unit->scale_length, 2); case B_UNIT_VOLUME: return value * pow(unit->scale_length, 3); case B_UNIT_MASS: return value * pow(unit->scale_length, 3); + case B_UNIT_CAMERA: /* *Do not* use scene's unit scale for camera focal lens! See T42026. */ default: return value; } } + +/******************** multiview *************************/ + +size_t BKE_scene_multiview_num_views_get(const RenderData *rd) +{ + SceneRenderView *srv; + size_t totviews = 0; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return 1; + + if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + srv = BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)); + if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) { + totviews++; + } + + srv = BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)); + if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) { + totviews++; + } + } + else { + for (srv = rd->views.first; srv; srv = srv->next) { + if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) { + totviews++; + } + } + } + return totviews; +} + +bool BKE_scene_multiview_is_stereo3d(const RenderData *rd) +{ + SceneRenderView *srv[2]; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return false; + + srv[0] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)); + srv[1] = (SceneRenderView *)BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)); + + return (srv[0] && ((srv[0]->viewflag & SCE_VIEW_DISABLE) == 0) && + srv[1] && ((srv[1]->viewflag & SCE_VIEW_DISABLE) == 0)); +} + +/* return whether to render this SceneRenderView */ +bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv) +{ + if (srv == NULL) + return false; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return false; + + if ((srv->viewflag & SCE_VIEW_DISABLE)) + return false; + + if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) + return true; + + /* SCE_VIEWS_SETUP_BASIC */ + if (STREQ(srv->name, STEREO_LEFT_NAME) || + STREQ(srv->name, STEREO_RIGHT_NAME)) + { + return true; + } + + return false; +} + +/* return true if viewname is the first or if the name is NULL or not found */ +bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return true; + + if ((!viewname) || (!viewname[0])) + return true; + + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + return STREQ(viewname, srv->name); + } + } + + return true; +} + +/* return true if viewname is the last or if the name is NULL or not found */ +bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return true; + + if ((!viewname) || (!viewname[0])) + return true; + + for (srv = rd->views.last; srv; srv = srv->prev) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + return STREQ(viewname, srv->name); + } + } + + return true; +} + +SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd, const int view_id) +{ + SceneRenderView *srv; + size_t nr; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return NULL; + + nr = 0; + for (srv = rd->views.first, nr = 0; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + if (nr++ == view_id) + return srv; + } + } + return srv; +} + +const char *BKE_scene_multiview_render_view_name_get(const RenderData *rd, const int view_id) +{ + SceneRenderView *srv = BKE_scene_multiview_render_view_findindex(rd, view_id); + + if (srv) + return srv->name; + else + return ""; +} + +size_t BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + size_t nr; + + if ((!rd) || ((rd->scemode & R_MULTIVIEW) == 0)) + return 0; + + if ((!viewname) || (!viewname[0])) + return 0; + + nr = 0; + for (srv = rd->views.first, nr = 0; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + if (STREQ(viewname, srv->name)) { + return nr; + } + else { + nr += 1; + } + } + } + + return 0; +} + +void BKE_scene_multiview_filepath_get( + SceneRenderView *srv, const char *filepath, + char *r_filepath) +{ + BLI_strncpy(r_filepath, filepath, FILE_MAX); + BLI_path_suffix(r_filepath, FILE_MAX, srv->suffix, ""); +} + +/** + * When multiview is not used the filepath is as usual (e.g., ``Image.jpg``). + * When multiview is on, even if only one view is enabled the view is incorporated + * into the file name (e.g., ``Image_L.jpg``). That allows for the user to re-render + * individual views. + */ +void BKE_scene_multiview_view_filepath_get( + const RenderData *rd, const char *filepath, const char *viewname, + char *r_filepath) +{ + SceneRenderView *srv; + char suffix[FILE_MAX]; + + srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)); + if (srv) + BLI_strncpy(suffix, srv->suffix, sizeof(suffix)); + else + BLI_strncpy(suffix, viewname, sizeof(suffix)); + + BLI_strncpy(r_filepath, filepath, FILE_MAX); + BLI_path_suffix(r_filepath, FILE_MAX, suffix, ""); +} + +const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char *viewname) +{ + SceneRenderView *srv; + + if ((viewname == NULL) || (viewname[0] == '\0')) + return viewname; + + srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)); + if (srv) + return srv->suffix; + else + return viewname; +} + +const char *BKE_scene_multiview_view_id_suffix_get(const RenderData *rd, const size_t view_id) +{ + if ((rd->scemode & R_MULTIVIEW) == 0) { + return ""; + } + else { + const char *viewname = BKE_scene_multiview_render_view_name_get(rd, view_id); + return BKE_scene_multiview_view_suffix_get(rd, viewname); + } +} + +void BKE_scene_multiview_view_prefix_get(Scene *scene, const char *name, char *rprefix, const char **rext) +{ + SceneRenderView *srv; + size_t index_act; + const char *suf_act; + const char delims[] = {'.', '\0'}; + + rprefix[0] = '\0'; + + /* begin of extension */ + index_act = BLI_str_rpartition(name, delims, rext, &suf_act); + BLI_assert(index_act > 0); + UNUSED_VARS_NDEBUG(index_act); + + for (srv = scene->r.views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) { + size_t len = strlen(srv->suffix); + if (STREQLEN(*rext - len, srv->suffix, len)) { + BLI_strncpy(rprefix, name, strlen(name) - strlen(*rext) - len + 1); + break; + } + } + } +} + +void BKE_scene_multiview_videos_dimensions_get( + const RenderData *rd, const size_t width, const size_t height, + size_t *r_width, size_t *r_height) +{ + if ((rd->scemode & R_MULTIVIEW) && + rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D) + { + IMB_stereo3d_write_dimensions( + rd->im_format.stereo3d_format.display_mode, + (rd->im_format.stereo3d_format.flag & S3D_SQUEEZED_FRAME) != 0, + width, height, + r_width, r_height); + } + else { + *r_width = width; + *r_height = height; + } +} + +size_t BKE_scene_multiview_num_videos_get(const RenderData *rd) +{ + if (BKE_imtype_is_movie(rd->im_format.imtype) == false) + return 0; + + if ((rd->scemode & R_MULTIVIEW) == 0) + return 1; + + if (rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D) { + return 1; + } + else { + /* R_IMF_VIEWS_INDIVIDUAL */ + return BKE_scene_multiview_num_views_get(rd); + } +} |