Motion blur investigation feature

This commit adds a way to debug Cycles motion blur issues which
are usually happening due to something crazy happening in between
of frames. Biggest trouble was that artists had no clue about
what's happening in subframes before they render. This is at
least inefficient workflow when dealing with motion blur shots
with complex animation.

Now there is an option in Time Line Editor which could be found
in View -> Show Subframe. This option will expose current frame
with it's subframe to the time line editor header and it'll allow
scrubbing with a subframe precision in time line editor.

Please note that none of the tools in Blender are aware of
subframe, so they'll likely be using current integer frame still.

This is something we don't consider a bug for now, the whole
purpose for now is to give a tool for investigation. Eventually
we'll likely tweak all tools to be aware of subframe.

Hopefully now we can finish the movie here in the studio..
This commit is contained in:
Sergey Sharybin 2017-02-15 16:19:05 +01:00
parent efbe47f9cd
commit 3e628eefa9
Notes: blender-bot 2023-02-14 07:09:35 +01:00
Referenced by commit 17689f8bb6, Fix T50904: Imprecise timeline frame selection using mouse
Referenced by issue #50904, Imprecise timeline frame selection using mouse
5 changed files with 66 additions and 15 deletions

View File

@ -49,7 +49,10 @@ class TIME_HT_header(Header):
row.prop(scene, "frame_preview_start", text="Start")
row.prop(scene, "frame_preview_end", text="End")
layout.prop(scene, "frame_current", text="")
if scene.show_subframe:
layout.prop(scene, "frame_float", text="")
else:
layout.prop(scene, "frame_current", text="")
layout.separator()
@ -135,6 +138,7 @@ class TIME_MT_view(Menu):
layout.prop(st, "show_frame_indicator")
layout.prop(scene, "show_keys_from_selected_only")
layout.prop(scene, "show_subframe")
layout.separator()

View File

@ -117,7 +117,8 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
/* Draw a light green line to indicate current frame */
UI_ThemeColor(TH_CFRAME);
const float x = (float)(scene->r.cfra * scene->r.framelen);
const float time = scene->r.cfra + scene->r.subframe;
const float x = (float)(time * scene->r.framelen);
glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);

View File

@ -95,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
int frame = RNA_int_get(op->ptr, "frame");
float frame = RNA_float_get(op->ptr, "frame");
bool do_snap = RNA_boolean_get(op->ptr, "snap");
if (do_snap && CTX_wm_space_seq(C)) {
@ -103,10 +103,15 @@ static void change_frame_apply(bContext *C, wmOperator *op)
}
/* set the new frame number */
CFRA = frame;
CFRA = (int)frame;
if (scene->r.flag & SCER_SHOW_SUBFRAME) {
SUBFRA = frame - (int)frame;
}
else {
SUBFRA = 0.0f;
}
FRAMENUMBER_MIN_CLAMP(CFRA);
SUBFRA = 0.0f;
/* do updates */
BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@ -125,18 +130,18 @@ static int change_frame_exec(bContext *C, wmOperator *op)
/* ---- */
/* Get frame from mouse coordinates */
static int frame_from_event(bContext *C, const wmEvent *event)
static float frame_from_event(bContext *C, const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
float viewx;
int frame;
float frame;
/* convert from region coordinates to View2D 'tot' space */
viewx = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
/* round result to nearest int (frames are ints!) */
frame = iroundf(viewx);
frame = viewx;
if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
CLAMP(frame, PSFRA, PEFRA);
@ -187,7 +192,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* as user could click on a single frame (jump to frame) as well as
* click-dragging over a range (modal scrubbing).
*/
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_seq_preview_begin(C, event);
@ -215,7 +220,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case MOUSEMOVE:
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
break;
@ -268,7 +273,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->undo_group = "FRAME_CHANGE";
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}

View File

@ -1716,6 +1716,7 @@ typedef struct Scene {
#define SCER_LOCK_FRAME_SELECTION (1<<1)
/* timeline/keyframe jumping - only selected items (on by default) */
#define SCE_KEYS_NO_SELONLY (1<<2)
#define SCER_SHOW_SUBFRAME (1<<3)
/* mode (int now) */
#define R_OSA 0x0001

View File

@ -792,6 +792,21 @@ static void rna_Scene_frame_current_set(PointerRNA *ptr, int value)
data->r.cfra = value;
}
static float rna_Scene_frame_float_get(PointerRNA *ptr)
{
Scene *data = (Scene *)ptr->data;
return (float)data->r.cfra + data->r.subframe;
}
static void rna_Scene_frame_float_set(PointerRNA *ptr, float value)
{
Scene *data = (Scene *)ptr->data;
/* if negative frames aren't allowed, then we can't use them */
FRAMENUMBER_MIN_CLAMP(value);
data->r.cfra = (int)value;
data->r.subframe = value - data->r.cfra;
}
static float rna_Scene_frame_current_final_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
@ -872,6 +887,12 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value)
data->r.pefra = value;
}
static void rna_Scene_show_subframe_update(Main *UNUSED(bmain), Scene *UNUSED(current_scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
scene->r.subframe = 0.0f;
}
static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
@ -7081,8 +7102,19 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_subframe", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "r.subframe");
RNA_def_property_ui_text(prop, "Current Sub-Frame", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
prop = RNA_def_property(srna, "frame_float", PROP_FLOAT, PROP_TIME);
RNA_def_property_ui_text(prop, "Current Sub-Frame", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
RNA_def_property_ui_range(prop, MINAFRAME, MAXFRAME, 0.1, 2);
RNA_def_property_float_funcs(prop, "rna_Scene_frame_float_get", "rna_Scene_frame_float_set", NULL);
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_sdna(prop, NULL, "r.sfra");
@ -7147,7 +7179,15 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_end_frame_set", NULL);
RNA_def_property_ui_text(prop, "Preview Range End Frame", "Alternative end frame for UI playback");
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL);
/* Subframe for moblur debug. */
prop = RNA_def_property(srna, "show_subframe", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_boolean_sdna(prop, NULL, "r.flag", SCER_SHOW_SUBFRAME);
RNA_def_property_ui_text(prop, "Show Subframe",
"Show current scene subframe and allow set it using interface tools");
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_show_subframe_update");
/* Timeline / Time Navigation settings */
prop = RNA_def_property(srna, "show_keys_from_selected_only", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCE_KEYS_NO_SELONLY);